AI News HubLIVE
站內改寫4 分鐘閱讀

在Amazon Bedrock上實現程式化工具呼叫

程式化工具呼叫(PTC)是一種新的正規化,透過讓模型生成程式碼來編排多個工具呼叫,從而減少延遲和令牌消耗。本文介紹了三種在Amazon Bedrock上實現PTC的方法:基於ECS的自託管Docker沙盒、使用Bedrock AgentCore Code Interpreter的託管方案,以及相容Anthropic SDK的代理路徑。

來源AWS Machine Learning Blog作者: Shreyas Subramanian

程式化工具呼叫(PTC)正在改變大語言模型(LLM)與外部工具互動的方式。在傳統的工具呼叫流程中,每次工具呼叫都需要一次完整的模型往返:模型呼叫工具、接收結果、推理、呼叫下一個工具,如此迴圈。對於需要多次工具呼叫的工作流,這會累積延遲和令牌消耗,因為每個中間結果都必須經過模型的上下文視窗。

PTC採取了不同的方法。模型編寫Python程式碼,在沙盒執行環境中程式化地呼叫多個工具。程式碼可以包含迴圈、條件判斷、過濾和聚合邏輯。模型只需推理一次生成程式碼,執行環境處理工具呼叫,僅將最終處理結果返回模型上下文。這大大降低了多工具工作流的延遲和令牌使用。PTC特別適合大數據處理、精確數值計算、多步驟流程編排以及隱私敏感場景——這些場景中原始資料不應進入模型上下文。

PTC最初是特定於提供商的功能,但底層模式——模型生成程式碼、沙盒執行、僅最終輸出返回上下文——是模型無關的。在本文中,我們展示了在Amazon Bedrock上實現PTC的三種方法:基於ECS的自託管Docker沙盒以實現最大控制、使用Amazon Bedrock AgentCore Code Interpreter的託管方案,以及透過代理實現Anthropic SDK相容路徑供喜歡該開發體驗的團隊使用。

傳統工具呼叫的瓶頸

考慮一個例子:“哪些工程團隊成員超出了Q3的差旅預算?”在傳統工具呼叫中(假設沒有並行函式呼叫),模型必須:呼叫工具獲取團隊成員列表(20人);為每個人呼叫工具獲取報銷記錄(20次單獨呼叫,每次返回50-100行專案);呼叫額外工具獲取預算閾值;將超過2000條報銷記錄送入上下文視窗;用自然語言推理整個資料集以過濾、比較和總結。這些工具呼叫中的每一次都需要一次完整的模型往返,產生三個問題:令牌消耗(每個中間結果都經過上下文)、延遲(20次順序呼叫意味著20次推理往返)和準確性(讓語言模型用自然語言過濾和比較數千條記錄容易出錯,而幾行Python程式碼就能精確處理)。

PTC如何解決

PTC翻轉了模式。模型編寫一個單一Python程式碼塊來編排工具呼叫、處理結果並僅返回最終輸出。以相同的費用審計為例,啟用PTC時,模型生成以下程式碼:

import asyncio import json

team_json = await get_team_members(department="engineering") team = json.loads(team_json)

expense_tasks = [get_expenses(employee_id=m["id"], quarter="Q3") for m in team] expenses_results = await asyncio.gather(*expense_tasks)

exceeded = [] for member, exp_json in zip(team, expenses_results): expenses = json.loads(exp_json) total_travel = sum(e["amount"] for e in expenses if e["category"] == "travel" and e["status"] == "approved") if total_travel > 5000: budget_json = await get_custom_budget(user_id=member["id"]) budget = json.loads(budget_json) limit = budget["budget_limit"] if total_travel > limit: exceeded.append({"name": member["name"], "spent": total_travel, "limit": limit, "exceeded_by": total_travel - limit})

print(f"{len(exceeded)} members exceeded budget:") print(json.dumps(exceeded, indent=2))

注意兩點:第一,asyncio.gather()並行發出所有20個費用查詢,工具呼叫幾乎同時發生;第二,過濾、聚合和預算比較在Python中完成,而非自然語言。只有最終的print()輸出返回模型上下文視窗,超過2000條原始費用記錄不會觸及它。模型僅取樣兩次:一次生成程式碼,一次解讀最終輸出。中間的所有操作(工具呼叫、資料處理、過濾)都在容器內進行,無需額外模型推理。

第一部分:使用Amazon Bedrock和Amazon ECS的自託管PTC

自託管的理由

託管PTC實現依賴提供商管理的沙盒環境,但自託管也有充分理由:模型無關(支援Amazon Bedrock上的多種模型,如Claude、Qwen、MiniMax、Llama、Nova等)、完全控制(可定製沙盒環境、安裝特定領域的Python包、配置安全策略以滿足需求)以及私有部署(將程式碼執行和中間資料保留在自己的AWS賬戶內)。

架構

自託管解決方案有兩個元件:編排器(您的應用程式,如ECS任務、Lambda或計算資源,使用Boto3呼叫InvokeModel API,管理Docker沙盒生命週期並處理工具呼叫迴圈)和Docker沙盒(執行模型生成的Python程式碼的隔離容器,透過標準輸入/輸出流與編排器通訊)。核心思路很簡單:將通常放在tool_config中的工具定義注入系統提示中,並指示模型編寫編排這些工具的Python程式碼。生成的程式碼在Docker沙盒中執行,編排器作為控制平面,透過IPC攔截工具呼叫,在外部執行工具,並將結果注入回沙盒。

系統提示

系統提示是使模型表現得像原生支援PTC的關鍵部分。它描述執行環境、可用工具和生成程式碼的規則。提示指導模型產生結構良好的Python程式碼,遵循原生PTC實現的相同模式:單程式碼塊、非同步工具呼叫和print()輸出。

核心元件

SandboxExecutor是中心元件,管理隔離Docker容器的生命週期,安全執行模型生成的程式碼,並處理工具呼叫的IPC協議。系統使用雙程序架構:編排器為每個程式碼執行請求啟動一個Docker容器,透過標準I/O流通訊,容器將工具呼叫請求寫入stderr,編排器透過stdin注入工具結果。

Runner指令碼由編排器動態生成,在啟動時注入每個Docker容器,處理程式碼執行、IPC協議和工具函式生成。它支援兩種執行模式:單次模式(執行程式碼後退出,適用於無狀態的一次性任務)和迴圈模式(保持容器執行以接受多次程式碼執行,支援會話重用和狀態保持)。

IPC協議

為了在文本流中可靠地分離不同訊息型別,系統定義了邊界標記:PTC_TOOL_CALL / PTC_END_CALL包裝工具呼叫請求(工具名稱+引數為JSON),PTC_OUTPUT標記程式碼執行的最終輸出。當Runner指令碼在執行程式碼中遇到工具呼叫時,它將呼叫序列化為JSON,在標記邊界之間寫入stderr,並在stdin上阻塞等待結果。編排器讀取stderr,解析工具呼叫,執行工具,並將結果寫回stdin。Runner指令碼解除阻塞並繼續執行。

編排器迴圈

在Amazon Bedrock上啟用PTC需要三個元素:指示模型編寫Python程式碼進行工具編排的系統提示、模型用於將程式碼提交到沙盒的execute_code工具定義,以及嵌入系統提示中的業務工具描述(不作為單獨的Amazon Bedrock工具)。編排器將Amazon Bedrock和Docker沙盒聯絡起來,核心迴圈包括呼叫Bedrock、在沙盒中執行程式碼、處理工具呼叫以及將結果返回給模型。

本文還介紹了使用Amazon Bedrock AgentCore Code Interpreter的託管方案和相容Anthropic SDK的代理路徑,但自託管方案提供了最大的靈活性和控制力。透過實施PTC,您可以顯著降低多工具工作流的延遲和令牌消耗,同時提高準確性和處理大數據集的能力。