Back to Blog
New Features2026-05-3012 min read

Curing AI Amnesia: Cross-Session Experience Knowledge Graph Makes AI Smarter Over Time

Building ExperienceStore for automatic diagnostic experience recording, semantic retrieval of historical solutions, and cross-session knowledge accumulation.

WeClaw_59_AI的"失忆症"处方:跨会话经验知识图谱让AI越用越聪明

系列文章第 59 篇 - 从"每次修 Bug 都从零开始"到"越用越聪明的个人助手"


📚 专栏信息

《从零到一构建跨平台 AI 助手:WeClaw 实战指南》专栏

本文是模块十第 2 篇,探讨如何用 SQLite + 向量检索为 AI 构建"经验记忆",让每一次自我修正都能复用上一次的智慧。

👨‍💻 作者与项目

作者简介:翁勇刚 WENG YONGGANG
新概念龙虾-WeClaw 开发团队负责人,一群专注于跨平台 AI 应用的实践者
理念:"再复杂的技术,也能用代码讲清楚"

📝 摘要

本文结构概览: 本文从两个"表面不同、根因相同"的真实 Bug 修复场景切入,揭示 AI 助手的核心体验缺陷——跨会话失忆症。然后设计 ExperienceStore(经验知识图谱)的 SQLite + 向量双存储架构,展示"记录经验 → 语义检索 → 上下文注入"的完整数据流,探讨经验泛化这一核心难点,最后给出经验积累系统的 Do's/Don'ts 清单。

背景:WeClaw 已经具备自我反思闭环(感知 → 诊断 → 修复 → 重启),但每次对话是无状态的。第 1 周花了 30 分钟修复 stock_query 的浮点解析 Bug,第 3 周 log_viewer 出现类似的编码问题时,AI 完全不记得上次的"防御性数据解析"经验,又从零分析了一遍。

核心问题:如何让 AI 在跨会话场景下积累经验,实现"越用越聪明"而非"每次从零开始"?

解决方案:构建 ExperienceStore,在每次自我修正闭环完成后自动记录结构化经验(trigger / diagnosis / fix / outcome),下次遇到类似问题时通过向量检索召回历史经验,注入 System Prompt 供 LLM 参考。

关键成果

  • 设计了 experience 数据模型(7 字段 + 向量 embedding)
  • 复用现有 embedding 模型和 SQLite 基础设施,零额外依赖
  • 提出"经验泛化"问题的 LLM 辅助抽象方案
  • 明确经验积累 vs 自主目标设定的投入产出比判断

适合读者:对 AI Agent 记忆系统、向量检索、知识图谱感兴趣的开发者

阅读时长:约 14 分钟

关键词经验积累向量检索跨会话记忆知识图谱Embedding语义搜索System Prompt


一、AI 的"失忆症"——一个被忽视的核心体验缺陷

1.1 两个场景,同一个根因

想象这两个真实场景:

第 1 周

用户:"stock_query 查询港股价格时报错了。"

AI 花 30 分钟排查,发现问题根因:外部 API 返回的价格字段有时是字符串 "N/A",直接 float() 转换导致 ValueError。

修复方案:引入 float_or_none() 安全转换函数,对无法解析的值返回 None 而非抛异常。

第 3 周

用户:"log_viewer 读取日志时出现编码异常。"

AI 从零开始分析,花了 20 分钟排查。发现根因:日志文件中的某些行包含非 UTF-8 字符,直接读取导致 UnicodeDecodeError。

修复方案:open() 时添加 errors="replace" 参数。

发现问题了吗?

┌──────────────────────────────────────────────────────┐
│                                                      │
│  stock_query Bug         log_viewer Bug              │
│  ──────────────          ──────────────              │
│  外部 API 返回 "N/A"     日志文件含非 UTF-8 字符       │
│       ↓                       ↓                      │
│  直接 float() 转换        直接 open() 读取             │
│       ↓                       ↓                      │
│  ValueError              UnicodeDecodeError          │
│       ↓                       ↓                      │
│  修复:防御性转换          修复:防御性读取             │
│                                                      │
│  共同根因:外部数据未做防御性解析                        │
│                                                      │
│  但 AI 在第 3 周完全不知道第 1 周的经验!               │
└──────────────────────────────────────────────────────┘

1.2 失忆症的本质:无状态对话架构

WeClaw 当前每次对话是无状态的。虽然 chat_history 可以检索历史对话文本,但它只存储原始聊天消息,不存储结构化的"诊断经验"。

维度chat_history(已有)ExperienceStore(需要)
存储内容原始对话文本结构化经验记录
检索方式关键词匹配向量语义检索
信息密度低(大量闲聊夹杂少量技术信息)高(每条记录都是提炼后的诊断结论)
跨会话可用部分(需手动翻阅)自动注入
适合场景"我们上周聊了什么?""上次类似的 Bug 是怎么修的?"

chat_history 不是不能用,而是用不好。让 AI 从几百条对话记录中找到"上次类似的 Bug 修复经验",就像让你在微信聊天记录里找"上次那个修水管师傅的电话"——技术上可行,体验上痛苦。

1.3 产品差异化:"越用越聪明"

这其实是 WeClaw 与普通 AI 助手的核心差异点。用户会感受到:

"它记得上次帮我修了什么,这次直接告诉我可能是类似的问题——这个 AI 在成长。"

这种体验粘性远强于每次对话都从零开始的竞品。


二、ExperienceStore 架构设计——SQLite + 向量的双存储方案

2.1 核心数据模型

每条经验记录包含 7 个结构化字段 + 1 个向量 embedding:

┌─────────────────────────────────────────────────────┐
│                  Experience 数据模型                  │
│                                                     │
│  ┌─────────────┐  ┌─────────────────────────────┐   │
│  │ 结构化字段   │  │ trigger: "tool_audit错误率上升" │   │
│  │ (SQLite)    │  │ diagnosis: "浮点解析bug"      │   │
│  │             │  │ fix: "添加float_or_none()"   │   │
│  │             │  │ outcome: "success"           │   │
│  │             │  │ related_files: ["stock.py"]  │   │
│  │             │  │ pattern: "防御性数据解析"      │   │  ← 抽象化标签
│  │             │  │ created: "2026-05-29"        │   │
│  └─────────────┘  └─────────────────────────────┘   │
│                                                     │
│  ┌─────────────┐  ┌─────────────────────────────┐   │
│  │ 向量字段     │  │ embedding: [0.12, -0.34,    │   │
│  │ (向量索引)   │  │   0.56, ...] (384维)        │   │
│  │             │  │                              │   │
│  │             │  │ 编码内容: trigger + diagnosis │   │
│  │             │  │           + fix + pattern    │   │
│  └─────────────┘  └─────────────────────────────┘   │
└─────────────────────────────────────────────────────┘

2.2 完整数据流

                    自我修正闭环完成
                         │
                         ▼
              ┌─────────────────────┐
              │  ExperienceStore    │
              │  .record()          │
              │                     │
              │  1. 提取结构化字段    │
              │  2. LLM 抽象化       │
              │     → pattern 标签   │
              │  3. Embedding 编码   │
              │  4. 写入 SQLite      │
              └────────┬────────────┘
                       │
                       │ 下次遇到类似问题
                       ▼
              ┌─────────────────────┐
              │  ExperienceStore    │
              │  .recall()          │
              │                     │
              │  1. 编码当前问题      │
              │  2. 向量相似度检索    │
              │  3. 返回 Top-K 经验   │
              └────────┬────────────┘
                       │
                       ▼
              ┌─────────────────────┐
              │  System Prompt      │
              │  注入相关经验         │
              │                     │
              │  "历史经验参考:       │
              │   3周前修复过类似     │
              │   的防御性解析问题..." │
              └─────────────────────┘

2.3 为什么选择 SQLite + 向量而非纯向量数据库?

方案优势劣势适合场景
纯向量数据库(如 Milvus)高性能检索额外依赖、运维成本高大规模 SaaS
纯 SQLite + 全文搜索零依赖、简单只能关键词匹配,无法语义检索简单日志
SQLite + 内嵌向量零额外依赖、语义检索、事务安全向量维度受限个人桌面应用

WeClaw 选择第三种方案。已有的基础设施几乎可以直接复用:

  • resources/embedding_models/:本地 embedding 模型(已部署)
  • SQLite:项目核心数据库引擎(已使用)
  • System Prompt 注入:已有的上下文管理机制

三、实战代码详解——ExperienceStore 的概念实现

3.1 经验记录与检索

以下是 ExperienceStore 的核心逻辑(概念版,展示设计思路):

class ExperienceStore:
    """跨会话经验知识图谱。
    
    在每次自我修正闭环完成后自动记录经验,
    下次遇到类似问题时通过向量检索召回历史经验。
    """

    def record(self, trigger, diagnosis, fix, outcome, files):
        """记录一次自我修正经验。"""
        
        # Step 1: 用 LLM 做抽象化,提取通用 pattern
        pattern = self._extract_pattern(trigger, diagnosis, fix)
        # 例:trigger="stock_query浮点错误", fix="float_or_none()"
        #   → pattern="防御性数据解析"
        
        # Step 2: 生成语义向量
        text = f"{trigger} {diagnosis} {fix} {pattern}"
        embedding = self.embedder.encode(text)
        
        # Step 3: 写入 SQLite
        self.db.execute("""
            INSERT INTO experiences 
            (trigger, diagnosis, fix, outcome, pattern, 
             related_files, embedding, created)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        """, (trigger, diagnosis, fix, outcome, pattern,
              json.dumps(files), embedding, datetime.now()))

    def recall(self, current_problem: str, top_k: int = 5):
        """检索与当前问题最相似的历史经验。"""
        query_emb = self.embedder.encode(current_problem)
        
        # 向量余弦相似度检索
        return self.db.vector_search(
            table="experiences",
            query_vector=query_emb,
            top_k=top_k
        )

3.2 经验抽象化:从具体 Fix 到通用 Pattern

_extract_pattern() 是整个系统最关键的一步。如果只记录"stock_query 的 float() 改成了 float_or_none()",那这条经验只对 stock_query 有用。我们需要 LLM 做抽象:

def _extract_pattern(self, trigger, diagnosis, fix) -> str:
    """用 LLM 从具体修复中提炼通用模式。"""
    prompt = f"""
    以下是 AI 系统的一次自我修复记录:
    - 触发:{trigger}
    - 诊断:{diagnosis}  
    - 修复:{fix}
    
    请用 3-5 个字概括这类问题的通用模式(如"防御性数据解析"、
    "并发竞态保护"、"编码兼容处理"),只输出模式名称。
    """
    return self.llm.generate(prompt, max_tokens=20)

这个抽象化步骤的价值:

具体记录(低泛化):
  "stock_query 的 float() 改为 float_or_none()"
  → 只对 stock_query 有用

抽象记录(高泛化):
  pattern = "防御性数据解析"
  → 对 log_viewer 编码问题、API 响应解析问题都有参考价值

3.3 与 System Prompt 的集成

在每次新对话开始或自我反思触发时,自动将相关经验注入上下文:

async def inject_experience_context(self, current_problem: str):
    """将相关历史经验注入 LLM 上下文。"""
    experiences = self.recall(current_problem, top_k=3)
    
    if not experiences:
        return ""
    
    context_lines = ["\n## 历史经验参考(自动检索)"]
    for i, exp in enumerate(experiences, 1):
        context_lines.append(
            f"\n{i}. [{exp.created[:10]}] {exp.pattern}\n"
            f"   触发:{exp.trigger}\n"
            f"   诊断:{exp.diagnosis}\n"
            f"   修复:{exp.fix}\n"
            f"   结果:{exp.outcome}"
        )
    
    return "\n".join(context_lines)

AI 看到的上下文注入效果:

## 历史经验参考(自动检索)

1. [2026-05-01] 防御性数据解析
   触发:stock_query 查询港股价格报错
   诊断:外部 API 返回 "N/A",直接 float() 转换失败
   修复:引入 float_or_none() 安全转换函数
   结果:success

2. [2026-05-15] 编码兼容处理
   触发:文件读取出现 UnicodeDecodeError
   诊断:日志文件含非 UTF-8 字符
   修复:open() 添加 errors="replace"
   结果:success

有了这段上下文,当 log_viewer 再次出现类似问题时,AI 会直接联想到"防御性数据解析"这个通用模式,而不是从零开始分析。


四、问题诊断与修复——经验系统的三个核心挑战

4.1 挑战一:经验噪声——"假经验"干扰决策

问题:并非所有修复都值得记录。如果 AI 修了一个 typo(变量名拼写错误),这条"经验"几乎没有复用价值,反而会在后续检索中成为噪声。

解决思路:引入经验质量评分机制。

# 记录时由 LLM 评估经验的复用价值
quality_prompt = """
评估以下修复经验的复用价值(1-5分):
- 1分:一次性问题(typo、配置错误)
- 3分:同类模块可能遇到(特定数据格式问题)
- 5分:通用模式(防御性解析、并发保护、编码兼容)
"""
# 只保存 quality >= 3 的经验

4.2 挑战二:经验膨胀——数据库越来越大,检索越来越慢

问题:随着使用时间增长,经验记录越来越多,向量检索的性能会下降,注入 System Prompt 的内容也会膨胀。

解决思路

┌──────────────────────────────────────────────┐
│              经验生命周期管理                    │
│                                              │
│  新增经验 → 活跃期(30天)→ 沉淀期 → 归档/淘汰   │
│                                              │
│  活跃期:全量参与检索                           │
│  沉淀期:仅 pattern 参与检索(摘要级别)          │
│  归档:outcome=failed 的经验 90 天后自动归档     │
│  淘汰:相似度 > 0.95 的经验合并去重              │
└──────────────────────────────────────────────┘

关键设计:相似经验合并。如果 3 条经验的 pattern 都是"防御性数据解析"且相似度 > 0.95,合并为一条"超级经验",记录多次修复的共同模式。

4.3 挑战三:经验误导——历史经验可能是错误的

问题:如果一次修复的 outcome 后来被证明是失败的(重启后问题依然存在),但经验已经被记录,后续可能会被错误地召回参考。

解决思路

# 闭环验证:重启后检查修复是否真正生效
async def verify_experience(self, experience_id: str):
    """重启后验证修复是否生效。"""
    exp = self.get(experience_id)
    
    # 检查相关错误是否不再出现
    recent_errors = await tool_audit.get_recent_errors(
        keyword=exp.trigger, hours=1
    )
    
    if recent_errors:
        # 修复失败,标记经验为无效
        self.update(experience_id, outcome="failed")
    else:
        # 修复成功,确认经验有效
        self.update(experience_id, outcome="verified")

教训:经验不是"记录了就完事",必须有闭环验证机制。一条被标记为 failed 的经验不会参与后续检索。


五、最佳实践——经验积累系统的设计原则

5.1 Do's / Don'ts

Do's(推荐做法):

  • 修复成功后才记录:只在自我修正闭环完成且验证成功后才调用 record()
  • 抽象化 pattern 标签:不只记具体 fix,更记通用 pattern
  • 限制注入数量:System Prompt 中最多注入 3-5 条经验,避免上下文膨胀
  • 经验去重合并:相似度 > 0.95 的经验自动合并,防止数据库膨胀
  • 闭环验证 outcome:重启后检查修复是否真正生效,失败经验标记为 failed
  • 复用现有基础设施:embedding 模型、SQLite 引擎、System Prompt 机制都是现成的

Don'ts(避免做法):

  • ❌ 不要记录 typo 类一次性修复(quality < 3)
  • ❌ 不要把完整代码 diff 存入经验——只存诊断思路和修复方案
  • ❌ 不要让经验注入占用过多 System Prompt 预算(建议 < 500 tokens)
  • ❌ 不要跳过闭环验证——未验证的经验可能是"毒药"
  • ❌ 不要在经验中存储用户敏感信息(遵循与 tool_audit 相同的脱敏原则)

5.2 投入产出比分析

在自我反思能力体系的后三项中,经验积累的投入产出比是最优的:

能力实现周期核心价值适用场景推荐优先级
跨会话经验积累1-2 周解决失忆症核心痛点所有对话场景P3(推荐)
自主设定改进目标2-4 周信号量不足(单用户)高并发 SaaS暂缓

为什么经验积累是刚需,自主目标是奢侈品?

WeClaw 是单用户桌面应用,日均交互量在几十到几百次级别,错误信号量不足以支撑"空闲自省"的统计显著性。每小时跑一次 LLM 分析,可能得到的结论是"今天一切正常"——白白消耗 API 费用。

而经验积累是被动触发的——只在自我修正闭环完成时才记录,零额外 API 消耗,零噪声产生。

5.3 黄金法则

让 AI "记住过去"比让 AI "主动思考未来"更实际。 对个人助手而言,经验积累是刚需,自主目标是奢侈品。先把"记忆力"做好,再考虑"想象力"。


六、总结与展望

6.1 核心要点回顾

本文从"失忆症"切入,设计了跨会话经验知识图谱:

3 个关键设计

  1. SQLite + 向量双存储:结构化字段用 SQLite 管理,语义检索用向量编码,零额外依赖
  2. LLM 辅助抽象化:不只记具体 fix,更记通用 pattern(如"防御性数据解析")
  3. 闭环验证机制:修复成功才记录,失败经验自动标记,未验证经验不参与检索

1 个核心公式

经验积累 = 结构化记录 + 语义检索 + 上下文注入 + 闭环验证

6.2 下一步学习方向

前置知识

  • ✅ 上一篇:《当 AI 学会"照镜子":自我反思闭环架构》
  • ✅ Embedding 模型原理与余弦相似度计算
  • ✅ System Prompt 上下文管理机制

后续主题

  • 📖 下一篇:《能力越强,护栏越硬:AI 自主进化的安全边界工程与核能类比》

6.3 互动环节

思考题

  1. 如果两条经验的 pattern 相同但 fix 不同(一个成功一个失败),系统应该如何处理?
  2. 经验注入 System Prompt 时,应该按时间排序还是按相似度排序?各有什么利弊?

讨论话题

你认为 AI 助手应该"记住"多少历史经验?如果记忆太多导致信息过载,该如何取舍?欢迎在评论区讨论。


下期预告:《能力越强,护栏越硬:AI 自主进化的安全边界工程与核能类比》

  • AI "突破沙箱"需要的六项能力,WeClaw 具备了几项?
  • 为什么说"权限提升"和"隐蔽行动"是真正的安全红线?
  • 能力-安全共演化:每扩展一项能力,需要多少安全护栏?

敬请期待!


附录 A:技术栈对比

组件已有基础设施ExperienceStore 复用方式
数据库引擎SQLite(tool_audit.db)新建 experience.db,同模式
向量编码resources/embedding_models/直接调用本地 embedding 模型
上下文注入System Prompt 构建机制在 prompt 组装阶段注入经验
触发时机自我反思闭环闭环最后一步自动 record()
检索时机自我反思第一步自动 recall() 并注入

附录 B:参考资料

  1. Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks
  2. SQLite Vector Search Extensions: sqlite-vec
  3. 上一篇:《当 AI 学会"照镜子":自我反思闭环架构从哲学之问到工程实践》
  4. 下一篇:《能力越强,护栏越硬:AI 自主进化的安全边界工程与核能类比》

版权声明:本文为 CSDN 博主「yweng18」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。