一个提示词模板,粘贴即用——从 OpenCode SQLite 数据库提取开发素材,过滤平台噪音,压缩工具调用,输出干净素材文件。全程 GLM-5.1 开发,经历 11 次调整修改。

完整提示词模板见 六、使用方法

前言:AI 编程的对话里到底有什么

用 AI 写代码的人都有个感受:最有价值的东西不在代码里,在对话里。 为什么要选方案 A 不选方案 B、踩过什么坑怎么解决的、某个功能的设计思路是什么——这些全藏在会话记录中,我们只能手动复制或者在会话中翻找。但会话一压缩,之前的对话就只存在于数据库中了,无法直接查看。

现在 AI 编程工具对"会话"的处理,有两种成熟方案:

第一种:会话状态持久化——让 AI 接着聊。 OpenCode 的 --continue、Claude Code 的 /resume、Cursor 的侧边栏历史。它们保存对话状态,让 AI 下次能接上。但解决的是"连续性"问题,不是"知识提取"问题。

第二种:知识记忆持久化——让 AI 记住项目。 Claude Code 的 MEMORY.md、GitHub Copilot Memory、OpenCode 的 opencode-mem 插件。它们帮 AI 记住项目模式、用户偏好、架构决策。但存的是摘要片段,原文细节全丢了。面向的是 AI,不是人。

第三种:对话知识提取——从对话中提取人能读、能复用的开发素材。

这第三种,目前没人做

能力 OpenCode 原生 Claude Code 记忆插件 导出工具 我们的模板
保留完整对话 ❌ 只存摘要 ✅ 原样导出
过滤工具调用噪音
工具调用做摘要
按对话回合结构化
过滤平台注入前缀
无需安装,粘贴即用 ❌ 需装插件 ❌ 需装工具

OpenCode 的 SQLite 数据库里存着完整的对话数据(用户消息、助手回复、每个工具调用的输入输出),但自带的导出功能输出的是原始数据——一条 bash 命令几 KB、工具调用的完整输出全混在一起,几千行根本没法看。Claude Code 的 /export 也是同样的问题。

记忆插件(opencode-mem、context-bank)面向 AI 存储,自动将对话压缩为 2-4 句摘要注入未来会话,原文细节不会在记忆召回时使用。导出工具(cctrace、claude-trace)只搬运不过滤。

我们需要的是:从完整对话中提取结构化开发素材,过滤噪音,压缩冗余,输出一份人能读、能复用、能写文档的素材文件。 这就是本文介绍的工具做的事。

一、痛点:AI 编程会话的信息黑洞

每天和 AI 对话几百条——功能怎么实现的、踩过什么坑、为什么选方案 A 不选方案 B——全在会话里。

但是想要翻找指定对话,整理会话内容,复盘错误,整合开发经验,都是个麻烦事。

我试过直接让 AI 把会话所有对话内容整理成文档,会出现两种情况,AI搜索大量信息导致上下文撑爆并消耗海量Token,或者提炼成功但是损失了用户原话、决策过程、错误现场中的关键细节。

所以需要两步走:先收集素材(原样保留),再根据自己的具体需求整理文档(只提炼一次)

但原始数据库里有三种东西混在一起,直接用不了:

  1. 有用的:用户指令、助手回复、代码改动、决策过程

  2. 噪音:平台注入的 [search-mode] 前缀、<system-reminder> 通知、MANDATORY 续文

  3. 膨胀:工具调用的完整输入输出(一条 bash 几 KB)

这个工具做的事:提取 1,洗掉 2,压缩 3,输出一份干净的开发素材文件。然后再用素材根据需求整理成文档,只提炼一次,自己决定保留哪些细节。

二、效果:提取的素材长什么样

先看结果,再讲过程。

以一个 896 条消息的 B站下载器开发会话为例,耗时10分钟,提取后得到 3,999 行素材文件,覆盖 121 个对话回合,57127词,913 个工具调用全部做了摘要。

素材文件中每个回合的格式

用户消息和助手回复全文原样保留,只在工具调用上做摘要。这样后续整理文档时有一手原始数据,只提炼一次不丢细节。

三、整体设计思路

一句话:主代理(GLM-5.1)调度 + 子代理(DeepSeek V4 Flash + MiniMax)逐批提取 + SQLite 直查数据库

为什么这样设计:896 条消息超出上下文窗口,必须分批。按 parentID 分组(每组 = 一个完整对话回合),每批 ~150 parts,不会在回合中间切断。

┌──────────┐     ┌───────────────┐     ┌──────────┐     ┌──────────┐
│ 列出会话  │────▶│ 分析结构分批   │────▶│ 子代理    │────▶│ 合并素材  │
│ (SQLite)  │     │ (parentID)    │     │ 逐批提取  │     │ → 最终md |
│           │     │               │     │ (并行10批) │     │          |
└──────────┘     └───────────────┘     └──────────┘     └──────────┘

以下进入 GLM-5.1 的完整开发流程,按 v1 → v11 的时间线讲述。


四、开发过程

v1→v2:数据源选型

v1:session_read 方案——失败了

第一版用 OpenCode 自带的 session_read API 读取历史会话。看起来合理,实际跑起来暴露三个问题:

1. 没有 offset 参数,无法分页

提示词里写了 session_read(session_id, limit=50, offset=实际起点),但 session_read 根本没有 offset 参数。GLM-5.1 花了 3 轮工具调用才确认这件事——limit=50 总是从第一条开始读,要读后面的消息只能加大 limit,每批都重复读前面已处理的消息。

2. 工具调用细节全部丢失

session_read 把工具调用压缩成 [tool: bash],看不到命令内容、参数和返回值。"AI 跑了什么命令、得到了什么结果"是最关键的信息,这一丢素材就只剩文字对话。

3. 搜索质量差

session_search 按关键词匹配消息片段,不支持精确匹配会话标题。每次给一个很明确的会话名字,搜索一大圈还是找不到。

GLM-5.1 在这里做了什么:它尝试了 limit=50、limit=100、limit=200 三种策略,每次都从第一条开始读。确认没有 offset 后,主动提出"去数据库直接查"的方案。

v2:SQLite 直查——成功

GLM-5.1 发现了 OpenCode 的底层数据库 /root/.local/share/opencode/opencode.db,三张核心表:

存什么
session 会话元数据(id、title、创建时间)
message 每条消息(role、parentID、data JSON)
part 消息组成部分(type="text"/"tool"/"reasoning",含完整 input/output)

对比测试:

维度 session_read SQLite 数据库
工具调用细节 全部丢失 完整可见
信息密度 100 条 → 258 行 20 条 → 229 行
分页能力 无 offset SQL LIMIT/OFFSET

SQLite 每条消息平均 11 行素材,session_read 只有 2.6 行。

跑通流程,4 批成功提取 781 行素材。质量满意,但慢——每批子代理要花 2-3.5 分钟。


v3→v4:子代理调度架构 + 第一次失败

v3:架构设计

GLM-5.1 自主设计了主代理 + 子代理的调度架构:

  • 主代理(GLM-5.1):负责调度和进度管理,维护 .task.md(任务指令)和 .progress.json(进度文件)

  • 子代理(DeepSeek V4 Flash Free):逐批提取,每个处理约 20 条消息

  • 三文件冗余:.task.md + .progress.json + 素材文件末尾,任何一个丢了都能从其他两个恢复

这个架构不是我先设计好再让 GLM-5.1 执行的——是它分析完上下文限制后直接提出的。

v4:第一次大失败

用精简版提示词在新会话测试,结果完全不能用——子代理把脚本的原始输出直接塞进了素材文件:

- **bash** `npx asar list /mnt/d/bilidown/resources/app.asar 2>/dev/null | head -20 ...` → /0.js /2.js /3.js /assets/css/...
- **bash** `cd /tmp/bilidown-src && npx asar extract-file ...` → grep: No such file or directory

完整的 bash 命令和 output 原样拼在一起,完全没有做"工具调用→摘要"的转换。

根因:子代理 prompt 只写了"读 .task.md 获取完整指令"——假设 DeepSeek V4 Flash 会主动去读。实际上它大概率没读,或者读了没严格照做。

GLM-5.1 在这里做了什么:它分析了失败素材文件,定位到问题出在子代理 prompt 太简略——弱模型需要更明确的指令。由此发明了"填空题级别 prompt":

# ❌ 旧:让子代理自己去读
你是素材收集器。
1. 读 .task.md 获取完整指令
2. 按 .task.md 的规则处理
​
# ✅ 新:内联关键规则(填空题级别)
【格式模板】
## 对话回合#{序号}
### 用户 / ### 助手 / ### 工具调用
​
【提取规则】
- bash: 用一句话描述意图,不贴完整命令
  ✅ bash 重新提取纯净源码。→ 386KB, 10642 行
  ❌ bash `npx asar extract /mnt/d/bilidown/...` → /0.js /2.js/...
​
【禁止】
- 不要粘贴完整 bash 命令(含管道、重定向、长路径)
- 不要粘贴完整 output(文件列表、几 KB 代码)

经验:弱模型 + 超详细 spec > 强模型 + 粗略 spec。


v5→v7:棘手问题——用户消息被注入了指令前缀

这是整个开发过程中最棘手的问题。GLM-5.1 花了 3 轮调整才彻底解决。

问题

OpenCode 的 oh-my-opencode 插件会在用户消息前面注入指令块。用户输入的是"怎么了,你刚刚改动之后好像卡住了",数据库里存的却是:

[analyze-mode]
ANALYSIS MODE. Gather context before diving deep:
...
***
MANDATORY delegate_task params: ALWAYS include load_skills=[] ...
***
怎么了,你刚刚改动之后好像卡住了,在检查什么吗

v4 的过滤逻辑是 startswith('[analyze-mode]') 一刀切——整条消息都扔了。但这条消息后面明明有用户的实际输入。

三版过滤逻辑的迭代

第一版:找最后一个 \n---\n 分隔线,取后面的内容。

失败:用户输入内容本身也可能包含 ---(比如粘贴的提示词模板),取"最后一个"会把用户输入切成两半。

第二版:遍历所有分隔线,检查每段首行是否以指令关键词(MANDATORY、ANALYSIS MODE、MAXIMIZE 等)开头。

问题:关键词列表永远不全,而且 ANALYSIS MODE 等其实不会出现在分隔线后面(它们在第一个 --- 之前)。

第三版:GLM-5.1 去查了 oh-my-opencode 源码,确认了注入模板的精确格式。结论:分隔线后面的注入段只有三种开头——MANDATORY[search-mode][analyze-mode]。不需要更多关键词。

核心逻辑:

_SKIP_PREFIXES = ('MANDATORY delegate_task', '[search-mode]', '[analyze-mode]')
segs = raw_text.split('\n---\n')
for i, seg in enumerate(segs):
    first_line = seg.strip().split('\n')[0]
    if any(first_line.startswith(sp) for sp in _SKIP_PREFIXES):
        continue
    # 找到第一个非注入段 → 后面全是用户输入(用 join 拼回,不截断用户内容中的 ---)
    text_content = '\n---\n'.join(segs[i:]).strip()
    break

极端 case:双前缀嵌套

GLM-5.1 在这里做了什么:它在分析 106 条前缀消息时,发现了双前缀消息——[search-mode] + MANDATORY + [analyze-mode] + MANDATORY + 用户输入,全挤在一条消息里。有些极端消息中,用户输入被追加到了 MANDATORY 模板的 Example 行末尾(Example: delegate_task(...)怎么了)。这种极端情况人类很难预见到,是 GLM-5.1 从数据库中挖掘出来的。

致命 bug:过滤做了但没用上

用 DeepSeek V4 Pro review 代码时发现:过滤逻辑只在 text_content 变量中做了清洗,但脚本输出部分仍然直接打印原始 p["text"]——过滤白做了。典型的"单元测试过了,集成没跑"。

最终修复:106 条前缀消息全量测试,0 条泄漏,0 条误丢。


v8:关键转折——GLM-5.1 自主优化执行策略

前面 4 批用旧版提示词跑的,效果还行但速度慢。我直接在新会话里跑了一版旧提示词,没想到效果出奇地好——112 个回合、3999 行素材,25 批全部完成,工具调用摘要清晰规范。

为什么好?不是随机性

去数据库里查了那个成功会话的完整执行记录。GLM-5.1 主代理自行做了 3 件提示词没要求的事

1. 自己创建了查询脚本

不是让子代理自己写 python3 内联代码,而是 GLM-5.1 先生成了 /tmp/bilidown-query.py,子代理只需 python3 /tmp/bilidown-query.py OFFSET COUNT

2. 从串行改为并行+临时文件+合并

25 个批次分成 5 组,每组 5 个子代理并行执行,每个写独立临时文件,主代理用 cat 合并。

3. 自适应精简子代理 prompt

观察到前几批成功后,主动降低了后续批次的 prompt 粒度:

批次 模型 Prompt 长度 每批耗时
1-5 GLM-5.1 ~2100 chars 2m49s ~ 7m29s
6-10 DeepSeek ~1100 chars 48s ~ 1m53s
11-15 DeepSeek ~610 chars 同上
16-25 DeepSeek ~360 chars 同上

效果好的根因不是提示词本身,而是执行提示词的主代理能力。

从成功经验中提炼改动

分析完成功会话后,提示词做了以下改动:

  1. 查询方式:session_search → 直查数据库(一条 SQL 列出主代理会话)

  2. 查询脚本:内联 python3 代码 → 预先生成独立脚本文件

  3. 并行策略:串行追加 → 每组 10 批并行(5 个 DeepSeek V4 Flash + 5 个 MiniMax 交替),独立临时文件再合并

  4. 子代理 prompt:依赖读 .task.md → 填空题级别内联(格式模板+正反例+禁止项)

  5. .task.md:140 行子代理指令手册 → 12 行主代理备忘录

  6. 消除重复:摘要模板、格式模板、查询代码各只保留一份


v9→v11:性能优化——脚本替代 AI

v10 质量满意但慢。优化目标:不降质量,提速

核心思路

v10 中子代理要做的机械工作太多了:解析消息结构、按回合分组、Markdown 防护(标题降级、围栏闭合、分隔线替换)、格式化输出。这些全是不需要 AI 判断的固定逻辑。

GLM-5.1 在这里做了什么:它设计了三阶段流水线,把机械工作全部交给 Python 脚本,AI 只做"摘要"这一件事。

┌──────────────┐     ┌───────────┐     ┌──────────┐
│ format_batch │────▶│ AI 子代理 │────▶│ merge    │
│ (Python)     │     │ (摘要)    │     │ (Python) │
│ DB → semi.md │     │ hints.txt │     │ semi.md  │
│ + hints.txt  │     │     ↓     │     │ + repl   │
│ 解析字段→    │     │  repl.txt │     │ = batch  │
│ 按字段截断   │     │           │     │ 替换占位 │
└──────────────┘     └───────────┘     └──────────┘
  • format_batch.py:DB → semi.md(工具调用位置留 [待摘要:N] 占位符)+ hints.txt(工具调用关键内容,按字段截断)

  • AI 子代理:只读 hints.txt → 输出 repl.txt(工具调用摘要)

  • merge_batch.py:semi.md + repl.txt → batch.md(机械替换占位符)

上下文缩减 70%

部分 v10 AI 读取 v11 AI 读取
用户消息 全读 不读(Python 直接写 semi.md)
助手消息 全读 前 200 字符(hints.txt 里)
工具调用 全读 按字段截断后的关键内容
合计 ~1230 KB ~367 KB

不同工具按字段截断到不同长度(都是实测出来的):

工具 保留什么 截断后
edit filePath + newString[:2000] ~2000 字符
background_output task_id + output[:1500] ~1500 字符
bash cmd[:150] + desc + output[:300] ~450 字符
read filePath + output[:300] ~300 字符

五、GLM-5.1 开发体验总结

11 次调整全程使用 GLM-5.1 作为主模型,搭配 DeepSeek V4 Flash + MiniMax 做执行层。

它擅长的

架构设计:从 v1 的 session_read 单体方案到 v3 的主代理+子代理架构,是 GLM-5.1 自己提出的。v9 的三阶段流水线(format_batch → AI 摘要 → merge)也是它设计的。

复杂调试:从数据库 106 条前缀消息中挖掘出双前缀嵌套的极端 case,定位到 oh-my-opencode 的 keyword-detector 注入逻辑。

自主优化:在 v8 的实际运行中,GLM-5.1 自行做了 3 件提示词没要求的事(创建脚本、并行化、自适应精简 prompt),说明它不只是执行指令,能主动改进方案。

它的短板(夹带私货)

Lite套餐生成速度慢:从0开始思考并生成500 行代码 20 分钟起步,30 分钟超时会导致丢失所有进度。

上下文限制:GLM-5.1 上下文长度只有200k,经常触发压缩

分流策略

GLM-5.1 做规划和调度("怎么干"),5个DeepSeek V4 Flash + 5个MiniMax M3做具体执行("照着干")。速度远快于 GLM-5.1一个模型执行,且质量一致——关键是 GLM-5.1 给了它们"填空题级别"的详细 spec(内联提示词模版)。

 🙋蹲队友拼智谱 Coding Plan!

🧩国内顶流编程大模型,20+主流工具全适配,性价比拉满,
👉立即参与「拼好模」:https://www.bigmodel.cn/glm-coding?ic=LJEKCPOQLP 

六、使用方法

3 步使用

  1. 新建 OpenCode 会话 → 复制阶段一提示词 → 替换 {花括号} → 粘贴发送

  2. 等跑完 → 翻阅素材文件确认无遗漏

  3. 复制阶段二提示词 → 粘贴发送 → 生成开发文档(阶段二的提示词只是示例,每个人需求不同,可以自行调整)

前置条件:WSL下的OpenCode + oh-my-opencode + SQLite 数据库

完整提示词模板session-doc-prompt/session-doc-prompt-v1.1.md at main · ssbh163/session-doc-prompt · GitHub

注意:目前提示词仅适配 WSL 下的 OpenCode,其他平台使用的 OpenCode 或终端 Agent 需要调整opencode实际数据库所在位置(/root/.local/share/opencode/opencode.db)。

七、总结

核心观点:AI 编程的工作成果不只体现在代码里,更体现在对话中。会话素材收集是填补"AI 编程文档空白"的第一步。

可改进方向

  • 适配更多 AI 编程工具:目前仅适配 WSL 下的 OpenCode(SQLite 数据库路径固定)。Cursor、Claude Code、Windsurf 等工具也有本地数据存储,理论上可以复用相同的"直查数据库 → 三阶段流水线 → 结构化输出"架构,只需适配数据源。

  • 封装为 OpenCode 插件或 Skill:当前形态是提示词模板,优点是零门槛粘贴即用,缺点是每次都要等 AI 自己生成 Python 脚本。封装成插件后脚本内置,省掉重复生成环节,速度和稳定性都会提升。

  • 批量提取 + 主题聚合:目前一次提取一个会话。实际开发中一个功能可能跨 3-5 个会话,后续可以支持批量提取后按主题自动聚合,把分散在多个会话中的同一功能开发过程合并成一份完整素材。

  • 素材去重:同一个问题在不同会话中反复出现(比如"怎么配路由"问了 3 遍),提取后应标记去重,避免文档冗余。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐