思考: LLM 自己“不知道”某個事實性問題的答案,但仍然能“知道”去調用工具獲取正確答案,這聽起來確實有點像個悖論
該內容觸及了大型語言模型(LLM)的核心局限性以及(Agents)的智能所在。
實際上,LLM 并不是真的“知道”某個特定事實是否正確,而是通過模式識別和指令遵循來運作的。
LLM 如何“知道”去調用工具?
LLM 知道去調用工具,并不是因為它在調用前就**“知道”工具能提供正確**答案,而是因為它被訓練成了能夠理解:
-
它自己的知識邊界: 大模型在訓練時接觸了大量的文本數據。對于某些特定、不常見的或時效性強的問題(比如“奧巴馬的生日”,雖然是常識但具體日期可能不在模型的精確記憶中),它可能沒有被明確地訓練過這些信息,或者它對這些信息的置信度很低。在代理的上下文中,當它面對一個它內部知識無法直接、高置信度地回答的問題時,它會傾向于尋求外部幫助。
-
工具的描述和用途: 這是最關鍵的一點。當我們將工具(比如
duckduckgo_search
)提供給代理時,我們同時提供了該工具的名稱和詳細描述。例如:@tool def duckduckgo_search(query: str) -> str:"""這個工具可以用于搜索互聯網上的信息。當你需要獲取實時信息、特定事實、事件日期、人物履歷等,且這些信息可能不在你的內部知識庫中時,請使用此工具。輸入應該是一個清晰的搜索查詢字符串。"""
大模型在“思考”階段,會:
- 分析用戶問題: “奧巴馬生日是哪天?”這是一個明顯需要事實性查詢的問題。
- 匹配工具描述: 它會將其對用戶問題的理解與它所擁有的所有工具的描述進行匹配。當它看到
duckduckgo_search
工具的描述提到“獲取實時信息、特定事實、事件日期、人物履歷”時,它會識別到這個工具與當前的任務高度相關。 - 遵循指令: 代理的 ReAct 提示模板(我們從
hub.pull("hwchase17/react")
拉取的那個)會明確指示 LLM 按照“思考-行動-觀察”的模式進行。如果 LLM 認為某個工具是解決當前問題的最佳方式,它就會按照 ReAct 提示的結構,生成Action: duckduckgo_search[奧巴馬生日]
這樣的指令。
-
預測下一個詞(Next Token Prediction): LLM 的底層機制始終是預測下一個最可能出現的詞。在代理的提示語境中,如果它判斷當前問題無法直接回答,并且有一個工具的描述與問題匹配,那么生成“
Thought: I need to find the birthday of Obama. Action: duckduckgo_search[Barack Obama birthday]
”這樣的文本序列,就成了當前語境下概率最高的“下一個詞”序列。
為什么它不會亂給一個答案(比如 1 月 1 日)?
在代理的場景下,LLM 之所以不會隨意編造一個錯誤答案(比如“奧巴馬生日是 1 月 1 日”),有幾個原因:
- 明確的提示指導: ReAct 提示模板明確地引導 LLM 進行推理,并說明在無法直接回答時應該使用工具。提示中通常包含這樣的指令:“如果你需要外部信息,請使用工具。一旦你有了答案,就用
Final Answer:
格式回答。” - 避免“幻覺”的傾向(在代理語境下): 雖然 LLM 本身可能產生幻覺,但在代理這種結構化的應用中,當它被明確賦予了“使用工具”的選擇時,它會傾向于選擇這一條路徑來獲取更可靠的信息,而不是“編造”一個。代理的訓練和提示工程旨在最大化其決策能力,最小化其不負責任的生成。
- 沒有足夠高的置信度: 對于像“奧巴馬生日”這樣的具體事實,如果 LLM 在其內部參數中沒有存儲這個精確信息,或者對其存儲的置信度不高,它就不會選擇直接生成一個答案。相反,它會識別出這是一個“外部知識”類型的問題,并轉向工具。
總結
大模型在代理中的行為,不是因為它“知道”某個答案是錯誤的,而是因為它在訓練中學會了:
- 識別不同類型的問題(可以理解問題)
- 評估自己內部知識的確定性(可以知道自己的知識邊界)
- 根據工具的描述和當前任務,判斷何時以及如何調用工具來獲取信息(可以知道外部信息,比如工具)
- 遵循明確的指令(如 ReAct 模式),在需要外部信息時,優先采取行動調用工具,而不是直接生成不確定的答案(優先跟隨指令,選擇可靠信息)
因此,代理的核心在于為 LLM 提供了一個決策框架和一套執行能力。LLM 就像一個聰明的學生,當遇到不會的問題時,它會根據老師(提示)的指導和手頭的資源(工具),去查閱資料(調用工具)而不是胡編亂造。工具的詳細描述就是它“查閱資料”的指南。