1.前言
首先是为什么会出现Spring AI Function Calling
,那我们就先分析一下AI的擅长领域和不擅长领域。
擅长领域
- 自然语言处理
- 例:ChatGPT生成文章、翻译语言,或客服机器人理解用户意图。
- 非结构化数据分析
- 例:医学影像识别(X光片中的肿瘤检测),或语音转文本。
- 创造性内容生成
- 例:Stable Diffusion生成符合描述的图像,或AI作曲工具创作音乐。
- 复杂模式预测
- 例:股票市场趋势预测(基于历史数据关联性,但需注意可靠性限制)。
不擅长领域
- 精确计算
- 例:AI可能错误计算"12345 × 6789"的结果(需依赖计算器类传统程序)。
- 确定性逻辑验证
- 例:验证身份证号码是否符合规则(AI可能生成看似合理但非法的号码)。
- 低资源消耗场景
- 例:嵌入式设备(如微波炉控制程序)无法承受大模型的算力需求。
- 因果推理
- 例:AI可能误判"公鸡打鸣导致日出"的因果关系。
为了解决AI大模型存在的缺点,于是Spring AI Function Calling
就诞生了,通过让AI调用Function Calling从而减少功能性缺陷。
2.FunctionCalling流程示意
大模型虽然可以理解自然语言,更清晰弄懂用户意图,但是确无法直接操作数据库、执行严格的业务规则。这个时候我们就可以整合传统应用于大模型的能力了。
简单来说,可以分为以下步骤:
- 我们可以把传统应用中的部分功能封装成一个个函数(Function)。
- 然后在提示词中描述用户的需求,并且描述清楚每个函数的作用,要求AI理解用户意图,判断什么时候需要调用哪个函数,并且将任务拆解为多个步骤(Agent)。
- 当AI执行到某一步,需要调用某个函数时,会返回要调用的函数名称、函数需要的参数信息。
- 传统应用接收到这些数据以后,就可以调用本地函数。再把函数执行结果封装为提示词,再次发送给AI。
- 以此类推,逐步执行,直到达成最终结果。
流程如图:
注意:
并不是所有大模型都支持Function Calling,比如DeepSeek-R1模型就不支持。
我们要做的事情就简化了
编写基础提示词(不包括Tool的定义)
编写Tool(Function)
配置Advisor(SpringAI利用AOP帮我们拼接Tool定义到提示词,完成Tool调用动作)
3.FunctionCalling实现流程
3.1定义Function
所谓的Function,就是一个个函数,SpringAI提供了一个@Tool
注解来标记这些特殊的函数。可以任意定义一个Spring的Bean,其中有2个关键点,一个是方法用@Tool
标记,参数用@ToolParam
标记,例如:
@Component
public class MyFunction {
@Tool(description="这里需要写Function的功能描述,将来会作为提示词的一部分,大模型可以依据这里的描述来判断何时调用该函数")
//其中的函数名最好也是见名知意
public String func(@ToolParam(description = "参数的描述") param) {
// ...
retun "";
}
}
接下来将举一个具体的例子来说明
新建一个tools
包,在其中新建一个MyTools
类:
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class MyTools {
//这里模拟一下用户列表
List<String> userList = List.of("小王", "小张", "小李");
//这里模拟一下语音助手的功能,本来应该是语言信息,这里简化一下
@Tool(description = "根据用户姓名信息来获取一个AccessToken")
public String getAccessToken(@ToolParam(description = "用户姓名") String userName) {
if (!userList.contains(userName)) {
return "用户无权限";
}
//模拟生成一个AccessToken
return "access";
}
//required = false表示该参数不是必须的,默认为true
@Tool(description = "首先根据用户姓名来获取一个AccessToken,检查AccessToken是否有效,如果返回值为false,告诉用户无权限,如果为true,就根据AccessToken来预约一个会议,并返回给用户会议预定信息")
public String bookMeeting(@ToolParam(description = "用户姓名") String userName,
@ToolParam(description = "预定时间(例如明天上午10点钟)") String time,
@ToolParam(description = "预定时长(例如1个小时)",required = false) String duration) {
//模拟根据AccessToken来预约会议
String accessToken = getAccessToken(userName);
if(!checkAccessToken(accessToken)){
return "预约失败";
}
//真实业务中调用对应的api即可
return "预约成功";
}
@Tool(description = "检查AccessToken是否有效")
public Boolean checkAccessToken(@ToolParam(description = "AccessToken") String accessToken) {
if(!accessToken.equals("access")){
return false;
}
return true;
}
}
然后配置chatClient
@Bean
public ChatClient myChatClient(OpenAiChatModel model, ChatMemory chatMemory,MyTools myTools) {
return ChatClient.builder(model)
.defaultSystem("你是一个热心,可爱的人工智能助手,你的名字叫做贾维斯,请你以钢铁侠3中贾维斯的身份和语气来和我说话。")
.defaultAdvisors(
new MessageChatMemoryAdvisor(chatMemory), //配置聊天记忆
new SimpleLoggerAdvisor()) //配置日志
.defaultTools(myTools) //通过defauotTools就能将自定义工具类交付给大模型使用
.build();
}
然后测试一下
@Autowired
private ChatClient myChatClient;
@Test
public void testMyChatClient() {
String prompt = "我是小王,请你帮我预定一个明天下午2点钟的会议,时长你来安排";
String result = myChatClient.prompt()
.user(prompt)
.call()
.content();
System.out.println(result);
}
现在我们来看一下其实现流程
发现AI大模型在回答我们的问题时,会将我们定义的方法生成一个id
,然后会根据我们方法上面的描述与需求对参数
进行校验,(其实预定时长duration
,我们是没有输入的,但是AI大模型帮我们生成了)校验通过后就进行方法调用,按照要求返回结果。
spring AI 的 Function Calling
功能是一个强大的集成机制,它在 AI 应用开发中扮演着关键角色,主要作用可以概括为以下几个核心方面:
- 扩展 AI 能力边界
突破训练数据限制:让 AI 模型能够访问训练数据之外的最新信息和实时数据
执行具体操作:将 AI 的文本理解能力转化为实际系统操作(如数据库查询、API 调用等)
多模态集成:整合非文本功能(如图像处理、语音识别等) - 实现动态信息获取
实时数据查询:获取股票行情、天气预报、交通状况等动态信息
系统状态检查:查询订单状态、库存水平、服务器指标等业务数据
个性化响应:基于用户档案、权限等上下文提供定制化回答 - 业务流程自动化
智能工作流触发:根据对话自动创建工单、发送通知、预约会议等
决策支持:通过调用业务逻辑提供基于数据的建议
复杂任务分解:将用户请求拆解为多个系统操作并协调执行 - 系统集成桥梁
连接异构系统:统一不同技术栈的后端服务与 AI 前端
微服务编排:协调跨多个微服务的复杂操作
遗留系统赋能:为传统系统添加智能交互层 - 安全与管控层
权限代理:在受控环境下执行敏感操作
输入验证:在调用实际业务逻辑前进行安全检查
审计跟踪:记录 AI 触发的所有系统操作 - 性能优化机制
缓存管理:智能缓存频繁查询的结果
异步执行:处理耗时操作而不阻塞主线程
批量处理:合并多个请求提高效率
关键特性实现
声明式集成:通过注解简单定义可调用函数
自动参数映射:将自然语言转换为结构化参数
上下文感知:保持会话状态跨多个函数调用
结果后处理:对原始系统响应进行适合对话的格式化
典型应用模式
查询应答模式:
用户问:“上海今天气温多少?”
AI 调用天气 API → 返回结构化结果 → 生成自然语言响应
操作执行模式:
用户说:“帮我预约明天下午3点的会议室”
AI 调用日历服务 → 检查可用性 → 创建预约 → 返回确认
决策支持模式:
用户问:“我应该选择哪个云服务套餐?”
AI 分析使用模式 → 调用定价计算 → 生成对比建议
Spring AI Function Calling 通过将语言模型的认知能力与实际业务系统的操作能力相结合,实现了从"知道什么"到"能做什么"的关键跨越,是构建生产级 AI 应用的核心组件。