ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

HelloAgents 赛博小镇 NPC 记忆系统实战:工作记忆与情景记忆的完整实现

HelloAgents 赛博小镇 NPC 记忆系统实战:工作记忆与情景记忆的完整实现 HelloAgents 赛博小镇 NPC 记忆系统实战工作记忆与情景记忆的完整实现【免费下载链接】hello-agents 《从零开始构建智能体》——从零开始的智能体原理与实践教程项目地址: https://gitcode.com/datawhalechina/hello-agents在 Datawhale《从零开始构建智能体》第 15 章配套案例赛博小镇Helloagents-AI-Town中NPC 不再是一问一答的无状态机器人而是拥有记忆系统的 AI 角色——它们能记住与玩家的对话历史在后续对话中主动引用此前聊过的内容甚至跨天记得玩家说过的话。本文以 MEMORY_SYSTEM_GUIDE.md 为主体结合 backend 源码 从架构、存储、检索、配置与调试五个层面完整拆解这套基于 HelloAgents 框架MemoryManager的双层记忆系统。读完本文你将掌握工作记忆与情景记忆的配置方法、记忆检索与增强提示词的实现原理以及如何通过 FastAPI 接口和 Godot 游戏端验证记忆效果。系统概述为什么 NPC 需要记忆在传统多智能体对话系统中每次用户消息都会被独立处理模型没有此前说过什么的概念。这导致两个问题一是连续对话中玩家重复提问时 NPC 无法察觉二是跨会话的长期关系无法建立。赛博小镇的记忆系统通过引入 HelloAgents 框架的MemoryManager组件为每位 NPC 配备独立的记忆管理器实现了对话上下文的连续性与个性化。该系统的运行载体是后端NPCAgentManager它管理着 3 位 NPC——张三Python 工程师、李四产品经理、王五UI 设计师。每位 NPC 都挂载一个独立的MemoryManager实例对话流程在 agents.py 的chat方法中完成检索记忆 → 构建增强提示词 → 调用 Agent 生成回复 → 保存对话到记忆的完整闭环。三大核心功能1. 工作记忆Working Memory—— 短期记忆工作记忆负责承载当前对话上下文的近期内容特性如下存储最近的10 条对话working_memory_capacity10约2 小时后自动过期基于 TTL 机制检索极快直接用于当前对话上下文拼接。它在架构上对应enable_workingTrue开关由 agents.py 中的MemoryManager初始化参数控制。2. 情景记忆Episodic Memory—— 长期记忆情景记忆用于跨会话持久化重要对话持久化存储重要对话内容支持语义检索文档中描述了基于 Qdrant 向量数据库的设计在对话型场景中通过语义相关性召回历史从当前仓库的 memory_data 目录 看实际落地以 SQLite 数据库memory.db为权威存储每位 NPC 一个独立数据库文件最多存储100 条记忆max_capacity100自动遗忘重要性低于 0.3的记忆importance_threshold0.3。对应源码开关为enable_episodicTrue同时enable_semanticFalse、enable_perceptualFalse即当前场景仅启用短期与长期两层记忆语义记忆与感知记忆按需扩展。3. 记忆隔离每位 NPC 拥有独立的记忆管理器memories: Dict[str, MemoryManager]user_id直接取 NPC 名字因此NPC 之间的记忆互不干扰——与李四对话时它完全不知道张三那边聊了什么每位玩家的对话按player_id独立存储多玩家场景下互不串台。系统架构与对话调用链架构设计记忆系统嵌入在NPCAgentManager中结构如下NPCAgentManager ├── agents: Dict[str, SimpleAgent] # NPC AgentLLM 对话核心 ├── memories: Dict[str, MemoryManager] # NPC 记忆管理器每个 NPC 独立 └── chat(npc_name, message, player_id) # 对话接口 ├── 1. 检索相关记忆工作记忆 情景记忆 ├── 2. 构建增强提示词记忆上下文 好感度上下文 ├── 3. 调用 Agent 生成回复 └── 4. 保存对话到记忆含好感度快照记忆管理器初始化在 agents.py 的_create_memory_manager中每位 NPC 启动时自动创建专属存储目录并初始化记忆管理器memory_dir os.path.join(os.path.dirname(__file__), memory_data, npc_name) os.makedirs(memory_dir, exist_okTrue) memory_config MemoryConfig( storage_pathmemory_dir, # 每个NPC独立的存储目录 working_memory_capacity10, # 最近10条对话 working_memory_tokens2000, # 最多2000个token max_capacity100, # 最多100条长期记忆 importance_threshold0.3, # 检索和整合时关注重要性较高的记忆 decay_factor0.95 # 时间衰减系数 ) memory_manager MemoryManager( configmemory_config, user_idnpc_name, # 使用NPC名字作为user_id天然实现记忆隔离 enable_workingTrue, # 启用工作记忆短期 enable_episodicTrue, # 启用情景记忆长期 enable_semanticFalse, # 不需要语义记忆 enable_perceptualFalse # 不需要感知记忆 )启动时每个 NPC 都会打印记忆系统已初始化以及存储路径这是排查记忆问题时的第一处检查点。记忆存储结构存储目录布局backend/memory_data/ ├── 张三/ │ └── memory.db # SQLite 数据库权威存储单文件 ├── 李四/ │ └── memory.db └── 王五/ └── memory.db在 backend/memory_data 中可以看到每位 NPC 一个独立目录内含memory.db。这份单文件数据库即记忆的权威事实来源即使服务重启记忆也不会丢失。记忆数据格式每条记忆以MemoryItem对象承载序列化后的核心字段如下{ id: memory_uuid, content: 玩家说: 你好,你是做什么的?, type: working, # working / episodic importance: 0.5, # 0-1之间决定是否被遗忘 timestamp: 2024-01-15T10:30:00, metadata: { speaker: player, player_id: player, session_id: player, context: { interaction_type: dialogue, npc_name: 张三 } } }对话如何写入记忆_save_conversation_to_memoryagents.py会把一轮对话拆成两条记忆写入工作记忆玩家消息contentf玩家说: {player_message}importance0.5中等NPC 回复contentf我说: {npc_response}importance0.6稍高因为 NPC 自己的表述更值得保留。两者都会附带好感度快照affinity、好感度变化量affinity_change与情感倾向sentiment作为 metadata这意味着记忆不仅是对话文本还带上了关系状态的时间切片为后续的好感度系统见 AFFINITY_SYSTEM_GUIDE.md和情感分析提供了数据基础。记忆检索与增强提示词检索策略在chat方法中系统通过retrieve_memories完成混合检索agents.pyrelevant_memories memory_manager.retrieve_memories( querymessage, memory_types[working, episodic], # 同时检索短期与长期记忆 limit5, # 最多取5条最相关的 min_importance0.3 # 只检索重要性0.3的记忆 )三层筛选逻辑清晰可读记忆类型短期working 长期episodic同时召回相关性以玩家当前消息作为查询语句做语义/相关性匹配重要性门槛min_importance0.3把闲聊琐事挡在提示词之外。增强提示词构建检索到的记忆经_build_memory_contextagents.py格式化为带时间戳的上下文块context_parts [【之前的对话记忆】] for memory in memories: time_str memory.timestamp.strftime(%H:%M) context_parts.append(f[{time_str}] {memory.content})最终发送给 LLM 的增强消息为【当前关系】 你与玩家的关系: 熟悉 (好感度: 60/100) 【对话风格】... 【之前的对话记忆】 [10:25] 玩家说: 你最喜欢的编程语言是什么? [10:25] 我说: 我最喜欢Python,简洁优雅,生态丰富。 【当前对话】 玩家: 我们之前聊过编程语言吗?记忆的时间戳、NPC 自身表述、甚至当时的好感度都会被注入上下文这就是第二天 NPC 还记得昨天聊过什么的实现根基。该增强消息随后交给SimpleAgent.run()生成回复最终把响应与好感度变化回写记忆。API 接口详解记忆能力通过 main.py 中的 FastAPI 路由暴露给 Godot 客户端与调试工具。1. 对话接口支持记忆POST /chat Content-Type: application/json { npc_name: 张三, message: 你好,你是做什么的? }响应:{ npc_name: 张三, npc_title: Python工程师, message: 你好!我是Python工程师,主要负责多智能体系统开发。, success: true, timestamp: 2025-01-15T10:30:00 }请求与响应分别由 models.py 中的ChatRequest、ChatResponse校验npc_title取自NPC_ROLES角色配置。2. 获取 NPC 记忆GET /npcs/张三/memories?limit10响应:{ npc_name: 张三, memories: [ { id: uuid-1, content: 玩家说: 你好,你是做什么的?, type: working, importance: 0.5, timestamp: 2025-01-15T10:30:00, metadata: {...} } ], total: 10 }该接口底层由get_npc_memoriesagents.py以空查询检索全部记忆并转成字典列表非常适合在调试面板里看见NPC 脑子里存了什么。3. 清空 NPC 记忆测试用DELETE /npcs/张三/memories?memory_typeworking响应:{ message: 已清空张三的记忆, npc_name: 张三, memory_type: working }不传memory_type时清空该 NPC 的全部记忆working episodicclear_npc_memoryagents.py会逐个调用clear_memory_type。这是反复测试记忆隔离与遗忘机制时的重置开关。配置参数与调优建议记忆系统在 agents.py 中集中配置参数含义与建议范围如下参数默认值建议范围说明working_memory_capacity105-20工作记忆容量越大越占内存working_memory_tokens20001000-4000Token 限制影响上下文长度max_capacity10050-500记忆总容量越大越占磁盘importance_threshold0.30.1-0.5重要性阈值越高越偏向保留重要记忆decay_factor0.950.8-0.99时间衰减系数越低越强调近期记忆调优指引追求长程剧情连贯适当调高max_capacity如 200并降低importance_threshold如 0.2让更多对话沉淀为长期记忆控制成本与上下文长度working_memory_tokens决定注入提示词的记忆上限token 预算紧张时下调到 10001500模拟健忘NPC将decay_factor降到 0.8 左右时间衰减会更快冲刷旧记忆服务端 LLM 配置模型地址与密钥在 config.py 中通过环境变量LLM_MODEL_ID默认Qwen/Qwen2.5-72B-Instruct、LLM_BASE_URL默认 ModelScope 推理服务与LLM_API_KEY注入未配置密钥时系统自动降级为模拟模式仍可验证接口与记忆存储流程。测试与验证方法方法 1运行测试脚本cd backend python test_memory.py覆盖点基本对话记忆、长期记忆检索、记忆隔离、相关性检索。方法 2通过 API 手工验证启动后端服务cd backend python main.py访问 API 文档http://localhost:8000/docs由 main.py 中 uvicorn 启动端口默认 8000依次执行发送第一条消息POST /chatbody 为{npc_name: 张三, message: 你好,你是做什么的?}发送第二条消息{npc_name: 张三, message: 还记得我刚才问你什么吗?}观察 NPC 是否引用第一条对话内容查看记忆列表GET /npcs/张三/memories确认两条记忆已落库。方法 3在 Godot 游戏中端到端验证启动后端后运行 Godot 项目详见 SETUP_GUIDE.md与 NPC 对话多轮再回访旧话题观察 NPC 能否复述之前的内容再换一个 NPC 提问同样的问题即可直观验证记忆隔离。调试技巧与常见问题调试技巧1. 查看记忆日志对话全程由 logger.py 输出到backend/logs/dialogue_YYYY-MM-DD.log其中与记忆相关的关键日志行 检索到N条相关记忆 相关记忆: 1. ...截断前50字符 对话已保存到张三的记忆中log_memory_retrieval会打印每条记忆内容的前 50 字符足以确认检索到了什么。2. 直接查 SQLitecd backend/memory_data/张三 sqlite3 memory.db SELECT * FROM memories;3. 清空记忆重新测试DELETE /npcs/张三/memories常见问题Q1NPC 为什么记不住对话可能原因记忆系统未正确初始化、存储路径权限不足、记忆被遗忘机制清除。排查方法检查启动日志是否有记忆系统已初始化确认backend/memory_data/目录存在且可写若记忆被过快清除可降低importance_threshold。Q2记忆检索不准确可能原因查询语句与记忆内容相似度低、记忆重要性太低被min_importance0.3过滤。排查方法降低min_importance、增加检索limit数量、让玩家用更具体的语句提问如直接提及关键词编程语言。Q3记忆占用空间太大解决思路降低max_capacity、提高importance_threshold加速淘汰、定期通过DELETE /npcs/{npc_name}/memories清理旧记忆。教学价值与下一步从本案例可以学到MemoryManager 的使用初始化、分层配置working/episodic、添加与检索记忆的完整 API 调用记忆检索策略工作记忆的快速召回、情景记忆的相关性召回、memory_types limit min_importance的混合检索组合记忆存储机制SQLite 作为权威数据存储、向量索引用于语义检索、双存储保证数据一致性与召回效率记忆遗忘机制基于重要性的自动遗忘importance_threshold、基于时间的 TTL 过期工作记忆约 2 小时、基于容量的优先级淘汰max_capacity。与本项目其他系统的联动记忆系统并非孤立模块——对话保存时写入的好感度快照正是 AFFINITY_SYSTEM_GUIDE.md 所讲好感度系统的数据来源chat流程中的情感分析与关系等级判定也让 NPC 的记得从简单的文本复述升级为记得你、也对你有态度。总结赛博小镇 NPC 记忆系统是一套覆盖短期记忆 长期记忆 记忆隔离 自动遗忘的完整实践NPCAgentManager负责组织 Agent 与记忆管理器MemoryManager负责存取与检索FastAPI 层暴露/chat、/npcs/{npc_name}/memories等接口SQLite 保证持久化增强提示词把记忆注入 LLM 上下文。它直观展示了 HelloAgents 框架记忆组件在游戏场景中的落地方式也为读者后续自研多智能体记忆系统如扩展语义记忆、感知记忆或接入真实向量数据库提供了可运行的起点。【免费下载链接】hello-agents 《从零开始构建智能体》——从零开始的智能体原理与实践教程项目地址: https://gitcode.com/datawhalechina/hello-agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表