Agent 记忆系统:架构、设计与LangChain 实践
Agent 记忆系统:架构、设计与LangChain 实践
一、背景:为什么 Agent 需要记忆系统?
1.1 问题的根源:LLM 的无状态本质
大语言模型(LLM)本质上是一个无状态函数:给定一段输入 Prompt,输出一段文本。它不具备跨会话的持久记忆,每次调用都从零开始。这在单轮问答场景下问题不大,但当我们把 LLM 包装成 Agent(智能体)时,问题就暴露了:
-
• 上下文窗口有限:即便是 128K token 的长上下文,也无法承载数月的交互历史、海量工具调用记录、外部知识库;
-
• 多轮对话失忆:用户在第 20 轮提到"上周说的那个方案",模型完全不知道;
-
• 个性化缺失:Agent 无法记住用户偏好、习惯、历史决策;
-
• 跨任务知识断层:Agent 在处理任务 B 时,无法利用任务 A 中积累的领域知识;
-
• 推理链丢失:复杂任务需要多步规划,中间推理过程无法持久化。
1.2 Agent 记忆系统要解决的核心问题
| 问题
|
描述
持久化
|
信息跨 session、跨进程持续存在
| |
检索效率
|
从海量历史中快速找到相关记忆
| |
遗忘机制
|
避免记忆无限膨胀,合理淘汰过时信息
| |
记忆类型区分
|
事实性知识 vs 情节记忆 vs 工作记忆的分层管理
| |
一致性
|
避免记忆冲突和矛盾
|
二、技术架构与设计思路
2.1 记忆分类体系(仿人类认知)
Agent 记忆系统借鉴了认知科学对人类记忆的分类,并在工程实现上有明确的对应关系:
<span leaf="">记忆层级 对应实现 读写特征</span><br><span leaf="">─────────────────────────────────────────────────────────────────────</span><br><span leaf="">感知缓冲(Sensory Buffer) → 原始 Prompt / 传感器输入 只写,极短暂</span><br><span leaf="">工作记忆(Working Memory) → LLM Context Window / Scratchpad 读写,单次生命周期</span><br><span leaf="">情节记忆(Episodic Memory)→ 向量数据库(时序 + 语义索引) 异步写,语义检索</span><br><span leaf="">语义记忆(Semantic Memory)→ 知识图谱 / 结构化 KV Store 读多写少,强一致</span><br><span leaf="">过程记忆(Procedural Mem)→ ToolSpec / Prompt 模板库 低频写,高频读</span><br><span leaf="">外部记忆(External Mem) → 文件系统 / 数据库 / 外部 API 按需访问</span>
这一分层不是单纯的学术分类,它直接决定了读写路径、存储选型、一致性级别的取舍:
-
• 工作记忆是"热数据",必须在 token 预算内;
-
• 情节记忆是"温数据",牺牲精确换取规模;
-
• 语义/过程记忆是"冷数据",强调结构化与可靠性。
2.2 整体架构设计
<span leaf="">┌─────────────────────────────────────────────────────────────────────┐</span><br><span leaf="">│ Agent Runtime │</span><br><span leaf="">│ │</span><br><span leaf="">│ ┌──────────────────────────────────────────────────────────────┐ │</span><br><span leaf="">│ │ Working Memory Layer │ │</span><br><span leaf="">│ │ ┌─────────────────────┐ ┌────────────────────────────┐ │ │</span><br><span leaf="">│ │ │ In-context Window │ │ Scratchpad(思维链草稿) │ │ │</span><br><span leaf="">│ │ │ (token budget管理) │ │ (ReAct / CoT 中间推理) │ │ │</span><br><span leaf="">│ │ └──────────┬──────────┘ └────────────┬───────────────┘ │ │</span><br><span leaf="">│ └──────────────┼─────────────────────────────┼─────────────────┘ │</span><br><span leaf="">│ │ 超出阈值触发压缩 │ 推理结束写回 │</span><br><span leaf="">│ ┌──────────────▼─────────────────────────────▼─────────────────┐ │</span><br><span leaf="">│ │ Memory Manager │ │</span><br><span leaf="">│ │ │ │</span><br><span leaf="">│ │ ┌───────────────┐ ┌────────────────┐ ┌────────────────┐ │ │</span><br><span leaf="">│ │ │ Episodic Store│ │ Semantic Store │ │Procedural Store│ │ │</span><br><span leaf="">│ │ │ │ │ │ │ │ │ │</span><br><span leaf="">│ │ │ · 事件流写入 │ │ · 实体/关系 │ │ · Tool注册表 │ │ │</span><br><span leaf="">│ │ │ · 向量化索引 │ │ · 知识三元组 │ │ · Prompt模板 │ │ │</span><br><span leaf="">│ │ │ · TTL过期管理 │ │ · 版本化更新 │ │ · 经验规则库 │ │ │</span><br><span leaf="">│ │ └───────┬───────┘ └───────┬────────┘ └───────┬────────┘ │ │</span><br><span leaf="">│ │ │ │ │ │ │</span><br><span leaf="">│ │ ┌───────▼──────────────────▼────────────────────▼────────┐ │ │</span><br><span leaf="">│ │ │ Memory Router & Scheduler │ │ │</span><br><span leaf="">│ │ │ · 读:多路归并(语义 + 时序 + 重要性三维排序) │ │ │</span><br><span leaf="">│ │ │ · 写:异步落盘 + 重要性过滤 + 冲突检测 │ │ │</span><br><span leaf="">│ │ │ · 整合(Consolidation):定时触发 LLM 摘要压缩 │ │ │</span><br><span leaf="">│ │ └───────────────────────────┬─────────────────────────────┘ │ │</span><br><span leaf="">│ └──────────────────────────────┼────────────────────────────────┘ │</span><br><span leaf="">│ │ │</span><br><span leaf="">│ ┌──────────────────────────────▼────────────────────────────────┐ │</span><br><span leaf="">│ │ Storage Backend │ │</span><br><span leaf="">│ │ │ │</span><br><span leaf="">│ │ ┌──────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │</span><br><span leaf="">│ │ │ 向量数据库 │ │ 关系/KV数据库 │ │ 知识图谱 │ │ │</span><br><span leaf="">│ │ │ Chroma/Milvus│ │ Postgres/Redis │ │ Neo4j/NebulaGraph│ │ │</span><br><span leaf="">│ │ │ Pinecone/ │ │ SQLite/DynamoDB │ │ │ │ │</span><br><span leaf="">│ │ │ Weaviate │ │ │ │ │ │ │</span><br><span leaf="">│ │ └──────────────┘ └─────────────────┘ └─────────────────┘ │ │</span><br><span leaf="">│ └────────────────────────────────────────────────────────────────┘ │</span><br><span leaf="">└─────────────────────────────────────────────────────────────────────┘</span>
2.3 Memory Manager 核心设计:写路径
写路径是记忆系统质量的决定因素,需解决三个关键问题:写什么、怎么写、何时写。
2.3.1 选择性写入与重要性过滤
不加区分地将所有对话写入向量库会带来两个问题:检索时噪音过多(低质记忆稀释高质结果)、存储膨胀。工程上的解决方案是写前过滤:
<span leaf="">原始交互 → [重要性评分器] → 评分 ≥ 阈值?</span><br><span leaf=""> ├─ Yes → [结构化提取] → 向量化 → 落库</span><br><span leaf=""> └─ No → 丢弃 或 仅存摘要</span>
重要性评分可以用 LLM 打分(成本高但准确),也可以用轻量规则(关键词命中、实体密度、用户显式确认):
<span><span leaf=""># 规则 + LLM 混合的重要性过滤器示例</span></span><br><span><span leaf="">class</span></span><span leaf=""> </span><span><span leaf="">ImportanceFilter</span></span><span leaf="">:</span><br><span leaf=""> KEYWORD_BOOST = [</span><span><span leaf="">"记住"</span></span><span leaf="">, </span><span><span leaf="">"重要"</span></span><span leaf="">, </span><span><span leaf="">"注意"</span></span><span leaf="">, </span><span><span leaf="">"下次"</span></span><span leaf="">, </span><span><span leaf="">"规范"</span></span><span leaf="">, </span><span><span leaf="">"错误"</span></span><span leaf="">, </span><span><span leaf="">"修复"</span></span><span leaf="">]</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">score</span></span><span leaf="">(</span><span><span leaf="">self, text: </span><span><span leaf="">str</span></span><span leaf="">, use_llm: </span><span><span leaf="">bool</span></span><span leaf=""> = </span><span><span leaf="">False</span></span></span><span leaf="">) -> </span><span><span leaf="">float</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf=""># 规则分(快速)</span></span><br><span leaf=""> rule_score = </span><span><span leaf="">sum</span></span><span leaf="">(</span><span><span leaf="">0.1</span></span><span leaf=""> </span><span><span leaf="">for</span></span><span leaf=""> kw </span><span><span leaf="">in</span></span><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.KEYWORD_BOOST </span><span><span leaf="">if</span></span><span leaf=""> kw </span><span><span leaf="">in</span></span><span leaf=""> text)</span><br><span leaf=""> rule_score = </span><span><span leaf="">min</span></span><span leaf="">(rule_score, </span><span><span leaf="">0.5</span></span><span leaf="">) </span><span><span leaf=""># 上限 0.5</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 内容密度分:实体数 / token数(简单启发式)</span></span><br><span leaf=""> density_score = </span><span><span leaf="">min</span></span><span leaf="">(</span><span><span leaf="">len</span></span><span leaf="">(re.findall(</span><span><span leaf="">r'[A-Z][a-z]+|[\u4e00-\u9fa5]{2,}'</span></span><span leaf="">, text)) / </span><span><span leaf="">50</span></span><span leaf="">, </span><span><span leaf="">0.3</span></span><span leaf="">)</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">if</span></span><span leaf=""> </span><span><span leaf="">not</span></span><span leaf=""> use_llm:</span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> rule_score + density_score</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># LLM 精确打分(高价值路径才触发)</span></span><br><span leaf=""> llm_score = </span><span><span leaf="">self</span></span><span leaf="">._llm_importance(text) </span><span><span leaf=""># 返回 0~1</span></span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> </span><span><span leaf="">0.4</span></span><span leaf=""> * (rule_score + density_score) + </span><span><span leaf="">0.6</span></span><span leaf=""> * llm_score</span>
2.3.2 记忆的结构化提取(Memory Extraction)
原始对话文本直接向量化效果差——同义表达导致召回不稳定。生产系统通常在写入前做结构化提取,将非结构化对话转成标准记忆单元:
<span leaf="">原始文本:"用户提到他们团队使用 GitFlow 分支策略,主要用 Java + Spring Boot,</span><br><span leaf=""> 讨厌用 Lombok,以前在项目 X 里用过 Kafka 踩了坑"</span><br><br><span leaf="">结构化提取结果:</span><br><span leaf="">[</span><br><span leaf=""> { type: "preference", subject: "user", key: "branch_strategy", value: "GitFlow" },</span><br><span leaf=""> { type: "tech_stack", subject: "user", items: ["Java", "Spring Boot"] },</span><br><span leaf=""> { type: "dislike", subject: "user", key: "library", value: "Lombok" },</span><br><span leaf=""> { type: "experience", subject: "user", domain: "Kafka", outcome: "negative" }</span><br><span leaf="">]</span>
每条结构化记忆单独向量化,检索精度远高于整段文本。
<span><span leaf="">from</span></span><span leaf=""> langchain_core.prompts </span><span><span leaf="">import</span></span><span leaf=""> ChatPromptTemplate</span><br><span><span leaf="">from</span></span><span leaf=""> langchain_core.output_parsers </span><span><span leaf="">import</span></span><span leaf=""> JsonOutputParser</span><br><span><span leaf="">from</span></span><span leaf=""> pydantic </span><span><span leaf="">import</span></span><span leaf=""> BaseModel</span><br><span><span leaf="">from</span></span><span leaf=""> typing </span><span><span leaf="">import</span></span><span leaf=""> </span><span><span leaf="">List</span></span><span leaf="">, </span><span><span leaf="">Literal</span></span><br><br><span><span leaf="">class</span></span><span leaf=""> </span><span><span leaf="">MemoryUnit</span></span><span leaf="">(</span><span><span leaf="">BaseModel</span></span><span leaf="">):</span><br><span leaf=""> </span><span><span leaf="">type</span></span><span leaf="">: </span><span><span leaf="">Literal</span></span><span leaf="">[</span><span><span leaf="">"preference"</span></span><span leaf="">, </span><span><span leaf="">"tech_stack"</span></span><span leaf="">, </span><span><span leaf="">"experience"</span></span><span leaf="">, </span><span><span leaf="">"fact"</span></span><span leaf="">, </span><span><span leaf="">"dislike"</span></span><span leaf="">, </span><span><span leaf="">"goal"</span></span><span leaf="">]</span><br><span leaf=""> subject: </span><span><span leaf="">str</span></span><br><span leaf=""> content: </span><span><span leaf="">str</span></span><br><span leaf=""> confidence: </span><span><span leaf="">float</span></span><span leaf=""> </span><span><span leaf=""># 0~1,提取置信度</span></span><br><br><span><span leaf="">class</span></span><span leaf=""> </span><span><span leaf="">MemoryExtractor</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf="">"""将对话转换为结构化记忆单元"""</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">__init__</span></span><span leaf="">(</span><span><span leaf="">self, llm</span></span><span leaf="">):</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.chain = (</span><br><span leaf=""> ChatPromptTemplate.from_template(</span><span><span leaf="">"""</span><br><span leaf="">从以下对话中提取值得长期记忆的信息单元,以 JSON 数组返回:</span><br><span leaf="">- 只提取明确表达的信息,不推断</span><br><span leaf="">- 每条记忆简洁完整,独立可理解</span><br><span leaf="">- 置信度:用户明确陈述=1.0,推断=0.5</span><br><br><span leaf="">对话内容:</span><br><span leaf="">{text}</span><br><br><span leaf="">输出格式:[{{"type": "...", "subject": "...", "content": "...", "confidence": 0.0}}]</span><br><span leaf=""> """</span></span><span leaf="">)</span><br><span leaf=""> | llm</span><br><span leaf=""> | JsonOutputParser()</span><br><span leaf=""> )</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">extract</span></span><span leaf="">(</span><span><span leaf="">self, text: </span><span><span leaf="">str</span></span></span><span leaf="">) -> </span><span><span leaf="">List</span></span><span leaf="">[MemoryUnit]:</span><br><span leaf=""> raw = </span><span><span leaf="">self</span></span><span leaf="">.chain.invoke({</span><span><span leaf="">"text"</span></span><span leaf="">: text})</span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> [MemoryUnit(**item) </span><span><span leaf="">for</span></span><span leaf=""> item </span><span><span leaf="">in</span></span><span leaf=""> raw </span><span><span leaf="">if</span></span><span leaf=""> item.get(</span><span><span leaf="">"confidence"</span></span><span leaf="">, </span><span><span leaf="">0</span></span><span leaf="">) >= </span><span><span leaf="">0.6</span></span><span leaf="">]</span>
2.3.3 记忆冲突检测与更新
记忆系统面临的一个棘手问题:用户说"我喜欢 Python",三个月后说"我现在主要写 Go 了"——新记忆与旧记忆冲突,不处理会导致 Agent 输出自相矛盾。
解决方案是在写入时做冲突检测:
<span><span leaf="">class</span></span><span leaf=""> </span><span><span leaf="">ConflictAwareMemoryWriter</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf="">"""写入时检测并解决记忆冲突"""</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">__init__</span></span><span leaf="">(</span><span><span leaf="">self, vectorstore, llm</span></span><span leaf="">):</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.vectorstore = vectorstore</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.llm = llm</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">write</span></span><span leaf="">(</span><span><span leaf="">self, new_memory: MemoryUnit</span></span><span leaf="">):</span><br><span leaf=""> </span><span><span leaf=""># 1. 检索高相似度的已有记忆(可能冲突)</span></span><br><span leaf=""> candidates = </span><span><span leaf="">self</span></span><span leaf="">.vectorstore.similarity_search(</span><br><span leaf=""> new_memory.content, k=</span><span><span leaf="">5</span></span><span leaf="">, score_threshold=</span><span><span leaf="">0.85</span></span><br><span leaf=""> )</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 2. 对高相似记忆做冲突判断</span></span><br><span leaf=""> </span><span><span leaf="">for</span></span><span leaf=""> old_doc </span><span><span leaf="">in</span></span><span leaf=""> candidates:</span><br><span leaf=""> conflict_type = </span><span><span leaf="">self</span></span><span leaf="">._detect_conflict(</span><br><span leaf=""> old_doc.page_content, new_memory.content</span><br><span leaf=""> )</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">if</span></span><span leaf=""> conflict_type == </span><span><span leaf="">"UPDATE"</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf=""># 更新:标记旧记忆为过期,写入新记忆</span></span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.vectorstore.delete([old_doc.metadata[</span><span><span leaf="">"id"</span></span><span leaf="">]])</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">._add_with_provenance(new_memory, supersedes=old_doc.metadata[</span><span><span leaf="">"id"</span></span><span leaf="">])</span><br><span leaf=""> </span><span><span leaf="">return</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">elif</span></span><span leaf=""> conflict_type == </span><span><span leaf="">"COMPLEMENT"</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf=""># 互补:两者共存,添加关联标记</span></span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">._add_with_provenance(new_memory, related=old_doc.metadata[</span><span><span leaf="">"id"</span></span><span leaf="">])</span><br><span leaf=""> </span><span><span leaf="">return</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 3. 无冲突,直接写入</span></span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">._add_with_provenance(new_memory)</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">_detect_conflict</span></span><span leaf="">(</span><span><span leaf="">self, old_text: </span><span><span leaf="">str</span></span><span leaf="">, new_text: </span><span><span leaf="">str</span></span></span><span leaf="">) -> </span><span><span leaf="">str</span></span><span leaf="">:</span><br><span leaf=""> prompt = </span><span><span leaf="">f"""判断两条信息的关系,只返回: UPDATE / COMPLEMENT / UNRELATED</span><br><span leaf=""> 旧信息:</span><span><span leaf="">{old_text}</span></span><br><span leaf=""> 新信息:</span><span><span leaf="">{new_text}</span></span><span leaf="">"""</span></span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.llm.invoke(prompt).content.strip()</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">_add_with_provenance</span></span><span leaf="">(</span><span><span leaf="">self, memory: MemoryUnit, **kwargs</span></span><span leaf="">):</span><br><span leaf=""> metadata = {</span><br><span leaf=""> </span><span><span leaf="">"id"</span></span><span leaf="">: </span><span><span leaf="">str</span></span><span leaf="">(uuid.uuid4()),</span><br><span leaf=""> </span><span><span leaf="">"type"</span></span><span leaf="">: memory.</span><span><span leaf="">type</span></span><span leaf="">,</span><br><span leaf=""> </span><span><span leaf="">"timestamp"</span></span><span leaf="">: time.time(),</span><br><span leaf=""> **kwargs</span><br><span leaf=""> }</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.vectorstore.add_texts([memory.content], metadatas=[metadata])</span>
2.4 Memory Manager 核心设计:读路径
2.4.1 三维加权检索
检索不是简单的 Top-K 向量相似度,需要综合三个维度:
<span leaf="">最终得分 = α × Relevance(q, m) + β × Importance(m) + γ × Recency(m, t)</span>
其中:
-
• Relevance:向量余弦相似度,衡量语义相关程度
-
• Importance:写入时计算并存储的重要性分数
-
• Recency:指数衰减函数
decay^(elapsed_hours),近期记忆得分更高
权重 α/β/γ 可根据场景动态调整:
-
• 精确事实查询(“我之前说的接口地址是?")→ 高 α(相关性优先)
-
• 周期性摘要(“今天做了什么?")→ 高 γ(时效性优先)
-
• 决策辅助(“这个方案之前评估过吗?")→ 高 β(重要性优先)
<span><span leaf="">import</span></span><span leaf=""> math</span><br><span><span leaf="">import</span></span><span leaf=""> numpy </span><span><span leaf="">as</span></span><span leaf=""> np</span><br><span><span leaf="">from</span></span><span leaf=""> dataclasses </span><span><span leaf="">import</span></span><span leaf=""> dataclass</span><br><br><span><span leaf="">@dataclass</span></span><br><span><span leaf="">class</span></span><span leaf=""> </span><span><span leaf="">RetrievalConfig</span></span><span leaf="">:</span><br><span leaf=""> alpha: </span><span><span leaf="">float</span></span><span leaf=""> = </span><span><span leaf="">0.5</span></span><span leaf=""> </span><span><span leaf=""># 相关性权重</span></span><br><span leaf=""> beta: </span><span><span leaf="">float</span></span><span leaf=""> = </span><span><span leaf="">0.3</span></span><span leaf=""> </span><span><span leaf=""># 重要性权重</span></span><br><span leaf=""> gamma: </span><span><span leaf="">float</span></span><span leaf=""> = </span><span><span leaf="">0.2</span></span><span leaf=""> </span><span><span leaf=""># 时效性权重</span></span><br><span leaf=""> decay: </span><span><span leaf="">float</span></span><span leaf=""> = </span><span><span leaf="">0.99</span></span><span leaf=""> </span><span><span leaf=""># 时效衰减因子(per hour)</span></span><br><span leaf=""> top_k: </span><span><span leaf="">int</span></span><span leaf=""> = </span><span><span leaf="">5</span></span><br><br><span><span leaf="">class</span></span><span leaf=""> </span><span><span leaf="">WeightedMemoryRetriever</span></span><span leaf="">:</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">__init__</span></span><span leaf="">(</span><span><span leaf="">self, vectorstore, config: RetrievalConfig = RetrievalConfig(</span><span></span><span leaf="">)</span></span><span leaf="">):</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.vs = vectorstore</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.cfg = config</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">retrieve</span></span><span leaf="">(</span><span><span leaf="">self, query: </span><span><span leaf="">str</span></span><span leaf="">, context: </span><span><span leaf="">dict</span></span><span leaf=""> = </span><span><span leaf="">None</span></span></span><span leaf="">) -> </span><span><span leaf="">list</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf=""># 动态权重调整(根据查询意图)</span></span><br><span leaf=""> cfg = </span><span><span leaf="">self</span></span><span leaf="">._adjust_weights(query, context)</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 召回候选集(比 top_k 多取,留出重排空间)</span></span><br><span leaf=""> candidates = </span><span><span leaf="">self</span></span><span leaf="">.vs.similarity_search_with_score(</span><br><span leaf=""> query, k=cfg.top_k * </span><span><span leaf="">4</span></span><br><span leaf=""> )</span><br><span leaf=""> </span><br><span leaf=""> scored = []</span><br><span leaf=""> </span><span><span leaf="">for</span></span><span leaf=""> doc, raw_similarity </span><span><span leaf="">in</span></span><span leaf=""> candidates:</span><br><span leaf=""> meta = doc.metadata</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 相关性:FAISS 返回 L2 距离,需转换为相似度</span></span><br><span leaf=""> relevance = </span><span><span leaf="">1</span></span><span leaf=""> / (</span><span><span leaf="">1</span></span><span leaf=""> + raw_similarity)</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 重要性:写入时预计算并存储</span></span><br><span leaf=""> importance = meta.get(</span><span><span leaf="">"importance"</span></span><span leaf="">, </span><span><span leaf="">0.5</span></span><span leaf="">)</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 时效性:指数衰减</span></span><br><span leaf=""> hours = (time.time() - meta.get(</span><span><span leaf="">"timestamp"</span></span><span leaf="">, time.time())) / </span><span><span leaf="">3600</span></span><br><span leaf=""> recency = math.</span><span><span leaf="">pow</span></span><span leaf="">(cfg.decay, hours)</span><br><span leaf=""> </span><br><span leaf=""> score = cfg.alpha * relevance + cfg.beta * importance + cfg.gamma * recency</span><br><span leaf=""> scored.append((doc, score))</span><br><span leaf=""> </span><br><span leaf=""> scored.sort(key=</span><span><span leaf="">lambda</span></span><span leaf=""> x: x[</span><span><span leaf="">1</span></span><span leaf="">], reverse=</span><span><span leaf="">True</span></span><span leaf="">)</span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> [doc </span><span><span leaf="">for</span></span><span leaf=""> doc, _ </span><span><span leaf="">in</span></span><span leaf=""> scored[:cfg.top_k]]</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">_adjust_weights</span></span><span leaf="">(</span><span><span leaf="">self, query: </span><span><span leaf="">str</span></span><span leaf="">, context: </span><span><span leaf="">dict</span></span></span><span leaf="">) -> RetrievalConfig:</span><br><span leaf=""> </span><span><span leaf="">"""根据查询意图动态调整权重"""</span></span><br><span leaf=""> cfg = RetrievalConfig(**</span><span><span leaf="">vars</span></span><span leaf="">(</span><span><span leaf="">self</span></span><span leaf="">.cfg))</span><br><span leaf=""> </span><span><span leaf="">if</span></span><span leaf=""> context </span><span><span leaf="">and</span></span><span leaf=""> context.get(</span><span><span leaf="">"intent"</span></span><span leaf="">) == </span><span><span leaf="">"recent_summary"</span></span><span leaf="">:</span><br><span leaf=""> cfg.gamma, cfg.alpha = </span><span><span leaf="">0.5</span></span><span leaf="">, </span><span><span leaf="">0.3</span></span><br><span leaf=""> </span><span><span leaf="">elif</span></span><span leaf=""> context </span><span><span leaf="">and</span></span><span leaf=""> context.get(</span><span><span leaf="">"intent"</span></span><span leaf="">) == </span><span><span leaf="">"fact_lookup"</span></span><span leaf="">:</span><br><span leaf=""> cfg.alpha, cfg.gamma = </span><span><span leaf="">0.7</span></span><span leaf="">, </span><span><span leaf="">0.1</span></span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> cfg</span>
2.4.2 分层检索融合(Hierarchical Retrieval Fusion)
不同类型的记忆应该走不同的检索路径,最终在 Working Memory 中融合:
<span><span leaf="">from</span></span><span leaf=""> langchain_core.runnables </span><span><span leaf="">import</span></span><span leaf=""> RunnableParallel, RunnableLambda</span><br><br><span><span leaf="">class</span></span><span leaf=""> </span><span><span leaf="">HierarchicalMemoryRetriever</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf="">"""多层记忆并行检索 + 融合"""</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">__init__</span></span><span leaf="">(</span><span><span leaf="">self, episodic_retriever, semantic_store, procedural_store</span></span><span leaf="">):</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.episodic = episodic_retriever </span><span><span leaf=""># 向量检索</span></span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.semantic = semantic_store </span><span><span leaf=""># 知识图谱/结构化查询</span></span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.procedural = procedural_store </span><span><span leaf=""># 工具/规范查询</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">retrieve_all</span></span><span leaf="">(</span><span><span leaf="">self, query: </span><span><span leaf="">str</span></span><span leaf="">, agent_state: </span><span><span leaf="">dict</span></span></span><span leaf="">) -> </span><span><span leaf="">dict</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf=""># 并行检索三类记忆(减少延迟)</span></span><br><span leaf=""> parallel = RunnableParallel({</span><br><span leaf=""> </span><span><span leaf="">"episodic"</span></span><span leaf="">: RunnableLambda(</span><span><span leaf="">lambda</span></span><span leaf=""> q: </span><span><span leaf="">self</span></span><span leaf="">.episodic.retrieve(q)),</span><br><span leaf=""> </span><span><span leaf="">"semantic"</span></span><span leaf="">: RunnableLambda(</span><span><span leaf="">lambda</span></span><span leaf=""> q: </span><span><span leaf="">self</span></span><span leaf="">.semantic.query(q)),</span><br><span leaf=""> </span><span><span leaf="">"procedural"</span></span><span leaf="">: RunnableLambda(</span><span><span leaf="">lambda</span></span><span leaf=""> q: </span><span><span leaf="">self</span></span><span leaf="">.procedural.lookup(q)),</span><br><span leaf=""> })</span><br><span leaf=""> raw = parallel.invoke(query)</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 融合:根据 token 预算截断,重要性优先</span></span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">._merge_with_budget(raw, budget=</span><span><span leaf="">2000</span></span><span leaf="">) </span><span><span leaf=""># token预算</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">_merge_with_budget</span></span><span leaf="">(</span><span><span leaf="">self, memories: </span><span><span leaf="">dict</span></span><span leaf="">, budget: </span><span><span leaf="">int</span></span></span><span leaf="">) -> </span><span><span leaf="">str</span></span><span leaf="">:</span><br><span leaf=""> sections = []</span><br><span leaf=""> remaining = budget</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 优先级:语义记忆(事实可靠)> 情节记忆(相关经验)> 过程记忆(工具使用)</span></span><br><span leaf=""> order = [</span><span><span leaf="">"semantic"</span></span><span leaf="">, </span><span><span leaf="">"episodic"</span></span><span leaf="">, </span><span><span leaf="">"procedural"</span></span><span leaf="">]</span><br><span leaf=""> </span><span><span leaf="">for</span></span><span leaf=""> key </span><span><span leaf="">in</span></span><span leaf=""> order:</span><br><span leaf=""> </span><span><span leaf="">for</span></span><span leaf=""> item </span><span><span leaf="">in</span></span><span leaf=""> memories.get(key, []):</span><br><span leaf=""> text = </span><span><span leaf="">f"[</span><span><span leaf="">{key}</span></span><span leaf="">] </span><span><span leaf="">{item}</span></span><span leaf="">"</span></span><br><span leaf=""> tokens = </span><span><span leaf="">len</span></span><span leaf="">(text) // </span><span><span leaf="">4</span></span><span leaf=""> </span><span><span leaf=""># 粗略 token 估算</span></span><br><span leaf=""> </span><span><span leaf="">if</span></span><span leaf=""> remaining - tokens > </span><span><span leaf="">0</span></span><span leaf="">:</span><br><span leaf=""> sections.append(text)</span><br><span leaf=""> remaining -= tokens</span><br><span leaf=""> </span><span><span leaf="">else</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf="">break</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> </span><span><span leaf="">"\n\n"</span></span><span leaf="">.join(sections)</span>
2.5 记忆整合(Consolidation):从情节到语义的升华
Consolidation 是记忆系统中最具技术价值的机制——将大量碎片化的情节记忆提炼成高层的语义记忆,类比人类睡眠中的记忆巩固过程。
这个过程分两步:
-
1. 摘要压缩(Summarization):将 N 条相关情节记忆合并为一条压缩摘要,降低存储成本
-
2. 反思提炼(Reflection):对压缩摘要做更高层的归纳,提取行为规律和洞见
<span><span leaf="">class</span></span><span leaf=""> </span><span><span leaf="">MemoryConsolidator</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf="">"""</span><br><span leaf=""> 记忆整合器:情节记忆 → 语义记忆</span><br><span leaf=""> 建议通过 cron 定时触发(如每天凌晨),或在情节记忆超过阈值时触发</span><br><span leaf=""> """</span></span><br><span leaf=""> </span><br><span leaf=""> REFLECTION_PROMPT = </span><span><span leaf="">"""</span><br><span leaf="">以下是 Agent 近期的记忆片段,请从中提炼出:</span><br><span leaf="">1. 用户的核心偏好和习惯规律(不超过5条)</span><br><span leaf="">2. 值得注意的重复性问题或错误模式</span><br><span leaf="">3. 可以优化 Agent 未来行为的洞见</span><br><br><span leaf="">记忆片段:</span><br><span leaf="">{memories}</span><br><br><span leaf="">以 JSON 格式输出:{{"preferences": [], "patterns": [], "insights": []}}</span><br><span leaf=""> """</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">__init__</span></span><span leaf="">(</span><span><span leaf="">self, episodic_store, semantic_store, llm, threshold: </span><span><span leaf="">int</span></span><span leaf=""> = </span><span><span leaf="">50</span></span></span><span leaf="">):</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.episodic = episodic_store</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.semantic = semantic_store</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.llm = llm</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.threshold = threshold </span><span><span leaf=""># 超过多少条情节记忆触发整合</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">should_consolidate</span></span><span leaf="">(</span><span><span leaf="">self</span></span><span leaf="">) -> </span><span><span leaf="">bool</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.episodic.count() >= </span><span><span leaf="">self</span></span><span leaf="">.threshold</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">consolidate</span></span><span leaf="">(</span><span><span leaf="">self, entity_id: </span><span><span leaf="">str</span></span></span><span leaf="">):</span><br><span leaf=""> </span><span><span leaf=""># 1. 取出待整合的情节记忆(按时间分组)</span></span><br><span leaf=""> episodes = </span><span><span leaf="">self</span></span><span leaf="">.episodic.fetch_recent(entity_id, limit=</span><span><span leaf="">self</span></span><span leaf="">.threshold)</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 2. 摘要压缩(多条 → 1条)</span></span><br><span leaf=""> combined_text = </span><span><span leaf="">"\n"</span></span><span leaf="">.join([e.content </span><span><span leaf="">for</span></span><span leaf=""> e </span><span><span leaf="">in</span></span><span leaf=""> episodes])</span><br><span leaf=""> summary = </span><span><span leaf="">self</span></span><span leaf="">.llm.invoke(</span><br><span leaf=""> </span><span><span leaf="">f"请将以下记忆片段压缩为一段连贯的摘要,保留关键信息:\n</span><span><span leaf="">{combined_text}</span></span><span leaf="">"</span></span><br><span leaf=""> ).content</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 3. 反思提炼(提取高层洞见)</span></span><br><span leaf=""> reflection_result = </span><span><span leaf="">self</span></span><span leaf="">.llm.invoke(</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.REFLECTION_PROMPT.</span><span><span leaf="">format</span></span><span leaf="">(memories=combined_text)</span><br><span leaf=""> ).content</span><br><span leaf=""> </span><br><span leaf=""> reflection = json.loads(reflection_result)</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 4. 写入语义记忆</span></span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.semantic.upsert(entity_id, {</span><br><span leaf=""> </span><span><span leaf="">"summary"</span></span><span leaf="">: summary,</span><br><span leaf=""> </span><span><span leaf="">"preferences"</span></span><span leaf="">: reflection[</span><span><span leaf="">"preferences"</span></span><span leaf="">],</span><br><span leaf=""> </span><span><span leaf="">"patterns"</span></span><span leaf="">: reflection[</span><span><span leaf="">"patterns"</span></span><span leaf="">],</span><br><span leaf=""> </span><span><span leaf="">"insights"</span></span><span leaf="">: reflection[</span><span><span leaf="">"insights"</span></span><span leaf="">],</span><br><span leaf=""> </span><span><span leaf="">"consolidated_at"</span></span><span leaf="">: time.time(),</span><br><span leaf=""> </span><span><span leaf="">"source_count"</span></span><span leaf="">: </span><span><span leaf="">len</span></span><span leaf="">(episodes)</span><br><span leaf=""> })</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 5. 清理已整合的情节记忆(可选:标记为已整合而非删除,保留溯源)</span></span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.episodic.mark_consolidated([e.</span><span><span leaf="">id</span></span><span leaf=""> </span><span><span leaf="">for</span></span><span leaf=""> e </span><span><span leaf="">in</span></span><span leaf=""> episodes])</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> reflection</span>
2.6 记忆的生命周期完整流图
<span leaf="">用户输入/工具调用</span><br><span leaf=""> │</span><br><span leaf=""> ▼</span><br><span leaf=""> ┌─────────────┐</span><br><span leaf=""> │ 感知缓冲 │ ← 原始输入,仅在当前帧有效</span><br><span leaf=""> └──────┬──────┘</span><br><span leaf=""> │ 流入 Working Memory</span><br><span leaf=""> ┌──────▼──────┐</span><br><span leaf=""> │ 工作记忆 │ ← token 消耗在此发生</span><br><span leaf=""> │ (上下文窗口)│</span><br><span leaf=""> └──────┬──────┘</span><br><span leaf=""> │ 超出 token 预算 or 轮次结束</span><br><span leaf=""> ▼</span><br><span leaf=""> ┌───────────────────────────────── ─┐</span><br><span leaf=""> │ Memory Manager │</span><br><span leaf=""> │ │</span><br><span leaf=""> │ [写路径] │</span><br><span leaf=""> │ 重要性评分 → 过滤 → 结构化提取 │</span><br><span leaf=""> │ → 冲突检测 → 向量化 → 落库 │</span><br><span leaf=""> │ │</span><br><span leaf=""> │ [整合触发](定时 or 阈值) │</span><br><span leaf=""> │ 情节记忆 → 摘要压缩 → 反思提炼 │</span><br><span leaf=""> │ → 写入语义记忆 │</span><br><span leaf=""> │ │</span><br><span leaf=""> │ [遗忘触发](定时清理) │</span><br><span leaf=""> │ TTL 过期 → 删除 │</span><br><span leaf=""> │ 低重要性 + 长时未访问 → 软删除 │</span><br><span leaf=""> └────────────────┬──────────────────┘</span><br><span leaf=""> │ 下次请求时读路径</span><br><span leaf=""> ┌────────────────▼──────────────────────┐</span><br><span leaf=""> │ 三维加权检索(Relevance+Importance+ │</span><br><span leaf=""> │ Recency)→ 分层融合 → 注入 Prompt │</span><br><span leaf=""> └───────────────────────────────────────┘</span>
2.7 存储选型决策矩阵
不同记忆类型对存储有不同要求,以下是选型决策矩阵:
| 记忆类型
|
查询模式
|
一致性要求
|
推荐存储
|
备注
工作记忆
|
顺序读写
|
强一致
|
In-memory(Python dict)
|
无需持久化
| |
情节记忆
|
语义相似度检索
|
最终一致
|
Chroma / Milvus / Weaviate
|
需支持 metadata 过滤
| |
语义记忆(KV型)
|
精确 Key 查找
|
强一致
|
Redis / DynamoDB
|
读高性能
| |
语义记忆(关系型)
|
实体关系图遍历
|
强一致
|
Neo4j / NebulaGraph
|
适合复杂关系推理
| |
过程记忆
|
分类检索
|
强一致
|
PostgreSQL + pgvector
|
混合查询场景
| |
事件溯源记忆
|
时序 + 回放
|
强一致(追加)
|
Kafka / EventStore
|
不可变,只追加
|
pgvector 方案(结构化 + 向量一体) 在中小规模场景下尤为实用,避免多系统维护成本:
<span><span leaf="">-- pgvector:在 Postgres 中直接存向量,同时保留结构化字段</span></span><br><span><span leaf="">CREATE</span></span><span leaf=""> EXTENSION IF </span><span><span leaf="">NOT</span></span><span leaf=""> </span><span><span leaf="">EXISTS</span></span><span leaf=""> vector;</span><br><br><span><span leaf="">CREATE TABLE</span></span><span leaf=""> agent_memories (</span><br><span leaf=""> id UUID </span><span><span leaf="">PRIMARY KEY</span></span><span leaf=""> </span><span><span leaf="">DEFAULT</span></span><span leaf=""> gen_random_uuid(),</span><br><span leaf=""> entity_id </span><span><span leaf="">VARCHAR</span></span><span leaf="">(</span><span><span leaf="">64</span></span><span leaf="">) </span><span><span leaf="">NOT NULL</span></span><span leaf="">, </span><span><span leaf="">-- 用户/Agent ID</span></span><br><span leaf=""> memory_type </span><span><span leaf="">VARCHAR</span></span><span leaf="">(</span><span><span leaf="">32</span></span><span leaf="">) </span><span><span leaf="">NOT NULL</span></span><span leaf="">, </span><span><span leaf="">-- episodic/semantic/procedural</span></span><br><span leaf=""> content TEXT </span><span><span leaf="">NOT NULL</span></span><span leaf="">,</span><br><span leaf=""> embedding VECTOR(</span><span><span leaf="">1536</span></span><span leaf="">), </span><span><span leaf="">-- OpenAI text-embedding-3-small</span></span><br><span leaf=""> importance </span><span><span leaf="">FLOAT</span></span><span leaf=""> </span><span><span leaf="">DEFAULT</span></span><span leaf=""> </span><span><span leaf="">0.5</span></span><span leaf="">,</span><br><span leaf=""> </span><span><span leaf="">timestamp</span></span><span leaf=""> TIMESTAMPTZ </span><span><span leaf="">DEFAULT</span></span><span leaf=""> NOW(),</span><br><span leaf=""> expires_at TIMESTAMPTZ, </span><span><span leaf="">-- TTL 过期时间</span></span><br><span leaf=""> is_active </span><span><span leaf="">BOOLEAN</span></span><span leaf=""> </span><span><span leaf="">DEFAULT</span></span><span leaf=""> </span><span><span leaf="">TRUE</span></span><span leaf="">,</span><br><span leaf=""> metadata JSONB </span><span><span leaf="">DEFAULT</span></span><span leaf=""> </span><span><span leaf="">'{}'</span></span><br><span leaf="">);</span><br><br><span><span leaf="">-- 向量索引(HNSW,低延迟近似最近邻)</span></span><br><span><span leaf="">CREATE</span></span><span leaf=""> INDEX </span><span><span leaf="">ON</span></span><span leaf=""> agent_memories</span><br><span leaf=""> </span><span><span leaf="">USING</span></span><span leaf=""> hnsw (embedding vector_cosine_ops)</span><br><span leaf=""> </span><span><span leaf="">WITH</span></span><span leaf=""> (m </span><span><span leaf="">=</span></span><span leaf=""> </span><span><span leaf="">16</span></span><span leaf="">, ef_construction </span><span><span leaf="">=</span></span><span leaf=""> </span><span><span leaf="">64</span></span><span leaf="">);</span><br><br><span><span leaf="">-- 复合索引:快速过滤特定实体的活跃记忆</span></span><br><span><span leaf="">CREATE</span></span><span leaf=""> INDEX </span><span><span leaf="">ON</span></span><span leaf=""> agent_memories (entity_id, memory_type, is_active, </span><span><span leaf="">timestamp</span></span><span leaf=""> </span><span><span leaf="">DESC</span></span><span leaf="">);</span><br><br><span><span leaf="">-- 三维加权检索(SQL 实现)</span></span><br><span><span leaf="">SELECT</span></span><br><span leaf=""> content,</span><br><span leaf=""> importance,</span><br><span leaf=""> (</span><span><span leaf="">1</span></span><span leaf=""> </span><span><span leaf="">-</span></span><span leaf=""> (embedding </span><span><span leaf=""><=></span></span><span leaf=""> $query_embedding)) </span><span><span leaf="">AS</span></span><span leaf=""> relevance, </span><span><span leaf="">-- 余弦相似度</span></span><br><span leaf=""> </span><span><span leaf="">EXP</span></span><span leaf="">(</span><span><span leaf="">-0.01</span></span><span leaf=""> </span><span><span leaf="">*</span></span><span leaf=""> </span><span><span leaf="">EXTRACT</span></span><span leaf="">(EPOCH </span><span><span leaf="">FROM</span></span><span leaf=""> (NOW() </span><span><span leaf="">-</span></span><span leaf=""> </span><span><span leaf="">timestamp</span></span><span leaf="">)) </span><span><span leaf="">/</span></span><span leaf=""> </span><span><span leaf="">3600</span></span><span leaf="">) </span><span><span leaf="">AS</span></span><span leaf=""> recency,</span><br><span leaf=""> (</span><br><span leaf=""> </span><span><span leaf="">0.5</span></span><span leaf=""> </span><span><span leaf="">*</span></span><span leaf=""> (</span><span><span leaf="">1</span></span><span leaf=""> </span><span><span leaf="">-</span></span><span leaf=""> (embedding </span><span><span leaf=""><=></span></span><span leaf=""> $query_embedding)) </span><span><span leaf="">+</span></span><br><span leaf=""> </span><span><span leaf="">0.3</span></span><span leaf=""> </span><span><span leaf="">*</span></span><span leaf=""> importance </span><span><span leaf="">+</span></span><br><span leaf=""> </span><span><span leaf="">0.2</span></span><span leaf=""> </span><span><span leaf="">*</span></span><span leaf=""> </span><span><span leaf="">EXP</span></span><span leaf="">(</span><span><span leaf="">-0.01</span></span><span leaf=""> </span><span><span leaf="">*</span></span><span leaf=""> </span><span><span leaf="">EXTRACT</span></span><span leaf="">(EPOCH </span><span><span leaf="">FROM</span></span><span leaf=""> (NOW() </span><span><span leaf="">-</span></span><span leaf=""> </span><span><span leaf="">timestamp</span></span><span leaf="">)) </span><span><span leaf="">/</span></span><span leaf=""> </span><span><span leaf="">3600</span></span><span leaf="">)</span><br><span leaf=""> ) </span><span><span leaf="">AS</span></span><span leaf=""> final_score</span><br><span><span leaf="">FROM</span></span><span leaf=""> agent_memories</span><br><span><span leaf="">WHERE</span></span><span leaf=""> entity_id </span><span><span leaf="">=</span></span><span leaf=""> $entity_id</span><br><span leaf=""> </span><span><span leaf="">AND</span></span><span leaf=""> is_active </span><span><span leaf="">=</span></span><span leaf=""> </span><span><span leaf="">TRUE</span></span><br><span leaf=""> </span><span><span leaf="">AND</span></span><span leaf=""> (expires_at </span><span><span leaf="">IS</span></span><span leaf=""> </span><span><span leaf="">NULL</span></span><span leaf=""> </span><span><span leaf="">OR</span></span><span leaf=""> expires_at </span><span><span leaf="">></span></span><span leaf=""> NOW())</span><br><span><span leaf="">ORDER</span></span><span leaf=""> </span><span><span leaf="">BY</span></span><span leaf=""> final_score </span><span><span leaf="">DESC</span></span><br><span leaf="">LIMIT </span><span><span leaf="">5</span></span><span leaf="">;</span>
三、核心技术实现(LangChain 示例)
3.1 工作记忆:ConversationBufferMemory
最基础的记忆形式,将历史对话塞进 Prompt。
<span><span leaf="">from</span></span><span leaf=""> langchain.memory </span><span><span leaf="">import</span></span><span leaf=""> ConversationBufferMemory</span><br><span><span leaf="">from</span></span><span leaf=""> langchain.chains </span><span><span leaf="">import</span></span><span leaf=""> ConversationChain</span><br><span><span leaf="">from</span></span><span leaf=""> langchain_openai </span><span><span leaf="">import</span></span><span leaf=""> ChatOpenAI</span><br><br><span leaf="">llm = ChatOpenAI(model=</span><span><span leaf="">"gpt-4o"</span></span><span leaf="">)</span><br><br><span leaf="">memory = ConversationBufferMemory(</span><br><span leaf=""> memory_key=</span><span><span leaf="">"chat_history"</span></span><span leaf="">,</span><br><span leaf=""> return_messages=</span><span><span leaf="">True</span></span><br><span leaf="">)</span><br><br><span leaf="">chain = ConversationChain(</span><br><span leaf=""> llm=llm,</span><br><span leaf=""> memory=memory,</span><br><span leaf=""> verbose=</span><span><span leaf="">True</span></span><br><span leaf="">)</span><br><br><span leaf="">chain.invoke({</span><span><span leaf="">"input"</span></span><span leaf="">: </span><span><span leaf="">"我叫张三,是一名后端工程师"</span></span><span leaf="">})</span><br><span leaf="">chain.invoke({</span><span><span leaf="">"input"</span></span><span leaf="">: </span><span><span leaf="">"帮我写一个 Python 快速排序"</span></span><span leaf="">})</span><br><span><span leaf=""># 第二轮调用时,模型仍然知道用户是张三</span></span>
缺点: 上下文无限增长,超出 token 限制后崩溃。
3.2 滑动窗口记忆:ConversationBufferWindowMemory
<span><span leaf="">from</span></span><span leaf=""> langchain.memory </span><span><span leaf="">import</span></span><span leaf=""> ConversationBufferWindowMemory</span><br><br><span leaf="">memory = ConversationBufferWindowMemory(</span><br><span leaf=""> k=</span><span><span leaf="">10</span></span><span leaf="">, </span><span><span leaf=""># 只保留最近 10 轮对话</span></span><br><span leaf=""> memory_key=</span><span><span leaf="">"chat_history"</span></span><span leaf="">,</span><br><span leaf=""> return_messages=</span><span><span leaf="">True</span></span><br><span leaf="">)</span>
适用场景: 对话轮次多、上下文时效性高(近期对话更重要)的场景。
3.3 摘要记忆:ConversationSummaryMemory
超过一定长度后,用 LLM 对历史进行压缩摘要:
<span><span leaf="">from</span></span><span leaf=""> langchain.memory </span><span><span leaf="">import</span></span><span leaf=""> ConversationSummaryMemory</span><br><br><span leaf="">memory = ConversationSummaryMemory(</span><br><span leaf=""> llm=llm,</span><br><span leaf=""> memory_key=</span><span><span leaf="">"chat_history"</span></span><span leaf="">,</span><br><span leaf=""> return_messages=</span><span><span leaf="">True</span></span><br><span leaf="">)</span><br><br><span><span leaf=""># 当对话积累到一定量,memory 会自动调用 LLM 生成摘要:</span></span><br><span><span leaf=""># "用户自我介绍为张三,后端工程师,讨论了快速排序实现,</span></span><br><span><span leaf=""># 并询问了 Redis 缓存最佳实践..."</span></span>
3.4 向量检索记忆:VectorStoreRetrieverMemory
这是 Agent 记忆系统最重要的组件之一——通过语义相似度检索历史记忆:
<span><span leaf="">from</span></span><span leaf=""> langchain.memory </span><span><span leaf="">import</span></span><span leaf=""> VectorStoreRetrieverMemory</span><br><span><span leaf="">from</span></span><span leaf=""> langchain_community.vectorstores </span><span><span leaf="">import</span></span><span leaf=""> Chroma</span><br><span><span leaf="">from</span></span><span leaf=""> langchain_openai </span><span><span leaf="">import</span></span><span leaf=""> OpenAIEmbeddings</span><br><br><span><span leaf=""># 初始化向量数据库</span></span><br><span leaf="">embedding = OpenAIEmbeddings()</span><br><span leaf="">vectorstore = Chroma(</span><br><span leaf=""> collection_name=</span><span><span leaf="">"agent_memory"</span></span><span leaf="">,</span><br><span leaf=""> embedding_function=embedding,</span><br><span leaf=""> persist_directory=</span><span><span leaf="">"./memory_db"</span></span><br><span leaf="">)</span><br><br><span leaf="">retriever = vectorstore.as_retriever(</span><br><span leaf=""> search_kwargs={</span><span><span leaf="">"k"</span></span><span leaf="">: </span><span><span leaf="">5</span></span><span leaf="">} </span><span><span leaf=""># 每次检索最相关的 5 条记忆</span></span><br><span leaf="">)</span><br><br><span leaf="">memory = VectorStoreRetrieverMemory(</span><br><span leaf=""> retriever=retriever,</span><br><span leaf=""> memory_key=</span><span><span leaf="">"relevant_history"</span></span><br><span leaf="">)</span><br><br><span><span leaf=""># 存入记忆</span></span><br><span leaf="">memory.save_context(</span><br><span leaf=""> inputs={</span><span><span leaf="">"input"</span></span><span leaf="">: </span><span><span leaf="">"用户偏好:喜欢简洁的代码风格,讨厌过度注释"</span></span><span leaf="">},</span><br><span leaf=""> outputs={</span><span><span leaf="">"output"</span></span><span leaf="">: </span><span><span leaf="">"已记录用户编码偏好"</span></span><span leaf="">}</span><br><span leaf="">)</span><br><br><span><span leaf=""># 检索:当用户问到代码风格时,自动召回相关记忆</span></span><br><span leaf="">relevant = memory.load_memory_variables(</span><br><span leaf=""> inputs={</span><span><span leaf="">"input"</span></span><span leaf="">: </span><span><span leaf="">"帮我重构这段代码"</span></span><span leaf="">}</span><br><span leaf="">)</span><br><span><span leaf=""># 自动返回「用户偏好:喜欢简洁的代码风格」相关记忆</span></span>
3.5 组合记忆:CombinedMemory
生产环境中通常需要多种记忆类型组合使用:
<span><span leaf="">from</span></span><span leaf=""> langchain.memory </span><span><span leaf="">import</span></span><span leaf=""> CombinedMemory, ConversationSummaryMemory</span><br><span><span leaf="">from</span></span><span leaf=""> langchain.memory </span><span><span leaf="">import</span></span><span leaf=""> VectorStoreRetrieverMemory</span><br><br><span><span leaf=""># 短期:摘要记忆(近期对话)</span></span><br><span leaf="">summary_memory = ConversationSummaryMemory(</span><br><span leaf=""> llm=llm,</span><br><span leaf=""> input_key=</span><span><span leaf="">"input"</span></span><span leaf="">,</span><br><span leaf=""> memory_key=</span><span><span leaf="">"recent_context"</span></span><br><span leaf="">)</span><br><br><span><span leaf=""># 长期:向量记忆(语义检索历史)</span></span><br><span leaf="">vector_memory = VectorStoreRetrieverMemory(</span><br><span leaf=""> retriever=retriever,</span><br><span leaf=""> input_key=</span><span><span leaf="">"input"</span></span><span leaf="">,</span><br><span leaf=""> memory_key=</span><span><span leaf="">"long_term_context"</span></span><br><span leaf="">)</span><br><br><span leaf="">combined = CombinedMemory(memories=[summary_memory, vector_memory])</span>
3.6 自定义重要性评分记忆
Generative Agents 论文提出的重要性 + 时效性 + 相关性三维加权检索:
<span><span leaf="">from</span></span><span leaf=""> langchain_core.documents </span><span><span leaf="">import</span></span><span leaf=""> Document</span><br><span><span leaf="">from</span></span><span leaf=""> langchain_community.vectorstores </span><span><span leaf="">import</span></span><span leaf=""> FAISS</span><br><span><span leaf="">import</span></span><span leaf=""> time</span><br><span><span leaf="">import</span></span><span leaf=""> math</span><br><br><span><span leaf="">class</span></span><span leaf=""> </span><span><span leaf="">ScoredMemory</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf="">"""带重要性评分和时效衰减的记忆系统"""</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">__init__</span></span><span leaf="">(</span><span><span leaf="">self, llm, embedding</span></span><span leaf="">):</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.llm = llm</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.vectorstore = FAISS.from_texts([</span><span><span leaf="">"init"</span></span><span leaf="">], embedding)</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.memories = [] </span><span><span leaf=""># 元数据存储</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">_importance_score</span></span><span leaf="">(</span><span><span leaf="">self, text: </span><span><span leaf="">str</span></span></span><span leaf="">) -> </span><span><span leaf="">float</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf="">"""让 LLM 评估记忆重要性 (1-10)"""</span></span><br><span leaf=""> prompt = </span><span><span leaf="">f"""评估以下信息的重要性,返回 1-10 的整数,只返回数字:</span><br><span leaf=""> 信息:</span><span><span leaf="">{text}</span></span><span leaf="">"""</span></span><br><span leaf=""> score = </span><span><span leaf="">self</span></span><span leaf="">.llm.invoke(prompt).content</span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> </span><span><span leaf="">float</span></span><span leaf="">(score.strip()) / </span><span><span leaf="">10.0</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">_recency_score</span></span><span leaf="">(</span><span><span leaf="">self, timestamp: </span><span><span leaf="">float</span></span><span leaf="">, decay_factor: </span><span><span leaf="">float</span></span><span leaf=""> = </span><span><span leaf="">0.99</span></span></span><span leaf="">) -> </span><span><span leaf="">float</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf="">"""时效性衰减分数"""</span></span><br><span leaf=""> hours_passed = (time.time() - timestamp) / </span><span><span leaf="">3600</span></span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> math.</span><span><span leaf="">pow</span></span><span leaf="">(decay_factor, hours_passed)</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">add_memory</span></span><span leaf="">(</span><span><span leaf="">self, text: </span><span><span leaf="">str</span></span></span><span leaf="">):</span><br><span leaf=""> importance = </span><span><span leaf="">self</span></span><span leaf="">._importance_score(text)</span><br><span leaf=""> metadata = {</span><br><span leaf=""> </span><span><span leaf="">"timestamp"</span></span><span leaf="">: time.time(),</span><br><span leaf=""> </span><span><span leaf="">"importance"</span></span><span leaf="">: importance,</span><br><span leaf=""> </span><span><span leaf="">"text"</span></span><span leaf="">: text</span><br><span leaf=""> }</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.memories.append(metadata)</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.vectorstore.add_texts([text], metadatas=[metadata])</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">retrieve</span></span><span leaf="">(</span><span><span leaf="">self, query: </span><span><span leaf="">str</span></span><span leaf="">, top_k: </span><span><span leaf="">int</span></span><span leaf=""> = </span><span><span leaf="">5</span></span></span><span leaf="">) -> </span><span><span leaf="">list</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf="">"""综合相关性 + 重要性 + 时效性排序"""</span></span><br><span leaf=""> docs_scores = </span><span><span leaf="">self</span></span><span leaf="">.vectorstore.similarity_search_with_score(query, k=</span><span><span leaf="">20</span></span><span leaf="">)</span><br><span leaf=""> </span><br><span leaf=""> results = []</span><br><span leaf=""> </span><span><span leaf="">for</span></span><span leaf=""> doc, relevance_score </span><span><span leaf="">in</span></span><span leaf=""> docs_scores:</span><br><span leaf=""> meta = doc.metadata</span><br><span leaf=""> recency = </span><span><span leaf="">self</span></span><span leaf="">._recency_score(meta[</span><span><span leaf="">"timestamp"</span></span><span leaf="">])</span><br><span leaf=""> importance = meta[</span><span><span leaf="">"importance"</span></span><span leaf="">]</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 综合得分(权重可调)</span></span><br><span leaf=""> final_score = (</span><br><span leaf=""> </span><span><span leaf="">0.5</span></span><span leaf=""> * (</span><span><span leaf="">1</span></span><span leaf=""> - relevance_score) + </span><span><span leaf=""># 相关性(转为正向)</span></span><br><span leaf=""> </span><span><span leaf="">0.3</span></span><span leaf=""> * importance + </span><span><span leaf=""># 重要性</span></span><br><span leaf=""> </span><span><span leaf="">0.2</span></span><span leaf=""> * recency </span><span><span leaf=""># 时效性</span></span><br><span leaf=""> )</span><br><span leaf=""> results.append((doc.page_content, final_score))</span><br><span leaf=""> </span><br><span leaf=""> results.sort(key=</span><span><span leaf="">lambda</span></span><span leaf=""> x: x[</span><span><span leaf="">1</span></span><span leaf="">], reverse=</span><span><span leaf="">True</span></span><span leaf="">)</span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> results[:top_k]</span>
四、行业通用解决方案
4.1 客服与对话场景
问题: 客服 Agent 需要记住同一用户在多次咨询中描述的问题、偏好,避免用户重复陈述。
解决方案架构:
<span leaf="">用户请求</span><br><span leaf=""> │</span><br><span leaf=""> ▼</span><br><span leaf="">用户身份识别(user_id)</span><br><span leaf=""> │</span><br><span leaf=""> ├─► 加载短期记忆(本次会话摘要)</span><br><span leaf=""> ├─► 检索长期记忆(该用户历史问题向量检索)</span><br><span leaf=""> └─► 检索用户画像(结构化:偏好、购买记录、等级)</span><br><span leaf=""> │</span><br><span leaf=""> ▼</span><br><span leaf="">LLM 生成回复(融合三类记忆)</span><br><span leaf=""> │</span><br><span leaf=""> ▼</span><br><span leaf="">记忆写回(重要信息提取 → 向量化存储)</span>
<span><span leaf="">class</span></span><span leaf=""> </span><span><span leaf="">CustomerServiceMemory</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf="">"""客服场景记忆系统"""</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">__init__</span></span><span leaf="">(</span><span><span leaf="">self, user_id: </span><span><span leaf="">str</span></span><span leaf="">, vectorstore, db</span></span><span leaf="">):</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.user_id = user_id</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.vectorstore = vectorstore</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.db = db </span><span><span leaf=""># 结构化用户画像数据库</span></span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">load_context</span></span><span leaf="">(</span><span><span leaf="">self, current_query: </span><span><span leaf="">str</span></span></span><span leaf="">) -> </span><span><span leaf="">dict</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf=""># 1. 结构化画像</span></span><br><span leaf=""> profile = </span><span><span leaf="">self</span></span><span leaf="">.db.get_user_profile(</span><span><span leaf="">self</span></span><span leaf="">.user_id)</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf=""># 2. 语义检索历史问题(相关问题优先)</span></span><br><span leaf=""> collection = </span><span><span leaf="">self</span></span><span leaf="">.vectorstore.as_retriever(</span><br><span leaf=""> search_kwargs={</span><br><span leaf=""> </span><span><span leaf="">"k"</span></span><span leaf="">: </span><span><span leaf="">3</span></span><span leaf="">,</span><br><span leaf=""> </span><span><span leaf="">"filter"</span></span><span leaf="">: {</span><span><span leaf="">"user_id"</span></span><span leaf="">: </span><span><span leaf="">self</span></span><span leaf="">.user_id}</span><br><span leaf=""> }</span><br><span leaf=""> )</span><br><span leaf=""> history_docs = collection.invoke(current_query)</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> {</span><br><span leaf=""> </span><span><span leaf="">"user_profile"</span></span><span leaf="">: profile,</span><br><span leaf=""> </span><span><span leaf="">"relevant_history"</span></span><span leaf="">: [d.page_content </span><span><span leaf="">for</span></span><span leaf=""> d </span><span><span leaf="">in</span></span><span leaf=""> history_docs]</span><br><span leaf=""> }</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">save_interaction</span></span><span leaf="">(</span><span><span leaf="">self, query: </span><span><span leaf="">str</span></span><span leaf="">, response: </span><span><span leaf="">str</span></span><span leaf="">, summary: </span><span><span leaf="">str</span></span></span><span leaf="">):</span><br><span leaf=""> </span><span><span leaf=""># 只存摘要,减少存储成本</span></span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.vectorstore.add_texts(</span><br><span leaf=""> [summary],</span><br><span leaf=""> metadatas=[{</span><br><span leaf=""> </span><span><span leaf="">"user_id"</span></span><span leaf="">: </span><span><span leaf="">self</span></span><span leaf="">.user_id,</span><br><span leaf=""> </span><span><span leaf="">"timestamp"</span></span><span leaf="">: time.time(),</span><br><span leaf=""> </span><span><span leaf="">"type"</span></span><span leaf="">: </span><span><span leaf="">"interaction_summary"</span></span><br><span leaf=""> }]</span><br><span leaf=""> )</span>
4.2 代码开发辅助场景
问题: 开发助手 Agent 需要记住项目结构、技术栈、团队编码规范、历史 Bug 经验。
解决方案: 分层记忆设计
<span><span leaf="">class</span></span><span leaf=""> </span><span><span leaf="">DevAssistantMemory</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf="">"""开发助手记忆系统"""</span></span><br><span leaf=""> </span><br><span leaf=""> MEMORY_TYPES = {</span><br><span leaf=""> </span><span><span leaf="">"project_context"</span></span><span leaf="">: </span><span><span leaf="">"项目元数据(技术栈、架构)"</span></span><span leaf="">,</span><br><span leaf=""> </span><span><span leaf="">"code_pattern"</span></span><span leaf="">: </span><span><span leaf="">"编码模式与最佳实践"</span></span><span leaf="">,</span><br><span leaf=""> </span><span><span leaf="">"bug_experience"</span></span><span leaf="">: </span><span><span leaf="">"历史 Bug 与修复经验"</span></span><span leaf="">,</span><br><span leaf=""> </span><span><span leaf="">"team_convention"</span></span><span leaf="">: </span><span><span leaf="">"团队规范与约定"</span></span><span leaf="">,</span><br><span leaf=""> }</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">__init__</span></span><span leaf="">(</span><span><span leaf="">self, project_id: </span><span><span leaf="">str</span></span><span leaf="">, vectorstore</span></span><span leaf="">):</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.project_id = project_id</span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.vectorstore = vectorstore</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">add_bug_experience</span></span><span leaf="">(</span><span><span leaf="">self, bug_desc: </span><span><span leaf="">str</span></span><span leaf="">, root_cause: </span><span><span leaf="">str</span></span><span leaf="">, fix: </span><span><span leaf="">str</span></span></span><span leaf="">):</span><br><span leaf=""> </span><span><span leaf="">"""记录 Bug 修复经验,供未来类似问题检索"""</span></span><br><span leaf=""> content = </span><span><span leaf="">f"""</span><br><span leaf=""> Bug描述:</span><span><span leaf="">{bug_desc}</span></span><br><span leaf=""> 根本原因:</span><span><span leaf="">{root_cause}</span></span><br><span leaf=""> 修复方案:</span><span><span leaf="">{fix}</span></span><br><span leaf=""> """</span></span><br><span leaf=""> </span><span><span leaf="">self</span></span><span leaf="">.vectorstore.add_texts(</span><br><span leaf=""> [content],</span><br><span leaf=""> metadatas=[{</span><br><span leaf=""> </span><span><span leaf="">"project_id"</span></span><span leaf="">: </span><span><span leaf="">self</span></span><span leaf="">.project_id,</span><br><span leaf=""> </span><span><span leaf="">"type"</span></span><span leaf="">: </span><span><span leaf="">"bug_experience"</span></span><span leaf="">,</span><br><span leaf=""> </span><span><span leaf="">"timestamp"</span></span><span leaf="">: time.time()</span><br><span leaf=""> }]</span><br><span leaf=""> )</span><br><span leaf=""> </span><br><span leaf=""> </span><span><span leaf="">def</span></span><span leaf=""> </span><span><span leaf="">retrieve_relevant_experience</span></span><span leaf="">(</span><span><span leaf="">self, current_issue: </span><span><span leaf="">str</span></span></span><span leaf="">) -> </span><span><span leaf="">list</span></span><span leaf="">:</span><br><span leaf=""> </span><span><span leaf="">"""遇到新问题时,检索历史经验"""</span></span><br><span leaf=""> docs = </span><span><span leaf="">self</span></span><span leaf="">.vectorstore.similarity_search(</span><br><span leaf=""> current_issue,</span><br><span leaf=""> k=</span><span><span leaf="">3</span></span><span leaf="">,</span><br><span leaf=""> </span><span><span leaf="">filter</span></span><span leaf="">={</span><br><span leaf=""> </span><span><span leaf="">"project_id"</span></span><span leaf="">: </span><span><span leaf="">self</span></span><span leaf="">.project_id,</span><br><span leaf=""> </span><span><span leaf="">"type"</span></span><span leaf="">: </span><span><span leaf="">"bug_experience"</span></span><br><span leaf=""> }</span><br><span leaf=""> )</span><br><span leaf=""> </span><span><span leaf="">return</span></span><span leaf=""> [d.page_content </span><span><span leaf="">for</span></span><span leaf=""> d </span><span><span leaf="">in</span></span><span leaf=""> docs]</span>
五、相关技术对比与关联
5.1 记忆系统 vs RAG(检索增强生成)
| 维度
|
记忆系统
|
RAG
数据来源
|
交互历史、Agent 自身经验
|
外部静态知识库
| |
更新频率
|
实时、持续更新
|
批量离线更新
| |
个性化
|
用户/Agent 专属
|
通常共享
| |
遗忘机制
|
需要(TTL、重要性淘汰)
|
通常不需要
| |
目标
|
经验积累与个性化
|
知识注入
|
结合使用: 记忆系统 + RAG 是互补的:RAG 提供领域知识底座,记忆系统提供个人化、历史化的动态上下文。
5.2 与知识图谱的关系
知识图谱可以作为语义记忆的存储后端,提供结构化的实体关系记忆:
<span><span leaf="">from</span></span><span leaf=""> langchain_community.graphs </span><span><span leaf="">import</span></span><span leaf=""> Neo4jGraph</span><br><br><span leaf="">graph = Neo4jGraph(url=</span><span><span leaf="">"bolt://localhost:7687"</span></span><span leaf="">, ...)</span><br><br><span><span leaf=""># 将记忆以图结构存储:用户 → 偏好 → 技术栈</span></span><br><span leaf="">graph.query(</span><span><span leaf="">"""</span><br><span leaf=""> MERGE (u:User {id: $user_id})</span><br><span leaf=""> MERGE (t:Technology {name: $tech})</span><br><span leaf=""> MERGE (u)-[:PREFERS {strength: $strength}]->(t)</span><br><span leaf="">"""</span></span><span leaf="">, {</span><span><span leaf="">"user_id"</span></span><span leaf="">: </span><span><span leaf="">"u001"</span></span><span leaf="">, </span><span><span leaf="">"tech"</span></span><span leaf="">: </span><span><span leaf="">"Python"</span></span><span leaf="">, </span><span><span leaf="">"strength"</span></span><span leaf="">: </span><span><span leaf="">0.9</span></span><span leaf="">})</span>
5.3 与 ReAct / Plan-and-Execute 的关系
记忆系统是 Agent 推理框架的基础设施:
-
• ReAct Agent:每步 Thought/Action/Observation 可以写入情节记忆,下次遇到类似任务直接复用推理链
-
• Plan-and-Execute:计划阶段检索历史相似任务的执行经验,优化规划质量
六、前沿进展与发展展望
6.1 当前主要研究方向
① Generative Agents(斯坦福,2023)
提出完整的 Agent 记忆架构:记忆流(Memory Stream)+ 反思(Reflection)+ 计划(Planning)。反思机制让 Agent 定期对记忆进行高层归纳,形成抽象洞见。
② MemGPT(2023)
借鉴操作系统虚拟内存思想,把 LLM 上下文窗口视为内存,外部存储视为磁盘,Agent 自主管理内存的换入换出。
③ A-MEM(2024)
动态记忆网络,让 Agent 在记忆之间建立关联链接,类似人类联想记忆。
6.2 技术挑战
| 挑战
|
描述
|
研究方向
记忆一致性
|
相互矛盾的记忆如何处理
|
记忆冲突检测与合并
| |
隐私安全
|
记忆可能包含敏感信息
|
差分隐私、记忆脱敏
| |
幻觉记忆
|
Agent 可能"记住"从未发生的事
|
记忆验证机制
| |
跨 Agent 记忆共享
|
多 Agent 协作时记忆同步
|
分布式记忆协议
| |
长期记忆压缩质量
|
LLM 摘要可能丢失关键细节
|
结构化提取 + 向量双存
|
6.3 发展趋势
近期:
-
• 记忆系统框架标准化(LangChain Memory v2、LlamaIndex Memory Modules)
-
• 向量数据库与关系数据库的融合(如 pgvector)
-
• 端侧轻量记忆系统(手机/IoT Agent)
中期:
-
• 记忆与微调的融合:重要记忆直接更新模型权重(LoRA 动态更新)
-
• 跨模态记忆:图像、音频、代码统一向量空间
-
• 联邦记忆:多端记忆隐私保护同步
长期展望:
-
• 真正连续学习的 Agent:记忆系统 + 在线学习,Agent 在使用中持续进化
-
• 记忆作为 Agent 的"人格"基础:稳定、可解释、可审计
七、总结
Agent 记忆系统是让 AI 从"工具"走向"伙伴"的关键基础设施。
| 维度
|
核心要点
架构
|
工作记忆 + 情节记忆 + 语义记忆 + 过程记忆分层设计
| |
存储
|
向量数据库(语义检索)+ 关系数据库(结构化)+ KG(关系网络)
| |
检索
|
相关性 × 重要性 × 时效性三维加权
| |
遗忘
|
TTL + LRU + 重要性阈值,避免记忆膨胀
| |
工程
|
LangChain Memory 模块提供开箱即用实现
| |
未来
|
迈向持续学习、跨模态、隐私保护的统一记忆平台
|
记忆系统的成熟,将使 Agent 真正具备"经验”——不再是每次归零的问答机器,而是能从每一次交互中成长的智能实体。
持续更新中,关注我获取更多干货
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/ai002/post/20260822/Agent-%E8%AE%B0%E5%BF%86%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1%E4%B8%8ELangChain-%E5%AE%9E%E8%B7%B5/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com