引言
在现代数据处理和信息检索中,基于距离的向量数据库检索是一种常用的方法。它依赖于将查询嵌入到高维空间中,并使用距离度量来找到相似的文档。然而,这种方法可能会受到查询措辞细微变化的影响,或者在嵌入无法准确捕获数据语义时产生不同的结果。为了缓解这些问题,通常需要进行繁琐的提示工程/调优。幸运的是,MultiQueryRetriever自动化了这一过程,通过生成多个不同视角的查询来丰富检索结果。
本文将带您深入了解如何使用MultiQueryRetriever提高检索效果,并提供完整的代码示例、常见问题和解决方案,以及进一步学习的资源。
主要内容
MultiQueryRetriever的工作原理
MultiQueryRetriever利用大语言模型(LLM)生成给定输入查询的多个不同视角的查询。对于每个生成的查询,MultiQueryRetriever检索一组相关文档,并通过取所有查询的唯一并集来获取更大、更丰富的潜在相关文档集合。这一过程有效地缓解了基于距离检索的局限性。
构建样本向量数据库
在本节中,我们将从RAG教程中的Lilian Weng的“LLM Powered Autonomous Agents”博客文章构建一个简单的向量数据库。
from langchain_chroma import Chroma
from langchain_community.document_loaders import WebBaseLoader
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 加载博客文章
loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
data = loader.load()
# 文本分割
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)
splits = text_splitter.split_documents(data)
# 向量数据库
embedding = OpenAIEmbeddings()
vectordb = Chroma.from_documents(documents=splits, embedding=embedding)
使用MultiQueryRetriever进行查询
下面的代码展示了如何使用MultiQueryRetriever来生成和执行多视角查询。
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_openai import ChatOpenAI
import logging
# 设置查询的LLM
question = "What are the approaches to Task Decomposition?"
llm = ChatOpenAI(temperature=0)
retriever_from_llm = MultiQueryRetriever.from_llm(
retriever=vectordb.as_retriever(), llm=llm
)
# 设置日志记录
logging.basicConfig()
logging.getLogger("langchain.retrievers.multi_query").setLevel(logging.INFO)
# 执行查询
unique_docs = retriever_from_llm.invoke(question)
print(len(unique_docs)) # 打印检索到的文档数量
在运行此代码时,您会看到INFO级别的日志中生成的查询,这展示了MultiQueryRetriever如何产生不同的查询视角。
常见问题和解决方案
为什么需要多个查询?
多个查询能提供不同的视角,增加找到相关文档的几率。这在查询措辞变化或嵌入不准确的情况下尤为重要。
如何定制生成的查询?
您可以通过自定义PromptTemplate和实现OutputParser来调整生成的查询。以下示例展示了如何实现。
from typing import List
from langchain_core.output_parsers import BaseOutputParser
from langchain_core.prompts import PromptTemplate
class LineListOutputParser(BaseOutputParser[List[str]]):
"""Output parser for a list of lines."""
def parse(self, text: str) -> List[str]:
lines = text.strip().split("\n")
return list(filter(None, lines)) # 移除空行
output_parser = LineListOutputParser()
QUERY_PROMPT = PromptTemplate(
input_variables=["question"],
template="""You are an AI language model assistant. Your task is to generate five
different versions of the given user question to retrieve relevant documents from a vector
database. By generating multiple perspectives on the user question, your goal is to help
the user overcome some of the limitations of the distance-based similarity search.
Provide these alternative questions separated by newlines.
Original question: {question}"""
)
总结和进一步学习资源
通过MultiQueryRetriever,您可以有效地提高基于向量数据库的检索系统的智能化水平,获得更全面的检索结果。其自动化的多视角查询生成机制减少了手动提示调优的工作量,是增强信息检索系统的一项重要工具。
如果您对这一技术感兴趣,可以进一步查阅以下资源:
- LangChain 文档和指南
- OpenAI API 文档
- 向量数据库的原理和应用
参考资料
- LangChain官方文档
- Lilian Weng的博客文章
- OpenAI API文档
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---