Spring AI 不仅简化了 AI 模型的接入,更通过优雅的工具调用机制让 AI 与现实世界交互。本文将深入剖析 Spring AI 工具调用的底层数据结构、上下文传递、立即返回机制以及执行原理。
在构建 AI 应用时,模型的知识是静态的。为了让 AI 能够查询实时天气、操作数据库或调用企业内部服务,我们需要用到 Function Calling(工具调用) 。Spring AI 对这一机制做了高度抽象和封装,本文将带你揭开 Spring AI 工具调用的神秘面纱。
一、工具调用的底层数据结构:AI 是如何“看懂”工具的?
AI 模型本身无法直接运行 Java 代码。Spring AI 通过一套精妙的底层结构,将 Java 方法“翻译”成 AI 能理解的描述。核心在于 ToolCallback 接口。
1.1 ToolCallback 接口解析
ToolCallback 是所有工具实现的基础,它定义了工具与 AI 交互的契约:
getToolDefinition():提供工具的 元数据定义(名称、描述、参数 Schema)。这部分信息会被序列化并发送给 AI 模型,AI 依靠它来判断“什么时候该用这个工具”。getToolMetadata():提供附加信息,例如是否returnDirect(直接返回,下文详解)。call():工具的实际执行逻辑入口。
1.2 注解背后的魔法:为什么 @Tool 注解就能生效?
当我们使用 @Tool(description = "获取用户订单") 标注一个方法时,Spring AI 在背后做了大量的转换工作:
JsonSchemaGenerator:自动解析方法签名和注解参数,生成符合 JSON Schema 规范的参数定义,填入ToolDefinition。ToolCallResultConverter:将方法返回的各种复杂类型(Object、List 等)统一转换为 String 格式,以便交还给 AI 模型处理。MethodToolCallback:这是一个核心适配器,它实现了ToolCallback接口,内部封装了对注解方法的反射调用。
一句话总结:Spring AI 在运行时构建了一个包含方法描述、参数结构和执行入口的“工具包装盒”,AI 拿到的只是包装盒上的“说明书”,执行时再通过包装盒里的“机关”触发真正的代码。
二、工具上下文:安全的“幕后数据通道”
在实际开发中,工具执行往往依赖于当前请求的上下文,例如 当前登录用户的 ID。如果让 AI 模型提供用户 ID,既不安全(可能被伪造),也不符合用户体验。
Spring AI 提供了 ToolContext 机制来解决这个问题。
2.1 核心特性
- 对 AI 不可见:
ToolContext中携带的数据 不会 作为 Prompt 的一部分发送给 AI 模型。 - 应用内部使用:仅在
call()方法执行时,由框架注入使用。
2.2 场景与流程图解
场景示例:用户自助退款。
用户说“我要退款”,AI 不需要询问“你是谁?”,而是直接调用退款工具,工具内部从 ToolContext 获取当前会话的 userId。
工具上下文流程:AI 决定调用工具,但具体的上下文参数(如 userId)由后端安全注入,不暴露给 AI。
2.3 实战逻辑模拟
- 用户请求:“我要退款。”
- Spring AI 处理:系统将用户输入转换为 Prompt,并附加工具定义
[用户退款工具](该工具定义中不包含 userId 参数,AI 认为该工具无需输入)。 - AI 决策:
toolCalls: { toolName: "用户退款工具", "params": {} } - 框架执行:Spring AI 找到该工具对应的
ToolCallback,在call方法内,开发者可以从ToolContext读取当前线程绑定的userId进行退款操作。 - 结果返回:工具执行返回“退款成功”。
三、立即返回:绕过 AI 的直接响应
在大多数对话场景中,工具执行的结果需要 AI 再次润色(例如:“正在查询天气...北京今天晴天”)。但在某些场景下,工具的结果就是最终答案,无需 AI 画蛇添足(例如:直接生成一个 PDF 文件流)。
3.1 默认流程 vs 立即返回流程
Spring AI 通过 returnDirect 属性改变了调用链条。
默认流程:AI决策 -> 执行工具 -> 将工具结果发回AI总结 -> 返回用户
立即返回流程:
在立即返回模式中,工具执行结果直接返回给调用者,不再回传 AI 模型进行二次处理。
3.2 适用场景与代码示例
这种模式非常适合:
- 返回二进制数据(图片、文件)。
- 返回大量结构化数据,不需要 AI 总结。
- 产生确定性结果的强操作(如数据库删除成功)。
使用方法:
public class FileTool {
@Tool(description = "根据查询条件生成销售报表PDF文件", returnDirect = true)
public byte[] generateSalesReport(ReportRequest request) {
// 1. 业务逻辑生成 PDF
// 2. 返回 PDF 字节流,Spring AI 会直接将 byte[] 作为 HTTP Response Body 返回
return pdfBytes;
}
}
四、工具底层执行原理:框架控制 vs 用户控制
Spring AI 提供了两种工具执行模式,默认情况下使用框架控制的工具执行。
4.1 核心组件:ToolCallingManager
ToolCallingManager 是管理 AI 工具调用全过程的“大脑”,负责两大核心职责:
- 解析定义:
resolveToolDefinitions()- 根据请求匹配要发送给模型的工具列表。 - 执行调用:
executeToolCalls()- 根据 AI 返回的指令执行具体的 Java 方法。
4.2 默认模式:框架控制的自动执行
这是最简单的模式,开发者只需配置好 ChatClient,Spring AI 会自动处理工具调用的循环逻辑。
完整执行链路图:
步骤拆解:
- 发起请求:用户提问。
- 定义传递:
ToolCallingManager通过ChatModelAPI将ToolDefinition发送给 AI 模型。 - AI 响应:模型返回
Chat Response,其中可能包含toolCalls指令。 - 分发与执行:
ToolCallingManager接收到指令,自动Dispatch Tool,在本地 JVM 执行对应代码。 - 循环(如需要) :如果
returnDirect=false,执行结果会作为新的消息再次发送给 AI,AI 可能继续调用工具或生成最终回答。 - 最终返回:框架将最终答案返回给用户。
4.3 进阶模式:用户控制的工具执行
在某些极端定制化的场景下,如果开发者不希望框架自动循环,也可以手动处理工具执行。这通常涉及实现 ToolCallback 或直接使用底层的 ChatModel API 处理 ToolCall 消息,给予开发者最大的控制权,但也意味着需要自行管理对话状态和循环逻辑。
通过本文的梳理,相信你已经掌握了 Spring AI 工具调用的骨架与脉络。利用好 ToolContext 保障安全,活用 returnDirect 优化响应效率,将让你的 AI 应用更加健壮和强大。