在過去一年中,我們與數十個團隊合作,跨行業構建大型語言模型(LLM)代理。一致發現,最成功的實施並非依賴複雜框架或專用庫,而是採用簡單、可組合的模式進行構建。
在這篇文章中,我們分享了從與客戶合作及自行構建代理過程中學到的經驗,並為開發者提供了構建高效代理的實用建議。
什麼是代理?#
“代理” 可以有多種定義方式。一些客戶將代理定義為能夠在較長時間內獨立運行的全自主系統,它們利用各種工具完成複雜任務。另一些客戶則用該術語來描述遵循預定義工作流程的更具規定性的實現。在 Anthropic,我們將所有這些變體歸類為代理系統,但在工作流程和代理之間劃出了重要的架構區別:
- 工作流程是通過預定義的代碼路徑編排 LLMs 和工具的系統。
- 代理,另一方面,是指 LLMs 動態指導自身進程和工具使用,保持對任務完成方式的控制的系統。
下面,我們將詳細探討這兩種類型的代理系統。在附錄 1(“實踐中的代理”)中,我們描述了客戶在使用這類系統時發現特別有價值的兩個領域。
何時(以及何時不)使用代理#
使用 LLMs 構建應用程序時,我們建議尋找最簡單的解決方案,僅在必要時增加複雜性。這可能意味著完全不構建代理系統。代理系統通常以延遲和成本為代價換取更好的任務性能,您應考慮這種權衡在何時是合理的。
當需要更高的複雜性時,工作流程為定義明確的任務提供了可預測性和一致性,而在需要大規模靈活性和模型驅動決策的情況下,代理則是更好的選擇。然而,對於許多應用來說,通過檢索和上下文示例優化單個 LLM 調用通常就足夠了。
何時以及如何使用框架#
有許多框架使得代理系統更易於實現,包括:
- LangGraph 來自 LangChain;
- 亞馬遜 Bedrock 的AI 代理框架;
- Rivet,一個拖放式 GUI LLM 工作流構建器;以及
- Vellum,另一款用於構建和測試複雜工作流程的圖形用戶界面工具。
這些框架通過簡化標準低級任務(如調用 LLMs、定義和解析工具以及將調用鏈式連接在一起)使得入門變得容易。然而,它們常常會創建額外的抽象層,這些層可能會掩蓋底層的提示和響應,使得調試變得更加困難。它們還可能誘使人們在簡單的設置就足夠的情況下增加複雜性。
我們建議開發者直接使用 LLM APIs 開始:許多模式只需幾行代碼即可實現。如果您確實使用框架,請確保理解底層代碼。對於內部機制的錯誤假設是客戶錯誤的常見來源。
查看我們的手冊以獲取一些示例實現。
構建模塊、工作流程和代理#
在本節中,我們將探討在生產環境中常見的代理系統模式。我們將從基礎構建模塊 —— 增強型 LLM—— 開始,逐步增加複雜性,從簡單的組合工作流到自主代理。
構建模塊:增強的 LLM#
增強的 LLM
代理系統的基本構建模塊是一個 LLM,通過檢索、工具和記憶等增強功能進行擴展。我們當前的模型能夠主動利用這些能力 —— 生成自己的搜索查詢、選擇合適的工具,並決定保留哪些信息。
增強的 LLM
我們建議重點關注實施的兩個關鍵方面:根據您的具體使用場景定制這些功能,並確保它們為您的 LLM 提供一個易於使用且文檔完善的接口。雖然實現這些增強功能的方法有很多,但一種方法是通過我們最近發布的模型上下文協議,該協議允許開發者通過簡單的客戶端實現與不斷增長的第三方工具生態系統集成。
在本文的剩餘部分,我們將假設每次 LLM 調用都能訪問這些增強功能。
工作流程:提示鏈#
提示鏈
提示鏈將任務分解為一系列步驟,其中每個 LLM 調用處理前一個調用的輸出。您可以在任何中間步驟添加程序化檢查(見下圖中的 “門控”),以確保過程仍在正軌上。
提示鏈工作流程
** 何時使用此工作流程:** 此工作流程非常適合任務能夠輕鬆且清晰地分解為固定子任務的情況。其主要目標是通過使每個 LLM 調用成為更簡單的任務,以犧牲延遲換取更高的準確性。
提示鏈有用的示例:
- 生成營銷文案,然後將其翻譯成另一種語言。
- 撰寫文檔大綱,檢查大綱是否符合特定標準,然後根據大綱編寫文檔。
工作流程:路由#
路由
路由對輸入進行分類並將其引導至專門的後續任務。這種工作流程實現了關注點的分離,並構建了更為專業化的提示。若缺乏此流程,針對某類輸入的優化可能會損害其他輸入的性能。
路由工作流程
** 何時使用此工作流程:** 路由適用於處理複雜任務,這些任務具有明顯不同的類別,更適合分開處理,並且可以通過 LLM 或更傳統的分類模型 / 算法準確進行分類。
路由有用的示例:
- 將不同類型的客戶服務查詢(一般問題、退款請求、技術支持)引導至不同的下游流程、提示和工具。
- 將簡單 / 常見問題路由到較小的模型,如 Claude 3.5 Haiku,而將困難 / 不尋常問題路由到更強大的模型,如 Claude 3.5 Sonnet,以優化成本和速度。
工作流程:並行化#
並行化
LLMs 有時可以同時處理一個任務,並通過編程方式聚合它們的輸出。這種工作流程,即並行化,主要體現在兩種關鍵變體中:
- ** 分段:** 將任務分解為並行運行的獨立子任務。
- ** 投票:** 多次運行同一任務以獲得多樣化的輸出。
並行化工作流程
** 何時使用此工作流程:** 當劃分的子任務可以並行化以加快速度,或需要多個視角或嘗試以獲得更高置信度的結果時,並行化是有效的。對於具有多重考量的複雜任務,LLMs 通常在每次考量由單獨的 LLM 調用處理時表現更好,這樣可以對每個具體方面給予集中關注。
並行化有用的示例:
- 分段:
- 實施防護措施,其中一個模型實例處理用戶查詢,而另一個則篩選其中的不當內容或請求。這種方法通常比讓同一個 LLM 調用同時處理防護措施和核心響應表現更好。
- 自動化評估以評估 LLM 性能,其中每個 LLM 調用評估模型在給定提示下性能的不同方面。
- 投票:
- 審查一段代碼以查找漏洞,其中多個不同的提示會審查並在發現問題時標記代碼。
- 評估給定內容是否不當,通過多個提示評估不同方面或要求不同的投票閾值以平衡誤報和漏報。
工作流程:協調器 - 工作者#
協調器 - 工作者
在協調器 - 工作者工作流中,一個中央 LLM 動態地分解任務,將它們分配給工作者 LLMs,並綜合它們的結果。
協調器 - 工作者工作流
** 何時使用此工作流程:** 此工作流程非常適合複雜任務,其中無法預測所需的子任務(例如,在編碼中,需要更改的文件數量以及每個文件中更改的性質可能取決於任務)。雖然它在拓撲結構上相似,但與並行化的關鍵區別在於其靈活性 —— 子任務不是預先定義的,而是由協調器根據特定輸入確定的。
編排器 - 工作器模式適用的示例:
- 每次對多個文件進行複雜更改的編碼產品。
- 涉及從多個來源收集和分析信息以尋找可能相關信息的搜索任務。
工作流程:評估者 - 優化器#
評估者 - 優化器
在評估者 - 優化器工作流程中,一個 LLM 調用生成響應,而另一個則在循環中提供評估和反饋。
評估者 - 優化器工作流程
** 何時使用此工作流程:** 當我們有明確的評估標準,且當迭代改進提供可衡量的價值時,此工作流程尤為有效。適合的兩個標誌是,首先,當人類明確表達反饋時,LLM 響應能得到顯著改善;其次,LLM 能夠提供此類反饋。這類似於人類作家在創作精煉文檔時可能經歷的迭代寫作過程。
評估優化器有用的示例:
- 文學翻譯中存在一些細微差別,譯者 LLM 可能最初未能捕捉到,但評估者 LLM 能夠提供有價值的批評意見。
- 需要多輪搜索和分析以收集全面信息的複雜搜索任務,由評估者決定是否需要進行進一步搜索。
代理#
代理正在生產中崭露頭角,因為 LLMs 在關鍵能力上成熟 —— 理解複雜輸入、參與推理和規劃、可靠地使用工具以及從錯誤中恢復。代理開始工作時,要麼接受人類用戶的指令,要麼與其進行互動討論。一旦任務明確,代理便獨立規劃和操作,必要時會返回人類以獲取更多信息或判斷。在執行過程中,代理在每一步從環境中獲取 “真實情況”(如工具調用結果或代碼執行)以評估其進展至關重要。隨後,代理可以在檢查點或遇到阻礙時暫停,等待人類反饋。任務通常在完成後終止,但為了保持控制,也常包含停止條件(如最大迭代次數)。
代理可以處理複雜的任務,但其實現通常較為直接。它們通常只是 LLMs,在一個循環中基於環境反饋使用工具。因此,清晰且深思熟慮地設計工具集及其文檔至關重要。我們在附錄 2(“工具提示工程”)中詳細闡述了工具開發的最佳實踐。
自主代理
** 何時使用代理:** 代理可以用於開放式問題,這類問題難以或無法預測所需的步驟數量,且無法硬編碼固定路徑。LLM 可能會運行多個回合,因此您必須對其決策能力有一定程度的信任。代理的自主性使其成為在可信環境中擴展任務的理想選擇。
代理的自主性意味著更高的成本和錯誤累積的潛在風險。我們建議在沙盒環境中進行廣泛測試,並設置適當的防護措施。
代理有用的示例:
以下示例來自我們自己的實現:
- 一個編碼代理,用於解決SWE-bench 任務,這些任務涉及根據任務描述對多個文件進行編輯;
- 我們的“計算機使用” 參考實現,其中 Claude 使用計算機來完成任務。
編碼代理的高級流程
組合和自定義這些模式#
這些構建模塊並非一成不變。它們是開發者可以根據不同使用場景塑造和組合的常見模式。與任何 LLM 功能一樣,成功的關鍵在於衡量性能並對實現進行迭代。重申一遍:只有在明顯改善結果的情況下,才應考慮增加複雜性。
摘要#
在 LLM 領域的成功,不在於構建最複雜的系統,而在於構建適合自身需求的正確系統。從簡單的提示開始,通過全面評估進行優化,僅當更簡單的解決方案無法滿足需求時,才添加多步驟的代理系統。
在實施代理時,我們努力遵循三個核心原則:
- 保持代理設計的簡潔性。
- 優先考慮透明度,明確展示代理的規劃步驟。
- 通過詳盡的工具文檔和測試,精心打造您的代理 - 計算機界面(ACI)。
框架可以幫助您快速入門,但在進入生產階段時,不要猶豫減少抽象層並使用基礎組件進行構建。遵循這些原則,您可以創建不僅功能強大,而且可靠、可維護並贏得用戶信任的代理。
致謝#
本文由 Erik Schluntz 和 Barry Zhang 撰寫。本作品借鑒了我們在 Anthropic 構建代理的經驗以及客戶分享的寶貴見解,對此我們深表感謝。
附錄 1:實踐中的代理#
我們與客戶的合作揭示了 AI 代理的兩個特別有前景的應用,這些應用展示了上述模式的實用價值。這兩個應用都說明了代理如何為需要對話和行動、具有明確成功標準、能夠實現反饋循環並整合有意義的人類監督的任務增加最大價值。
A. 客戶支持#
客戶支持將熟悉的聊天機器人界面與通過工具集成增強的功能相結合。這對於更開放的代理來說是一個自然的選擇,因為:
- 支持互動自然遵循對話流程,同時需要訪問外部信息和操作;
- 工具可以集成以提取客戶數據、訂單歷史記錄和知識庫文章;
- 例如發放退款或更新票據等操作可以通過編程方式處理;以及
- 成功可以通過用戶自定義的解決方案來明確衡量。
幾家公司已通過基於使用量的定價模式證明了這種方法的可行性,該模式僅對成功解決的問題收費,顯示出對其代理有效性的信心。
B. 編碼代理#
軟件開發領域展現了 LLM 功能的顯著潛力,其能力已從代碼補全發展到自主解決問題。代理之所以特別有效,原因在於:
- 代碼解決方案可通過自動化測試進行驗證;
- 代理可以利用測試結果作為反饋來迭代解決方案;
- 問題空間定義明確且結構清晰;以及
- 輸出質量可以客觀衡量。
在我們自己的實現中,代理現在能夠僅根據拉取請求描述解決 SWE-bench Verified 基準中的真實 GitHub 問題。然而,儘管自動化測試有助於驗證功能,但人工審查對於確保解決方案符合更廣泛的系統要求仍然至關重要。
附錄 2:工具提示工程#
無論您正在構建何種代理系統,工具很可能都是您代理的重要組成部分。工具使 Claude 能夠通過在我們的 API 中指定其確切結構和定義來與外部服務和 API 進行交互。當 Claude 響應時,如果它計劃調用工具,它將在 API 響應中包含一個工具使用塊。工具定義和規範應與您的整體提示一樣受到提示工程的高度重視。在這個簡短的附錄中,我們描述了如何對您的工具進行提示工程。
指定同一操作通常有多種方式。例如,您可以通過編寫差異(diff)或重寫整個文件來指定文件編輯。對於結構化輸出,您可以在 markdown 或 JSON 中返回代碼。在軟件工程中,這些差異是表面上的,可以無損地從一種格式轉換為另一種格式。然而,某些格式對於 LLM 來說比其他格式更難編寫。編寫差異需要知道在編寫新代碼之前塊頭中有多少行正在更改。在 JSON 中編寫代碼(與 markdown 相比)需要對換行符和引號進行額外的轉義。
我們關於決定工具格式的建議如下:
- 給模型足夠的標記來 “思考”,以免它自己陷入困境。
- 保持格式接近模型在互聯網文本中自然所見的形式。
- 確保沒有格式化的 “開銷”,例如必須準確計算數千行代碼,或對其編寫的任何代碼進行字符串轉義。
一個經驗法則是考慮人機界面(HCI)投入了多少努力,並計劃在創建良好的代理 - 計算機界面(ACI)時投入同樣多的努力。以下是一些關於如何做到這一點的思考:
- 站在模型的角度思考。根據描述和參數,使用此工具是否顯而易見,還是需要仔細思考?如果是後者,那麼模型很可能也是如此。一個好的工具定義通常包括使用示例、邊緣情況、輸入格式要求以及與其他工具的明確界限。
- 如何更改參數名稱或描述以使事情更明顯?將其視為為團隊中的初級開發者編寫一份優秀的文檔字符串。在使用許多類似工具時,這一點尤為重要。
- 測試模型如何使用您的工具:在我們的工作台中運行多個示例輸入,以查看模型會犯哪些錯誤,並進行迭代。
- 防錯您的工具。改變參數,使其更難以出錯。
在構建我們的代理時,我們實際上花了更多時間優化我們的工具,而不是整體提示。例如,我們發現當代理移出根目錄後,模型在使用相對文件路徑的工具時會出錯。為了解決這個問題,我們將工具更改為始終要求絕對文件路徑 —— 我們發現模型使用這種方法時毫無瑕疵。