譯者 | 布加迪
審校 | 重樓
如果你正在構(gòu)建一個(gè)檢索增強(qiáng)生成(RAG)應(yīng)用程序,就知道其功能有多強(qiáng)大,前提是當(dāng)它順暢運(yùn)行時(shí)。但是語義嵌入模型并不是什么魔法。大多數(shù)RAG實(shí)現(xiàn)依賴語義相似性作為唯一的檢索機(jī)制,將每個(gè)文檔放入到向量數(shù)據(jù)庫中,并對(duì)每個(gè)查詢運(yùn)用相同的檢索邏輯。這種方法適用于簡(jiǎn)單直觀的問題,但常常檢索上下文無關(guān)(但語義相似)的文檔。當(dāng)精準(zhǔn)的查詢需要精確的答案時(shí),僅語義相似性就會(huì)導(dǎo)致混淆或不正確的響應(yīng)。
問題不在于你的模型,而在于你的檢索過程。
我們?cè)谶@里將介紹一種更好的方法:代理混合搜索。通過使用結(jié)構(gòu)化元數(shù)據(jù)并讓大語言模型(LLM)為每個(gè)查詢選擇最佳檢索操作,你就可以將RAG應(yīng)用程序變成真正智能化的助手。我們將從介紹核心概念入手,然后通過一個(gè)示例將簡(jiǎn)單的“信用卡策略QA機(jī)器人”變成動(dòng)態(tài)適應(yīng)用戶需求的代理系統(tǒng)。
告別千篇一律的檢索,迎接更智能化的RAG體驗(yàn)。
為什么你的RAG應(yīng)用程序不盡如人意?
究其核心,RAG將LLM與外部知識(shí)聯(lián)系起來。你可以為文檔編制索引,使用向量搜索檢索語義相似的文檔,并讓LLM根據(jù)這些結(jié)果生成響應(yīng)。是不是覺得聽起來很簡(jiǎn)單?
但簡(jiǎn)單性是一把雙刃劍。雖然許多開發(fā)人員致力于改進(jìn)知識(shí)庫——用更多的文檔或更好的嵌入來豐富知識(shí)庫,或者針對(duì)LLM對(duì)提示進(jìn)行微調(diào),但真正的瓶頸常常在于檢索過程本身。大多數(shù)RAG實(shí)現(xiàn)依賴語義相似性作為一種通用策略。這種方法常常檢索錯(cuò)誤的文檔:要么提取上下文無關(guān)的結(jié)果,因?yàn)檎Z義相似性不是查詢的正確方法,要么檢索太多重疊或冗余的文檔,從而降低了響應(yīng)的有用性。如果沒有一種更智能的方法來過濾和優(yōu)先處理結(jié)果,依賴細(xì)微差別的精準(zhǔn)查詢會(huì)繼續(xù)失敗。
想象一下QA機(jī)器人負(fù)責(zé)回答特定的問題,比如“如果我晚10天支付Premium Card賬單會(huì)發(fā)生什么?”或“A銀行的基礎(chǔ)卡提供購買保障嗎?”這些問題需要精確的答案,這些答案取決于策略之間的細(xì)微差別。同樣,考慮一下像三星這樣的公司的支持機(jī)器人,支持從智能手機(jī)到冰箱的眾多產(chǎn)品。比如,“如何重置我的Galaxy S23?”就需要檢索該款手機(jī)所特有的操作說明,而查詢冰箱的保修需要完全不同的文檔。借助簡(jiǎn)單的向量搜索,機(jī)器人可能會(huì)獲取語義相關(guān)但上下文無關(guān)的文檔,因混入用于全然不同的產(chǎn)品或用例的信息而混淆響應(yīng)或引起幻覺。
無論你的LLM或嵌入有多先進(jìn),這個(gè)問題始終存在。開發(fā)人員常通過微調(diào)模型或調(diào)整提示作為對(duì)策,但真正的解決方案在于改進(jìn)文檔在生成之前的檢索方式。簡(jiǎn)單的檢索系統(tǒng)要么檢索太多的內(nèi)容,迫使LLM篩選不相關(guān)的信息——這有時(shí)可以借助巧妙的提示加以緩解;要么檢索太少的內(nèi)容,使LLM“盲目行動(dòng)”,沒有必要的上下文來生成有意義的響應(yīng)。通過使檢索更智能化、上下文感知,混合搜索解決了這兩個(gè)問題:它通過針對(duì)相關(guān)主題進(jìn)行搜索來減少不相關(guān)的干擾信息,并確保檢索的文檔含有LLM所需的更多精確信息。這大大提高了RAG應(yīng)用程序的準(zhǔn)確性和可靠性。
解決方案:代理混合搜索
解決方案異常簡(jiǎn)單,卻具有變革性:將結(jié)構(gòu)化元數(shù)據(jù)支持的混合搜索與LLM的代理決策功能相結(jié)合,以實(shí)現(xiàn)代理混合搜索。這種方法不需要全面改變你的架構(gòu)或丟棄現(xiàn)有的投入,它立足于已有的系統(tǒng)上,卻可以帶來全新的智能和靈活性。
從簡(jiǎn)單到代理:更智能化的流程
一個(gè)典型的RAG應(yīng)用程序遵循簡(jiǎn)單直觀的過程:提問→搜索→生成。用戶的問題被傳遞給檢索引擎(常常是向量搜索),檢索語義上最相似的文檔。然后將這些文檔傳遞給LLM以生成響應(yīng)。這對(duì)于簡(jiǎn)單的查詢很有效,但是面對(duì)需要精細(xì)的檢索策略時(shí)卻束手無策。
代理混合搜索使用一種更智能化、適應(yīng)性更強(qiáng)的流程:提問→分析→搜索→生成,取代了這種死板僵硬的流程。LLM不是直接跳轉(zhuǎn)到檢索,而是分析問題以確定最佳檢索策略。這種靈活性使系統(tǒng)能夠更準(zhǔn)確地處理更廣泛的用例。
功能解鎖
有了代理型混合搜索,你的RAG應(yīng)用程序?qū)⒆兊霉δ墚惓?qiáng)大:
- 多個(gè)知識(shí)庫——LLM可以根據(jù)問題動(dòng)態(tài)決定查詢哪個(gè)知識(shí)庫。比如說,QA機(jī)器人可能從一個(gè)數(shù)據(jù)庫提取一般的策略信息,從另一個(gè)數(shù)據(jù)庫提取某家銀行特有的常見問答(FAQ)。
- 定制的搜索查詢——LLM 可以定制自定義搜索查詢,而不是僅僅依賴語義相似性。比如說,“A銀行的哪些卡提供購買保障?”之類的問題可能會(huì)觸發(fā)對(duì)帶有“購買保障”標(biāo)簽的卡執(zhí)行元數(shù)據(jù)過濾的搜索。
- 元數(shù)據(jù)過濾器——通過使用結(jié)構(gòu)化的元數(shù)據(jù)(比如信用卡名、銀行名稱、部門、日期)豐富文檔,可以實(shí)現(xiàn)精確的、針對(duì)性的搜索,避免了不相關(guān)的結(jié)果。
- 多個(gè)搜索操作——有些問題需要將查詢分解成多個(gè)子部分。比如說,“Premium Card的資格要求和好處是什么?”可能需要對(duì)資格標(biāo)準(zhǔn)執(zhí)行一次搜索,對(duì)好處執(zhí)行另一次搜索。
這些功能擴(kuò)展了應(yīng)用程序可以處理的查詢類型。你的RAG應(yīng)用程序現(xiàn)在可以處理探索性研究、多步驟推理和特定領(lǐng)域的任務(wù),同時(shí)保持準(zhǔn)確性,而不是局限于簡(jiǎn)單的事實(shí)發(fā)現(xiàn)。
工作機(jī)理:徹底轉(zhuǎn)變信用卡策略QA機(jī)器人
不妨看一個(gè)例子。假設(shè)你正在構(gòu)建一個(gè)機(jī)器人來回答有關(guān)多家銀行信用卡策略的問題。這是一個(gè)簡(jiǎn)單的實(shí)現(xiàn):
簡(jiǎn)單的方法
文檔在向量數(shù)據(jù)庫中建立索引,機(jī)器人執(zhí)行簡(jiǎn)單的語義搜索來檢索最相似的文檔。無論用戶查詢資格要求、費(fèi)用或取消策略,檢索邏輯都是相同的。
from langchain_core.runnables import (
RunnablePassthrough,
ConfigurableField,
)
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_astradb.graph_vectorstores import AstraDBVectorStore
llm = ChatOpenAI()
embeddings = OpenAIEmbeddings()
vectorstore = AstraDBVectorStore(
collection_name="knowledge_store",
embedding=embeddings,
)
ANSWER_PROMPT = (
"Use the information in the results to provide a concise answer the original question.\n\n"
"Original Question: {question}\n\n"
"Vector Store Results:\n{'\n\n'.join(c.page_content for c in context)}\n\n"
)
retriever = vectorstore.as_retriever()
# Construct the LLM execution chain
chain = (
{"context": retriever, "question": RunnablePassthrough()}
| ChatPromptTemplate.from_messages([ANSWER_PROMPT])
| llm
)
結(jié)果怎樣?對(duì)于像“我的會(huì)員年費(fèi)是多少?”這樣的問題,系統(tǒng)可能從不相關(guān)的卡檢索策略,因?yàn)榍度雰?yōu)先注重廣泛的相似性而不是特殊性。
chain.invoke("How much is my annual membership fee?",)
# > Response: Your annual membership fee could be $250, $95, $695, or $325, depending on the specific plan or card you have chosen. Please refer to your specific card member agreement or plan details to confirm the exact amount of your annual membership fee.
代理方法
在代理混合搜索方法中,我們通過以下手段對(duì)系統(tǒng)進(jìn)行改進(jìn):
用元數(shù)據(jù)豐富文檔——在索引策略時(shí),我們添加了結(jié)構(gòu)化元數(shù)據(jù),比如:
- 卡名(“Premium Card”)
- 銀行名稱(“A銀行”)
- 策略部分(“費(fèi)用”、“獎(jiǎng)勵(lì)”、“資格”)
使用LLM來選擇檢索操作——機(jī)器人使用查詢上下文來決定以下問題,而不是盲目地執(zhí)行向量搜索:
- 是否應(yīng)該搜索語義上相似的策略?
- 是否應(yīng)該根據(jù)信用卡或銀行元數(shù)據(jù)進(jìn)行過濾?
- 是否應(yīng)該針對(duì)特定的策略部分發(fā)出多個(gè)查詢?
從多個(gè)搜索組合響應(yīng)——機(jī)器人智能地組合結(jié)果,以生成精確、可信賴的答案。
下面是它實(shí)際上的樣子:
示例代碼:
from typing import List, Literal
from pydantic import BaseModel, Field
from langchain_core.documents.base import Document
from langchain_core.tools import StructuredTool
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
("system", "Concisely answer the following question, using information retrieved from tools and the provided information about the user."),
("system", "The following card types are associated with the user: {cards}"),
("system", "Always use the provided tools to retrieve information needed to answer policy-related questions."),
("human", "{question}"),
MessagesPlaceholder("agent_scratchpad"),
])
# First we define the parameters to our search operation
class RetrieveInput(BaseModel):
question: str = Field(description="Question to retrieve content for. Should be a simple question describing the starting point for retrieval likely to have content.")
card_type: str = Field(description=f"Search for documents related to this card type. Value must be one of {pages.keys()}")
# Next, create a "tool" that implements the search logic
def retrieve_policy(question: str, card_type: str) -> List[Document]:
print(f"retrieve_policy(card_type: {card_type}, question: {question})")
retriever = graph_vectorstore.as_retriever(
search_type = "similarity",
search_kwargs = {"metadata_filter": {"card-type": card_type}},
)
return list(retriever.invoke(question))
policy_tool = StructuredTool.from_function(
func=retrieve_policy,
name="RetrievePolicy",
description="Retrieve information about a specific card policy.",
args_schema=RetrieveInput,
return_direct=False,
)
# Finally, construct an agent to use the tool we created
agent = create_tool_calling_agent(llm, [policy_tool], prompt)
agent_executor = AgentExecutor(agent=agent, tools=[policy_tool], verbose=True)
在這個(gè)示例中,機(jī)器人認(rèn)識(shí)到查詢具有高度針對(duì)性,使用元數(shù)據(jù)過濾器根據(jù)所提供的用戶配置文件來檢索準(zhǔn)確的策略。此外,LLM重寫用戶的問題,以便完全專注于檢索相關(guān)文檔所需的信息。
agent_executor.invoke({
"question": "How much is my annual membership fee?",
"cards": ["gold"],
})
# > Agent: Invoking: `RetrievePolicy` with `{'question': 'annual membership fee', 'card_type': 'gold'}`
# > Response: Your annual membership fee could be $250, $95, $695, or $325, depending on the specific plan or card you have chosen. Please refer to your specific card member agreement or plan details to confirm the exact amount of your annual membership fee.
由于LLM選擇如何使用搜索工具,我們并不僅限于為每個(gè)問題使用相同的過濾器。比如說,LLM可以動(dòng)態(tài)地認(rèn)識(shí)到用戶針對(duì)與自己的策略不同的策略詢問問題,并創(chuàng)建相應(yīng)的過濾器。
agent_executor.invoke({
"question": "What's the annual membership fee for platinum cards?",
"cards": ["gold"],
})
# > Agent: Invoking: `RetrievePolicy` with `{'question': 'annual membership fee for platinum cards', 'card_type': 'platinum'}`
# > Response: The annual membership fee for Platinum cards is $695. Additionally, each Additional Platinum Card has an annual fee of $195, but there is no annual fee for Companion Platinum Cards.
LLM甚至決定多次使用某個(gè)工具。比如說,下列問題需要LLM不僅了解問題中提及的策略,還需要了解用戶的當(dāng)前策略。
agent_executor.invoke({
"question": "How much would my membership fee change if I upgraded to a platinum card?",
"cards": ["gold"],
})
# > Agent: Invoking: `RetrievePolicy` with `{'question': 'membership fee for gold card', 'card_type': 'gold'}`
# > Agent: Invoking: `RetrievePolicy` with `{'question': 'membership fee for platinum card', 'card_type': 'platinum'}`
# > Response: The annual membership fee for your current American Express? Gold Card is $325. If you were to upgrade to a Platinum Card, the annual fee would be $695. Therefore, upgrading from a Gold Card to a Platinum Card would increase your annual membership fee by $370.
不妨在這個(gè)筆記本:Agentic_Retrieval.ipynb中親自試一試代碼。
為什么這管用?
神奇之處在于利用LLM作為決策者。你不需要硬編碼檢索邏輯,而是允許LLM分析查詢并動(dòng)態(tài)選擇最佳方法。這種靈活性使你的系統(tǒng)更智能化、適應(yīng)性更強(qiáng),而不需要對(duì)基礎(chǔ)結(jié)構(gòu)進(jìn)行重大改變。
回報(bào):更智能化的檢索,更精準(zhǔn)的響應(yīng)
采用代理混合搜索可以將你的RAG應(yīng)用程序變成能夠處理復(fù)雜細(xì)微查詢的系統(tǒng)。通過引入更智能化的檢索,你可以獲得幾大好處:
- 提高準(zhǔn)確性——更智能化的檢索確保為每個(gè)查詢顯示正確的文檔,減少幻覺和不相關(guān)的結(jié)果。這直接提高了LLM響應(yīng)的質(zhì)量。
- 增強(qiáng)信任——通過只提取上下文適當(dāng)?shù)男畔?,你可以避免混淆關(guān)鍵細(xì)節(jié)等令人尷尬的錯(cuò)誤,確保用戶對(duì)系統(tǒng)有信心。
- 支持更廣泛的用例——?jiǎng)討B(tài)搜索策略允許你的應(yīng)用程序處理更復(fù)雜的查詢、整合多個(gè)知識(shí)來源,并為更廣泛的用戶和場(chǎng)景提供服務(wù)。
- 簡(jiǎn)化維護(hù)——你可以讓LLM動(dòng)態(tài)調(diào)整檢索策略,減少對(duì)持續(xù)手動(dòng)干預(yù)的需要,而不是硬編碼檢索規(guī)則或手動(dòng)管理過濾器。
- 面向未來的可擴(kuò)展性——隨著數(shù)據(jù)集日益龐大或知識(shí)庫日益多樣化,代理方法可以擴(kuò)展以應(yīng)對(duì)新的挑戰(zhàn),無需對(duì)系統(tǒng)進(jìn)行根本性改變。
通過使檢索更智能化、更具適應(yīng)性,你可以提高系統(tǒng)的整體性能,無需進(jìn)行重大改動(dòng)。
兼顧靈活性和成本
為檢索過程添加代理層確實(shí)帶來了幾個(gè)不足:
- 增加延遲——每個(gè)查詢分析都需要額外的LLM調(diào)用,執(zhí)行多個(gè)定制的搜索可能比單個(gè)操作花費(fèi)更長(zhǎng)的時(shí)間。這可能會(huì)稍微延長(zhǎng)響應(yīng)時(shí)間,尤其對(duì)于對(duì)延遲敏感的應(yīng)用程序而言。
- 提高了推理成本——查詢分析和編排多個(gè)搜索增加了計(jì)算開銷,對(duì)于查詢量大的系統(tǒng)而言這可能會(huì)增加成本。
- 編排的復(fù)雜性——雖然實(shí)現(xiàn)很簡(jiǎn)單,但維護(hù)一個(gè)動(dòng)態(tài)選擇檢索策略的系統(tǒng)可能會(huì)帶來額外的調(diào)試或測(cè)試問題。
盡管存在這些不足,但代理混合搜索的好處通常壓倒成本。對(duì)于大多數(shù)應(yīng)用而言,增加的靈活性和精度大大提高了用戶滿意度和系統(tǒng)可靠性,使投入物有所值。此外,延遲和成本問題通??梢酝ㄟ^緩存、預(yù)計(jì)算過濾器或僅針對(duì)復(fù)雜查詢進(jìn)行分析等優(yōu)化手段來予以緩解。
如何理解和管理這些不足,你可以充分發(fā)揮代理混合搜索的潛力,以構(gòu)建更智能化、更強(qiáng)大的RAG應(yīng)用程序。
結(jié)語
代理混合搜索是充分發(fā)揮RAG應(yīng)用程序的潛力的關(guān)鍵。通過使用結(jié)構(gòu)化元數(shù)據(jù)豐富文檔,并讓LLM智能化決定檢索策略,你可以不僅限于簡(jiǎn)單的語義相似性,構(gòu)建用戶可以真正依賴的助手。
這是一個(gè)很容易接受的改變,會(huì)帶來驚人的巨大回報(bào)。何不在你的下一個(gè)項(xiàng)目中試一下?用戶和未來的你會(huì)感謝你的。
原文標(biāo)題:Supercharge Your RAG App With Agentic Hybrid Search,作者:Ryan Michael