---
title: "chat - 聊天会话（对话）的记忆与持久化"
---

大语言模型的接口是无状态的服务，如果需要形成有记忆的会话窗口。需要使用“多消息”提示语，把历史对话都输入。


### 1、使用“聊天会话”接口（ChatSession）

ChatSession 可以记录消息，还可以作为提示语的参数使用（直接输给 chatModel 的提示语，先输给 chatSession）。起到会话记忆的作用。

```java
public void case3() throws IOException {
    //聊天会话
    ChatSession chatSession = InMemoryChatSession.builder()
             .maxMessages(10)
             .sessionId("session-1") //安排个会话id
             .build(); 
    
    
    //1.同步请求
    chatModel.prompt("hello")
             .session(chatSession) // 输入或输出的消息，自动记录到会话里（并从中获取历史消息）
             .options(o -> {
                o.systemPrompt("你是个美女客服，声音甜美。");
             })
             .call();  
   
    
    //2.流式请求
    chatModel.prompt("Who are you?")
            .session(chatSession) // 输入或输出的消息，自动记录到会话里（并从中获取历史消息）
            .stream(); 
}
```

### 2、ChatSession 内置实现对比



| 实现类 | 存储介质 | 适用场景 | 备注 |
| -------- | -------- | -------- |  -------- |
| InMemoryChatSession     | 本地内存 (Map)     | 单机开发、单元测试、低频演示     |  临时性记忆，进程重启后数据即刻丢失     |
| FileChatSession     | 本地 File     | 本地客户端、CLI 智能体、单机工具     |  持久化到磁盘，程序关闭后记忆依然有效     |
| RedisChatSession     | Redis 数据库     | 分布式环境、生产环境、高并发     |  多节点共享，确保分布式部署时记忆一致     |


生成情况复杂，可能需要进一步定制（可复制它们进行修改定制）


### 3、基于 Web 的聊天会话记忆参考

```java
import org.noear.solon.ai.chat.ChatModel;
import org.noear.solon.ai.chat.ChatSession;
import org.noear.solon.ai.chat.message.ChatMessage;
import org.noear.solon.ai.chat.session.InMemoryChatSession;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Header;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.web.sse.SseEvent;
import reactor.core.publisher.Flux;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Controller
public class DemoController {
    @Inject
    ChatModel chatModel;

    final Map<String, ChatSession> sessionMap = new ConcurrentHashMap<>();

    //手动转为 sse
    @Mapping("case3")
    public Flux<SseEvent> case3(@Header("sessionId") String sessionId, String prompt) throws IOException {
        ChatSession chatSession = sessionMap.computeIfAbsent(sessionId, 
                k ->  InMemoryChatSession.builder().sessionId(k).build());

        //注意：chatSession
        return chatModel.prompt(prompt)
                    .session(chatSession)
                    .options(o -> {
                        o.systemPrompt("你是个美女客服，声音甜美。");
                     })
                    .stream()
                    .filter(resp -> resp.hasContent())
                    .map(resp -> new SseEvent().data(resp.getContent()));
    }
}
```


### 4、ChatMessage （消息）的序列化方法（可协助定制）



| 接口          | 描述         | 
| -------- | -------- | 
| `ChatMessage.toJson(message)`     | 把单条消息转为 json     | 
| `ChatMessage.fromJson(json)`     | 把 json 转为单条消息     | 
| `ChatMessage.toNdjson(messages)`     | 把一批消息转为 ndjson     | 
| `ChatMessage.fromNdjson(ndjson)`     | 把 ndjson 转为一批消息     | 


以上方法 v3.8.0 后支持。v3.8.0 前的可以 copy 里面的代码。



### 5、ChatSession 的接口字典（参考）

```java
package org.noear.solon.ai.chat;

import org.noear.solon.ai.chat.message.ChatMessage;
import org.noear.solon.ai.chat.prompt.Prompt;
import org.noear.solon.lang.NonNull;
import org.noear.solon.lang.NonSerializable;
import org.noear.solon.lang.Preview;

import java.io.*;
import java.util.*;
import java.util.function.Consumer;

/**
 * 聊天会话接口
 *
 * <p>用于管理对话过程中的消息序列。设计上支持易持久化特性，
 * 是构建聊天机器人或 AI 交互应用的基础存储单元。</p>
 */
public interface ChatSession extends NonSerializable {
    static String ATTR_SESSIONID = "__sessionId";

    /**
     * 获取会话id
     */
    String getSessionId();

    /**
     * 获取消息
     */
    List<ChatMessage> getMessages();

    /**
     * 获取最近消息
     *
     * @param windowSize 窗口大小
     */
    List<ChatMessage> getLatestMessages(int windowSize);

    /**
     * 移除最近消息
     *
     * @param windowSize 窗口大小
     */
    void removeLatestMessage(int windowSize);

    /**
     * 添加消息
     */
    default void addMessage(String userMessage) {
        addMessage(ChatMessage.ofUser(userMessage));
    }

    /**
     * 添加消息
     */
    default void addMessage(ChatMessage... messages) {
        addMessage(Arrays.asList(messages));
    }

    /**
     * 添加消息
     */
    default void addMessage(Prompt prompt) {
        addMessage(prompt.getMessages());
    }

    /**
     * 添加消息
     */
    void addMessage(Collection<? extends ChatMessage> messages);

    /**
     * 是否为空
     */
    boolean isEmpty();

    /**
     * 清空消息
     */
    void clear();


    /// //////////////////////////////////////

    /**
     * 临时属性（不需要持久化）
     */
    @NonNull
    Map<String, Object> attrs();
}
```



