当前位置: 首页 > news >正文

石家庄网站开发与优化html网页制作房地产页面

石家庄网站开发与优化,html网页制作房地产页面,360网址导航,肇庆网站上排名一、前言 Spring AI 提供跨 AI 供应商(如 OpenAI、Hugging Face 等)的一致性 API, 通过分装的ChatModel或ChatClient即可轻松调动LLM进行流式或非流式对话。 本专栏主要围绕着通过OpenAI调用各种大语言模型展开学习(因为大部分模型都兼容O…

一、前言

Spring AI 提供跨 AI 供应商(如 OpenAI、Hugging Face 等)的一致性 API, 通过分装的ChatModelChatClient即可轻松调动LLM进行流式或非流式对话。

本专栏主要围绕着通过OpenAI调用各种大语言模型展开学习(因为大部分模型都兼容OpenAI方式调用接口),接下来将探索Spring AI的多轮对话(包括手动组装历史消息和Spring AI的ChatMemory

二、术语

2.1 Prompt

输入给大语言模型的指令或问题,通过提供上下文和任务要求,帮助模型理解用户意图、引导模型生成特定输出(包括特定格式-如JSON格式)

2.2 Message

包括3种角色的消息

2.3 ChatMemory

Spring AI 中的 ChatMemory 是用于解决大语言模型(LLM)无状态问题的核心组件,通过管理对话上下文实现多轮交互的连贯性。其核心模块包括 MessageWindowChatMemoryMessageChatMemoryAdvisorPromptChatMemoryAdvisor。

2.2.1 ChatMemory(记忆存储接口)

  • 定位:定义对话消息的存储规范(增删查),是记忆管理的抽象底座。
  • 核心方法:
void add(String conversationId, Message message);  // 存储消息
List<Message> get(String conversationId);          // 获取历史消息
void remove(String conversationId);               // 删除会话
  • 实现类:MessageWindowChatMemory是唯一官方实现。

2.2.2 MessageWindowChatMemory(滑动窗口记忆管理)

  • 定位:ChatMemory的默认实现,通过窗口机制控制记忆长度。
  • 核心特性:
    • 默认保存最近20条消息(可配置maxMessages
    • 自动移除旧消息(保留系统消息)。
    • 依赖ChatMemoryRepository实现持久化(内存/JDBC/Redis等)。
  • 协作方式:
    • 存储原始Message对象(含角色信息)
    • 为Advisor提供原始对话数据源。

2.2.3 MessageChatMemoryAdvisor(结构化记忆注入)

  • 定位:将ChatMemory中的历史消息按原始角色结构注入Prompt。
  • 工作流程:
    • MessageWindowChatMemory读取指定conversationId的历史消息。
    • 将每条消息作为独立对象(保留user/assistant角色)加入Prompt消息列表。
  • 适用场景:需精准区分角色上下文的场景(如客服对话、多轮追问)。

2.2.4PromptChatMemoryAdvisor(扁平化记忆注入)

  • 定位:将历史消息拼接为纯文本块,插入系统提示词。
  • 工作流程:
    • MessageWindowChatMemory获取历史消息。
    • 拼接消息内容(丢失角色标签),追加到SystemMessage
  • 适用场景:成本敏感型场景或兼容老旧模型(如单文本输入的LLM)。

三、代码

3.1 项目依赖

<?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.better</groupId><artifactId>spring-ai-parent</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging><modules><module>models/chat/chat-openai-deepseek</module></modules><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.4.5</version><relativePath/></parent><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><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><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.57</version></dependency></dependencies><!--Spring AI模块的依赖版本管理--><dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><!--正式生产版本:1.0.0 GA(2025年5月20日发布)是首个稳定且支持生产环境的版本,ChatClient 成为官方推荐的核心 API--><version>1.0.0</version> <!-- GA 版本 --><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement></project>

3.2 配置yml

server:port: 8321
spring:ai:openai:base-url: https://api.deepseek.comapi-key: ${OPENAI_API_KEY}chat:options:model: deepseek-chat  # 可选模型:deepseek-chat/deepseek-reasonertemperature: 0.6      # 响应随机性控制,默认值

3.3 手动组装上下文消息

package com.better.springai.history;import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** 高级封装ChatClient*/
@RestController
@Slf4j
class MessageWindowChatMemoryController {private final ChatClient chatClient;public MessageWindowChatMemoryController(ChatClient.Builder chatClientBuilder) {this.chatClient = chatClientBuilder.build();}/*** 通过MessageWindowChatMemory记忆存储方式进行对话* return void* @author luchuyan* @time 2025/7/20 19:20**/@GetMapping("/chatWithMessageWindowChatMemory")public void chatWithMessageWindowChatMemory() {// 消息窗口聊天记忆ChatMemory chatMemory = MessageWindowChatMemory.builder().maxMessages(2) // 保存最新对话消息数量.build();// 对话ID,业务上唯一对话标识String conversationId = "001";// 第一次对话UserMessage userMessage1 = new UserMessage("你的名字叫做狗蛋,会讲普通话、潮汕话");chatMemory.add(conversationId, userMessage1);ChatResponse response1 = chatClient.prompt(new Prompt(chatMemory.get(conversationId))).call().chatResponse();chatMemory.add(conversationId, response1.getResult().getOutput());log.info("用户第1次提问:{}",userMessage1.getText());log.info("AI第1次回复:{}",response1.getResult().getOutput().getText());log.info("第1次对话后记忆存储消息:{} \n\n",JSON.toJSONString(chatMemory.get(conversationId)));// 第二次对话UserMessage userMessage2 = new UserMessage("你的名字是什么?仅需回答名字即可,不要输出其他无关内容");chatMemory.add(conversationId, userMessage2);ChatResponse response2 = chatClient.prompt(new Prompt(chatMemory.get(conversationId))).call().chatResponse();chatMemory.add(conversationId, response2.getResult().getOutput());log.info("用户第2次提问:{}",userMessage2.getText());log.info("AI第2次回复:{}",response2.getResult().getOutput().getText());log.info("第2次对话后记忆存储消息:{}\n\n",JSON.toJSONString(chatMemory.get(conversationId)));// 第二次对话UserMessage userMessage3 = new UserMessage("你会讲什么话?");chatMemory.add(conversationId, userMessage3);ChatResponse response3 = chatClient.prompt(new Prompt(chatMemory.get(conversationId))).call().chatResponse();chatMemory.add(conversationId, response3.getResult().getOutput());log.info("用户第3次提问:{}",userMessage3.getText());log.info("AI第3次回复:{}",response3.getResult().getOutput().getText());log.info("第3次对话后记忆存储消息:{}",JSON.toJSONString(chatMemory.get(conversationId)));}}

执行结果:

3.4 ChatMemory自动组装上下文消息

3.4.1 MessageWindowChatMemory

package com.better.springai.history;import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** 高级封装ChatClient*/
@RestController
@Slf4j
class MessageWindowChatMemoryController {private final ChatClient chatClient;public MessageWindowChatMemoryController(ChatClient.Builder chatClientBuilder) {this.chatClient = chatClientBuilder.build();}/*** 通过MessageWindowChatMemory记忆存储方式进行对话* return void* @author luchuyan* @time 2025/7/20 19:20**/@GetMapping("/chatMessageWindowChatMemory")public void chatMessageWindowChatMemory() {// 消息窗口聊天记忆ChatMemory chatMemory = MessageWindowChatMemory.builder().maxMessages(2) // 保存最新对话消息数量.build();// 对话ID,业务上唯一对话标识String conversationId = "001";// 第一次对话UserMessage userMessage1 = new UserMessage("你的名字叫做狗蛋,会讲普通话、潮汕话");chatMemory.add(conversationId, userMessage1);ChatResponse response1 = chatClient.prompt(new Prompt(chatMemory.get(conversationId))).call().chatResponse();chatMemory.add(conversationId, response1.getResult().getOutput());log.info("用户第1次提问:{}",userMessage1.getText());log.info("AI第1次回复:{}",response1.getResult().getOutput().getText());log.info("第1次对话后记忆存储消息:{} \n\n",JSON.toJSONString(chatMemory.get(conversationId)));// 第二次对话UserMessage userMessage2 = new UserMessage("你的名字是什么?仅需回答名字即可,不要输出其他无关内容");chatMemory.add(conversationId, userMessage2);ChatResponse response2 = chatClient.prompt(new Prompt(chatMemory.get(conversationId))).call().chatResponse();chatMemory.add(conversationId, response2.getResult().getOutput());log.info("用户第2次提问:{}",userMessage2.getText());log.info("AI第2次回复:{}",response2.getResult().getOutput().getText());log.info("第2次对话后记忆存储消息:{}\n\n",JSON.toJSONString(chatMemory.get(conversationId)));// 第二次对话UserMessage userMessage3 = new UserMessage("你会讲什么话?");chatMemory.add(conversationId, userMessage3);ChatResponse response3 = chatClient.prompt(new Prompt(chatMemory.get(conversationId))).call().chatResponse();chatMemory.add(conversationId, response3.getResult().getOutput());log.info("用户第3次提问:{}",userMessage3.getText());log.info("AI第3次回复:{}",response3.getResult().getOutput().getText());log.info("第3次对话后记忆存储消息:{}",JSON.toJSONString(chatMemory.get(conversationId)));}}

执行结果:

3.4.2 MessageChatMemoryAdvisor

package com.better.springai.history;import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
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.MessageWindowChatMemory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** 高级封装ChatClient*/
@RestController
@Slf4j
class MessageChatMemoryAdvisorController {private final ChatClient chatClient;private ChatMemory chatMemory;public MessageChatMemoryAdvisorController(ChatClient.Builder chatClientBuilder) {chatMemory = MessageWindowChatMemory.builder().maxMessages(2) // 保留最近的2条消息.build();this.chatClient = chatClientBuilder.clone().defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())  // 通过MessageChatMemoryAdvisor策略进行组装对话消息.build();}@GetMapping("/chatMessageChatMemoryAdvisor")public void chatMessageChatMemoryAdvisor() {// 对话ID,业务上唯一对话标识String conversationId = "002";String question1 = "你的名字叫做狗蛋,会讲普通话、潮汕话";String responseContent1 = chatClient.prompt().user(question1).advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId)).call().content();log.info("用户第1次提问:{}",question1);log.info("AI第1次回复:{}",responseContent1);log.info("第1次对话后记忆存储消息:{} \n\n", JSON.toJSONString(chatMemory.get(conversationId)));String question2 = "你的名字是什么?仅需回答名字即可,不要输出其他无关内容";String responseContent2 = chatClient.prompt().user(question2).advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId)).call().content();log.info("用户第2次提问:{}",question2);log.info("AI第2次回复:{}",responseContent2);log.info("第2次对话后记忆存储消息:{} \n\n",JSON.toJSONString(chatMemory.get(conversationId)));String question3 = "你会讲什么话?";String responseContent3 = chatClient.prompt().user(question3).advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId)).call().content();log.info("用户第3次提问:{}",question3);log.info("AI第3次回复:{}",responseContent3);log.info("第3次对话后记忆存储消息:{} \n\n",JSON.toJSONString(chatMemory.get(conversationId)));}}

3.4.3 PromptChatMemoryAdvisor

和上面MessageChatMemoryAdvisor代码仅defaultAdvisors 处配置的不一样

    public PromptChatMemoryAdvisorController(ChatClient.Builder chatClientBuilder) {chatMemory = MessageWindowChatMemory.builder().maxMessages(2) // 保留最近的2条消息.build();this.chatClient = chatClientBuilder.clone()
//                .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())  // 通过MessageChatMemoryAdvisor策略进行组装对话消息.defaultAdvisors(PromptChatMemoryAdvisor.builder(chatMemory).build())  // 通过PromptChatMemoryAdvisor策略进行组装对话消息.build();}

完整代码:

package com.better.springai.history;import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.PromptChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** 高级封装ChatClient*/
@RestController
@Slf4j
class PromptChatMemoryAdvisorController {private final ChatClient chatClient;private ChatMemory chatMemory;public PromptChatMemoryAdvisorController(ChatClient.Builder chatClientBuilder) {chatMemory = MessageWindowChatMemory.builder().maxMessages(2) // 保留最近的2条消息.build();this.chatClient = chatClientBuilder.clone()
//                .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())  // 通过MessageChatMemoryAdvisor策略进行组装对话消息.defaultAdvisors(PromptChatMemoryAdvisor.builder(chatMemory).build())  // 通过PromptChatMemoryAdvisor策略进行组装对话消息.build();}@GetMapping("/chatPromptChatMemoryAdvisor")public void chatPromptChatMemoryAdvisor() {// 对话ID,业务上唯一对话标识String conversationId = "002";String question1 = "你的名字叫做狗蛋,会讲普通话、潮汕话";String responseContent1 = chatClient.prompt().user(question1).advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId)).call().content();log.info("用户第1次提问:{}",question1);log.info("AI第1次回复:{}",responseContent1);log.info("第1次对话后记忆存储消息:{} \n\n", JSON.toJSONString(chatMemory.get(conversationId)));String question2 = "你的名字是什么?仅需回答名字即可,不要输出其他无关内容";String responseContent2 = chatClient.prompt().user(question2).advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId)).call().content();log.info("用户第2次提问:{}",question2);log.info("AI第2次回复:{}",responseContent2);log.info("第2次对话后记忆存储消息:{} \n\n",JSON.toJSONString(chatMemory.get(conversationId)));String question3 = "你会讲什么话?";String responseContent3 = chatClient.prompt().user(question3).advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId)).call().content();log.info("用户第3次提问:{}",question3);log.info("AI第3次回复:{}",responseContent3);log.info("第3次对话后记忆存储消息:{} \n\n",JSON.toJSONString(chatMemory.get(conversationId)));}}

四、参考资料

4.1 Spring AI官网文档

  • Chat Memory :: Spring AI Reference
  • Chat Client API :: Spring AI Reference

最后:如果文章对你有帮助,别忘了点赞支持一下,谢谢~

http://www.dtcms.com/a/400399.html

相关文章:

  • 网站怎么做二维码链接地址建筑网站建设需要注意哪些
  • 如何把怎己做的网页放到网站上开放平台模式
  • 建设项目网站wordpress还有价值么
  • 网站开发 php python公司建立网站的好处
  • 新手制作网站工具删除wordpress.org
  • 网站备案 公司wordpress注册开启邮件验证
  • 5分钟快速校准!Franka Research 3机械臂解锁科研新速度
  • 【java实现用户编辑上传图片功能】
  • 工业设计灵感网站黄石建设工程信息网
  • 职教集团网站建设方案网页编辑pdf
  • 做创意ppt网站湖南百度推广开户
  • 深圳网站建站建设公司地址美化wordpress后台
  • 网站建设的总体设计自媒体怎么注册
  • 成都市微信网站建电子商务平台网站建设方式
  • 网站浏览器图标怎么做外包活一般是怎么接的
  • 使用DLLM框架对Dream 7B模型在S1K数据集上进行有监督微调
  • linux下gcc升级
  • 卓越职业院校建设专题网站舆情管理
  • 网站建设公司擅自关闭客户网络建立网站定制
  • Python实现手榴弹爆炸算法(Grenade Explosion Method, GEM)(附完整代码)
  • 做wap网站django网站开发规范
  • 百度云网站建设视频甘肃兴城建设有限公司网站
  • 动态分配的UDP_TEST_EQUIPMENT_REQUEST端口
  • todesk远程时出现提示“正在等待对方手动授权”,需要关掉什么设置
  • 深圳网站建设公司佰达网站广告连接如何做
  • 给网站定位提供定制型网站建设
  • 01-基于FPGA和LTC2308的数字电压表设计(总概述)
  • 永川集团网站建设广州正规网站建设
  • 深入理解布隆过滤器
  • 为什么用asp做网站东阳网站建设