1.面试题目 #
请详细阐述什么是工具调用(Tool Calling),它在大型语言模型(LLM)应用中扮演什么角色?并结合Spring AI框架,说明如何定义、注册和使用工具,以及其内部的调用流程。请特别强调Spring AI如何简化这一过程。
2.参考答案 #
2.1 工具调用(Tool Calling)的定义与作用 #
2.1.1 核心定义 #
工具调用(Tool Calling),也常被称为函数调用(Function Calling),是一种允许AI大模型在对话过程中,根据用户需求或内部判断,请求并执行外部工具来完成特定任务的机制。
2.1.2 作用与价值 #
AI大模型本身通常不具备实时查询、操作外部系统或访问特定API的能力(例如查询实时天气、操作数据库、发送邮件等)。工具调用机制解决了这一局限性:
- 能力扩展:使LLM能够调用外部工具,从而扩展其功能边界,执行超出其预训练知识范围的任务
- 实时性与准确性:获取最新数据或执行实时操作,提高LLM响应的准确性和实用性
- 任务自动化:LLM可以根据对话上下文自主决定何时以及如何调用工具,实现更复杂的自动化工作流
重要提示: 真正执行工具的是我们的应用程序,而非AI服务器本身。
2. Spring AI 实现工具调用的核心流程 #
2.2.1 架构图解 #
下图展示了Spring AI中工具调用的简化流程:
- Chat Request (聊天请求):用户发起聊天请求,同时提供Tool Definition (工具定义)给AI模型
- AI Model (AI模型):根据聊天请求和已注册的工具定义,判断是否需要调用工具。如果需要,AI模型会生成一个包含工具名称和参数的工具调用请求
- Dispatch Tool Call Requests (分派工具调用请求):Spring AI框架接收到AI模型的工具调用请求
- Tool (外部工具):Spring AI根据请求分派到对应的外部工具进行执行
- Tool (外部工具):工具执行完毕后,将结果返回给Spring AI的
Dispatch Tool Call Requests - AI Model (AI模型):Spring AI将工具执行结果转换后返回给AI模型
- Chat Response (聊天响应):AI模型根据工具执行结果生成最终的聊天响应
2.2.2 具体实现步骤 #
1. 定义工具
使用注解方式定义工具,在Java类中将希望作为工具的方法标记上 @Tool 注解:
@Component
public class WeatherTool {
@Tool(description = "获取指定城市的天气信息")
public String getWeather(
@ToolParam(description = "城市名称", required = true) String city) {
// 实际调用天气API并返回结果
return "The weather in " + city + " is sunny with 25 degrees Celsius.";
}
@Tool(description = "获取未来几天的天气预报")
public String getWeatherForecast(
@ToolParam(description = "城市名称", required = true) String city,
@ToolParam(description = "预报天数", required = false) Integer days) {
// 调用天气预报API
return "未来" + (days != null ? days : 3) + "天" + city + "的天气预报...";
}
}
@Component
public class DatabaseTool {
@Tool(description = "查询用户信息")
public String getUserInfo(
@ToolParam(description = "用户ID", required = true) String userId) {
// 查询数据库并返回用户信息
return "用户ID: " + userId + " 的详细信息...";
}
@Tool(description = "更新用户状态")
public String updateUserStatus(
@ToolParam(description = "用户ID", required = true) String userId,
@ToolParam(description = "新状态", required = true) String status) {
// 更新数据库中的用户状态
return "用户 " + userId + " 状态已更新为: " + status;
}
}2. 注册与使用工具
Spring AI提供了多种灵活的工具注册方式:
@Configuration
public class ToolConfig {
@Bean
public ChatClient chatClient(ChatModel chatModel,
WeatherTool weatherTool,
DatabaseTool databaseTool) {
return ChatClient.builder(chatModel)
.defaultTools(weatherTool, databaseTool) // 全局注册工具
.build();
}
}
@Service
public class ChatService {
private final ChatClient chatClient;
private final WeatherTool weatherTool;
private final DatabaseTool databaseTool;
public ChatService(ChatClient chatClient,
WeatherTool weatherTool,
DatabaseTool databaseTool) {
this.chatClient = chatClient;
this.weatherTool = weatherTool;
this.databaseTool = databaseTool;
}
// 方式1:使用全局注册的工具
public String chatWithGlobalTools(String userMessage) {
return chatClient.call(new Prompt(userMessage))
.content();
}
// 方式2:按需使用特定工具
public String chatWithSpecificTools(String userMessage) {
return chatClient.call(new Prompt(userMessage,
new ChatOptions(Map.of("tools", List.of(weatherTool)))))
.content();
}
// 方式3:动态组合工具
public String chatWithDynamicTools(String userMessage, List<Object> tools) {
return chatClient.call(new Prompt(userMessage,
new ChatOptions(Map.of("tools", tools))))
.content();
}
}3. 调用流程(Spring AI框架自动执行)
当使用配置了工具的 ChatClient 进行对话时,如果AI模型判断需要使用某个工具,Spring AI框架会自动执行以下步骤:
@RestController
@RequestMapping("/api/chat")
public class ChatController {
private final ChatService chatService;
@PostMapping
public ResponseEntity<ChatResponse> chat(@RequestBody ChatRequest request) {
// Spring AI自动处理工具调用流程:
// 1. 解析AI模型的工具调用请求
// 2. 根据工具名找到对应的Java方法并执行
// 3. 将工具执行结果转换并返回给AI模型
// 4. AI模型根据工具结果生成最终回复
String response = chatService.chatWithGlobalTools(request.getMessage());
return ResponseEntity.ok(new ChatResponse(response));
}
}2.3 高级用法与最佳实践 #
2.3.1 工具参数验证 #
@Component
public class AdvancedTool {
@Tool(description = "发送邮件")
public String sendEmail(
@ToolParam(description = "收件人邮箱", required = true) String to,
@ToolParam(description = "邮件主题", required = true) String subject,
@ToolParam(description = "邮件内容", required = true) String content) {
// 参数验证
if (!isValidEmail(to)) {
throw new IllegalArgumentException("无效的邮箱地址: " + to);
}
// 执行邮件发送逻辑
return "邮件已成功发送到: " + to;
}
private boolean isValidEmail(String email) {
return email.matches("^[A-Za-z0-9+_.-]+@(.+)$");
}
}2.3.2 异步工具调用 #
@Component
public class AsyncTool {
@Tool(description = "异步处理文件")
public CompletableFuture<String> processFile(
@ToolParam(description = "文件路径", required = true) String filePath) {
return CompletableFuture.supplyAsync(() -> {
// 模拟文件处理
try {
Thread.sleep(5000); // 模拟耗时操作
return "文件 " + filePath + " 处理完成";
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return "文件处理被中断";
}
});
}
}2.3.3 工具调用监控与日志 #
@Component
public class MonitoredTool {
private static final Logger logger = LoggerFactory.getLogger(MonitoredTool.class);
@Tool(description = "带监控的数据库查询")
public String queryDatabase(
@ToolParam(description = "SQL查询语句", required = true) String sql) {
long startTime = System.currentTimeMillis();
logger.info("开始执行数据库查询: {}", sql);
try {
// 执行数据库查询
String result = executeQuery(sql);
long duration = System.currentTimeMillis() - startTime;
logger.info("数据库查询完成,耗时: {}ms", duration);
return result;
} catch (Exception e) {
logger.error("数据库查询失败: {}", e.getMessage(), e);
return "查询失败: " + e.getMessage();
}
}
private String executeQuery(String sql) {
// 实际的数据库查询逻辑
return "查询结果...";
}
}2.4 Spring AI的优势 #
Spring AI通过其简洁的API和自动化的处理流程,极大地降低了在LLM应用中实现工具调用的复杂性:
2.4.1 开发效率 #
- 简化定义:只需使用
@Tool和@ToolParam注解即可定义工具 - 自动处理:框架自动处理工具调用请求的解析、执行和结果转换
- 类型安全:支持多种Java类型,提供编译时类型检查
2.4.2 集成便利 #
- Spring生态:与Spring框架无缝集成,利用依赖注入和组件管理
- 配置灵活:支持全局注册和按需使用两种方式
- 扩展性强:易于添加新工具和修改现有工具
2.4.3 可维护性 #
- 清晰结构:工具定义和注册机制清晰,便于理解和维护
- 日志支持:内置日志记录,便于调试和监控
- 错误处理:提供完善的错误处理机制
2.5 实际应用场景 #
2.5.1 智能客服系统 #
// 工具:查询订单状态、处理退款、发送通知等
@Tool(description = "查询订单状态")
public String getOrderStatus(@ToolParam(description = "订单号") String orderId) {
// 查询订单状态逻辑
}2.5.2 数据分析助手 #
// 工具:执行SQL查询、生成图表、导出报告等
@Tool(description = "执行数据分析查询")
public String analyzeData(@ToolParam(description = "分析类型") String analysisType) {
// 数据分析逻辑
}2.5.3 内容管理系统 #
// 工具:创建文章、更新内容、发布通知等
@Tool(description = "创建新文章")
public String createArticle(@ToolParam(description = "文章标题") String title,
@ToolParam(description = "文章内容") String content) {
// 文章创建逻辑
}2.6 总结 #
Spring AI的工具调用机制通过简洁的注解和自动化的处理流程,使得开发者能够轻松地将外部工具集成到LLM应用中。这种设计不仅提高了开发效率,还增强了系统的灵活性和可维护性,为构建复杂的AI应用提供了强大的支持。