互動模式
學習如何平衡大語言模型 (LLM) 能力與傳統程式碼,並實施護欄來管理不可預測的 AI 行為。
將對 LLM 的請求等同於函式呼叫是一個誤區。給定一組相同的輸入並按相同的順序執行,函式的作用是可預測的。我們可以編寫測試、注入故障,並針對各種輸入對函式進行強化。
LLM 則並非如此。更好的思維方式是將 LLM 視為使用者,並將從它們那裡獲得的資料視為使用者輸入。像使用者一樣,LLM 具有不可預測性,經常(部分或全部)出錯,有時甚至純屬隨機。為了在這些條件下保護我們的應用程式,我們需要圍繞 LLM 輸入構建與處理使用者輸入相同的護欄。
如果我們能成功做到這一點,就能以解決問題和創造力的形式,為應用程式帶來媲美人類的非凡能力。
關注點分離
#LLM 在某些方面表現出色,而在其他方面則表現不佳;關鍵在於發揮其優勢,同時規避其劣勢。舉個例子,讓我們看看 Crossword Companion(填字遊戲伴侶)中的任務列表。
任務列表是需要解決的一系列線索。其目標是使用任務列表中的顏色和解決方案來顯示解決過程中的進度。最初的實現為模型提供了一個管理任務列表的工具,要求它在進行過程中提供進度更新。Flash 模型無法以這種方式解開謎題,但 Pro 模型可以。遺憾的是,它是在大塊時間裡完成的,只記得更新一兩次任務列表,中間間隔很長。無論如何提示,都無法說服它邊做邊更新任務。你會發現現代 AI 代理在管理自己的任務列表時也會出現同樣的表現;這就是目前 LLM 演進所處的階段。
那麼,我們如何獲得一致、確定性的任務列表更新呢?將任務管理從 LLM 手中拿走,交由程式碼處理。
概括地說,在將 LLM 解決方案應用於你面臨的問題之前,請問自己:LLM 是否是該工作的最佳工具?類人的解決問題能力和創造力是否值得以不可預測性作為代價?
問題的答案來自實驗。以下是示例中的一些例子:
| 任務 | LLM 適用性 | 程式碼適用性 |
|---|---|---|
| 解析網格的大小、內容和線索 | 利用視覺和語言理解能力,非常適合 LLM | 編寫程式碼來完成此任務非常困難 |
| 驗證網格內容 | 可以使用另一個 LLM 來檢查工作,這是可行的 | 人類透過一眼檢視並進行調整會更容易 |
| 處理任務列表 | LLM 不太可能持續穩定地完成此任務 | 編寫程式碼遍歷任務列表並即時更新非常簡單 |
| 解決每個線索 | 利用語言理解和生成能力,非常適合 LLM | 面對依賴於文字遊戲、名稱和俚語的現實世界線索,這非常困難 |
| 解決衝突 | LLM 在這種迴圈處理上表現不一致 | 人類透過一眼檢視並進行調整會更容易 |
這當然是一個需要判斷的問題,但如果你能合理地編寫程式碼來完成它,你的結果將是可預測的。然而,如果編寫程式碼變得異常困難,那麼可以考慮使用 LLM,前提是你必須像我們在示例中所做的那樣構建護欄。
“詢問”模式 vs “代理”模式
#除了程式碼與 LLM 之間的取捨,還需要考慮另一個關鍵點。模型大致以兩種模式執行:“詢問 (ask)”和“代理 (agent)”。
當我們提示 LLM 但不提供影響世界的工具時(例如,沒有任何工具,或者僅提供用於查詢資料的工具),LLM 處於“詢問”模式。填字遊戲推理模型和線索求解模型都在詢問模式下執行,僅將工具用於補充資料。
另一方面,當我們為 LLM 提供一組允許它代表我們在現實世界中進行操作的工具時——例如讀取和寫入檔案、執行 bash 命令、載入網頁、呼叫 Web API 等——該 LLM 就處於“代理”模式。
護欄
#詢問模式和代理模式之間的區別不在於你選擇的模型或給出的提示,而在於你提供的工具。工具與“工具呼叫”部分中描述的代理迴圈相結合,允許 LLM 在它認為必要時頻繁呼叫任意數量的這些工具。賦予它這種能力,責任就在於你——確保你將其視為不可預測的物件;它更像是一個人,而不是一個程式。
你可以透過驗證使用者輸入相同的方式來做到這一點:構建一套測試用例,觀察你的應用如何應對 LLM 的響應。給真實的 LLM 提供各種各樣的提示,並模擬工具來評估 LLM 是如何使用它們的。就像你第一次使用者測試體驗一樣,你第一次的 LLM 測試結果可能會讓你感到驚訝。利用這些資料來構建所需的護欄,從而強化你的應用程式。
在示例中,我們不必防範惡意行為,但確實需要防範不完美的結果。正是針對真實世界資料的大量測試,促使我們引入了“人在迴路 (human-in-the-loop)”機制,以防範嘗試解決無效謎題或處理衝突的解決方案。透過這種方式,Flutter 和 Firebase AI Logic 的結合,成為了駕馭 LLM 力量併為你的應用帶來獨特能力的完美組合。