文章目录
- 简述
- 工具定义
- 工具上下文
- 直接返回
- 方法:直接返回
- 工具执行
- 框架控制工具执行
- 用户控制的工具执行
- 异常处理

简述
工具调用(也称为函数调用)是 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);
}