赞
踩
基于距离的向量数据库检索在高维空间中嵌入查询,并根据“距离”查找相似的嵌入文档。
但是,如果查询措辞
发生细微变化,或者嵌入不能很好地捕获数据的语义,检索可能会产生不同的结果。有时需要进行及时的工程/调整来手动解决这些问题,但这可能很乏味。
MultiQueryRetriever
通过使用 LLM
从不同角度为给定的用户输入查询生成多个查询,从而自动执行提示调整过程。对于每个查询,它都会检索一组相关文档,并采用所有查询之间的唯一并集来获取更大的一组潜在相关文档。通过对同一问题生成多个视角,MultiQueryRetriever
或许能够克服基于距离的检索的一些限制,并获得更丰富的结果集。
小节下:同一个问题,生成多个角度的问题。
# 构建示例向量数据库 from langchain.vectorstores import Chroma from langchain.document_loaders import WebBaseLoader from langchain.embeddings.openai import OpenAIEmbeddings from langchain.text_splitter 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)
简单使用:
指定用于查询生成的 LLM
,检索器将完成其余的工作。
from langchain.chat_models import ChatOpenAI from langchain.retrievers.multi_query import MultiQueryRetriever # 问题 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.get_relevant_documents(query=question) # 获取生成内容的文档长度 len(unique_docs)
结果:
INFO:langchain.retrievers.multi_query:Generated queries: ['1. How can Task Decomposition be approached?', '2. What are the different methods for Task Decomposition?', '3. What are the various approaches to decomposing tasks?']
您还可以提供提示和输出解析器,以将结果拆分为查询列表。
from typing import List from langchain import LLMChain from pydantic import BaseModel, Field from langchain.prompts import PromptTemplate from langchain.output_parsers import PydanticOutputParser # 输出解析器会将 LLM 结果拆分为查询列表 class LineList(BaseModel): # “lines”是解析输出的键(属性名称) lines: List[str] = Field(description="Lines of text") class LineListOutputParser(PydanticOutputParser): def __init__(self) -> None: super().__init__(pydantic_object=LineList) def parse(self, text: str) -> LineList: lines = text.strip().split("\n") return LineList(lines=lines) output_parser = LineListOutputParser() QUERY_PROMPT = PromptTemplate( input_variables=["question"], template="""你是一名AI语言模型助手。你的任务是生成五个 给定用户问题的不同版本,用于从向量中检索相关文档 数据库。通过对用户问题产生多种观点,您的目标是帮助 用户克服了基于距离的相似性搜索的一些限制。 提供这些替代问题,并用换行符分隔。 Original question: {question}""", ) llm = ChatOpenAI(temperature=0) # Chain llm_chain = LLMChain(llm=llm, prompt=QUERY_PROMPT, output_parser=output_parser) # Other inputs question = "任务分解的方法有哪些?" # 执行 retriever = MultiQueryRetriever( retriever=vectordb.as_retriever(), llm_chain=llm_chain, parser_key="lines" ) # “lines”是解析输出的键(属性名称) # 结果 unique_docs = retriever.get_relevant_documents( query="课程中关于回归的内容是怎样的?" ) # 文档数量 len(unique_docs)
结果:
INFO:langchain.retrievers.multi_query:Generated queries: ["1. 该课程对回归的看法是什么?", '2. 您能否提供课程中讨论的有关回归的信息?', '3. 课程如何涵盖回归主题?', "4. 该课程关于回归的教学内容是什么?", '5. 关于课程,提到了回归?']
11
现在的搜索,其实是基于向量库的检索,本质上是距离的检索。而我们搜索的措辞
的微妙变化,会产生不同的结果,这需要我们手动调整,这个工作枯燥乏味。
MultiQueryRetriever
,可以基于你给出的问题,生成多个相关问题。通过生成多角度问题,来自动调整这种微妙的措施
变化。
MultiQueryRetriever
的使用步骤:
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)
llm
:llm = ChatOpenAI(temperature=0)
retriever_from_llm = MultiQueryRetriever.from_llm( retriever=vectordb.as_retriever(), llm=llm )
unique_docs = retriever_from_llm.get_relevant_documents(query=question) len(unique_docs)
参考地址:
https://python.langchain.com/docs/modules/data_connection/retrievers/how_to/MultiQueryRetriever
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。