SpringAi-memory

1.基于memory对话记忆

SpringAI 基于 ChatMemory 实现对话的记忆,也就是上下⽂内容的存储、发送请求时候附带。 ChatMemory 表示聊天对话记忆的存储,它提供添加消息到对话、从对话中检索消息以及清除对话历 史的⽅法。

java 复制代码
public interface ChatMemory {
    default void add(String conversationId, Message message) {
        this.add(conversationId, List.of(message));
   }
 // 添加消息到记忆
    void add(String conversationId, List<Message> messages);
 // 获取对话历史
    List<Message> get(String conversationId, int lastN);
 // 清除对话记忆
    void clear(String conversationId);
}

Spring AI 提供了 ChatMemory 的实例⽤于存储聊天上下⽂,默认使⽤内存的⽅式进⾏实现,将对 话直接存储在内存中。

2.什么是会话 ID

SpringAI 中, conversationId 是⽤于标识和隔离不同对话会话的核⼼参数,通过该 ID 实现对 话上下⽂的持久化与连续性管理。它有如下的⼀些核⼼作⽤:

  • 会话隔离:为每个对话分配唯⼀ ID ,确保不同会话的数据独⽴存储和读取。
  • 上下⽂持久化:通过 ChatMemoryRepository 接⼝,将过滤后的消息(如⽤户输⼊、 AI 回 复)按 conversationId 存储,⽀持本地内存或 JDBC 数据库等存储⽅式。

3.具体实现(基于内存)

3.1. 书写 ChatMemoryConfig 配置类

java 复制代码
@Configuration
public class ChatMemoryConfig {
    @Bean("inMemoryChatMemory")
    public ChatMemory chatMemory() {
        return MessageWindowChatMemory.builder()
               .chatMemoryRepository(new 
InMemoryChatMemoryRepository()) // 对话记忆默认使⽤内存⽅式
               .maxMessages(3) // 保存最近的三条历史记录
               .build();
   }
}

注意: 其实内存⽅式就是默认的⽅式,如果不⾃定义 ChatMemory 对象,默认的 ChatMemory 对象已经实现了内存记忆功能。 保存的历史记录⾄少三条,因为会保存多个⻆⾊信息。

3.2修改ChatClientConfig控制类

java 复制代码
@Bean("openAiChatClient")
    public ChatClient openAiChatClient(OpenAiChatModel openAiChatModel){
        return ChatClient.builder(openAiChatModel).build();
    } 
@Bean("openAiChatClient2")
    public ChatClient openAiChatClient2(OpenAiChatModel openAiChatModel){
        return ChatClient.builder(openAiChatModel)
                //引入chatMemory in
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(inMemoryChatMemory).build())
                .build();
    }

3.3控制层类

分别为入门版、提升版以及手撕版

java 复制代码
//入门版写法
    @GetMapping(value = "/stream",produces = "text/html;charset=utf-8")
    public Flux<String> stream(@RequestParam("question") String question){
        history+=question+"/n";
        return openAiChatClient.prompt()
                .user(history)
                .stream().content();
    }
    //提升版
    @GetMapping(value = "/history1",produces = "text/html;charset=utf-8")
    public Flux<String> history1(@RequestParam("question") String question){
        return openAiChatClient2.prompt()
                .user(question)
                .stream().content();
    }
    //手撕版
    @GetMapping(value = "/history2",produces = "text/html;charset=utf-8")
    public String history2(@RequestParam("question") String question,@RequestParam("id") String id){
        //1.获取到原来的消息
        List<Message> historyMessages=chatMemory.get(id);
        log.info("历史记录:{}",historyMessages);
        if (historyMessages==null || historyMessages.size()==0){
            historyMessages =new ArrayList<>();
        }
        //2.将当用户的消息组装后存放到历史中
        Message userMessage=new UserMessage(question);
        historyMessages.add(userMessage);
        chatMemory.add(id,historyMessages);
        //3.获取到大模型的回答
        Prompt prompt=new Prompt(historyMessages);
        String result=openAiChatClient.prompt(prompt).call().content();
        Message assistantMessage = new AssistantMessage(result);
        //4.将大模型回答的消息存放到历史记录中
        historyMessages.add(assistantMessage);
        chatMemory.add(id,historyMessages);
        //5.返回结果
        return result;
    }

4.基于JDBC实现

4.1引入依赖

XML 复制代码
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>

4.2修改yml文件

XML 复制代码
spring:
    ai:
       chat:
          memory:
            repository:
              jdbc:
                initialize-schema: always(第二次运行需修改为never)
                schema: classpath:schema-mysql.sql
  datasource:
    password: 123456
    username: root
    url: jdbc:mysql://localhost:3306/sys
    driver-class-name: com.mysql.cj.jdbc.Driver

4.3在resources目录下新建schema-mysql.sql

sql 复制代码
CREATE TABLE IF NOT EXISTS SPRING_AI_CHAT_MEMORY
(
    conversation_id VARCHAR(36) NOT NULL,
    content         TEXT        NOT NULL,
    type            VARCHAR(10) NOT NULL,
    `timestamp`     TIMESTAMP   NOT NULL,
    CONSTRAINT TYPE_CHECK CHECK (type IN ('USER', 'ASSISTANT', 'SYSTEM', 'TOOL'))
    );

会在yml文件所写的数据库中新建SPRING_AI_CHAT_MEMORY表,会将对话记录存到该表中

4.4写ChatMemoryConfig类

java 复制代码
@Bean("jdbcMemoryChatMemory")
    public ChatMemory jdbcChatMemory(JdbcChatMemoryRepository jdbcChatMemoryRepository) {
        return MessageWindowChatMemory.builder()
                .chatMemoryRepository(jdbcChatMemoryRepository)
                .build();
    }

4.5写ChatClientConfig类

java 复制代码
@Bean("openAiChatClient3")
    public ChatClient openAiChatClient3(OpenAiChatModel openAiChatModel) {
        return ChatClient.builder(openAiChatModel)
                // 引入chatMemory  jdbc
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(jdbcMemoryChatMemory).build())
                .build();
    }

4.6写controller类

java 复制代码
@GetMapping(value = "/history3", produces = "text/html;charset=utf-8")
    public Flux<String> history3(@RequestParam("question") String question, @RequestParam("id") String id) {
        return openAiChatClient3.prompt()
                .advisors(a -> a.param("chat_memory_conversation_id", id))
                .user(question)
                .stream().content();
    }

4.7编写启动类

java 复制代码
package com.jiazhong.mingxing.ai.siliconflow.memory.glm;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AiSiliconflowMemoryGlmApplication {
    public static void main(String[] args) {
        SpringApplication.run(AiSiliconflowMemoryGlmApplication.class);
    }
}

启动后在浏览器中写入具体路径即可实现。

相关推荐
阿里云大数据AI技术5 分钟前
阿里云 EMR Serverless StarRocks(Stella 2.2.0) 发布:内表与湖表同时支持向量、全文与 AI Function,一条 SQL 完成多模态检索
人工智能
格林威6 分钟前
工业相机Chunk功能全解析:图像嵌入时间戳、编码器元数据(附堡盟C#代码)
开发语言·人工智能·数码相机·计算机视觉·c#·视觉检测·工业相机
怪奇云呼军10 分钟前
闪电智能Voice Agent:ASR 首字延迟和最终识别延迟怎么测?t0-t3 埋点实战
人工智能·科技·ai·语音识别
冬哥聊AI17 分钟前
百万行代码里跑Claude Code?三面这题80%的人答不上来
人工智能
甄同学18 分钟前
第二十三篇:Tasks系统,Claude Code如何统一管理7种后台任务
人工智能
独隅19 分钟前
IntelliJ IDEA 接入多种AI大模型插件终极指南(2026.1 企业合规版)
java·人工智能·intellij-idea
有Li23 分钟前
EvoMDT:用于多癌种结构化临床决策的自进化多智能体系统文献速递/医学智能体前沿
人工智能·学习·分类·文献·医学生
小刘BlandNew34 分钟前
AI核心概念大串联
人工智能
墨染天姬37 分钟前
【AI】自驱动智能体
人工智能
D2aZXN3FhrDa7e2121 小时前
佛山乐从低预算实体店如何选择?看美诚AI自动化获客方案
运维·人工智能·自动化·佛山美诚科技有限公司