1.什么是spring AI
Spring AI 是 Spring 官方推出的一个基于 Spring 生态的 AI 应用开发框架,旨在简化将人工智能(如大语言模型、生成式 AI)集成到 Java 应用中的过程。它提供了统一的 API 和工具,让开发者能更轻松地调用 AI 模型
2.项目集成Spring ai
本篇文章需使用JDK17 以上的版本 ,spring boot 版本为3.2.5 ,且在通义百炼申请了大模型的api-key请大家务必与我的版本一致
引入spring AI Alibaba的maven坐标
<!--Spring Ai alibaba--> <dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter</artifactId><version>1.0.0-M6.1</version> </dependency>
application.yml
api-key需要使用自己的我这里是错误的api-key演示
spring:ai:dashscope:api-key: "sk-5sadd21dsanbd1321ndsakda"chat:options:model: qwen-plus
3.项目测试
编写一个类,当spring boot项目启动时自动会执行一次run方法
package com.example.demo.demos;import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;import jakarta.annotation.Resource;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;/*** 使用springAi框架调用ai*//*** 实现 CommandLineRunner接口的话在,每次项目启动时就会执行一次他的run方法*/@Component
public class SpringAiInvoke implements CommandLineRunner {@Resourceprivate ChatModel dashscopeChatModel;@Overridepublic void run(String... args) throws Exception {// 调用模型 Prompt是模型输入AssistantMessage message = dashscopeChatModel.call(new Prompt("你是谁")).getResult().getOutput();System.out.println(message.getText()); // 输出结果 文本响应}
}
4.构建初始化大模型类
初始化大模型,主要是初始化ChatClient 接口的实现类,给ChatClient 配置一些默认的配置
例如提示词,对话记忆,及Advisor(顾问,类似于AOP)
为什么有了chatModel还需要chatClient?
CatModel 相较于 ChatClient 更为底层,Catmodel所使用的Api是直接对大模型进行调用,
例如:
处理模型本身的参数(如温度值
temperature
、最大 token 数maxTokens
)。返回原始响应数据(如
ChatResponse
包含消息、元数据)。
而ChatClien主要是与业务交互提供了更高级的抽象方法
例如:
提供更高层次的抽象,隐藏复杂性(如
Prompt
对象构建、响应解析)。集成 Spring 生态特性(如自动重试、监控)。
标准化输入输出(如直接返回
String
而非ChatResponse
)
但是本质上ChatClient也是在调用CatModel,只不过提供了更多便捷的方法
总结:
ChatClient
本质上是对 ChatModel
的封装,提供更高层次的便捷方法,而初始化 ChatClient
时通常需要传入 ChatModel
。这种设计看似冗余,但背后有明确的架构意图和实际价值。
演示:
当前是初始化了大模型和配置
package com.example.demo.app;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.stereotype.Component;@Component
public class AiApp {ChatClient chatClient;// 构造函数 初始化大模型时会注入对象 (根据使用的名称注入,例如阿里的就注入dashscopeChatClient)public AiApp(ChatModel dashscopeChatModel) {//创建一个基于内存的会话历史记录ChatMemory memory = new InMemoryChatMemory();chatClient= ChatClient.builder(dashscopeChatModel) //传入大模型对象.defaultSystem("你当前的角色是i桂航小助手,解决学生在学校的各种疑问") //设置系统提示词 例如当前aiapp是一个学校客服系统,角色是i桂航小助手.defaultAdvisors(new MessageChatMemoryAdvisor(memory)//设置一个advisor (顾问) 当前设置的是处理对话上下文的advisor//也设置多个advsior 和自定义的advisor).build();}}
5.ChatClien实现对话
给AiApp类中添加新的对话方法
//Chatclien对话public String dochat(String message,String sessionId){ChatResponse chatResponse = chatClient.prompt().user(message)//传入用户输入信息.advisors(advisorSpec -> advisorSpec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, sessionId)//对话的会话id 用于查看是否是当前上下文.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 3) //检索上下文的长度 如果长度过长所消耗的Token数量会过大).call().chatResponse();log.info("chatResponse: {}", chatResponse.getResult().getOutput().getText());//输出模型返回的结果return chatResponse.getResult().getOutput().getText();}
测试调用对话
@SpringBootTest
class DemoApplicationTests {@AutowiredAiApp app;@Testvoid contextLoads() {app.dochat("你好,请记住我的朋友叫Java", "1");app.dochat("你是谁? 回复不超过10个字","1");app.dochat("我的朋友叫什么?还有帮忙回忆一下回复不超过几个字?","1");}}
输出的结果为
说明实现了对话,且具有了对话记忆功能
6.结构化输出(将大模型输出转为JAVA对象)
引入maven
<!--springAi结构化输出--> <dependency><groupId>com.github.victools</groupId><artifactId>jsonschema-generator</artifactId><version>4.38.0</version> </dependency>
在AiApp类中编写一个用于返回,一个Java对象的聊天 方法
其中创建了一个Tmplate类 与一个 聊天方法
//JDK14提供的语法 用于创建一个对象public record Template(String title, List<String> mesages){}public Template dochatTemplate(String message, String sessionId){Template template = chatClient.prompt("现在你需要根据用户的需求给出建议标题为: 给{xxx}的建议,内容列出列表").user(message).advisors(advisorSpec -> advisorSpec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, sessionId).param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 3)).call().entity(Template.class);//输出成为一个Java对象log.info("结果:{}", template);return template;}
测试 :
@Testvoid dochatTemplate() {AiApp.Template template = app.dochatTemplate("你好,我叫小明,在学校我有些困惑,请给我3条建议", "1");}
输出结果
大模型给出的返回值变成了Taplate对象 ,建议也变成了List集合