ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AgentScope 学习系列 - 03:让大模型拥有记忆,多用户多会话隔离

AgentScope 学习系列 - 03:让大模型拥有记忆,多用户多会话隔离 和大模型的调用是无记忆的大模型不知道我们上一次让它做了什么。那么本文就讲一下如何让大模型感知到之前的对话记忆。本节开始之前先探讨个问题如果张三和李四同时用一个智能体对话他们的记忆会不会混乱呢如果张三开了两个对话那么它的身份信息是否可以共享呢所以我们先看看AgentScope是如何管理多用户和多对话的ReActAgent在调用之间是无状态的——同一个 agent 实例可以同时服务多个用户和会话。每次call()通过RuntimeContext携带的(userId, sessionId)来定位该次调用应该使用哪份对话状态互不干扰。我们来看一下代码怎么写有小伙伴反馈说我总是粘代码水字数重复的代码块创建model和ReActAgent的我后面就不重复粘了需要的小伙伴可以去看源码。我直接贴关键实现的方法。1. 默认单次会话全局共享privatestaticvoidnoStatus(ReActAgentagent){System.out.println(--------------用户第一次对话);Msgreplyagent.call(newUserMessage(我是笑小枫的小伙伴张三三你可以记住我吗)).block();System.out.println(--------------大模型第一次回复reply.getTextContent());System.out.println(--------------用户第二次对话);MsgreplyTwoagent.call(newUserMessage(我是谁呀)).block();System.out.println(--------------大模型第二次回复replyTwo.getTextContent());}仔细看的小伙伴可能有疑问了这不是有记忆了吗那么问题来了同一个智能体如果你是谁是李四问的它也只知道张三三。这时候的记忆是共享在内存里的所有人都是同一个记忆。我们注释掉第一次对话再来执行一次可以看到它已经不知道我是谁了。那么我们应该怎么给它加用户隔离保存上下文的记忆呢我们可以使用stateStore进行状态保存。让我们一起看看怎么用吧。2. 用户会话隔离为了我们方便查看在创建模型时可以指定记忆的保存位置和格式.stateStore(new JsonFileAgentStateStore(Paths.get(.agentscope/sessions)))。ReActAgentstateAgentReActAgent.builder().name(笑小枫的学习助手).sysPrompt(你是笑小枫的学习助手可以帮助用户快速学习使用AgentScope开发智能体。).model(model).stateStore(newJsonFileAgentStateStore(Paths.get(.agentscope/sessions))).build();然后我们开始创建测试代码。细心的小伙伴可能发现了agent.call传入了的是List了不再是单个消息了因为要传递历史的聊天数据所以要用List。privatestaticvoidstate(ReActAgentagent){// userId zhangsansessionId session-1System.out.println(--------------张三第一次对话);Msgreplyagent.call(List.of(newUserMessage(我是笑小枫的小伙伴张三三你可以记住我吗)),RuntimeContext.builder().userId(zhangsan).sessionId(session-1).build()).block();System.out.println(--------------大模型第一次回复张三reply.getTextContent());// userId zhangsansessionId session-1System.out.println(--------------张三第二次对话);MsgreplyTwoagent.call(List.of(newUserMessage(我是谁呀)),RuntimeContext.builder().userId(zhangsan).sessionId(session-1).build()).block();System.out.println(--------------大模型第二次回复张三replyTwo.getTextContent());// userId zhangsansessionId session-2System.out.println(--------------张三第三次对话);MsgreplyThreeagent.call(List.of(newUserMessage(我是谁呀)),RuntimeContext.builder().userId(zhangsan).sessionId(session-2).build()).block();System.out.println(--------------大模型第三次回复张三replyThree.getTextContent());// userId lisisessionId session-1System.out.println(--------------李四第一次对话);MsgreplyLisiagent.call(List.of(newUserMessage(我是谁呀)),RuntimeContext.builder().userId(lisi).sessionId(session-1).build()).block();System.out.println(--------------大模型第二次回复李四replyLisi.getTextContent());}通过截图可以清晰的看到数据已经隔离了。我们只保留第二次会话通过截图仍可以看出大模型还存在记忆。在.agentscope/sessions下可以清晰的看到我们保存记忆的文件层级。3. AgentState保存位置上面演示了演示了讲上下文信息以json的格式保存在指定的目录下除此之外我们还能保存在什么地方只要实现io.agentscope.core.state.AgentStateStore接口,任何后端都能接进来。选择哪一种,取决于你的部署形态:实现模块适用场景InMemoryAgentStateStoreagentscope-core单元测试 / 单进程演示;进程退出全部丢失JsonFileAgentStateStoreagentscope-core单机开发、文件落盘即可恢复;不能跨节点共享。HarnessAgent默认值,落在~/.agentscope/state/agentId/(可通过agentscope.state.home系统属性改根目录);单机RedisAgentStateStoreagentscope-extensions-redis生产首选,多副本共享;支持 Jedis / Lettuce / Redisson(Standalone / Cluster / Sentinel)MysqlAgentStateStoreagentscope-extensions-mysql需要把状态沉淀进关系型库(审计、报表)时使用这里就不一一演示了后面实战时再演示放在其它位置。4. 常见问题4.1 无需记忆如果我们的智能体不需要记忆怎么办呢把stateStore设置为InMemoryAgentStateStore即可。什么场景下会出现不需要记忆的场景呢例如后面直接使用平台的编排功能快速创建一个对话翻译的智能体。这个智能体就不需要记忆说白了就是直接调用大模型。4.2 上下文压缩关于上下文压缩可以通过Middleware去拓展当然HarnessAgent已经天然封装这个能力这里就不展开讲了后面放到HarnessAgent统一介绍。5.文章小结到这里关于 AgentScope 的记忆管理就聊得差不多了。简单回顾一下本文的核心ReActAgent本身是无状态的同一个实例可以同时服务多个用户和会话状态隔离靠的是每次调用传入的RuntimeContext。(userId, sessionId)是记忆的定位坐标userId 决定这是谁的记忆sessionId 决定这是哪场对话的记忆。两者组合才能实现真正的多用户、多会话隔离。记忆存哪由stateStore决定单机开发用JsonFileAgentStateStore落盘即可生产环境推荐RedisAgentStateStore实现多副本共享需要审计报表就上MysqlAgentStateStore。本系列源码https://gitee.com/hack-feng/maple-agent-demo
返回列表