## 引言
在高维空间中基于距离的向量数据库检索,通过嵌入查询和文档来查找相似项。然而,查询措辞的细微变化或嵌入无法很好地捕捉数据语义时,检索结果可能会有所不同。为了手动解决这些问题,通常会进行提示工程或调整,但这往往很繁琐。`MultiQueryRetriever`通过使用大型语言模型(LLM)为给定的用户输入生成多个查询,从不同的视角自动化地进行提示调整。这样可以获得一个更大、更具潜在相关性的文档集合。
## 主要内容
### 构建示例向量数据库
我们将使用Lilain Weng在RAG教程中的博客文章来创建一个向量数据库。
```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
指定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)
print(len(unique_docs)) # 输出文档数量
# INFO:langchain.retrievers.multi_query:Generated queries: ['1. How can Task Decomposition be achieved through different methods?', ...]
自定义提示
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
# 输出解析器将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_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)) # 输出文档数量
常见问题和解决方案
- 查询生成不理想:尝试调整LLM的温度参数以获得更多样化的查询。
- 文档重复:确保使用适当的文档去重策略以获取唯一结果。
总结和进一步学习资源
MultiQueryRetriever为复杂查询带来了更高的灵活性,为开发者解决了基于距离的相似性搜索的一些局限性。通过此工具,您可以优化数据检索,获得更全面的结果集。
进一步学习资源:
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---