qqqide滴上下文背包设计

文档发表:2026-07-15 · 阅读:53 · 更新:2026-08-02

状态:V16 已落地。2026-07-23 定稿。


1. 起源 — 我们遇到了什么问题

你跟 AI 结对编程 50 层楼之后,每一层楼的完整对话(你的问题 + AI 的思考 + 工具调用 + 工具输出)都还躺在上下文窗口里。50 层楼 ≈ 250K tokens 起步。再往后,要么倾家荡产付 token 费,要么 AI 开始"遗忘"最早讨论过的架构决策。

更致命的是 缓存失效:大多数 LLM 服务商按 prompt tokens 计费,但对不变的前缀提供缓存折扣(prefix caching)。如果你每次发送新消息时都重建了整个上下文数组——即使 99% 的内容和上一轮一模一样——缓存全部失效,每一轮都按全新 prompt 计费。

三个问题纠缠在一起:

问题表现根因
上下文膨胀每层楼 ~5K tokens,50 层 = 250K工具输出(尤其是终端命令结果)原样保留
缓存失效实际计费 = 全量 tokens,非增量消息对象被替换或 splice → API 视为新内容
质量衰减旧上下文被截断 → AI 丢失早期决策被迫在 token 预算和上下文完整性之间做取舍

2026 年 6 月,我们开始系统性地解决这个问题。以下是完整的推演历程。


2. 架构推演 — V10 → V11 → V12 → V13 → V14 → V15 → V16

V10 · AI 语义压缩(已废弃)

思路:让 AI 自己压缩自己的历史——三专家模型并行,各自产出摘要,投票选最优。

失败原因

  • 质量不稳定:同一段对话,三次压缩结果不同。AI 有时会遗漏关键决策。
  • 缓存全断:压缩后的文本和原始对话完全不同 → 前缀缓存 0% 命中。
  • 费用悖论:压缩本身消耗 ~5K tokens(三专家 × 并行),加上缓存失效,反而不如不压缩。
  • 回滚漏洞:压缩失败时无法精确恢复到压缩前状态。

结论:AI 不适合做确定性压缩。压缩必须是纯本地、纯确定性的机械过程


V11 · 机械筛 + 追加式饼干(已废弃)

思路:不再让 AI 压缩。改为本地机械筛——逐条消息按固定规则转为 Q/A/工具摘要行。压缩结果(饼干)追加到 conversation 数组。

格式

[0] Z (规则/铁律)
[1] biscuitPrefix (旧楼层压缩)
[2] DE (不可恢复工具输出)
[3] biscuitLatest (最新楼层压缩)
[4] 当前楼层原始消息

失败原因 — splice 漏洞: 每次楼层完结时,旧的 biscuitLatest 被 splice 移除,新压缩内容作为新的消息对象注入。LLM API 看到消息对象变了 → 缓存从 biscuit 位置全部断裂。虽然内容只多了几行,但因为是新对象 → 全量重新编码。

实际效果:每层 ~15-40K tokens 计费(V10 的 38K 有所改善,但远未达预期)。


V12 · 原地追加,零 splice

核心洞察:缓存命中的关键不是"内容是否相似",而是消息对象是否同一个引用。只要消息对象不变,仅 content 字符串尾部增长,LLM API 就能识别前缀并给予缓存折扣。

改动

  • biscuit 消息对象永不替换,仅 content += 新饼干行
  • DE 消息对象永不替换,仅 content = 全新序列化(原地更新,但仍是同一对象)
  • 删除所有 splice 操作

效果

发送楼层 N+1 时的背包:
  [0] Z                     ← 100% 命中(永不变化)
  [1] biscuit msg           ← 前缀命中(对象不变,仅最后一行新)
  [2] DE msg                ← 前缀命中(对象不变,仅最后条目新)
  [3] user_msg F(N+1)       ← 新内容(唯一新 token 大头)

每层实际计费: ~2-4K tokens(仅 biscuit 末行 + DE 末条目 + 用户新消息)
V11: ~15-40K tokens
V10: ~38K tokens
无压缩: ~5K tokens/层 但背包无限膨胀 → 必死

V12 的遗留问题

  • DE(不可恢复工具输出 + AI 代码块)和 biscuit 有大量重叠——同一份终端输出在 biscuit 的绝对包装盒和 DE 各存一份 → token 翻倍
  • DE 的 FIFO 轮转触发时,DE content 变化 → 缓存从 DE 处断裂(低频但存在)
  • DE 的代码提取依赖启发式规则,可能漏掉 AI 纯文本中的代码

V13 · DE 消除 + 双包装盒体系(最终形态)

核心洞察:DE 的存在本身就是冗余。绝对包装盒(╔K...╚)已经在 biscuit 里保留了不可恢复工具的完整输出,DE 再存一份毫无意义。至于 AI 产出的代码——可以通过 sha256 引用 timeline 中的历史版本,无需在 DE 中保留全文。

改动

  • DE 概念全消除。_deBlock 消息、deEntries 字段、所有序列化/解析函数全部删除。
  • 20 个工具重新分类为双包装盒体系
类别数量成员处理方式
温柔包装盒15read/search/find/list/diag/edit/write/create/delete/revert/timeline_versions/diff_versions/fetch_webpage/search_webbiscuit 仅一行头(结果可从磁盘重读或参数重跑复现)
绝对包装盒5run_command / generate_image / remove_background / analyze_image / get_vision_context╔K...╚ 包裹完整输出,阀值压缩时可剥离体部
  • 阀值压缩:新增 _stripAbsoluteBoxes() — 正则 ╔K[\s\S]*?\n╚\n 精准剥离绝对包装盒体部,保留头行。手动触发(🗜️按钮,threshold=0)或自动触发(建楼中 _lastApiPromptTokens 超阈值)。
  • sha256 考古:读工具传 sha256= → biscuit 标记 @sha=xxx(12 位 hex);写工具产出 → ➜ sha=xxx。AI 可随时用 sha256 参数回读历史版本 blob,零额外 IO 零 token 浪费。

压缩饼干最终格式

=== F1 2026-07-16 01:10:44 UTC+8 ===
Q: 用户编辑框原文一字不差
[A → read_file] /path @sha=bdf18b5043c9 L:1-200/958
[A → search_text] "pattern" 1 hit
[A → edit_file] /path 3chg ➜ sha=94b4e3f7c56e
[A → run_command] "psql -U postgres -d dgs -c 'SELECT...'" 2318c
╔K
 id | name
 1 | qqqide
╚
A: 已修复,原因是...
=== F2 2026-07-16 02:30:15 UTC+8 ===
...

阀值压缩后(剥离绝对盒体部):

=== F1 2026-07-16 01:10:44 UTC+8 ===
Q: 用户编辑框原文一字不差
[A → read_file] /path @sha=bdf18b5043c9 L:1-200/958
[A → search_text] "pattern" 1 hit
[A → edit_file] /path 3chg ➜ sha=94b4e3f7c56e
[A → run_command] "psql -U postgres -d dgs -c 'SELECT...'" 2318c
A: 已修复,原因是...

体部剥离,头行保留——AI 知道执行了什么命令、输出了多少字符,但不再为 16KB 的终端输出付 token 费。


3. 最终形态全景

3.1 背包物理结构

agent.conversation[]:
  [0] Z (sg0, 规则/铁律/vision context, _persistent) — 永不变,100% 缓存命中
  [1] 压缩饼干 (1条 _biscuit msg, content 尾部追加) — 前缀缓存命中
  [2] 当前楼层原始消息 (user + assistant + tool) — 新建楼层时变化

对比 V12 少了 DE 消息。三元素,零冗余。

3.2 机械筛 — 纯本地确定性转换

原始消息饼干格式
userQ: [全量内容](剥离 [File:] 注入块和 CURRENT TIME)
assistant 纯文本A: [全量内容]
assistant 含 tool_callsA: 行(如有文本),再 [A → xxx] file1, file2 工具行
tool 返回(温柔派)摘要追加到上一工具行
tool 返回(绝对派)头行 + ╔K...╚ 包裹完整输出
system[S] [全量内容]

关键特性

  • 零网络调用,零 AI 费用,纯客户端 CPU
  • 完全确定性——同一输入永远同一输出
  • 不含代码正文(AI 产出的代码通过 sha256 在 timeline 中引用)
  • 不含 CURRENT TIME(避免每层时间戳不同导致缓存断裂)

3.3 双包装盒 — 按复现性分流

分类逻辑:一个工具的输出能否被精确复现?

  • 能复现(温柔派)→ 只保留一行摘要。AI 需要细节时可重新执行工具或用 sha256 考古。
  • 不能复现(绝对派)→ 保留完整输出(╔K...╚),但允许阀值压缩时剥离体部。

温柔派 15 个

  • 文件类 6:read_file / edit_file / write_file / create_file / delete_file / revert_file
  • 搜索类 4:search_text / search_content / find_files / list_files
  • 诊断类 1:get_diagnostics
  • 网络类 2:fetch_webpage / search_web(成功返回后落地成文→温柔)
  • Timeline 类 2:timeline_versions / diff_versions

绝对派 5 个

  • 终端 1:run_command
  • 视觉 4:get_vision_context / analyze_image / generate_image / remove_background

3.4 缓存经济学

发送楼层 N+1 时的 token 构成:
  Z:              0 tokens (100% 缓存命中)
  biscuit 前缀:    0 tokens (前缀命中,仅最后 ~200 tokens 新)
  当前楼层:        ~3-5K tokens (user + assistant + tool results)

每层实际增量计费: ~200-500 tokens (仅 biscuit 新行)
vs 无压缩方案:     ~5K tokens/层 × N 层 → 线性增长
vs ChatGPT 方案:   全量重算,无前缀缓存优化

为什么缓存能命中

  • Z 消息对象永不替换 → API 识别为同一消息
  • biscuit 消息对象永不替换,仅 content 字符串尾部增长 → API 识别前缀
  • 当前楼层的 user 消息每次不同 → 从 biscuit 末尾到 user 消息之间是新内容

3.5 阀值压缩 — 精准手术

触发条件:建楼中 _lastApiPromptTokens > 阈值(默认 600K,100-1000K 可调)或手动点击 🗜️。

操作_stripAbsoluteBoxes(biscuitContent) → 正则 ╔K[\s\S]*?\n╚\n → 替换为空。

安全性

  • ╔K(U+2554 双线框+K)在二进制/ANSI/JSON/HTML 中概率趋零
  • 非贪婪 [\s\S]*? 锚定行首 ╚,绝不跨越到下一盒子
  • 转义:╔K→╔K\、╚→╚\ 仅碰撞触发(概率→0),零常态开销
  • 头行(命令+字符数)完整保留 → AI 不失上下文

3.6 持久化与自愈

持久化:
  ctx.json (per-quest, 原子 tmp+rename)
    └── biscuitLines[] — 每层楼的压缩行数组

自愈:
  ctx.json 损坏/丢失
    → D 路径: _rebuildBackpack(conversation)
    → 从原始 conversation 消息重新机械筛
    → 生成 biscuitLines → 写入 ctx.json
    → 零数据丢失

3.7 错误处理

  • 未恢复 fatal 楼层:不进饼干。原始消息保留在 conversation,AI 能直接看到 _error 消息。
  • 已恢复 fatal 楼层:进饼干,格式 [ERR] [HH:MM] 错误文本。重启时扫描 biscuit 重建错误日志。
  • 时间戳持久化_errorTime 字段写入 conversation 消息,重启精确恢复。

4. 与当前市面方案对比

维度ChatGPTClaudeCursorqqqide V16
压缩方式无压缩,全量保留无压缩无压缩本地机械筛,确定性
缓存优化无前缀缓存优化原地追加,~90% 前缀命中
工具输出原样保留原样保留原样保留双包装盒分流,体部可剥离
历史引用sha256 考古,精确引用历史 blob
每层增量~5K+ tokens~5K+ tokens~5K+ tokens~200-500 tokens
50层累计~250K tokens~250K tokens~250K tokens~10-25K tokens (biscuit) + 当前层
数据所有权云,不可导出云,不可导出云,不可导出本地,用户完全拥有
全文检索仅标题conv-ui.html 全文检索历史
跨会话引用不支持Projects 手动不支持sha256 跨楼层精确引用
压缩费用N/AN/AN/A(纯本地 CPU)

核心差异

  1. ChatGPT/Claude 的策略是"什么都不丢" — 完整保留一切,让 token 预算自然淘汰旧内容。用户没有控制权:不能选择保留什么、丢弃什么。本质上是"被动遗忘"。
  1. qqqide 的策略是"精准保留 + 可控丢弃" — 机械筛保证结构化的 Q&A 链路完整;双包装盒保证不可复现的输出被保留但可剥离;sha256 保证可复现的内容随时精确回读。用户主动选择压缩粒度。
  1. 数据所有权是最终分水岭 — 所有云方案的本质缺陷不是技术上的,而是架构上的:上下文存在服务商的服务器上,用户只有访问权没有所有权。qqqide 的上下文是项目目录下的纯文本文件(ctx.json + all.txt),用户可以用任何工具处理、备份、迁移。

5. 如果没有 qqqide

上下文背包不是一个"锦上添花"的功能。它是 AI 编程助手能否长期可用的基石。

5.1 当前市场的真实困境

今天使用任何主流 AI 编程助手的用户,都在经历同一种体验:

  • 前 10 层楼:AI 表现惊艳。它记得你的代码库结构、你的命名习惯、你偏好的方案。
  • 10-30 层楼:token 窗口开始吃紧。AI 开始"忘记"早期讨论的架构决策。你需要重复解释。
  • 30 层楼之后:你必须手动"修剪"上下文——删除旧对话、开新会话。每一次修剪都是一次上下文清零。AI 重新理解你的代码库,重新建立默契。

这个循环没有终点。 每次上下文清零 → AI 重新理解 → 你又花了 token 费重新教它 → 窗口又满了 → 再次清零。

5.2 没有压缩背包的世界

如果上下文背包不存在:

  1. 长对话不可持续 — 50 层楼后要么破产要么失忆。大型重构任务(需要 100+ 轮交互)无法在一个会话中完成。
  2. 跨项目经验无法积累 — 你在项目 A 里教会 AI 的架构模式,在项目 B 里要从头再教。因为没有可迁移的上下文格式。
  3. 用户永远是被动的 — 你不能决定保留什么、丢弃什么。是系统在替你遗忘,不是你在管理记忆。
  4. 上下文是租来的,不是拥有的 — 换一个工具 → 一切归零。你的对话历史锁在别人的服务器上。

5.3 背包的核心哲学

上下文是 AI 时代最稀缺的生产资料。
代码可以重写,但"AI 为什么这样改"的推理链无法重建。

三个权利用户必须拥有:
  ① 所有权 — 上下文数据在本地,纯文本,随时可迁移
  ② 控制权 — 你决定压缩什么、保留什么、丢弃什么
  ③ 检索权 — 全文检索所有历史上下文,跨会话引用

qqqide 上下文背包是这三个权利的技术实现。

6. 未解决问题

  1. >200 层 — 饼干自身需二次压缩。当前每层 ~200 字符,200 层 = 40K chars,仍在可控范围。但 500+ 层时需要考虑对 biscuit 本身再做一次压缩(稀有场景)。
  1. 跨 quest 上下文共享 — 目前每个 quest 的背包独立。项目 A 第 3 层楼讨论的架构决策,项目 B 无法自动引用。需要跨 quest 的 facts grid(设计已预留,待实现)。
  1. AI 纯文本中的代码 — 机械筛只从 tool_call arguments 提取代码,不处理 AI 在纯文本回复中内联的代码块。这些代码不会被 sha256 引用,丢失后不可恢复(影响较小——AI 回复中的代码通常是示例,非生产代码)。

附录 A · 版本演进速查

版本日期核心改动每层计费缓存命中
V102026-06AI 语义压缩(三专家并行)~38K0%
V112026-07 初机械筛 + 追加式饼干 + splice~15-40K0%(splice 漏洞)
V122026-07 中原地追加,零 splice~2-4K~90%
V132026-07-16DE 消除 + 双包装盒 + 阀值压缩 + sha256~200-500~90%
V142026-07-17floorMsgs 升序修复重排→缓存全断 bug~200-500~90%
V152026-07-19三按钮压缩(absolut/edit only/only facts) + fx Grid + _compressFloor~200-500~90%
V162026-07-23biscuit 唯一性强制(去重→先合并再删) + _findDynamicMsg 修复(Z 阻断)~200-500~90%

附录 B · 关键文件

文件职责
server-app/ai-panel/agent-context.js背包核心:机械筛、包装盒、阀值压缩、ctx 持久化
server-app/ai-panel/panel-floor.js楼层完结触发 _rebuildBackpack
server-app/ai-panel/panel-quest.jsctx.json 读写
server-app/goods/conv/conv-ui.html上下文背包管理 UI
do/拓扑/铁律 §56上下文压缩铁律
do/拓扑/架构 压缩章节架构级描述