Dev Log · Source Walkthrough · 承接上篇:记忆架构

从源码看 X02 如何完成一次「记忆召回」

当用户说「继续昨天的工作」时,X02 到底如何判断需要回忆、怎样搜索历史,以及如何把记忆重新放回当前 Prompt。

前面介绍的是 Operator X02 的记忆设计理念。这一节进一步从源码角度说明整个召回流程。

X02 的 AI 记忆相关代码主要位于:

src/ide/aiAssistant/

conversationManager.ts保存用户可以看到的完整聊天记录
aiHistorySearch.ts建立长期记忆索引、判断是否需要回忆、搜索相关历史
apiProviderManager.ts组合最近对话、相关记忆和系统提示,形成最终 Prompt
contextStatusBar.ts显示消息、文件、工程决定和上下文负载信息

X02 并不是把完整历史记录直接发给模型,而是将「聊天显示」和「AI 记忆召回」分成两个不同的系统

STEP 01完整聊天与长期记忆分开保存

X02 使用两个独立的本地存储。

ai_conversations

完整对话

聊天侧边栏、历史会话显示、重新打开旧聊天。

= 完整会议录像
ai_conversation_history_v3

记忆索引

不是完整聊天副本,而是面向搜索的记忆索引。

  • userMessage
  • assistantResponse
  • keywords
  • topics
  • timestamp
  • referenceCount
  • summary
  • decayScore
= 整理好的会议索引卡

用户需要查看完整对话时,X02 打开「录像」;AI 需要回忆旧知识时,X02 搜索「索引卡」。这种分离可以避免每次请求都重新加载全部历史内容。

STEP 02先判断这次是否真的需要回忆

引擎挂在全局 window.aiHistorySearchapiProviderManager.ts 调用它的 intelligentHistorySearch(message)。整个过程分两个阶段 —— 这也是省 token 的关键

记忆搜索并不会在每一条消息中执行。X02 首先通过 aiHistorySearch.ts 中的 shouldSearchHistory(message) 判断当前用户输入是否依赖过去的信息。

例如「继续之前那个功能。」「和上一次的方法比较。」「昨天那个 CAN Bug 怎么解决的?」这些语句包含:

因此会触发长期记忆搜索。但如果用户只是问「什么是 Python?」或「生成一个 Hello World。」,系统通常不会搜索历史。

用户消息 触发门 shouldSearchHistory 5 类正则(≈140+ 条) 不中 跳过 不搜 · 不注入 · 0 token 命中 混合搜索 hybridSearch 关键词 + 主题 + 时效 localStorage ≤ 150 · 14 天衰减 注入上下文 · top 5 · 截断

图 · 触发不中 → 直接跳过(零开销);命中才本地搜索并注入

这是 X02 节省 Context 的一个重要设计 —— 不是每一轮都搜索全部记忆,而是只有真正需要时才回忆。如果触发条件没有命中,系统会返回:

{ should: false, reason: "No history search needed" }

这意味着本轮不会加入额外的历史记忆,也不会浪费相关 Token。

阶段一:触发门shouldSearchHistory(message)

  • 先排除机器生成内容[X02 TOOL RESULT][PROJECT CONTEXT]、banner),否则会误触发、让 reference count 失控。
  • 依次匹配 5 类正则:explicitReferences · ambiguousPronouns · followUpPatterns · comparisonPatterns · projectReferences(仅当消息 < 150 字符)。
  • 命中任一 → 继续搜索;都不中 → 不搜、不注入(零 token)

阶段二:混合搜索hybridSearch(query)

  • 对每条历史算加权分数,阈值 ≥ 0.25,取 top 5(见下一节)。

STEP 03通过混合评分寻找最相关的记忆

确认需要回忆后,X02 会调用 hybridSearch(query) 对历史记忆进行评分。当前快速模式主要考虑三个维度:

总相关度

关键词 · 主题 · 时效的加权组合

关键词匹配0.45
主题匹配0.30
时间相关性0.25

例如用户问:「继续之前的 CAN Timeout 修复。」

A:修复 CAN Timeout 问题 0.91
B:修改 React 登录页面 0.18
C:讨论 ADAS 安全目标 0.33

╎ 过滤线 0.25 —— 低于此值的结果直接丢弃

过滤之后按得分从高到低排列,最终最多保留 Top 5。也就是说,即使本地存储了 150 条历史记录,本轮也不会全部放入 Prompt —— 它只选择最相关的几条。

STEP 04旧记忆会自然衰减

像人一样会遗忘:相关度随时间指数衰减,但被引用越多衰减越慢calculateDecayScore(entry) 会根据记忆年龄和引用次数调整权重,当前设计采用大约 14 天的衰减周期。

1.0 0 14 天 · 减半 被引用:衰减更慢 · 留存 无引用:快速衰减 时间(天) →

图 · e^(-age/14) 指数衰减;referenceBoost 让常用记忆「不会忘」

decay = e^(-ageDays / 14) // 14 天半衰期 + referenceBoost = min(referenceCount · 0.15, 0.5) // 被引用越多越慢 + recentRefBonus = 7 天内被引用过 ? 0.1 : 0 clamp 到 [0,1]

markAsReferenced(id):每次某条被召回就 referenceCount++ → 常用的几乎不衰减,没人碰的沉底、到 150 上限被裁掉。

Reinforced

项目一直使用 AUTOSAR

经常被搜索和引用,referenceCount 增加并得到额外加成,长期保持较高权重。

Faded

测试一个已经删除的 UI 按钮

很久以前、再也没有使用过,逐渐沉到记忆列表底部,并可能在达到 150 条存储上限时被裁剪。

这使 X02 的长期记忆更像人类:经常使用的知识越来越牢固,不再使用的信息逐渐淡化。

STEP 05把记忆重新注入当前 Prompt

完成搜索之后,apiProviderManager.ts 开始构建最终请求。最近对话使用 historyMsgs.slice(-10),每条消息再限制到大约 600 字符 —— 这部分相当于 X02 的 Working Memory

然后系统调用 window.aiHistorySearch.intelligentHistorySearch(message)。如果 shouldSearch = true 并且找到相关记忆,X02 就把这些结果组合成一条新的 system message。单条召回结果还会进一步截断:用户消息最多约 200 字符,助手回答最多约 400 字符。

System Prompt 系统提示
+
最近 10 条消息 Working Memory · 每条 ≤ 600 字符
+
Top-5 相关长期记忆 200 / 400 字符截断
+
当前用户输入 Current Thinking
=
Final Prompt

这意味着 X02 不会让长期记忆直接取代当前对话。长期记忆只是作为辅助背景加入,让模型知道:之前发生了什么、过去作出了什么决定、当前任务和哪个旧项目有关。

EXAMPLE一个完整例子

假设昨天用户和 X02 讨论:CAN Driver 在高负载下出现 Timeout,最终决定增加重试机制,并将等待时间调整到 100 ms。今天用户只输入「继续昨天那个问题。」X02 的内部流程大致如下:

  1. 收到用户消息「继续昨天那个问题」
  2. shouldSearchHistory()识别到「继续」和「昨天」 → 需要搜索历史
  3. hybridSearch()搜索关键词、主题和近期记录
  4. 找到高相关记忆「CAN Driver Timeout」「增加重试机制」「等待时间调整到 100 ms」
  5. 取 Top 结果并截断只保留最相关的几条
  6. apiProviderManager.ts 组装 Prompt系统提示 + 最近聊天 + 相关记忆 + 当前请求
  7. 发送给模型Final Prompt
  8. 模型继续昨天的工程工作用户不需要重新解释整个问题,模型也不需要重新阅读全部历史聊天。

WHY为什么这比单纯 Token Window 更像工程师?

Token Window 主要解决「模型最多可以接收多少内容」。而 X02 的记忆系统解决的是:当前应该记住什么、什么时候需要回忆、哪些旧知识更重要、哪些内容可以逐渐忘记。因此 X02 的架构可以分为两个层次:

Cognitive

认知层

  • Working Memory
  • Long-term Memory
  • Recall Engine

决定「该想什么」

Resource · 未来加入

资源层

  • Token Budget Manager

决定「最多能放多少」

这两者结合后,才会形成一个完整的 AI 工程记忆系统。

TUNING想改哪里就改哪个

这套记忆系统的每一个行为都对应一处具体的符号 —— fork 之后想调整,直接改这些:

想改的东西
文件 / 符号
什么算「要记住」的触发
aiHistorySearch.ts · HISTORY_TRIGGER_PATTERNS
相关度权重 / 阈值 / top-K
CONFIG.weights · minRelevanceScore · maxHistoryResults
衰减速度 / 存储上限
decayHalfLifeDays · MAX_STORED_CONVERSATIONS
开启语义搜索
CONFIG.enableEmbeddings / enableAISearch
最近窗口大小 / 截断
apiProviderManager.ts · slice(-10) / substring(0,600)
上下文大小估算公式
contextStatusBar.ts · contextSizeEstimate

STATUS当前源码设计的技术特点

未来可以升级的方向

目前的 X02 设计已经建立了一个清晰的工程记忆基础。下一步不是推翻当前架构,而是在其上加入:真实 Token Budget、本地语义重排、记忆类型分类、冲突检测、Memory Inspector

这样 X02 就能同时拥有:类人的记忆管理方式,以及机器级的精确资源控制。