将用户上下文及其使用权还给用户

文档发表:2026-07-22 · 阅读:112 · 更新:2026-08-02

1. 要解决什么问题

你跟 AI 聊了三个月,帮它理解了你的代码库架构、你的命名习惯、你偏好的技术栈。然后你换了一个 AI 工具——一切归零。所有的"默契"、所有积累的上下文、所有你花时间解释过的事情——都留在了上一个工具的服务器上。你无法导出、无法搜索、无法迁移。

你创造了上下文,但你并不拥有它。

当今所有主流 AI 编程助手(ChatGPT、Claude、GitHub Copilot、Cursor、JetBrains AI Assistant)的共同架构是:对话历史存储在服务商的云服务器上。你是租客,不是房东。你能"用"你的上下文,但你不能"带走"它——不能全文检索它、不能跨会话引用它、不能在新工具里复用它。

更根本的问题是:上下文是 AI 时代最稀缺的生产资料。 代码可以重写,但"AI 为什么这样改"的推理链、"上次踩过什么坑"的经验、"这个架构决策是怎么来的"的来龙去脉——这些一旦丢失,无法重建。而当今的所有方案,都在系统性地制造这种丢失。

本质问题:用户的上下文数据,所有权和使用权应该无条件归属用户,而不是服务商。


2. 历史方案的失败点

ChatGPT:「会话列表 + 搜索框」

  • 对话存在 OpenAI 服务器上,用户在网页端可以搜索标题
  • 不能全文检索对话内容(只能搜标题)
  • 导出是手动的一次性 JSON dump,没有工具链消费
  • 跨会话引用?不存在。一个会话里让 AI 参考另一个会话的内容?复制粘贴。
  • 根本缺陷:上下文是活的(持续生长),但 ChatGPT 把它当死的(静态列表)。

Claude:「Projects + 知识库」

  • Projects 允许上传文件作为背景知识
  • 但对话历史仍然不可全文检索
  • 知识库需要手动维护——每次学到新东西,用户要自己摘出来放进知识库
  • 根本缺陷:把"上下文管理"的负担转嫁给了用户。AI 应该自动积累上下文,而不是让用户当档案管理员。

GitHub Copilot:「内联补全 + 聊天面板」

  • 聊天面板有历史记录,但仅限当前 IDE 会话
  • 没有跨会话引用
  • 上下文窗口内的代码理解是实时的,但不持久化——下次打开 IDE,AI 重新读你的代码
  • 根本缺陷:上下文是瞬时的(ephemeral)。每次对话从零开始,浪费 token 重复理解已理解过的东西。

Cursor:「代码库索引 + 聊天历史」

  • 代码库索引(codebase indexing)是所有工具里最先进的
  • 聊天历史存储在云端,支持简单的历史浏览
  • 但不支持全文检索历史对话
  • 上下文不可导出、不可迁移到其他工具
  • 根本缺陷:代码库上下文优秀,但对话上下文管理停留在"聊天记录列表"层面。

JetBrains AI Assistant:「IDE 内嵌 + 云存储」

  • 对话历史存在 JetBrains 云
  • 没有跨会话搜索
  • 上下文完全绑定 JetBrains 生态
  • 根本缺陷:和所有云方案一样——你拥有的是访问权,不是所有权。

共同缺陷:三条铁律全部违反

铁律含义现存方案
可检索用户能全文检索所有历史上下文无一做到
可迁移上下文是开放格式,可导入其他工具仅 ChatGPT 有 JSON 导出,但无工具链消费
可复用新会话能自动引用旧会话的上下文无一做到

所有方案都假设:上下文是服务商的资产,用户只是被授权访问。 这是一个根本性的错误。上下文是用户花时间、花精力、花钱创造的智力成果。它应该和用户的代码一样,物理存储在用户的硬盘上,以开放格式保存,随时可检索、可迁移、可复用。


3. 我们如何一步步设计和实现

我们的方案不是一次性"设计"出来的。它是七个步骤的递进推演——每一步解决上一步暴露的问题,最终收敛到一套完整的上下文所有权架构。

3.1 第一步:回答"上下文存哪里"——本地文件系统的选择

最初始的问题是:AI 对话记录应该存在哪里?

云方案的诱惑是巨大的:零配置、多设备同步、不占本地空间。但我们对云方案做了三个追问,答案全部否定:

  1. 用户能随时拿到原始数据吗? 不能。云端 API 只能按服务商规定的粒度访问(标题列表、单个会话),没有批量导出。
  2. 数据格式是谁定义的? 服务商。用户无法控制格式演进,今天能读的数据明天可能因为 API 变更而失效。
  3. 服务停止后数据还在吗? 不在。你的上下文和你的订阅一起消失。

结论:上下文必须和用户的代码放在一起——物理上、格式上、控制权上。

我们选择的方案是:所有上下文存储在项目根目录下的 _qqq/quests/ 中,和项目代码处于同一棵文件树。拷贝项目文件夹 = 完整迁移所有 AI 对话历史。Git 可以版本控制它(如果用户选择),任何备份工具都能保护它。

这是最"无聊"的选择——文件系统。但正是这个"无聊"的选择,解开了后续所有创新的枷锁。因为数据在本地,我们才能在它上面建搜索引擎、建跨任务引用、建 trace 因果链。

3.2 第二步:回答"存什么格式"——双轨制(all.json + all.txt)

文件系统存放什么格式?我们拒绝单一格式,因为上下文有两种根本不同的消费者:

消费者需求格式要求
机器(AI 模型)加载到上下文窗口、解析 tool_calls、读取计费信息结构化 JSON
人类(开发者)快速浏览对话内容、grep 关键词、在记事本里打开纯文本 TXT

于是有了双轨制——每层楼(floor)同时产生两个文件:

  • all.json:机器消费。包含完整 conversation 数组(每条消息的 role、content、tool_calls、tool_call_id)、计费元数据(ge 消耗、模型 tier)、文件快照引用(blob_hash 指向 timeline)。AI 可以在一个 read_file 调用里加载整层楼的完整上下文。
  • all.txt:人类消费。同样的对话内容,但是纯文本 Markdown 格式——用户消息、AI 回复、工具调用和结果,按时间顺序排列。任何文本编辑器、grep、ripgrep 都能直接消费。

第三个文件 reasoning.txtall.txt 的截断版——工具返回结果截断到 300 字。用途是快速审计:"这一层楼 AI 调了什么工具、拿到了什么结果",不需要翻阅可能几十 KB 的完整工具输出。

关键原则:一个事实,两份表达。 不冗余存储——两份文件描述同一段对话,但针对不同的消费者优化。JSON 给 AI 做结构化推理,TXT 给人做全文检索和快速阅读。

3.3 第三步:回答"怎么组织"——quest/floor/house/room 层级目录

下一个问题:当有 50 个 quest、每个 quest 有 20 层楼时,怎样组织目录结构才不会变成一锅粥?

我们定义了一个严格的层级命名体系:

quest(一次对话会话)
  └── floor(一次用户回车,可能含多次 API 调用)
        └── house(一次 API 调用,可能含多次 tool call)
              └── room(一次工具调用)

对应的目录结构:

_qqq/quests/
├── _index.json              ← 所有 quest 的元信息索引
├── q1.搭建数据库层/
│   ├── f1.设计 schema/
│   │   ├── all.json
│   │   ├── all.txt
│   │   └── reasoning.txt
│   ├── f2.调试索引/
│   └── f3.性能优化/
├── q2.重构 API 层/
│   └── f1.开始/
└── q3.前端改造/
    └── ...

这个层级体系的关键属性是:每层楼是独立可寻址的最小单元。 你可以精确引用 "q1/f2"——那一层楼的完整对话、完整推理、完整工具调用链——而不需要加载整个 q1。这为跨任务引用奠定了基础:AI 不需要把整个 quest 塞进上下文窗口,只需要精确加载相关的几层楼。

3.4 第四步:回答"怎么快速找到"——_index.json + ripgrep 全文检索

目录结构解决了"怎么存",但没解决"怎么找"。当积累了上百层楼、几十万个字时,用户需要两种查找能力:

A. 结构化查找 — _index.json

_index.json 是一个轻量索引文件,记录了所有 quest 的元信息:quest ID、标题、创建时间、楼层数、每层楼的标题和状态。加载这个文件(通常 < 10KB)就能画出完整的 quest 列表,不需要扫描目录。

B. 全文检索 — ripgrep

用户真正需要的是:"我三个月前和 AI 讨论过 PostgreSQL 的 WAL 配置——是哪次对话来着?"

qqqide 集成了 ripgrep(Rust 实现、mmap 加速、SIMD 向量化),直接对 _qqq/quests/ 下所有 all.txt 执行正则搜索。结果毫秒级返回——因为数据在本地,因为格式是纯文本。

用户输入: "PostgreSQL WAL"
ripgrep 扫描: _qqq/quests/**/all.txt
返回: q1/f3/all.txt:42 → "我们决定把 WAL 段大小设为 64MB..."
       q5/f1/all.txt:18 → "PostgreSQL WAL 归档用 pg_receivewal..."

对比的关键差异:

ChatGPTClaudeCopilotCursorqqqide
搜索范围标题标题标题全文
搜索速度云端 API,不定云端 API,不定N/A云端本地,毫秒
离线可用
正则支持

这不是一个"更好的搜索框"。这是把 AI 对话从"聊天软件"变成了"知识库"。而这一切的前提是第 3.1 步的选择——数据在本地,才能跑本地搜索引擎。

3.5 第五步:回答"代码和对话什么关系"——Timeline trace 因果链

有了对话的存储和检索,下一个自然的问题是:这些对话产生了哪些代码?反过来,这段代码是哪次对话产生的?

我们自建了 timeline 版本系统(_qqq/timeline/),核心架构:

blobs/{sha256[:2]}/{sha256}.gz  ← 文件内容不可变快照(SHA256 行尾归一化去重)
timeline.db                     ← SQLite 全量快照索引
timeline.wal                    ← NDJSON 增量日志(≤99 行)

每次 AI 工具调用(write_file、edit_file、create_file)在完成时自动捕获文件快照,并打上 trace 标记:

trace = "q{questId}/f{floorNum}/h{houseNum}/r{roomNum}"

例如 q3/f2/h1/r2 意味着:这个文件变更是 quest 3、第 2 层楼、第 1 次 API 调用、第 2 个工具调用产生的。

效果:

用户在 diff 窗口看到某行代码变更
  → trace 显示: q3/f2/h1/r2
  → 点击跳转到 q3 的第 2 层楼
  → 看到 AI 当时的完整推理:
    "这个字段必须改成 TEXT 而不是 VARCHAR(255),
     因为 PostgreSQL 里两者存储效率相同,
     但 TEXT 避免了未来数据超长的风险..."

传统的 Git blame 只能回答谁、什么时候改的,commit message 最多回答改了什么。但永远回答不了为什么这样改。Trace 把代码和产生它的推理链永久绑定——这是只有 AI 辅助编程时代才会出现的新型工程知识。

3.6 第六步:回答"怎么跨任务复用"——跨 quest 上下文协作

前五步都是基础设施。第六步是它们共同支撑的核心能力:跨任务上下文协作。

完整工作流

┌─────────────────────────────────────────────────────────┐
│ 步骤 1: 全文检索定位相关上下文                           │
│                                                         │
│   用户在 q8 ("重构 API 层") 中,需要参考之前的数据库设计  │
│   → ripgrep 搜索 "schema" "PostgreSQL" "表结构"          │
│   → 命中 q1/f1, q1/f3, q5/f2                             │
│   → 每个命中显示匹配行 + 文件路径 + 楼层标题              │
│                                                         │
├─────────────────────────────────────────────────────────┤
│ 步骤 2: 提取成果                                         │
│                                                         │
│   用户打开 q1/f3(PostgreSQL schema 设计的那层楼)         │
│   → all.txt 显示完整的人类可读对话                        │
│   → 看到 AI 在 q1/f3 中的结论:                          │
│     "最终 schema 使用 UUID 主键、BRIN 索引、               │
│      分区表按月份 range 切分..."                          │
│   → 用户知道:这就是我要复用的成果                         │
│                                                         │
├─────────────────────────────────────────────────────────┤
│ 步骤 3: 注入新任务                                       │
│                                                         │
│   方式 A — 手动引用:                                      │
│     用户在 q8 中说 "参考 q1/f3 的 schema 设计继续"         │
│     → AI 读取 q1/f3/all.json                             │
│     → AI 看到 q1/f3 的完整对话上下文                      │
│     → AI 知道当时的约束、决策、踩过的坑                    │
│     → 在 q1/f3 的基础上继续,不重复解释                    │
│                                                         │
│   方式 B — 自动发现:                                      │
│     AI 在 q8 中自动搜索相关历史楼层                        │
│     → 将相关上下文注入当前对话                             │
│     → 用户不需要知道哪些历史有关                           │
│     → AI 像一个记得所有历史的老搭档                        │
│                                                         │
├─────────────────────────────────────────────────────────┤
│ 步骤 4: 开分支                                           │
│                                                         │
│   用户想基于 q1 的全部成果尝试不同的方向                   │
│   → 创建 q9 "换 MySQL 引擎重做数据库层"                    │
│   → 将 q1 的完整上下文作为 q9 的起点                       │
│   → AI 看到: q1 的设计决策 + q9 的新目标                   │
│   → "把 PostgreSQL schema 翻译成 MySQL,                  │
│      注意 q1/f3 提到的 BRIN 索引在 MySQL 中不存在,         │
│      需要用其他方案替代..."                               │
│                                                         │
└─────────────────────────────────────────────────────────┘

为什么只有 qqqide 能做到

这个工作流对云方案来说在物理上不可行,原因有三:

  1. 数据不在本地。云方案的对话历史在服务商服务器上。你无法用 ripgrep 扫描它——API 只支持按标题搜索,不支持全文。每次查找都要网络往返,延迟不可预测。
  1. 格式不可消费。即使云方案给了你导出,通常是一次性 JSON dump,没有目录结构、没有索引、没有楼层粒度的独立寻址。你不能精确引用 "会话 3 的第 5 条消息"——你只能把整个 JSON 塞给 AI。
  1. 没有 trace 关联。代码和对话是分离的——你在 Git 里看到一行改动,不知道它对应哪次 AI 对话。反之,你在对话里提到 "改了 schema.sql",不知道当时的代码是什么状态。

qqqide 做到这一点,是因为我们在前五步已经建造了完整的原料保存体系:

  • 第 3.1 步(本地存储)→ 数据就在 ripgrep 能扫到的地方
  • 第 3.2 步(双轨格式)→ JSON 给 AI 加载,TXT 给 ripgrep 搜索
  • 第 3.3 步(层级目录)→ 每层楼独立可寻址,精确引用不浪费 token
  • 第 3.4 步(全文检索)→ 毫秒级定位相关上下文
  • 第 3.5 步(trace 因果链)→ 代码能找到产生它的对话,对话能找到它产生的代码

五步递进,缺一不可。缺任何一步,跨任务协作就是空中楼阁。

3.7 第七步:预渲染——重启零损耗

最后一步是消除摩擦:如果每次重启 IDE 都要重新渲染所有对话 HTML,用户会感觉"卡"。

我们在 all.json 中引入了 ai_html 字段:每层楼在流式渲染完成后,将最终的 DOM HTML 预计算并持久化。下次重启时,直接从 ai_html 读出 innerHTML——零重新渲染,零等待。

流式渲染完成
  → _contentWrap.innerHTML 序列化为 HTML 字符串
  → 写入 all.json 的 ai_html 字段
  → 重启时: ai_html → innerHTML
  → 用户看到的是完全相同的渲染结果,瞬间加载

这不是性能优化。这是所有权的一部分——你拥有的不仅是对话的文本内容,还有对话的视觉呈现。 即使三十年后,你用不同的工具打开 all.json,那段对话的完整面貌依然可以还原。


4. 核心突破:一切原料的完整保存

回看这七步,可以归纳为一个核心命题:跨任务上下文协作的前提,是拥有一切原料。

什么是一切原料?一场 AI 对话产生的全部可留存信息:

原料存储位置用途
完整对话(结构化)all.jsonAI 加载到上下文窗口
完整对话(人类可读)all.txt全文检索、快速浏览、跨工具消费
审计摘要reasoning.txt快速了解"AI 做了什么"
代码快照(SHA256 不可变)timeline/blobs/任何时候恢复任何版本
代码变更索引timeline.db + timeline.wal查询文件变更历史
因果链trace 标记 (q{n}/f{n}/h{n}/r{n})代码 ↔ 对话双向追溯
预渲染 HTMLall.jsonai_html重启即时恢复
Quest 元信息_index.jsonO(1) 列出所有对话

云方案只给你其中最多 2 项(对话文本 + 会话列表),而且是以服务商控制的格式、在服务商控制的服务器上。

我们的方案给你全部 8 项,在你自己的硬盘上,以开放格式保存。

这就是"将上下文还给用户"的技术含义。不是一句口号——是七步递进建造的完整原料保存体系。因为所有原料都在本地,你才能:

  • 全文检索:ripgrep 扫所有 all.txt,毫秒级
  • 精确引用:读某一层楼的 all.json,AI 看到完整上下文
  • 开分支:复制一个 quest 的全部上下文作为新起点
  • 查因果:看到代码 → trace → 找到产生它的对话 → 看到当时的推理
  • 迁移:拷贝项目文件夹 = 带走一切

这不是功能对比,是物理可行性对比

能力云方案的物理瓶颈qqqide 的物理基础
全文检索数据在远端,API 不支持数据在本地,ripgrep 直扫
精确引用无楼层粒度导出每层楼独立目录 + all.json
开分支无法复制完整上下文本地目录拷贝
查因果代码和对话无关联trace 标记双向链接
迁移服务商控制导出格式和粒度开放格式 + 本地文件

所有能力差异的根源,不是"我们做得更好",而是"我们拥有原料"。 一旦数据在本地、格式开放、层级可寻址、因果有 trace,跨任务协作就是自然的产物。反过来说,数据在云端、格式封闭、层级扁平、因果断裂——再聪明的算法也做不了跨任务协作。


5. 与一切现存方案的对比矩阵

维度ChatGPTClaudeCopilotCursorJetBrains AIqqqide
上下文物理位置云端云端云端云端云端本地硬盘
数据所有权访问权访问权访问权访问权访问权所有权
全文检索✅ ripgrep
开放格式JSON导出JSON+TXT
人类可读存档✅ all.txt
离线可用部分
跨会话引用
代码-对话关联✅ trace
可迁移性手动导出拷贝文件夹
隐私云端明文云端明文云端明文云端明文云端明文本地
免订阅费
不绑定厂商✅ 开放格式

这不是"我们比他们多几个功能"。这是两种完全不同的上下文哲学

  • 云哲学:上下文是服务的附属品。你付费获得访问权,服务终止 = 上下文蒸发。
  • 本地哲学:上下文是你的财产。你创造它,你拥有它,你控制它。工具只是帮助你在本地管理它。

6. 深层含义:上下文是 AI 时代的源代码

代码开源运动用了三十年让"代码应该属于写它的人"成为共识。AI 时代面临同样的问题,只是资产从"代码"变成了"上下文"。

代码是死的,上下文是活的。 一段代码可以重写,但"为什么这样写"的推理链、"踩过哪些坑"的经验库、"架构决策怎样演化"的时间线——这些一旦丢失,无法用金钱买回来。

今天的所有 AI 工具都在做同一件事:用免费/低价的服务换取你的上下文数据。 你越用,积累越多;积累越多,迁移成本越高;迁移成本越高,你越离不开。这不是技术选择,这是商业锁定。

我们的方案在根本架构上拒绝这个模式:

  • 上下文物理存储在用户硬盘上,开放格式(JSON + TXT)
  • 全文检索、跨任务引用、代码关联全部本地完成
  • 零厂商锁定:拷贝文件夹 = 完整迁移到任何兼容工具
  • 隐私:对话内容从不出你的电脑(AI 调用时发送的仅是当前楼层上下文)

用户创造了上下文。用户应该拥有上下文。用户应该能随意使用自己的上下文——搜索、引用、迁移、删除。这不是一个"feature request",这是数字时代的基本权利。


7. 结论

我们把 AI 上下文从云端的"服务附属品"变成了本地的"用户财产"。七步递进实现:

步骤问题方案
上下文存哪里本地文件系统 _qqq/quests/,和代码同树
存什么格式双轨制:all.json(机器)+ all.txt(人类)
怎么组织quest/floor/house/room 层级,每层楼独立可寻址
怎么快速找到_index.json 索引 + ripgrep 全文检索
代码和对话什么关系Timeline trace 因果链,双向追溯
怎么跨任务复用搜索→定位→提取→注入,或直接开分支
重启损耗预渲染 ai_html,重启零重建

七步共同指向一个目标:用户对自己创造的上下文拥有完整的所有权和使用权。 AI 工具的角色是帮助用户管理和复用这些上下文,而不是把上下文锁在自己的服务器上。

核心洞察只有一个:你只有拥有一切原料,才能真正使用它们。 全文检索、跨任务引用、因果追溯、任务分支——这些不是"高级功能",而是用户对自己数据的基本权利。我们只是把这些权利从服务商手里拿回来,还给了用户。

这就是我们将用户上下文及其使用权还给用户的方式。