算法学习 Agent 的上下文记忆设计:别让每次对话都从零开始

📅 2026/7/9 9:39:53
算法学习 Agent 的上下文记忆设计:别让每次对话都从零开始
算法学习 Agent 的上下文记忆设计别让每次对话都从零开始一、每次打开 Agent 都要重新自我介绍使用 AI 辅助学习算法时一个很让人沮丧的体验是你昨天刚和 Agent 讨论过动态规划的「最优子结构」概念今天打开对话它又开始问你你了解 DP 吗。这不是模型的问题是上下文记忆机制的问题。聊天类 Agent 的默认行为是每次对话独立不携带任何历史信息。但对于算法学习这种渐进式、有依赖关系的场景上下文记忆是刚需——你不知道学习者昨天卡在了哪个概念上就无法给出连贯的指导。这篇文章讨论算法学习 Agent 的上下文记忆应该如何设计包括记忆的存储结构、检索策略和遗忘机制。二、记忆的分层架构flowchart TD subgraph 短期记忆 A[当前对话历史] B[本轮讨论的概念] C[最近的纠错记录] end subgraph 长期记忆 D[知识掌握图谱] E[典型错误模式] F[学习进度与节奏偏好] end subgraph 工作记忆 G[当前题目信息] H[候选算法列表] I[中间推导状态] end 短期记忆 --|摘要压缩后| 长期记忆 长期记忆 --|按需检索| 工作记忆 工作记忆 --|推理结束后清理| 短期记忆三种记忆的定位不同短期记忆保留最近几轮对话的完整上下文不压缩。长期记忆结构化的知识状态持久存储按需检索。工作记忆当前推理任务需要的临时信息任务完成后释放。三、实现记忆管理器from dataclasses import dataclass, field from typing import Optional import time import json from collections import OrderedDict dataclass class KnowledgeNode: 知识图谱节点记录学习者在某个知识点上的掌握状态 设计思路 每个知识点独立记录包含掌握程度、最近练习时间、 错误历史等信息。知识点之间可以建立前置依赖关系。 concept_id: str # 知识点唯一标识如 dp.state_transfer concept_name: str # 知识点名称如 状态转移方程 mastery_level: float # 掌握程度 0.0-1.0 last_practice_at: float # 最近练习时间戳 error_count: int 0 # 累计错误次数 # 前置知识点如状态转移依赖最优子结构 prerequisites: list[str] field(default_factorylist) class ContextMemoryManager: 上下文记忆管理器 三种记忆的统一管理入口。 短期记忆用滑动窗口保留最近 K 轮对话。 长期记忆以知识图谱形式持久化存储。 工作记忆按任务生命周期动态创建和释放。 # 短期记忆保留的最近对话轮数 SHORT_TERM_WINDOW 10 def __init__(self, user_id: str, storage_path: str ./memory_store): self.user_id user_id self.storage_path storage_path # 短期记忆用 OrderedDict 实现 FIFO 淘汰 self._short_term: OrderedDict[int, str] OrderedDict() # 长期记忆核心是知识图谱 self._knowledge_graph: dict[str, KnowledgeNode] {} # 工作记忆临时存储随任务创建和销毁 self._working_memory: dict[str, any] {} # 加载持久化的长期记忆 self._load_long_term() def add_conversation(self, turn_id: int, message: str) - None: 记录一轮对话到短期记忆 self._short_term[turn_id] message # 淘汰最旧的记录 while len(self._short_term) self.SHORT_TERM_WINDOW: oldest_key next(iter(self._short_term)) removed self._short_term.popitem(lastFalse) # 淘汰前做一次摘要写入长期记忆 self._summarize_and_persist(removed) def update_knowledge( self, concept_id: str, mastery_delta: float, prerequisites: Optional[list[str]] None, ) - None: 更新知识图谱中的掌握程度 Args: mastery_delta: 掌握程度变化正值进步负值表示遗忘或出错 if concept_id not in self._knowledge_graph: self._knowledge_graph[concept_id] KnowledgeNode( concept_idconcept_id, concept_nameconcept_id, mastery_level0.3, # 初始掌握程度 last_practice_attime.time(), ) node self._knowledge_graph[concept_id] # 使用指数移动平均更新掌握程度避免单次波动过大 alpha 0.3 # 平滑系数 node.mastery_level max(0.0, min(1.0, node.mastery_level alpha * mastery_delta )) node.last_practice_at time.time() if mastery_delta 0: node.error_count 1 if prerequisites: node.prerequisites prerequisites self._save_long_term() def get_context_for_prompt(self, concept_id: Optional[str] None) - str: 为下一轮 LLM 调用构建上下文提示 组合短期记忆 相关长期记忆生成一个信息丰富的 prompt。 parts [] # 短期记忆最近几轮对话原文 if self._short_term: recent list(self._short_term.values())[-5:] parts.append(【近期对话】\n \n.join(recent)) # 长期记忆当前知识点的掌握状态 if concept_id and concept_id in self._knowledge_graph: node self._knowledge_graph[concept_id] parts.append( f【学习状态】{node.concept_name}: f掌握程度 {node.mastery_level:.0%}, f累计错误 {node.error_count} 次 ) # 附上未掌握的前置知识点 unfinished_prereqs [ p for p in node.prerequisites if self._knowledge_graph.get(p, KnowledgeNode(, , 0)).mastery_level 0.6 ] if unfinished_prereqs: parts.append(f【前置知识薄弱】{, .join(unfinished_prereqs)}) return \n\n.join(parts) if parts else def create_workspace(self, task_id: str, initial_state: dict) - None: 为当前任务创建工作记忆空间 self._working_memory[task_id] initial_state def get_workspace(self, task_id: str) - dict: 获取工作记忆空间 return self._working_memory.get(task_id, {}) def release_workspace(self, task_id: str) - None: 释放工作记忆 self._working_memory.pop(task_id, None) def _summarize_and_persist(self, message: str) - None: 将短期记忆中的对话压缩写入长期记忆 # 简化实现提取关键词和结论 # 生产环境应使用轻量 LLM 做摘要 keywords self._extract_keywords(message) for kw in keywords: self.update_knowledge(kw, mastery_delta0.02) def _extract_keywords(self, text: str) - list[str]: 简易关键词提取实际应使用 NLP 或 LLM return [] # 占位 def _save_long_term(self) - None: 持久化长期记忆 pass # 实际上通过文件或数据库存储 def _load_long_term(self) - None: 加载长期记忆 pass四、边界分析与权衡4.1 记忆精度 vs 存储成本保留每轮对话的完整原文精度最高但存储成本大。对历史对话做摘要压缩存储成本小但可能丢失细节。折中方案是近期对话保留原文远期对话保留摘要。4.2 知识图谱的更新策略当前使用指数移动平均更新掌握程度。这种方式的优点是平滑、抗噪声缺点是反应慢——如果你突然顿悟了一个知识点EMA 需要多轮才能追上真实水平。可以引入突变检测机制如果连续 3 次正确率 100%跳跃式提升掌握程度。4.3 跨会话的记忆一致性当用户同时打开多个设备与 Agent 对话时记忆的同步一致性问题会出现。解决方案是在后端维护单一记忆源前端只做展示。这涉及到分布式一致性的老问题。4.4 遗忘机制的必要性不是所有记忆都值得保留。三个月前的错误模式可能已经不再适用。遗忘机制有两种策略时间衰减越久远的记忆权重越低和容量淘汰记忆总数超限时淘汰最不重要的。对于算法学习场景时间衰减更合理。五、总结上下文记忆设计的核心矛盾是信息量越大检索越精准但存储和计算成本越高。分层记忆架构短期-长期-工作是平衡这个矛盾的常用方案。对于算法学习 Agent 来说知识图谱是最核心的长期记忆载体——它不仅记录学了什么还记录掌握到什么程度以及还有什么前置知识未掌握。这种结构化的记忆是 Agent 从「对答如流」升级为「因材施教」的关键。