文章目錄
- 簡述
- 工具定義
- 工具上下文
- 直接返回
- 方法:直接返回
- 工具執行
- 框架控制工具執行
- 用戶控制的工具執行
- 異常處理

簡述
工具調用(也稱為函數調用)是 AI 應用程序中的一種常見模式,允許模型與一組 API 或工具進行交互,從而增強其功能。
工具主要用于:
- 信息檢索。此類別中的工具可用于從外部源(如數據庫、Web 服務、文件系統或 Web 搜索引擎)檢索信息。目標是增強模型的知識,使其能夠回答其他方式無法回答的問題。因此,它們可用于檢索增強生成 (RAG) 方案。例如,工具可用于檢索給定位置的當前天氣、檢索最新的新聞文章或查詢數據庫以獲取特定記錄。
- 采取行動。此類別中的工具可用于在軟件系統中執行作,例如發送電子郵件、在數據庫中創建新記錄、提交表單或觸發工作流。目標是自動執行原本需要人工干預或顯式編程的任務。例如,可以使用工具為與聊天機器人交互的客戶預訂航班,在網頁上填寫表單,或在代碼生成場景中實現基于自動測試 (TDD) 的 Java 類
工具定義
獲取類中用戶時區的當前日期和時間
class DateTimeTools {@Tool(description = "Get the current date and time in the user's timezone")String getCurrentDateTime() {return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();}}
我們將通過傳遞 via 方法的實例來為模型提供該工具。當模型需要知道當前日期和時間時,它將請求調用工具。在內部,將調用工具并將結果返回給模型,然后模型將使用工具調用結果生成對原始問題的最終響應。
ChatModel chatModel = ...String response = ChatClient.create(chatModel).prompt("What day is tomorrow?").tools(new DateTimeTools()).call().content();System.out.println(response);
未使用工具的
使用工具之后
工具上下文
Spring AI 支持通過 API 將額外的上下文信息傳遞給工具。此功能允許您提供額外的用戶提供的數據,這些數據可用于工具執行以及 AI 模型傳遞的工具參數。ToolContext
class CustomerTools {@Tool(description = "Retrieve customer information")Customer getCustomerInfo(Long id, ToolContext toolContext) {return customerRepository.findById(id, toolContext.get("tenantId"));}}
在調用 時,將使用用戶提供的數據填充 。ToolContextChatClient
ChatModel chatModel = ...String response = ChatClient.create(chatModel).prompt("Tell me more about the customer with ID 42").tools(new CustomerTools()).toolContext(Map.of("tenantId", "acme")).call().content();System.out.println(response);
同樣,您可以在直接調用 時定義工具上下文數據。ChatModel
ChatModel chatModel = ...
ToolCallback[] customerTools = ToolCallbacks.from(new CustomerTools());
ChatOptions chatOptions = ToolCallingChatOptions.builder().toolCallbacks(customerTools).toolContext(Map.of("tenantId", "acme")).build();
Prompt prompt = new Prompt("Tell me more about the customer with ID 42", chatOptions);
chatModel.call(prompt);
工具類內容
public class CustomerTools {@Tool(description = "Retrieve customer information")String getCustomerInfo(Long id, ToolContext toolContext) {Map<String, Object> context = toolContext.getContext();return context.get("tenantId").toString();}}
直接返回
默認情況下,工具調用的結果將作為響應發送回模型。然后,模型可以使用結果繼續對話。
在某些情況下,您寧愿將結果直接返回給調用方,而不是將其發送回模型。例如,如果構建依賴于 RAG 工具的代理,則可能希望將結果直接返回給調用方,而不是將其發送回模型以進行不必要的后處理。或者,也許您有某些工具可以結束代理的推理循環。
每個實現都可以定義工具調用的結果是應直接返回給調用方還是發送回模型。默認情況下,結果將發送回模型。但是,您可以根據每個工具更改此行為。ToolCallback
負責管理工具執行生命周期的 ,負責處理與工具關聯的屬性。如果該屬性設置為 ,則工具調用的結果將直接返回給調用方。否則,結果將發送回模型。ToolCallingManagerreturnDirecttrue
方法:直接返回
使用聲明性方法從方法構建工具時,可以通過將注釋的屬性設置為 來標記工具以將結果直接返回給調用者。returnDirect@Tooltrue
class CustomerTools {@Tool(description = "Retrieve customer information", returnDirect = true)Customer getCustomerInfo(Long id) {return customerRepository.findById(id);}}
如果使用編程方法,您可以通過接口設置屬性并將其傳遞給 .returnDirectToolMetadataMethodToolCallback.Builder
ToolMetadata toolMetadata = ToolMetadata.builder().returnDirect(true).build();
這種操作可以只返回結果
工具執行
工具執行是使用提供的輸入參數調用工具并返回結果的過程。工具執行由接口處理,接口負責管理工具執行生命周期。ToolCallingManager
public interface ToolCallingManager {/*** Resolve the tool definitions from the model's tool calling options.*/List<ToolDefinition> resolveToolDefinitions(ToolCallingChatOptions chatOptions);/*** Execute the tool calls requested by the model.*/ToolExecutionResult executeToolCalls(Prompt prompt, ChatResponse chatResponse);}
如果您使用的是任何 Spring AI Spring Boot Starters,則是接口的自動配置實現。您可以通過提供自己的 Bean 來自定義工具執行行為。DefaultToolCallingManagerToolCallingManagerToolCallingManager
@Bean
ToolCallingManager toolCallingManager() {return ToolCallingManager.builder().build();
}
默認情況下,Spring AI 會從每個實現中透明地為您管理工具執行生命周期。但是,您可以選擇退出此行為并自行控制工具執行。本節介紹這兩種方案。ChatModel
框架控制工具執行
使用默認行為時,Spring AI 會自動攔截來自模型的任何工具調用請求,調用工具并將結果返回給模型。所有這些都是通過每個實現使用 .ChatModelToolCallingManager
用戶控制的工具執行
在某些情況下,您寧愿自己控制工具執行生命周期。您可以通過將 的屬性設置為 來做到這一點。internalToolExecutionEnabledToolCallingChatOptionsfalse
當您使用此選項調用 時,工具執行將委托給調用方,從而使您能夠完全控制工具執行生命周期。您有責任檢查 中的工具調用并使用 .ChatModelChatResponseToolCallingManager
以下示例演示了用戶控制的工具執行方法的最小實現:
ChatModel chatModel = ...
ToolCallingManager toolCallingManager = ToolCallingManager.builder().build();ChatOptions chatOptions = ToolCallingChatOptions.builder().toolCallbacks(new CustomerTools()).internalToolExecutionEnabled(false).build();
Prompt prompt = new Prompt("Tell me more about the customer with ID 42", chatOptions);ChatResponse chatResponse = chatModel.call(prompt);while (chatResponse.hasToolCalls()) {ToolExecutionResult toolExecutionResult = toolCallingManager.executeToolCalls(prompt, chatResponse);prompt = new Prompt(toolExecutionResult.conversationHistory(), chatOptions);chatResponse = chatModel.call(prompt);
}System.out.println(chatResponse.getResult().getOutput().getText());
異常處理
當工具調用失敗時,異常將傳播為可以捕獲以處理錯誤。A 可用于處理具有兩種結果的 a:生成要發送回 AI 模型的錯誤消息,或引發由調用方處理的異常。ToolExecutionExceptionToolExecutionExceptionProcessorToolExecutionException
@FunctionalInterface
public interface ToolExecutionExceptionProcessor {/*** Convert an exception thrown by a tool to a String that can be sent back to the AI* model or throw an exception to be handled by the caller.*/String process(ToolExecutionException exception);}
如果您使用的是任何 Spring AI Spring Boot Starters,則是接口的自動配置實現。默認情況下,錯誤消息將發送回模型。構造函數允許您將屬性設置為 或 。如果 ,將拋出異常,而不是將錯誤消息發送回模型。DefaultToolExecutionExceptionProcessor
ToolExecutionExceptionProcessor
DefaultToolExecutionExceptionProcessor
alwaysThrowtrue
false
true
@Bean
ToolExecutionExceptionProcessor toolExecutionExceptionProcessor() {return new DefaultToolExecutionExceptionProcessor(true);
}