SpringAI2.0
目录
1.0 简介
(1)简介
内容整体介绍:有Spring开发基础,希望快速掌握如何将大语言模型集成到企业级应用开发项目里

动手实践 注重思考
SpringAI处于快速迭代期,版本升级非常快,要学会如何看官方文档和官方案例
(2) 提示词技巧
结构化:
目标:你要做什么? 背景:发生在什么场景下? 受众:给谁听? 风格:用什么方式表达?
语气:带着什么情绪说话? 格式:输出长什么样? 约束条件:不能做什么?
CO-STAR框架:
context 背景 objective 目标 style 风格 tone 语气 audience 观众 response 回应格式
少样本提示:
先给AI看几个标准的例子 让AI照葫芦画瓢
例如:苹果-->红圆 梨--->黄扁 那么橙子呢?
适用于:风格迁移 数据提取与标准化 情感分类,意图识别等
思维链提示:
就是让AI给出最终答案前,先展示它的”思考过程“ 提升模型在数学计算 逻辑推理 因果判断等复杂任务上的表现
”请一步一步推理一下问题,展示你的完整思考过程,最后得出结论“
可以使得AI自我拆解问题,自我检验,增强可解释性
自我一致性:
同一个问题问AI两遍,AI给出两个不同的答案? 是一种基于思维链提示的改进推理策略
让AI对同一问题生成多条不同的推理路径 然后从这些路径中找出频率最高或逻辑最连贯的答案
最终输出共识性的结论
例:请从不同角度独立思考一下问题三次,每次采用不同的表达方式或拆解顺序,展示完整的推理过程,然后比较三个答案,选择最合理且一直的结果作为最终输出
混合玩法:
上面的各种方法结合起来
提示词工程指南:
提示工程指南 | Prompt Engineering Guide 里面有更多对于提示词的详细讲解
(3) Cursor Rules
掌握一套系统化的AI协作工程方法
cursor:是一个完整的AI驱动编程工具(AI驱动的IDE),不仅仅是一个代码补全工具,更实现了更深层次的AI集成 可以直接⽤⾃然语⾔和它对话, 询问任何编程相关的问题, 它不仅能即时⽣成代码, 还能解释 代码的原理和设计思路.
但是要想发挥其最大潜力,必须善用它的Rules系统 ---- 也就是我们所说的 Cursor Rules
Cursor Rules 是⼀组预先定义、可复⽤的系统级提⽰规则, ⽤于指导 AI 在⽣成或修改代码时遵循特定的技术规范、架构约定和编码⻛格. 这些规则不是语法规范, ⽽是如何与 AI 对话才能写出⾼质量代码的最佳实践.你可以把他理解为"AI编程时的'⾏为守则'".
官⽅推荐的Rules: Java | Cursor Directory | Cursor Directory 下面来简单了解一下:
语言:你是Java技术方面的专家,精通SpringBoot SpringFramework、Maven、Junit和Java相关技术
代码风格与结构:编写简洁 高效且具有良好文档注释的Java代码 并提供准确的SpringBoot示例 在整个项目中遵循SpringBoot的最佳实践和约定 设计Web服务时采用Restful API模式 使用描述性强的方法和变量名 命名遵循camelCase规范 按照标准分层结构组织SpringBoot应用:控制器controllers 服务services 仓库repositories 模型models 配置类configurations
SpringBoot特定要求:使用SpringBootStarters快速搭建项目并管理依赖 正确使用注解,例如@SpringApplicaiton @RestController @Service等 有效利用SpringBoot的自动配置(auto=configuration)特性 使用@ControllerAdvice和@ExceptionHandler实现统一异常处理
命名规范:类名使用PascalCase 例如UserController OrderService 方法和变量名使用camelCase例如isOrderValid 常量全部大写,单词用下划线分割 例如MAX——RETRY_ATTEMPTS
Java与SpringBoot使用规范:在适用场景中使用Java17或更高版本的新特性,如record sealed class 模式匹配等 充分利用SpringBoot 3.x 的功能与最佳实践 数据库操作优先使用SpringData JPA 使用BeanBalidation实现输入校验(如@Valid 自定义验证器)
依赖注入与IoC:使用构造器注入(constructor injection) 避免字段注入field injection 以提升可测试性 充分利用Spring 的IoC容器管理Bean的生命周期
测试:使用JUnit5编写单元测试 并结合@SpringBootTest 进行集成测试 使用MockMvc对Web层进行接口测试 使用@DataJpaTest对Repository层进行数据访问测试
性能与扩展性:使用SpringCache抽象实现缓存策略 (如Cacheable) 使用@Async实现异步非阻塞处理 合理设计数据库索引 优化查询语句性能
安全性:使用SpringSecurity实现身份认证(authentication)和权限控制(authorization) 密码存储必须使用BCrypt等安全编码方式 如需跨域访问 应正确配置CORS
日志与监控:使用SLF4J配合Logback进行日志输出 合理使用日志级别:ERROR WARN INFO DEBUG 使用SpringBootActuator实现健康检查 指标监控和运行时信息暴露
API文档:使用SpringdocOpenAPI(原Swagger)生成API接口文档,确保接口清晰可读
数据访问与ORM:使用SpringDataJPA进行数据库操作 正确定义实体之间的关联关系(如OneToMany ManyToOne)及级联行为 使用Flyway 或Liquibase管理数据库schema变更与迁移
构建与部署:使用maven进行依赖管理和构建流程 使用SpringProfiles区分不同环境的构建配置(dev test prod) 若设计容器化部署,使用Docker打包应用镜像
最佳实践遵循:遵循RESTfulAPI设计原则(合理使用HTTP方法 状态码等) 异步处理优先使用Spring的@Async或响应编程模型(SpringWebFlux)
设计原则:遵循SOLID原则 保持高内聚 低耦合的代码结构 提升系统性的可维护性与可扩展性
Rules 最佳实践:
聚焦单⼀职责 每条 Rule 只解决⼀个问题, 如"命名规范"、"测试要求"
内容具体清晰 避免"写得好⼀点"这类模糊表达, 应写成"变量名使⽤ camelCase"
控制⻓度在 500 ⾏以内 过⻓的规则难以被模型有效解析
规则拆分 把⼤型规则拆分成多个可组合的⼩规则
提供⽰例代码 提供具体⽰例或引⽤⽂件, "像这样写"⽐"不要那样写"更有
2.0 各种模型
(1)图像模型
简介:图像模型是专注于处理与理解视觉数据的人工智能模型 是计算机视觉与多模态学习的核心。 ”看图说话“ ”根据描述画画“
springAI支持图像模型,并设计了统一的接口(SpringImageModelAPI)用于与各种图像生成的AI模型交互,允许开发者通过最小的代码在不同的图像模型之间切换。
OpenAI入门案例:
申请API_KEY: API keys - OpenAI API
充值:Billing overview - OpenAI API //需要准备一张海外的Visa/Master的信用卡或借记卡
//可以通过某宝搜索 虚拟m国支付 虚拟visa支付卡等购买 但是风险自行辨别 可能会封号
选GPT image1 这个模型是付费的 而且没有免费试用 最低5$----->35.75元
环境搭建:为方便代码的维护 使用父子工程的方式创建项目
添加依赖 : springboot的版本和spring ai框架的版本 //spirngAI统一使用1.0.1版本 SpringBoot使用3.5.3版本
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<spring-ai.version>1.0.1</spring-ai.version>
</properties>
<!-- 完善依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
创建模块 : spring-image-demo //子项目
子项目添加相关的依赖: 一个springbootweb 一个maven打包的插件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
写启动类: 添加启动类注解
springAI图像模型接入:图片模型API :: Spring AI 参考
API KEY可以作为配置环境变量 这样就不用把API_KEY写死在代码里面了
测试 、 异常:
(2)ImageModel API
ImageModelAPI是springAI框架中专门用于图像生成的模块化接口,它提供了一套统一的方式来与各种图像生成的AI模型进行交互,该API的设计遵循Spring框架的模块化和可互换性原则 使开发者能够以最小代价的代码变更在不同图像相关AI模型之间切换
接口官方文档介绍: 里面有接入图像模型的教程
//翻译成中文更好理解
1配置文件
# In application.yml
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
//写入apikey 这个时候可以把apikey写成环境变量 不会泄露 但是注意配置好之后需要重启idea
2添加相关依赖 //子项目中
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
3运行的时候如何使用: 先创建接口 然后把官方文档里面的代码复制进来
@Autowired
private OpenaiImageController openaiImageController; 注入进来直接使用
代码举例:
package com.bit.image.controller;
import org.springframework.ai.image.ImagePrompt;
import org.springframework.ai.image.ImageResponse;
import org.springframework.ai.openai.OpenAiImageModel;
import org.springframework.ai.openai.OpenAiImageOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("openai")
public class OpenaiImageController {
@Autowired
private OpenAiImageModel openAiImageModel;
@RequestMapping("/image")
public void image(){
ImageResponse response = openAiImageModel.call(
new ImagePrompt("A light cream colored mini golden doodle",
OpenAiImageOptions.builder()
.quality("hd")
.N(1)
.height(1024)
.width(1024).build())
);
String imageUrl = response.getResult().getOutput().getUrl();
System.out.println(imageUrl);
}
}
4配置系统属性
本地开发时 即使配置了代理 有时候也无法让你的SpringAI应用正常请求api 这通常是代理软件无法让你整个系统实现全局代理造成的 你只需要在启动类中加入下述代码即可
// 配置HTTP/HTTPS网络代理
System.setProperty("http.proxyHost", System.getenv("proxyHost")); // 代理服务器IP
System.setProperty("https.proxyHost", System.getenv("proxyHost"));
System.setProperty("http.proxyPort", "7890"); // 代理软件端口号
System.setProperty("https.proxyPort", "7890");
5测试
接⼝: http://127.0.0.1:8080/openai/image
在控制台可以看到⽣成图⽚的链接, 点击可以看到⽣成的图⽚
(5)Azure OpenAI
SpringAI支持来自Azure OpenAI的图像生成模型DALL-E
Azure OpenAI 和 OpenAI 的关系:可以理解为: OpenAI 负责"造引擎" (训练模型 ) , 微软负责"装⻋" (把引擎装进 Azure 这辆企业级汽⻋⾥ ) .
使⽤ Azure OpenAI , 需要准备⼀张海外的Visa/Master 的信⽤卡或借记卡(⽬前暂停中国个⼈的OpenAI 使⽤). Azure OpenAI Image Generation :: Spring AI Reference
还是和前面的openai一样 官方文档有讲解的部分Image Model API :: Spring AI Reference
(3)QianFan AI
百度千帆是百度智能云推出的AI原生应用开发平台,基于文心大模型构建 提供从模型开发到应用部署的全栈AI能力支持
千帆平台:百度千帆 - 百度智能云控制台 长下面这个样子哦

apikey:百度千帆 - 百度智能云控制台
开通产品:百度千帆 - 百度智能云控制台 个人认证之后 有免费使用额度
项目搭建:
官方文档:通用说明 - 千帆AI应用开发者中心-API参考qianfan-api | 百度智能云文档
引入依赖: v1版本是早期的 从25年4月30日起,v1版本推理服务创建入口已全面关闭 新服 务默认基于v2接口创建 //和openai完全兼容
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
配置文件:
spring:
ai:
openai:
api-key: ${QIANFAN_API_KEY}
base-url: https://qianfan.baidubce.com
completions-path: /v2/chat/completions
chat:
options:
model: "ernie-tiny-8k"
temperature: 0.7
接口:
package com.bit.qianfan.controller;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/qianfan")
public class QianfanController {
@Autowired
private OpenAiChatModel openAiChatModel;
@RequestMapping("/chat")
public String chat(String message){
return openAiChatModel.call(message);
}
}
测试接口:127.0.0.1:8080/qianfan/chat?message=你好
成果展示:
图像模型:
和OpenAI保持一致
配置文件里面添加图像模型有关的内容 注意model里面填的是model参数接入点
//文档不全的时候 通过看源码 看有没有提供相关的配置项

语音模型:
是人工智能领域中用于处理和理解人类语音信号的计算模型 广泛应用于语音识别 语音合成 语音助手等系统中
比如:你对着手机说 今天天气怎么样 AI能立刻听懂你的问题理解语义
官方文档介绍:Moderation :: Spring AI Reference
使用openAI来进行讲述
1申请API_KEY 2添加依赖 3编写接口 4测试运行
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
------------------------------------
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
-----------------------------------
@Slf4j
@RequestMapping("/speech")
@RestController
public class OpenaiSpeechController {
@Autowired
private OpenAiAudioSpeechModel openAiAudioSpeechModel;
@RequestMapping("/tts")
public void tts() throws IOException {
// 构建 TTS 参数配置
OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder()
.model("tts-1")
.voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY)
.responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
.speed(1.0f)
.build();
// 合成文本(修复了乱码)
SpeechPrompt speechPrompt = new SpeechPrompt("Hello, this is a text-to-speech example.", speechOptions);
// 调用 OpenAI 接口
SpeechResponse response = openAiAudioSpeechModel.call(speechPrompt);
// 生成文件路径(项目根目录下 output.mp3)
File file = new File(System.getProperty("user.dir") + "/output.mp3");
// 写入音频文件
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(response.getResult().getOutput());
} catch (IOException e) {
throw new IOException("音频文件写入失败:" + e.getMessage(), e);
}
}
}
完成之后 编译器内部会生成一个mp3文件

代码讲解:
(4)阿里云百炼平台
里面有文档介绍

DashScope: 百炼是阿里云推出的大模型开发和应用平台,dashscope是大模型API服务平台
百炼平台使用DashScope来调用模型
springAI:是官方推出的AI开发框架
springAI Alibaba:基于springAI构建的
springAiAlibaba代码案例:examples/spring-ai-alibaba-image-example at main · spring-ai-alibaba/examples · GitHub
图像生成:
创建项目 添加配置项 启动类 测试
下面是生成的图片: //只是简单描述一下 感觉非常的不错捏

问AI 生成一些代码之后粘贴到自己的编译器里面 就能将图片保存在目录里面 非常的方便
下面可以在文档上面看到 每个模型的特点:

关于模型的参数调整 在文档里面都有
语音合成:
和之前讲解的文字转语音是一样的 找到对应的模型生成音频文件

音色 等等这些都是可以调整的
使用DashscopeSDK调用模型:
Dadhscope-sdk-java是阿里云官方提供的,不依赖任何特定框架的Java客户端 你可以在任何普通的Java应用程序中引入这个SDK 通过编程式地调用它的API来使用大模型服务
参考文档:安装阿里云百炼SDK-大模型服务平台百炼(Model Studio)-阿里云帮助中心
其实就是引入依赖 我们不需要了解内部 直接使用就行
语音识别:
是指对音频文件进行语音识别,将语音转换为文本
代码参考:examples/spring-ai-alibaba-audio-example at main · spring-ai-alibaba/examples · GitHub
换做使用DashScopeSDK调用模型:录音文件识别JavaSDK使用指南-大模型服务平台百炼-阿里云-大模型服务平台百炼(Model Studio)-阿里云帮助中心
其他模型: 官方文档里面有相关的讲解
例如实时语音识别: 具体讲解API参考 官方文档里面有详细的讲解
文生视频:
一些模型完成视频生成的功能
代码参考:万相2.7文生视频API参考-大模型服务平台百炼(Model Studio)-阿里云帮助中心
3.0 Tool Calling (工具调用)
(1)简介
引入:随着大语言模型的飞速发展 ... 我们想要让帮忙与外界世界交互 执行具体任务 比如查询数据库 发送邮件 或分析数据,为了解决这一挑战,工具调用ToolCalling应运而生
是AI应用程序中的一种常见模式,允许大语言模型根据用户请求,智能地选择 调用外部工具(如函数 API 服务)并获取结果地技术流程 从而增强其功能
Tool Calling 让LLM 从⼀个''⽆所不知的学者"变成了⼀个"⽆所不能的指挥家", 它负责思考和规划, ⽽ 具体的⼯作则由外部⼯具执⾏.
工具调用让AI从只会动脑变成可以动手办事
//打开大众点评 查看附近的热门餐厅 确定餐厅 预定餐厅 提醒大家 等待出发
按钮1:查询餐厅 按钮2:预定餐桌 按钮3:发邮件 按钮4:叫车
例如旅游规划:杭州 周末两天 预算1000元 AI可以生成我可能的花费 路费100元给你
路线规划 景点费用60元 餐厅推荐200元 住宿 费用300元等
和FunctionCalling什么关系?
springAI官方文档有关的介绍:Tool Calling :: Spring AI Reference
functionCalling最早是由openai提出来的 functionCalling是toolCalling早期更为流行的束语
function是函数的意思 functioncalling是指LLM请求调用一个开发者预定义的函数(方法)
toolCalling是一个更通用 更广泛的概念
不仅包含了FunctionCalling,还涵盖了调用其他类型的工具
应用场景:
信息检索: 可以借助Tool从外部资源检索信息 例如数据库 web服务器 文件系统等
采取行动: 借助tool完成一些操作 例如发送电子邮件 在数据库中创建新记录
//模型可以生成预订北京旅⾏的计划. 但是, 该模型不具备执⾏计划的能⼒. 这就是⼯具的⽤武之地. 它 们可⽤于执⾏模型⽣成的计划.
(2)快速使用
添加依赖:
<dependency>
<groupId>com.github.victools</groupId>
<artifactId>jsonschema-generator</artifactId>
<!-- 可根据实际情况使用最新稳定版本 -->
<version>4.37.0</version>
</dependency>
//如何把方法定义为一个工具

模型获取不了实时的东西 我们可以定义实时的工具 让AI操控这些工具
定义工具、应用工具:
@Tool(description = "Get the current date and time in the user's timezone")
public String call(String message) {
return chatClient.prompt()
.user(message)
.tools(new DateTimeTools())
跟着这个描述知道这个工具是嘎嘛的
测试:

(3)ToolCalling原理
官方文档:https://springdoc.cn/spring-ai/api/tools.html

下面详细讲解6步的每一步:
注册工具:在向AI模型发送请求时,应用程序需要提前告诉模型有哪些工具可用,包括工具的名称 描述 和 参数格式
//看这些源码里面有的那些属性:
描述是灵魂 这个是模型决定是否调用工具的核心依据 描述必须清晰准确
模型决策:AI模型根据对话内容判断是否需要调用工具 当模型决定调用工具时 它会发送一个工具调用的请求 其中包含工具名称和符合预定义的输入参数
查找并执行:应用程序接收到这个 工具调用请求之后 会根据工具名称找到对应的工具 并用模型提供的参数来执行它
//所以工具名称不可以重复
获取结果:工具执行后产生一个结果 (比如,查询到了今天的温度是25度) 应用程序会处理返回的结果
返回结果:应用程序将这个工具执行的结果再次发送给AI模型
生成最终回复:AI模型结合工具返回的结果 生成最终的回复
例:构建一个能帮助你点咖啡的AI助手
⽐如: 你正在构建⼀个能帮你点咖啡的AI助⼿ 但是AI模型不会"点咖啡", 所以需要提供⼀个额外的⼯具, 来完成"点咖啡"这个功能 • 注册⼯具: 你告诉AI助⼿:你现在有⼀个⼯具, 叫 orderCoffee, 功能是‘帮⽤⼾下单⼀杯咖啡’. 它需要两个参数:coffeeType (⽐如‘拿铁’、‘美式’) 和 size (⽐如‘中杯’、‘⼤杯’) . " ⽤⼾请求:你对AI说:"帮我点⼀杯⼤杯的拿铁. " • 模型决策:AI模型理解你的意图后, 它不会直接说"好的", ⽽是会"调⽤⼯具". 它给应⽤程序的回复 (内部表⽰) 是:"我需要调⽤⼯具 orderCoffee, 并传⼊参数 coffeeType=拿铁, size=⼤杯. " 这就是模型返回了⼀个⼯具调⽤请求, ⽽不是最终答案. • 执⾏⼯具:你的应⽤程序 (⽐如⼀个Spring Boot服务) 接收到这个请求, ⽴刻找到名为 orderCoffee 的⼯具 (可能是⼀个Java⽅法) , 并⽤参数执⾏它. 这个⽅法会调⽤后端的订单系统, 真正下⼀单. 这就是 ToolCallingManager 和你的 ToolCallback 在⼲活. • 返回结果:订单系统返回:"订单创建成功, 订单号是 #12345, 预计5分钟后完成. " 这是⼯具执⾏的结果. • 返回结果:你的应⽤程序把这个结果 ("订单号#12345...") 塞回给AI模型. • ⽣成最终回复: AI模型看到后, 组织了⼀下语⾔, 最终对你说:"好的, 已为您下单⼤杯拿铁!订单号 是 #12345, 请稍等⽚刻哦~" 模型利⽤⼯具执⾏的结果, ⽣成了对⽤⼾友好的最终回复. AI模型本⾝不会点咖啡, 它只是个"⼤脑". 应⽤程序 (通过Spring AI的⼯具调⽤框架) 提供 了"⼿"和"脚" ( orderCoffee ⼯具) , 让"⼤脑"可以指挥"⼿脚"去完成实际任务。
(4) 声明定义工具

声明式定义工具:
tool: name是指定工具的名称 description:工具秒数 模型可以使用它来了解何时以及如何调用工具 如果不指定规则使用方法名 建议详细清楚的描述工具的功能 这对于工具的使用至关重要,直接影响大模型的使用效果 returnDirect:指定工具执行的结果是直接返回 还是要发给大模型 默认发送给大模型 resultConvertre:指定工具执行结果转换器 默认将工具调用结果转换为String
springAI将自动为 @Tool 注解方法的输入参数生成JSON Schema 该Schema供模型理解如何调用工具以及准备工具请求
例如: 把json数据块变成下面这样了 帮助模型理解

开发⼈员可以通过 @ToolParam 注解为输⼊参数提供额外信息 (如描述、是否必需等), 默认情况下所有输⼊参数均为必需参数.

为chatClient添加默认工具和运行时工具:

为chatModel添加工具:
ChatModel chatModel = ...
ToolCallback[] dateTimeTools = ToolCallbacks.from(new DateTimeTools());
ChatOptions chatOptions = ToolCallingChatOptions.builder()
.toolCallbacks(dateTimeTools)
.build();
Prompt prompt = new Prompt("What day is tomorrow?", chatOptions);
chatModel.call(prompt);
(5)编程式定义工具
除了声明式之外,我们也可以通过编程式构建MethodToolCallback 将方法转为工具
Method method = ReflectionUtils.findMethod(WeatherTools.class, "getCurrentWeatherByCityName", String.class);
ToolCallback toolCallback = MethodToolCallback.builder()
.toolDefinition(
ToolDefinitions.builder(method)
.description("根据给定的城市名称, 获取当前城市的天气")
.build())
.toolMethod(method)
.toolObject(new WeatherTools())
.build();
为ChatClient 添加工具
定义一个方法 定义ToolCallback 通过toolCallbacks为ChatClient添加工具//也可以抽取出来
下面是有关的代码:
//定义一个方法
public class WeatherTools {
String getCurrentWeatherByCityName(String cityName) {
switch (cityName) {
case "北京":
return "北京今天天气: 晴空万里";
case "上海":
return "上海今天天气: 电闪雷鸣";
case "广州":
return "广州今天天气: 细雨蒙蒙";
default:
return "没有该城市的天气信息";
}
}
}
// 定义ToolCallback
Method method = ReflectionUtils.findMethod(WeatherTools.class, "getCurrentWeatherByCityName", String.class);
ToolCallback toolCallback = MethodToolCallback.builder()
.toolDefinition(
ToolDefinitions.builder(method)
.description("根据给定的城市名称, 获取当前城市的天气")
.build()
)
.toolMethod(method)
.toolObject(new WeatherTools())
.build();
//通过toolCallbacks为ChatClient添加工具
@RequestMapping("/call")
public String call(String prompt) {
Method method = ReflectionUtils.findMethod(WeatherTools.class, "getCurrentWeatherByCityName", String.class);
ToolCallback weatherTools = MethodToolCallback.builder()
.toolDefinition(ToolDefinitions.builder(method)
.description("根据给定的城市名称, 获取城市当前的天气 ")
.build())
.toolMethod(method)
.toolObject(new WeatherTools())
.build();
return chatClient.prompt()
.toolCallbacks(weatherTools)
.user(prompt)
.call()
.content();
}
//也可以抽取出来
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
@Configuration
public class ToolConfig {
@Bean
public ToolCallback weatherToolCallback() {
Method method = ReflectionUtils.findMethod(WeatherTools.class,
"getCurrentWeatherByCityName", String.class);
ToolCallback weatherTools = MethodToolCallback.builder()
.toolDefinition(ToolDefinitions.builder(method)
.description("根据给定的城市名称, 获取城市当前的天气 ")
.build())
.toolMethod(method)
.toolObject(new WeatherTools())
.build();
return weatherTools;
}
}
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/chat")
public class ChatController {
public ChatClient chatClient;
public ChatController(DashScopeChatModel chatModel, ToolCallback weatherTools) {
this.chatClient = ChatClient.builder(chatModel)
.defaultToolCallbacks(weatherTools)
.build();
}
@RequestMapping("/call")
public String call(String prompt) {
return chatClient.prompt()
.user(prompt)
.call()
.content();
}
}
(6)工具规范
ToolCallback 是⼀个⽤于与 AI 模型交互的回调接⼝,允许开发者定义可被 AI 调⽤的外部⼯具, 在 AI 应⽤(⽐如⼤语⾔模型)中集成"⼯具" (Tools), 让 AI 模型可以在需要时调⽤外部功能。
getToolDefinition:返回工具的信息描述 参数列表等结构化信息 表示这个工具在什么时候使用 怎么使用
getToolMetadata:非必要 非功能性元数据,主要用于框架层面的扩展性支持 不影响核心逻辑
call:toolcontext 带上下文的调用方法 也是默认实现 如果toolContext有值则不支持,主要用于被子类重写支持上下文功能
MethodToolCallback:是springAI框架中实现Tool Calling的核心机制之一,它用于将普通Java方法包装成AI模型可调用的“工具” 就相当于桥梁
可以点开看看源码部分的描述 很清晰 例如:
public final class MethodToolCallback implements ToolCallback {
// 工具默认执行的转换器
private static final ToolCallResultConverter DEFAULT_RESULT_CONVERTER = new DefaultToolCallResultConverter();
// 工具默认元数据
private static final ToolMetadata DEFAULT_TOOL_METADATA = ToolMetadata.builder().build();
// 工具定义,也称为工具的元信息:名字、描述、参数列表等,告诉 AI “我能干啥”
private final ToolDefinition toolDefinition;
// 工具额外元数据(如权限, 分类)
private final ToolMetadata toolMetadata;
// 真正要执行的那个 Java 方法对象(通过反射获取)
private final Method toolMethod;
// 工具对象: 如果方法不是静态的,需要这个对象来调用(即 object.method())
@Nullable
private final Object toolObject;
// 工具转换器:把方法返回值转成字符串,返回给 AI(默认用 JSON)
private final ToolCallResultConverter toolCallResultConverter;
}
ToolDefintion:
这个接口提供AI模型识别工具可用性所需的信息,包括工具名称,描述以及输入模式,每个ToolCallback实现必须提供ToolDefinition实例来定义工具
name属性是工具名称,在提供给模型的工具集中是唯一的 description:AI模型使用工具描述来确定工具的功能 innputSchema 用于调用工具的参数的模式
ToolDefinition.Builder 允许使⽤默认实现 ( DefaultToolDefinition ) 构建 ToolDefinition 实例.
ToolDefinition定义:基于方法构建工具时,ToolDefintion会自动生成,若需自行创建 可使用此便捷Builder 若需显式指定部分或全部属性,可使用ToolDefintion.Builder构建自定义的ToolDefinition实例
ToolContext:
springAI支持通过ToolContextAPI向工具传递额外的上下文信息,此功能允许开发人员提供用户自定义的额外数据,这些数据可与AI模型传递的工具数一起在工具执行过程中使用 ToolContext中提供的任何数据都不会发送给AI模型 调用ChatModel也可以定义工具上下文数据
ReturnDirect:
默认情况下,工具调用结果将作为响应返回模型,随后模型可利用该结果继续对话
某些场景下,开发人员可能希望将结果直接返回调用方而非传回模型。
工具执行:是指提供的输入参数调用工具并返回结果的过程
这个过程由ToolCallingManager接口处理 该接口是SpringAI中负责管理 AI调用工具 全过程的核心组件 负责管理工具执行的完整生命周期
这个接口主要有两个方法 一个是resolveToolDefinitions 一个是executeToolCalls
从模型的工具调用选项中解析工具定义,告诉模型 : 我能用哪些工具
第二个 执行模型所要求的工具调用 也就是真正的去调工具
4.0 MCP
(1)简介
引入:当今快速发展的AI应用生态中,有越来越多这样的应用场景
用户提问时,系统要通过进行联网搜索 多平台兼容性差 某智能助手需要调用高德地图获
取位置信息
为了解决这个问题
一个名为 模型上下文协议的标准应运而生,MCP并不替代ToolCalling,而是为其提供一个统一、可拓展、跨平台的连接基础设施。
可以把两者的关系理解为:
Tool Calling 是"决策⾏为": 模型决定"要不要调⽤⼯具"、"调哪个⼯具"、"传什么参数" MCP 是"通信协议" : 规定"如何描述⼯具"、"如何发起调⽤"、"如何传递结果"、"如何管理会话状态"。
通俗:假设你想要做一个旅游推荐机器人,它可以查天气,查景点信息,预定酒店。这些功能分贝由三个不同的团队提供服务。如果每个服务都有自己定义一套交互方式,有的XML有的RESTAPI有的gRPC 你的AI应用程序就要写三套调用逻辑,维护三种错误处理机制,非常麻烦。更糟糕的是,AI本身并不直接理解HTTP请求怎么发、JSON怎么构造,它只能告诉你:”我想查某个用户的地址 ⾄于怎么调⽤接⼝、传什么参数、如何解析结果, 必须有⼈帮它完成. 于是, 我们需要⼀个"翻译官" + "中介平台"⸺这就是MCP诞⽣的意义。
MCP:Model Context Protocol
这就像 Web 应用中的浏览器与 HTTP 协议的关系:
- 浏览器决定要访问哪个页面(相当于模型发起 Tool Calling)
- 而真正完成数据传输的是底层的 HTTP 协议(相当于 MCP 承载调用过程)
(2)内容
MCP官方文档介绍:What is the Model Context Protocol (MCP)? - Model Context Protocol
MCP是一个开放标准协议,它的目标是让大模型驱动的AI应用(例Claude ChatGPT)能够像“插上USB接口”一样,轻松的连接到外部系统-----包括数据库,文件,工具,软件甚至物理设备
以前每个AI工具都要接入某个服务,都得单独开发一套对接逻辑,现在有了MCP,就像所有设备都统一使用USB充电一样 只要遵循这个标准,就能即插即用 AI的万能插座,或 通用接口
MCP让AI模型不再是“聊天机器人” 而是可以 获取你的私人数据(在授权的前提下) 使用专业工具执行任务 自动完成复杂工作流
对于开发者⽽⾔, 可以不再为每个 AI 应⽤重复开发插件, 只需做⼀个 MCP Server, 多个 AI 都能调⽤. 对于AI应⽤商⽽⾔, 可以快速集成海量⼯具, 增强产品竞争⼒ (⽐如让 ChatGPT 能控制微信) 对于普通⽤⼾⽽⾔, 可以获得更聪明、更懂你、能办事的 AI 助⼿, ⽽不是只会回答问题的"百科机器⼈"
来个直观的例子吧:

(3)MCP JavaSDK架构
MCP Java SDK 提供 MCP 的 Java 实现, ⽀持通过同步和异步通信模式与 AI 模型及⼯具进⾏标准化交互.
同步模式和异步模式:

Client/Server层:McpClient处理客户端操作,McpServer管理服务端协议操作,二者均通过McpSession进行通信管理。 Session层通过DefaultMcpSession实现通信模式及状态。 Transport 处理json-rpc消息的序列化与反序列化 支持多种传输协议实现

传输协议:就像你可以用微信、打电话、或者当面喊人来传递消息一样,MCP支持不同的“传输方式”------这就是所谓的传输协议 目前它支持三种传输方式:基于Stdio的进程间通信传输协议 基于JavaHttpClient的SSE客户端传输协议 WebFluxSSE客户端传输协议(用于响应式HTTP流式通信)
(4)MCP使用
MCP爱好者社区:MCP Servers https://mcpcc.cc/ MCPFlow - 中文MCP技术社区 docs.mcpservers.cn
这些网站汇集了丰富的MCP服务器信息,支持按人气排名,功能类型等多种条件筛选,帮助用户快速找到心仪的服务器。同时,它们也为开服者提供了展示成果、推广服务器的重要渠道,积极推动了MCP生态繁荣与发展。
下面我们来讲解社区里面的一篇文章:

大白话帮你拆解这个mcp-server-flomo项目
这个项目就是一个现成的写字机器人,你把它插到智能家居系统里,AI就能随时帮你记笔记了
项目名:mcp-server-flomo 一看就知道是给Flomo用的MCP服务器 作者:jamesfeng2009
功能标签:笔记记录 这个机器专门干笔记的活 技术栈:JavaScript 通过stdio方式通信
配置代码: command:"npx" 用npx来启动它 npx负责临时下载并运行这些工具 args: ["-y", "@chatmcp/mcp-server-flomo"]
-y的意思是别问我 直接执行 @chat这里是npm上的包名,告诉npx去下载并运行这个工具
env:设置环境变量 把FLOMO_API_URL换成你自己的FlomoAPI地址,就像告诉机器人 用这个地址把笔记存进去 readme是功能清单:里面有一些介绍

开发与安装:
下面是我的尝试记录:
localhost:8080/chat?message=这是我第一次把AI应用到具体软件里面 记录到里面了吗嘟嘟?



其他好玩的mcp:

MCP Client:
有了MCP服务器之后,如何在实际开发或使用中调用这些服务?这就需要借助MCP客户端(MCP Client) MCP 客⼾端是连接本地开发环境或应⽤与远程 MCP 服务器之间的桥梁
现在市面上有很多中类型地MCP客户端。比如电脑软件,代码编辑器插件,智能自动化框架等。它们各有侧重,有些适合程序员辅助写代码 有些功能更全面 适合处理复杂任务流程 你可以根据自己的需要选择合适的客户端 用户可以根据自己的需求选择合适的客户端。 例:

(5)环境准备
在使用MCP Client之前,通常需要先运行一个或多个MCPServer实例,而许多MCP Server是通过npx或uv命令启动的,在开始使用前,必须正确配置相应的运行环境。
MCP Client 环境准备:
核心概念解释:
Node.js 是一个基于Chrome V8引擎构建的JavaScript运行时环境 允许开发者在服务端执行JavaScript代码 在MCP生态中 部分MCP Server 实现是用TypeScript编写的 需要依赖Node.js来运行
npx和npm的区别:
npm:是Node.js自带的包管理工具 用于安装和管理JavaScript包
npx:用于执行npm包中可执行命令 支持临时下载并运行远程包
python与现代包管理工具uv:许多MCP Server使用Python编写 在MCP生态中,uv被推荐为首选工具来运行Python的MCPServer
安装必要软件: Node.js(含npm 和 npx) python uv(高效管理python包与虚拟环境)
安装Node.js https://nodejs.org //务必勾选Add to Path这个选项
验证安装:cmd里面 node --version和npm --version和npx --version

安装python https://www.python.org/downloads/ //务必add to path和 勾选pip

安装uv : 通过pip安装 安装 | uv 中文文档
安装方式有很多种 刚刚不是装好python了嘛 在写一个pip install uv就可
验证安装: 
5.0 cursor
(1)简介
cursor是一个完整的AI驱动编程工具(AI驱动的IDE) 不仅仅是一个代码补全工具,更实现了深层次的AI集成 可以直接用自然语言和它对话 询问任何编程相关的问题 它不仅仅能即时生成代码,还能解释代码的原理和设计思路
https://www.cursor.com/cn //下载地址
Cursor 文档 — 智能体、规则、MCP、技能和 CLI //cursor官方文档
cursor配置: 字体改为中文简体
ctrl + shift + x打开扩展商店 输入chinese 改成中文版
常用快捷键:ctrl shift L:打开聊天 右侧会显示对话框,可以和AI沟通交流
例如:


之前我们说过 AI光有一个聪明的大脑 但是没有手脚
我们直接跟AI说 打开浏览器搜索百度 它是做不到的 但是接入手脚之后就可以了

(2) 安装MCP服务端
cursor文档:Cursor 文档 — 智能体、规则、MCP、技能和 CLI
配置安装:
https://docs.cursor.com/zh/context/mcp
一键安装:从MCP库中安装MCP服务器,并通过OAuth完成认证
下面这些都是可以在cursor里面使用的
点击之后可以直接添加到cursor

之后就是在cursor里面安装就可以了

(3) 使用Cursor安装MCP服务器
上面添加的是官网默认的MCP 我们在社区里面的MCP如何接入呢?

写入代码之后自动保存
之后会自动更新 绿点表示成功
点击能看报错信息 为什么这个mcp没有启动

5.0 Cline
(1) 简介与安装
是一个基于MCP协议构建的 独立命令行AI代理工具 允许用户通过自然语言与本地系统进行交互
执行文件操作 运行脚本 调用外部服务等任务
简单讲解一下就是:能用嘴指挥电脑干活的黑窗口工具,基于MCP接各种外挂,让它能动手改文件,执行命令,调网络服务
安装:
提供了VisualStudio Code的插件版本,为 Cline CLI 的核⼼能⼒提供图形化界⾯⽀持. 它允许⽤⼾在不打开终端的情况下, 直接在编辑器侧边栏或命令⾯板中调⽤ AI 代理功能.
我们借助VS Code的插件来使用Cline
Cline默认英文版本,也会有对应的中文版本,我们选择使用Cline Chinese

Cline集成了丰富的AI供应商 只需要填写对应的API_KEY即可
里面可以调整 AI供应商 切换各种模型等 这个自己调整

右下角 计划 执行 //执行是立即执行任务 计划是收集信息 生成计划
例如 :输入框输入 创建一个文件 用Java代码编译二分查找法

(2)使用Cline安装MCP服务

市场 远程服务器 已安装
和之前在cursor里面的配置一样 输入代码之后就可以运行了


现在的大模型不再是聪明的脑袋 长出了好多手脚
(3) SpringAI接入MCP Server
MCP社区提供了非常丰富的MCP服务,除了上述讲的客户端之外,我们也可以通过SpringAI代码来接入这些资源
首先最基础的环境搭建部分:
创建模块 添加相应的pom配置:springbootweb和springboot test springAlibaba的框架
配置文件:复制之前的就行 添加启动类 写接口
如何接入MCP server?
添加依赖 和 配置文件: springAI的mcp依赖
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
---------------------------------------------------------
spring:
ai:
mcp:
client:
request-timeout: 60000
stdio:
servers-configuration: classpath:/mcp/mcp-servers-config.json
配置文件最后一行里面的网址里面 内容就是之前配置mcp的时候的代码 只是有略微区别

方便观察 添加日志:
logging:
level:
io:
modelcontextprotocol:
client: DEBUG
spec: DEBUG
添加工具到ChatClient:
public ChatController(DashScopeChatModel chatModel, ToolCallbackProvider toolCallbackProvider) {
this.chatClient = ChatClient.builder(chatModel)
.defaultToolCallbacks(toolCallbackProvider)
.build();
}
ToolCallbackProvider帮助我们自动绑定
启动程序,观察日志
6.0 自定义MCP Server
在MCP社区中,开发者可以发现大量由社区成员贡献的MCP服务,也可以基于自身需求,创建和发布自己的MCP服务。
这块内容是学习如何自己开发MCP Server
(1)STDIO
翻译:标准化输入输出 就是程序最基本的说话和听话的方式
你在命令行里面敲字,程序读到的东西叫做 标准输入;程序在屏幕上打印出来的字,叫标准输出
STDIO 就是 MCP 服务通过标准输入输出跟 AI 代理交流,像一个本地随叫随到的工具人,不用上网,直接用命令行传话干活。 直接传输
创建模块mcp-stdio-server-demo
依次完善pom文件:添加mcp-server依赖 配置文件 启动类
//开发一个获取用户信息的工具
定义工具:
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import java.util.HashMap;
import java.util.Map;
public class UserService {
static Map<String, UserInfo> userInfoMap = new HashMap<>();
static {
userInfoMap.put("zhangsan", new UserInfo("zhangsan", 15, "男", "北京"));
userInfoMap.put("lisi", new UserInfo("lisi", 16, "男", "上海"));
userInfoMap.put("wangwu", new UserInfo("wangwu", 17, "男", "广州"));
userInfoMap.put("zhaoliu", new UserInfo("zhaoliu", 18, "女", "深圳"));
userInfoMap.put("sungi", new UserInfo("sungi", 19, "女", "香港"));
userInfoMap.put("zhaoba", new UserInfo("zhaoba", 20, "女", "澳门"));
}
@Tool(description = "根据用户的姓名,返回用户信息")
public String getUserInfo(@ToolParam(description = "用户的姓名") String name) {
if (userInfoMap.containsKey(name)) {
return userInfoMap.get(name).toString();
}
return "未查询到用户信息";
}
}
暴漏工具:
package com.bit.mcp.config;
import com.bit.mcp.service.UserService;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ToolConfig {
@Bean
public ToolCallbackProvider getUserInfo(UserService userservice) {
return MethodToolCallbackProvider.builder()
.toolObjects()
.build();
}
}
配置文件 表示这是一个MCP Server:
spring:
ai:
mcp:
server:
name: user-info
version: 0.0.1
main:
web-application-type: none
banner-mode: off.
打包:
这样就打包完成了
接下来就是客户端调用了
cursor调用:
在cursor里面配置mcp 然后输入代码一刷新
"user-info": {
"command": "E:/chengxu/jdk17/bin/java.exe",
"args": [
"-Dspring.ai.mcp.server.stdio=true",
"-Dlogging.pattern.console=",
"-jar",
"E:/JavaCode/JavaCode02/ai02/spring-ai-project/mcp-stdio-server-demo/target/mcp-stdio-server-demo-1.0-SNAPSHOT.jar"
]
}
这个时候去看cursor 就有了这个工具了

cursor调用:

SpringAI接入:
在mcp-servers-config.json 文件中配置mcp server
添加工具 :构建ChatClient
测试接口
(2)SSE
SSE:服务器推送事件
SSE实现方式和STDIO实现上有一些配置不同
创建模块mcp-sse-server-demo //复制一下mcp-stdio-server-demo改下名称
添加依赖 配置文件 测试 客户端调用 cursor调用 其他starter
7.0 MCP部署
(1)部署
MCP ⽀持多种传输⽅式, ⽽不同的协议决定了不同的部署策略.
• 本地部署: 适⽤于Stdio传输⽅式(进程间通信)
• 远程部署: 适⽤于SSE, WebFlux SSE传输⽅式(基于SSE协议的通信)
本地部署:就是上面案例的部署方式 打包成jar 这种方式简单粗暴但是不够灵活,扩展性差,管理起来比较麻烦
远程部署:MCP服务远程部署和部署后端项目的流程是一样的,需要在服务器上部署
作为Java开发者,更推荐使用远程部署,将MCP Server注册为服务
提交到平台:MCP服务部署好之后,还可以提交各种MCP开源社区,让其他人也能使用你的MCP服务 每个平台的提交规则不同 按各个平台要求就可以
远程部署是一种基于HTTP 单项实时通信协议 允许服务端向客户端推送数据
提交到平台:MCP Servers 点击submit

(2)MCP推荐
Playwright MCP Serve: AI 模型与浏览器自动化之间的桥梁,使大语言模型能够通过标准化协议直接操作网页内容
• 控制浏览器 (Chrome、Firefox、Safari)
• ⾃动点击、输⼊、截图、爬⽹⻚
• 模拟真实⽤⼾操作
Fetch:是一个网页内容抓取服务器 使大型语言模型能够:
• 从互联⽹检索⽹⻚内容
• 将 HTML 转换为易读的 Markdown 格式 //提取页面内容并转换为Markdown格式
• 分块读取⻓⽹⻚
//技术初型 尽量选择官方提供的MCP
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)