AI大模型+Function Calling技术方案
ztj100 2025-06-23 23:41 39 浏览 0 评论
在 AI 智能体开发的过程中,RAG(Retrieval-Augmented Generation) 和 功能调用(Function Calling) 已经成为两种至关重要的模式。RAG 通过结合检索技术和生成模型的强大能力,使智能体能够实时从外部数据源获取信息,并在生成过程中增强其知识深度和推理能力。Function Calling模式为智能体提供了调用外部工具的能力,极大地扩展了其应用范围。智能体可以通过调用外部工具(如数据库操作、业务规则执行、算法工具调用等),完成更为复杂的任务和操作。这种灵活性使得智能体在各种实际场景中都能表现得更为高效和精确。本文将介绍使用Spring AI 开源框架,验证AI大模型如何调用外部函数。
1、什么是Function Calling
功能调用(Function Calling)允许大型语言模型(LLM)在必要时调用一个或多个可用的工具,这些工具通常由开发者定义。工具可以是任何东西:网页搜索、对外部 API 的调用,或特定代码的执行等。
功能调用是AI应用与模型交互中一个非常典型的范式,它可以辅助模型更好的回答用户问题。我们在给模型输入的过程中,附带上可用的函数列表(包含函数名、函数描述等),模型在收到问题和函数列表后,根据对问题的推理在必要的时候发起对函数的调用。
SpringAI 帮我们规范了函数定义、注册等过程,并在发起模型请求之前自动将函数注入到 Prompt 中,而当模型决策在合适的时候去调用某个函数时,Spring AI 完成函数调用动作,最终将函数执行结果与原始问题再一并发送给模型,模型根据新的输入决策下一步动作。这其中涉及与大模型的多次交互过程,一次函数调用就是一次完成的交互过程。
2、开发示例前提条件
- JDK为17以上版本,本人使用的jdk21版本;
- SpringBoot版本为3.x以上,本项目使用的是SpringBoot 3.3.3版本;
- 本文采用了阿里巴巴的Qwen大模型进行实验与验证。若选用阿里巴巴的AI服务,则需首先在阿里云平台上开通相应的大型模型服务,并获取所需的API密钥,以便在后续代码中调用。具体的开通与配置步骤,请参阅阿里云大模型服务平台“百炼”的相关文档和指南https://help.aliyun.com/zh/model-studio/developer-reference/get-api-key。这样可以确保您能够顺利地集成和使用这些先进的AI资源。
3、添加maven依赖
创建springboot工程后,在pom.xml文件里引入ai相关sdk包,本示例使用了spring-ai-alibaba框架和Qwen模型,而spring-ai-alibaba又是基于spring-ai开发的,所以引入spring-ai-alibaba即可。
Pom.xml完整内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yuncheng</groupId>
<artifactId>spring-ai-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-ai.version>1.0.0-M5</spring-ai.version>
<spring-ai-alibaba.version>1.0.0-M5.1</spring-ai-alibaba.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.3</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>${spring-ai-alibaba.version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
<repository>
<id>aliyun</id>
<name>aliyun Repository</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
3、配置yml文件
#配置访问阿里巴巴AI服务的api-key,并指定了使用qwen-plus模型
server:
port: 8080
spring:
application:
name: spring-ai-demo
ai:
dashscope:
api-key: sk-b90ad31bb3eb4a158524928354x39dc5
chat:
options:
model: qwen-plus
4、创建自定义的FunctionTools
自定义函数需要提供一个 name、description 和 function call signature,以便模型知道函数能做什么、期望的输入参数。Spring AI 使这一过程变得简单,只需定义一个返回 java.util.Function 的 @Bean 定义,并在调用 ChatModel 时将 bean 名称作为选项进行注册。在底层,Spring 会用适当的适配器代码包装你的 POJO(即函数),以便与 AI 模型进行交互,免去了编写繁琐的样板代码。FunctionCallback.java 接口和配套的 FunctionCallbackWrapper.java 工具类包含了底层实现代码,它们是简化 Java 回调函数的实现和注册的关键。
以下是自定义了模拟算术运算的函数,可以执行加法和乘法运算,在实际的业务中,你可以在自定义函数中执行数据库操作、调用HTTP服务、执行业务逻辑等。
import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;
@Configuration
public class FunctionTools {
private static final Logger logger = LoggerFactory.getLogger(FunctionTools.class);
public record AddOperationRequest(int d1, int d2) {
}
public record MulOperationRequest(int d1, int d2) {
}
@Bean
@Description("加法运算")
public Function<AddOperationRequest, Integer> addOperation() {
return request -> {
logger.info("加法运算函数被调用了:" + request.d1 + "," + request.d2 );
return request.d1 + request.d2;
};
}
@Bean
@Description("乘法运算")
public Function<MulOperationRequest, Integer> mulOperation() {
return request -> {
logger.info("乘法运算函数被调用了:" + request.d1 + "," + request.d2 );
return request.d1 * request.d2;
};
}
}
如何定义&注册函数:
您可以在应用程序上下文中定义 @Beans,就像定义任何其他 Spring 管理对象一样。
在内部,Spring AI ChatModel 将创建一个 FunctionCallbackWrapper 包装器的实例,该包装器添加通过 AI 模型调用它的逻辑。@Bean 的名称作为 ChatOption 传递。
@Description 注释是可选的,它提供了函数描述,可帮助模型了解何时调用该函数。这是一个重要的属性,可帮助 AI 模型确定要调用哪个客户端函数。
5、创建ChatClient并启用自定义函数
以下代码创建一个简单的Controller类来测试验证。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/ai")
public class FunctionCallController {
private static final Logger log = LoggerFactory.getLogger(FunctionCallController.class);
@Autowired
private ChatModel chatModel;
@GetMapping(value = "/chat", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
public String ragJsonText(@RequestParam(value = "userMessage") String userMessage){
return ChatClient.builder(chatModel)
.build()
.prompt()
.system("""
您是算术计算器的代理。
您能够支持加法运算、乘法运算等操作,其余功能将在后续版本中添加,如果用户问的问题不支持请告知详情。
在提供加法运算、乘法运算等操作之前,您必须从用户处获取如下信息:两个数字,运算类型。
请调用自定义函数执行加法运算、乘法运算。
请讲中文。
""")
.user(userMessage)
.functions("addOperation", "mulOperation")
.call()
.content();
}
}
为了让模型知道并调用您的自定义函数,您需要在 Prompt 请求中启用它,如上述代码,在functions("addOperation", "mulOperation")中告知ChatClient要使用这两个自定义函数。
另外指定了System Prompt:要求AI 模型被设定为一个算术计算器代理,能够执行加法和乘法运算,并且要求用户提供两个数字和运算类型。这个提示词内容很关键,如何让AI按照自己的意图去执行,要不断测试提示词内容。
6、测试验证Function Calling
以下测试通过4次提问进行验证AI大模型如何调用自定义函数Function:
第1次提问:打招呼
http://localhost:8080/ai/chat?userMessage=你好
返回信息如下:
你好!我是一个算术计算器的代理,目前我可以帮助你进行加法运算和乘法运算。请提供两个数字以及你想要进行的运算类型。
通过返回信息说明了,给ChatClient设置的system提示词生效了,按照默认角色输出了打招呼内容。
第2次提问:算加法
http://localhost:8080/ai/chat?userMessage=3加5等于几
返回信息如下:
3加5等于8。
此时查看后台日志输出,springai.functioncall.FunctionTools : 加法运算函数被调用了:3,5
通过返回信息说明了,证明确实调用了自定义加法函数
第3次提问:算乘法
http://localhost:8080/ai/chat?userMessage=2乘9等于多少
返回信息如下:
2乘9等于18。如果您还有其他数学问题,欢迎继续提问。
此时查看后台日志输出,springai.functioncall.FunctionTools : 乘法运算函数被调用了:2,9
通过返回信息说明了,证明确实调用了自定义乘法函数
第4次提问:算减法
http://localhost:8080/ai/chat?userMessage=5减3等于多少
返回信息如下:
目前我只能协助进行加法和乘法运算。减法功能将在后续版本中添加,敬请期待。如果您有其他运算需求,欢迎告诉我。
由于该示例中没有自定义减法运算函数,所以AI大模型还是按照提示词理解输出的,没有调用其它工具进行输出。
验证DeepSeek是否支持Function Calling
修改yml配置文件中的model值,改成deepseek-v3或deepseek-r1,重启springboot后再次测试。
spring:
ai:
dashscope:
api-key: sk-b90ad31bb3eb4a158524928354x39dc5
chat:
options:
model: deepseek-v3
再次请求http://localhost:8080/ai/chat?userMessage=3加5等于几
后台报错:
InternalError.Algo.InvalidParameter: The tool call is not supported
说明deepseek-v3和deepseek-r1目前不支持function calling功能。
相关推荐
- Linux集群自动化监控系统Zabbix集群搭建到实战
-
自动化监控系统...
- systemd是什么如何使用_systemd/system
-
systemd是什么如何使用简介Systemd是一个在现代Linux发行版中广泛使用的系统和服务管理器。它负责启动系统并管理系统中运行的服务和进程。使用管理服务systemd可以用来启动、停止、...
- Linux服务器日常巡检脚本分享_linux服务器监控脚本
-
Linux系统日常巡检脚本,巡检内容包含了,磁盘,...
- 7,MySQL管理员用户管理_mysql 管理员用户
-
一、首次设置密码1.初始化时设置(推荐)mysqld--initialize--user=mysql--datadir=/data/3306/data--basedir=/usr/local...
- Python数据库编程教程:第 1 章 数据库基础与 Python 连接入门
-
1.1数据库的核心概念在开始Python数据库编程之前,我们需要先理解几个核心概念。数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它就像一个电子化的文件柜,能让我们高效...
- Linux自定义开机自启动服务脚本_linux添加开机自启动脚本
-
设置WGCloud开机自动启动服务init.d目录下新建脚本在/etc/rc.d/init.d新建启动脚本wgcloudstart.sh,内容如下...
- linux系统启动流程和服务管理,带你进去系统的世界
-
Linux启动流程Rhel6启动过程:开机自检bios-->MBR引导-->GRUB菜单-->加载内核-->init进程初始化Rhel7启动过程:开机自检BIOS-->M...
- CentOS7系统如何修改主机名_centos更改主机名称
-
请关注本头条号,每天坚持更新原创干货技术文章。如需学习视频,请在微信搜索公众号“智传网优”直接开始自助视频学习1.前言本文将讲解CentOS7系统如何修改主机名。...
- 前端工程师需要熟悉的Linux服务器(SSH 终端操作)指令
-
在Linux服务器管理中,SSH(SecureShell)是远程操作的核心工具。以下是SSH终端操作的常用命令和技巧,涵盖连接、文件操作、系统管理等场景:一、SSH连接服务器1.基本连接...
- Linux开机自启服务完全指南:3步搞定系统服务管理器配置
-
为什么需要配置开机自启?想象一下:电商服务器重启后,MySQL和Nginx没自动启动,整个网站瘫痪!这就是为什么开机自启是Linux运维的必备技能。自启服务能确保核心程序在系统启动时自动运行,避免人工...
- Kubernetes 高可用(HA)集群部署指南
-
Kubernetes高可用(HA)集群部署指南本指南涵盖从概念理解、架构选择,到kubeadm高可用部署、生产优化、监控备份和运维的全流程,适用于希望搭建稳定、生产级Kubernetes集群...
- Linux项目开发,你必须了解Systemd服务!
-
1.Systemd简介...
- Linux系统systemd服务管理工具使用技巧
-
简介:在Linux系统里,systemd就像是所有进程的“源头”,它可是系统中PID值为1的进程哟。systemd其实是一堆工具的组合,它的作用可不止是启动操作系统这么简单,像后台服务...
- Linux下NetworkManager和network的和平共处
-
简介我们在使用CentoOS系统时偶尔会遇到配置都正确但network启动不了的问题,这问题经常是由NetworkManager引起的,关闭NetworkManage并取消开机启动network就能正...
你 发表评论:
欢迎- 一周热门
-
-
MySQL中这14个小玩意,让人眼前一亮!
-
旗舰机新标杆 OPPO Find X2系列正式发布 售价5499元起
-
面试官:使用int类型做加减操作,是线程安全吗
-
C++编程知识:ToString()字符串转换你用正确了吗?
-
【Spring Boot】WebSocket 的 6 种集成方式
-
PyTorch 深度学习实战(26):多目标强化学习Multi-Objective RL
-
pytorch中的 scatter_()函数使用和详解
-
与 Java 17 相比,Java 21 究竟有多快?
-
基于TensorRT_LLM的大模型推理加速与OpenAI兼容服务优化
-
这一次,彻底搞懂Java并发包中的Atomic原子类
-
- 最近发表
-
- Linux集群自动化监控系统Zabbix集群搭建到实战
- systemd是什么如何使用_systemd/system
- Linux服务器日常巡检脚本分享_linux服务器监控脚本
- 7,MySQL管理员用户管理_mysql 管理员用户
- Python数据库编程教程:第 1 章 数据库基础与 Python 连接入门
- Linux自定义开机自启动服务脚本_linux添加开机自启动脚本
- linux系统启动流程和服务管理,带你进去系统的世界
- CentOS7系统如何修改主机名_centos更改主机名称
- 前端工程师需要熟悉的Linux服务器(SSH 终端操作)指令
- Linux开机自启服务完全指南:3步搞定系统服务管理器配置
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)
- vmware17pro最新密钥 (34)
- mysql单表最大数据量 (35)