如何使用 MultiQueryRetriever
基於距離的 向量資料庫 檢索 嵌入 (表示) 高維空間中的查詢,並根據距離度量找到相似的嵌入文件。但是,檢索可能會因查詢措辭的細微變化,或嵌入無法很好地捕捉資料的語義而產生不同的結果。提示工程/調整有時用於手動解決這些問題,但可能很繁瑣。
MultiQueryRetriever 自動化提示調整的過程,透過使用 LLM 為給定的使用者輸入查詢從不同角度生成多個查詢。對於每個查詢,它檢索一組相關文件,並取得所有查詢的唯一聯集,以獲得更大的潛在相關文件集。透過針對同一個問題產生多個角度,MultiQueryRetriever
可以減輕基於距離的檢索的一些限制,並獲得更豐富的結果集。
讓我們使用 Lilian Weng 在 LLM Powered Autonomous Agents 部落格文章中,來自 RAG 教學 的內容來建立向量儲存
# Build a sample vectorDB
from langchain_chroma import Chroma
from langchain_community.document_loaders import WebBaseLoader
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
# Load blog post
loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
data = loader.load()
# Split
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)
splits = text_splitter.split_documents(data)
# VectorDB
embedding = OpenAIEmbeddings()
vectordb = Chroma.from_documents(documents=splits, embedding=embedding)
USER_AGENT environment variable not set, consider setting it to identify your requests.
簡單用法
指定用於查詢生成的 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
)
API 參考:MultiQueryRetriever | ChatOpenAI
# Set logging for the queries
import logging
logging.basicConfig()
logging.getLogger("langchain.retrievers.multi_query").setLevel(logging.INFO)
unique_docs = retriever_from_llm.invoke(question)
len(unique_docs)
INFO:langchain.retrievers.multi_query:Generated queries: ['1. How can Task Decomposition be achieved through different methods?', '2. What strategies are commonly used for Task Decomposition?', '3. What are the various ways to break down tasks in Task Decomposition?']
5
請注意,檢索器 生成的底層查詢記錄在 INFO
層級。
提供您自己的提示
在底層,MultiQueryRetriever
使用特定的 提示 生成查詢。要自訂此提示
- 製作一個具有問題輸入變數的 PromptTemplate;
- 實作一個如下所示的 輸出解析器,將結果分割成查詢列表。
提示和輸出解析器必須共同支援生成查詢列表。
from typing import List
from langchain_core.output_parsers import BaseOutputParser
from langchain_core.prompts import PromptTemplate
from pydantic import BaseModel, Field
# Output parser will split the LLM result into a list of queries
class LineListOutputParser(BaseOutputParser[List[str]]):
"""Output parser for a list of lines."""
def parse(self, text: str) -> List[str]:
lines = text.strip().split("\n")
return list(filter(None, lines)) # Remove empty 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)
# Chain
llm_chain = QUERY_PROMPT | llm | output_parser
# Other inputs
question = "What are the approaches to Task Decomposition?"
API 參考:BaseOutputParser | PromptTemplate
# Run
retriever = MultiQueryRetriever(
retriever=vectordb.as_retriever(), llm_chain=llm_chain, parser_key="lines"
) # "lines" is the key (attribute name) of the parsed output
# Results
unique_docs = retriever.invoke("What does the course say about regression?")
len(unique_docs)
INFO:langchain.retrievers.multi_query:Generated queries: ['1. Can you provide insights on regression from the course material?', '2. How is regression discussed in the course content?', '3. What information does the course offer regarding regression?', '4. In what way is regression covered in the course?', "5. What are the course's teachings on regression?"]
9