langchian4j---会话功能

5 阅读2分钟

1. 核心抽象:ChatMemory 接口

在 LangChain4j 中,记忆系统的核心接口是 ChatMemory。它的职责非常纯粹:维护对话历史的顺序,并根据策略进行截断。

1.1 两种主流实现(短期记忆的落地)

正如你笔记中提到的“滑动窗口”策略,LangChain4j 直接提供了现成的类:

  • MessageWindowChatMemory(按消息数量滑动):

    保留最近的 NN 条消息。比如设置 N=10N=10,那么第 11 条消息进来时,第 1 条就会被丢弃。

  • TokenWindowChatMemory(按 Token 数量滑动):

    这是最推荐的方式。它会根据指定的 Tokenizer(分词器)计算历史记录的总 Token 数。如果超过限制(如 2000 Tokens),它会逐条删除最早的消息,直到余下的内容符合长度限制。


2. 记忆的持久化:ChatMemoryStore

默认情况下,ChatMemory 是存储在内存里的(InMemoryChatMemoryStore)。这在生产环境下显然不够,因为服务器重启记忆就丢了。

ChatMemoryStore 就是为了解决这个问题。它是一个简单的接口,你只需要实现 getMessages(Object memoryId)updateMessages(Object memoryId, List<ChatMessage> messages) 两个方法,就可以把记忆对接到:

  • Redis: 适合高性能、高频次的短期记忆。
  • JDBC (MySQL/PostgreSQL): 适合需要持久化存储的场景。
  • MongoDB: 适合存储非结构化的对话数据。

面试加分点: LangChain4j 允许通过 memoryId 来区分不同用户或不同会话。在你的代码逻辑里,这个 memoryId 通常就是 userId


3. 实战代码实现

我们可以通过 LangChain4j 的 AiServices 快速集成记忆功能。以下是一个结合了 Token 滑动窗口自定义存储 的标准实现:


4. 如何融入你的“长期记忆(主动录入)”设计?

LangChain4j 的 ChatMemory 主要解决的是对话连贯性(短期) 。对于你提到的长期记忆(主动录入+向量检索) ,在 LangChain4j 中是通过 ContentRetriever (RAG) 来实现的。

联合运作流程:

  1. 用户输入: “帮我写一段 Java 代码”。
  2. 长期记忆检索: 系统通过 ContentRetriever 到向量数据库里搜一下用户的“个人标签”。
  3. 命中: 搜到“用户是 Java 后端开发,偏好 Spring Boot”。
  4. 注入: 将这段信息作为 SystemMessage 注入。
  5. 短期记忆拼接: ChatMemory 自动把最近 5 轮对话记录拼在后面。
  6. 发送给 LLM: 最终的 Prompt 包含了:系统指令(长期记忆) + 历史对话(短期记忆) + 当前问题

5. 总结与建议

LangChain4j 的设计非常符合 “高内聚、低耦合” 的原则。

  • 如果你追求简单稳定,直接用 MessageWindowChatMemory
  • 如果你追求成本精控,一定要用 TokenWindowChatMemory
  • 如果你需要多端同步,必须实现 ChatMemoryStore 对接到 Redis。