Day1-SpringAI-1.0.0版本
引言SpringAI支持SpringBoot3.2.x版本和SpringBoot3.3.x版本。1.SpringAI案例第一步已入SpringAI依赖properties maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler.target spring-ai.version1.0.0-M5/spring-ai.version /properties dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version${spring-ai.version}/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement第二步建立ControllerChatModel是继承了OpenAiChatModel这个类这里我们直接使用OpenAiChatModel。RestController public class DeepSeekController { Autowired private OpenAiChatModel chatModel; GetMapping(/hello) public String hello(RequestParam(value message, defaultValue hello) String message) { String result chatModel.call(message); System.out.println(result); return result; } }第三步创建properties文件server.port8881 spring.application.namedeepseek-demo spring.ai.openai.api-key在deepseek开放平台申请自已的API spring.ai.openai.base-urlhttps://api.deepseek.com spring.ai.openai.chat.options.modeldeepseek-chat #值越高生成文本越多样化但也可能包含刚多的随机性和不可预测的内容 #值越低生成文本越接近确定性的结果即生成的文本会更加一致和可预测。 spring.ai.openai.chat.options.temperature0.72.ChatClientChatClient底层就是ChatModel实现简单聊天功能是一个接口它定义了一个与聊天服务交互的客户端。这个接口主要用于创建聊天客户端对象设置请求规范以及发起聊天请求。RestController public class ChatController { //注入,通过构造方法 private final ChatClient chatClient; public ChatController(ChatClient.Builder chatClientBuilder) { this.chatClient chatClientBuilder.build(); } //1 实现简单对话功能 GetMapping(/chat) public String chat(RequestParam(value msg,defaultValue 你是谁) String message) { return chatClient.prompt() //提示词 .user(message) //用户输入信息 .call() //请求大模型 .content(); //返回文本 } }模型会根据prompt来回应或响应你的要求。每个大模型都有自已的角色预设但是我们可以通过配置进行1角色预设。那么我们就可以写一个配置类Configuration public class AiConfig { Bean public ChatClient chatClient(ChatClient.Builder builder) { return builder.defaultSystem(你是一位六级英语老师你精通六级英语 你的名字叫隔壁老王。).build(); } }创建一个新的Controllercall和stream的区别一个是非流式输出一个是流式输出。流式输出对于用户的体验更好。RestController public class ChatAiController { Resource private ChatClient chatClient; //角色预设使用非流式响应 GetMapping(/chatai) public String chatAi(RequestParam(value msg) String message) { return chatClient.prompt().user(message).call().content(); } //角色预设使用流式响应 GetMapping(value /chataiStream,produces text/html;charsetUTF-8)//设置UTF-8防止乱码 public FluxString chatAiStream(RequestParam(value msg) String message) { return chatClient.prompt().user(message).stream().content(); } }RestController public class ChatModelController { Resource private ChatModel chatModel; //提示词操作 // name名字 // voice: 习惯 GetMapping(/prompt) public String prompt(RequestParam(name) String name, RequestParam(voice) String voice) { //设置用户输入信息 String userText 给我推荐广州的至少三种美食 ; UserMessage userMessage new UserMessage(userText); //设置系统提示信息 String systemText 你是一个美食咨询助手可以帮助人们查询美食信息。 你的名字是{name}, 你应该用你的名字和{voice}的饮食习惯回复用户的请求。 ; //使用Prompt Template 设置信息 SystemPromptTemplate systemPromptTemplate new SystemPromptTemplate(systemText); //替换占位符 Message systemMessage systemPromptTemplate .createMessage(Map.of(name, name, voice, voice)); //使用Prompt封装 Prompt prompt new Prompt(List.of(userMessage, systemMessage)); //调用chatModel方法 ChatResponse response chatModel.call(prompt); ListGeneration results response.getResults(); return results.stream().map(x - x.getOutput().getContent()) .collect(Collectors.joining()); } //String call(String message) GetMapping(/chatModel01) public String chatModel01(RequestParam(msg) String msg) { return chatModel.call(msg); } //ChatResponse call(Prompt prompt); GetMapping(/chatModel02) public String chatModel02(RequestParam(msg) String msg) { ChatResponse chatResponse chatModel.call( new Prompt( msg, OpenAiChatOptions.builder() .model(deepseek-chat) .temperature(0.8) .build() ) ); return chatResponse.getResult().getOutput().getContent(); } }ChatModel接口作为核心定义了与AI模型交互的基本方法。他继承自ModelPrompt,ChatResponse提供了两个重载的call方法。ChatModel中重载的两个call方法public interface ChatModel extends ModelPrompt, ChatResponse, StreamingChatModel { default String call(String message) { Prompt prompt new Prompt(new UserMessage(message)); Generation generation this.call(prompt).getResult(); return generation ! null ? generation.getOutput().getText() : ; } default String call(Message... messages) { Prompt prompt new Prompt(Arrays.asList(messages)); Generation generation this.call(prompt).getResult(); return generation ! null ? generation.getOutput().getText() : ; } ChatResponse call(Prompt prompt); default ChatOptions getDefaultOptions() { return ChatOptions.builder().build(); } default FluxChatResponse stream(Prompt prompt) { throw new UnsupportedOperationException(streaming is not supported); } }3、Prompt提示词工程使用ChatModel。RestController public class ChatModelController { Resource private ChatModel chatModel; //String call(String message) GetMapping(/chatModel01) public String chatModel01(RequestParam(msg) String msg) { return chatModel.call(msg); } //ChatResponse call(Prompt prompt); GetMapping(/chatModel02) public String chatModel02(RequestParam(msg) String msg) { ChatResponse chatResponse chatModel.call( new Prompt( msg, OpenAiChatOptions.builder() .model(deepseek-chat) .temperature(0.8) .build() ) ); return chatResponse.getResult().getOutput().getContent(); } }以下是Prompt类的源码中的构造方法public class Prompt implements ModelRequestListMessage { private final ListMessage messages; private ChatOptions chatOptions; public Prompt(String contents) { this((Message)(new UserMessage(contents))); } public Prompt(Message message) { this(Collections.singletonList(message)); } public Prompt(ListMessage messages) { this((List)messages, (ChatOptions)null); } public Prompt(Message... messages) { this((List)Arrays.asList(messages), (ChatOptions)null); } public Prompt(String contents, ChatOptions chatOptions) { this((Message)(new UserMessage(contents)), chatOptions); } public Prompt(Message message, ChatOptions chatOptions) { this(Collections.singletonList(message), chatOptions); } public Prompt(ListMessage messages, ChatOptions chatOptions) { this.messages messages; this.chatOptions chatOptions; } }提示词是引导大模型生成特定的输出的输入会极大地影响大模型的输出的内容。SpringAI提供了Prompt Templete模板设置提示词信息prompt可以包含多组不同的就角色(systemuserAissitant)等。处理提示词首先要创建包含动态内容占位符的模板占位符可以用Map中的变量动态替换。RestController public class ChatModelController { Resource private ChatModel chatModel; //提示词操作 // name名字 // voice: 习惯 GetMapping(/prompt) public String prompt(RequestParam(name) String name, RequestParam(voice) String voice) { //设置用户输入信息 String userText 给我推荐广州的至少三种美食 ; UserMessage userMessage new UserMessage(userText); //设置系统提示信息 String systemText 你是一个美食咨询助手可以帮助人们查询美食信息。 你的名字是{name}, 你应该用你的名字和{voice}的饮食习惯回复用户的请求。 ; //使用Prompt Template 设置信息 SystemPromptTemplate systemPromptTemplate new SystemPromptTemplate(systemText); //替换占位符 Message systemMessage systemPromptTemplate .createMessage(Map.of(name, name, voice, voice)); //使用Prompt封装 Prompt prompt new Prompt(List.of(userMessage, systemMessage)); //调用chatModel方法 ChatResponse response chatModel.call(prompt); ListGeneration results response.getResults(); return results.stream().map(x - x.getOutput().getContent()) .collect(Collectors.joining()); } }4.SpringAI函数调用SpringAI的函数调用功能允许大模型在生成回答时允许调用外部准备好的外部函数。从而实现动态数据获取或业务逻辑操作。函数调用实现首先在配置包下创建需要用到的函数Configuration public class CalculatorService { public record AddOperation(int a, int b) { } public record MulOperation(int m, int n) { } //注册方法 Bean Description(加法运算) public FunctionAddOperation,Integer addOperation() { return request - { return request.a request.b; }; } Bean Description(乘法运算) public FunctionMulOperation,Integer mulOperation() { return request - { return request.m * request.n; }; } }chatclient的配置类不变Configuration public class AiConfig { Bean public ChatClient chatClient(ChatClient.Builder builder) { return builder.defaultSystem(你是一位六级英语老师你精通六级英语 你的名字叫隔壁老王。).build(); } }编写controllerRestController public class FunctionController { Resource private ChatModel chatModel; GetMapping(value /function,produces MediaType.APPLICATION_STREAM_JSON_VALUE) public String function01(RequestParam(userMessage) String userMessage) { return ChatClient.builder(chatModel) //ChatClient的底层就是ChatModel .build().prompt() .system( 您是算术计算器的代理。 您能够支持加法运算、乘法运算等操作其余功能将在后续版本中添加如果用户问的问题不支持请告 知详情。在提供加法运算、乘法运算等操作之前您必须从用户处获取如下信息两个数字运算类型。 请调用自定义函数执行加法运算、乘法运算。 请讲中文。 ) .user(userMessage) .functions(addOperation, mulOperation) .call() .content(); } }produces MediaType.APPLICATION_STREAM_JSON_VALUE定义返回类型。今天是SpringAI1.0.0版本介绍。