用 LangChain4j 轻松搞定多用户记忆隔离

👉一键直达《JavaAI应用开发实战》知识库

👉一键获取《JavaAI应用开发实战》代码仓库

👉一键获取访问密码

当前以下视频系列课程正持续更新中:

💡 为什么值得订阅?

所有资料均由小编精心整理,保证代码可运行、可调试,省去你东拼西凑的时间成本,专注核心技能提升。

各位同学,大家好!上节课咱们给 AI 加上了“记忆”——比如你告诉它:“你叫小编”,它就真的记住了,下次聊天还能喊你“小编”。是不是觉得挺酷?

来,咱们想象一个场景:

你的 AI 客服同时接待两位用户——张三和李四。
张三说:“我叫张三,订单号是 123。”
紧接着,李四问:“我叫什么?我的订单呢?”
结果 AI 一脸认真地回答:“你叫张三,订单号 123。”

……是不是瞬间冷汗直流?!

这可不是小 bug,这是用户数据串台!轻则体验崩坏,重则隐私泄露、法律风险!所以,真正的生产级 AI 应用,必须做到:一人一套记忆,互不干扰!

那问题来了:怎么实现?自己手写 Map 套 Map?加锁?分布式缓存?别急——LangChain4j 已经帮你想好了,一行注解 + 几行配置,直接搞定!

今天这节课,咱们就手把手,从“翻车现场”到“稳如老狗”,彻底掌握 多用户记忆隔离 的实战方案!


【理论:为什么记忆会“串台”?核心思路是什么?】

首先,咱们得搞清楚:为什么上节课的记忆会串?

很简单——因为咱们用的是全局共享的记忆池!所有用户的对话都塞进同一个地方,AI 取的时候根本不分你是谁、他是谁,自然就乱套了。

就像你去银行办业务,结果柜员拿着隔壁老王的存折给你算账……这能行吗?

所以,解决思路非常直白:给每个用户发一个专属“小账本”

  • 张三说话 → 记在张三的本子上
  • 李四提问 → 只看李四的本子
  • 谁也别碰谁的,清清楚楚!

这个“小账本”的钥匙,就是我们今天要讲的 MemoryId(记忆 ID)。它可以是:

  • 用户的唯一 ID(比如 user_id = 1001)
  • 或者一次会话的 session_id(比如 UUID)

只要这个 ID 能唯一区分用户或会话,就行!

而 LangChain4j 给咱们提供了一个超级好用的机制:@MemoryId 注解 + ChatMemoryProvider,自动根据 ID 创建、查找、更新对应的“小账本”。

底层其实就是一个 Map> ——

  • Key 是用户 ID
  • Value 是这个用户的对话历史(不是字符串,而是带角色、内容、时间戳的 Message 对象)

【实战:手把手写代码】

好,理论懂了,现在咱们动手写代码!目标:实现一个接口,不同用户问“我是谁”,AI 能正确回答各自的名字。

第一步:定义 AI 助手接口

咱们先定义一个接口,叫 AssistantUnique,里面放两个方法:

// 定义支持多用户隔离的 AI 助手接口
public interface AssistantUnique {

    // 普通聊天方法
    String chat(
        @MemoryId int memoryId,      // ← 关键!用这个 ID 区分用户
        @UserMessage String userMessage  // 用户说的话
    );

    // 流式响应(用于实时打字效果)
    TokenStream stream(
        @MemoryId int memoryId,
        @UserMessage String userMessage
    );
}

重点来了:

  • @MemoryId:标记哪个参数是“记忆 ID”
  • @UserMessage:标记用户输入的内容

这两个注解,就是 LangChain4j 的“眼睛”,让它知道怎么拆解你的参数。

你可能会想:为啥用 int?能不能用 String?当然可以!比如传用户的 UUID 字符串更安全。这里用 int 只是为了演示方便。


第二步:注册 Bean,配置记忆提供者

接下来,在 Spring Boot 里把这个接口变成一个可用的 Bean。咱们写在一个配置类里,比如 AiConfig.java

@Bean
public AssistantUnique assistantUnique(
    ChatModel qwenChatModel, 
    StreamingChatModel qwenStreamingChatModel
) {
    return AiServices.builder(AssistantUnique.class)
        .chatModel(qwenChatModel)              // 普通聊天模型
        .streamingChatModel(qwenStreamingChatModel) // 流式模型
        .chatMemoryProvider(memoryId -> 
            MessageWindowChatMemory.builder()
                .maxMessages(10)   // ← 最多记 10 条,防内存爆炸!
                .id(memoryId)      // ← 绑定当前用户的 ID
                .build()
        )
        .build();
}

敲黑板!这里最关键的是 .chatMemoryProvider(...) 这一段:

  • 它是一个函数:输入 memoryId,输出一个专属的 ChatMemory
  • 每次调用 chat() 时,LangChain4j 会自动:
    1. 拿到你传的 memoryId
    2. 调这个函数,拿到对应用户的“小账本”
    3. 把历史消息 + 新消息拼成完整上下文,喂给大模型
    4. 把新对话再存回去

而且用的是 MessageWindowChatMemory —— 它会自动只保留最近 N 条消息(这里是 10 条),避免对话太长把内存撑爆。这在生产环境里极其重要

小贴士:你用的模型不限于通义千问!换成 OpenAI、文心一言、讯飞星火都行,LangChain4j 都封装好了,接口通用。


第三步:写个测试接口,验证效果

现在,咱们写个简单的 HTTP 接口来测试:

@RestController
@RequestMapping("/ai")
public class AiController {

    @Autowired
    private AssistantUnique assistantUnique; // 注入我们配好的助手

    @GetMapping("/memory_chat")
    public String memoryChat(
        @RequestParam(defaultValue = "我是谁") String message,
        @RequestParam Integer userId  // ← 用 userId 当 memoryId
    ) {
        return assistantUnique.chat(userId, message);
    }
}

启动服务后,咱们用浏览器或 Postman 来测试三轮:

✅ 测试 1:用户 1 告诉 AI 自己叫“小编”
GET /ai/memoryId_chat?message=我叫小编&userId=1

→ AI 回:“好的,我知道了!”

(此时,userId=1 的“小账本”里记下了这条)

❌ 测试 2:用户 2 问“我叫什么?”
GET /ai/memoryId_chat?message=我叫什么&userId=2

→ AI 回:“抱歉,我不知道您的名字,因为我没有之前的聊天记录。”

(完美!没串台!userId=2 的账本是空的)

✅ 测试 3:用户 1 再问“我叫什么?”
GET /ai/memoryId_chat?message=我叫什么&userId=1

→ AI 回:“您刚才告诉我您叫小编!”

(精准命中!说明记忆隔离成功!)


【收尾:本节课的核心收获】

好,咱们来总结一下,今天你真正掌握了什么:

  1. 为什么必须做记忆隔离?
    → 防止用户数据串台,避免隐私泄露,这是生产系统的底线!
  2. 核心思路是什么?
    → 给每个用户/会话分配唯一 MemoryId,实现“一人一本小账本”。
  3. LangChain4j 怎么帮你?
    → 用 @MemoryId 注解 + chatMemoryProvider,自动管理隔离记忆。
  4. 生产环境要注意什么?
    → 用 MessageWindowChatMemory 限制消息数量(比如 maxMessages=10),防止内存溢出!
  5. 底层原理是什么?
    → 本质是 Map<MemoryId, List<Message>>,通过 ID 精准读写,绝不混淆。

最后留个思考题:
现在记忆是存在内存里的,如果服务重启,所有“小账本”就丢了。
那怎么把记忆存到 Redis 或数据库里,做到“断电不丢”?

别急,下节课咱们就讲 《聊天记忆持久化:让 AI 真正“不忘事”》

今天的课就到这里,记得动手敲一遍代码,跑通测试!有问题随时留言,咱们下节课见!👋

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小编码上说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值