dsh-conversation-digest · 个人提示词效能工作台
预览

示意图,非实拍:实际界面跟随宿主主题,按钮位于输入框右侧。
把「每次都要自己想起来」变成「存在档案里、下次自动补上」。
DeepSeek Harness(DSH)插件:读你的历史对话,指出你提问上的问题,并在你下次发言前把这些毛病补上。
它做什么
你大概遇到过这些:指令没说清楚,来回返工三轮;输出格式交代过一次,下次又忘了交代;工具调用失败,其实是因为你没说前置条件。
复盘历史提问 —— 扫本机会话记录(只取你自己打的字,系统注入的不算),找出指令模糊、反复交代的约束、漏说的前置条件;每条给出出现次数、证据(哪个会话第几条)和一段可直接粘贴的改写草稿。
改写正在写的草稿 —— 输入框右侧 ✨ 优化,按上面找到的问题改写草稿,一次给 简洁 / 标准 / 严谨 三档,可以只复制,也可以直接替换输入框。
把好用的问法存下来 —— 采纳的改写自动归档、按任务类型打标签;下次输入相似内容时,输入框上方提示「你上次补上这条约束后效果更好,要不要带上」。
| 能力 | 怎么用 | 你得到什么 |
|---|---|---|
| 复盘历史提问 | 设置页「开始复盘」 | 一份改进清单,每条带可直接粘贴的改写草稿 |
| 改写当前草稿 | 输入框右侧 ✨ 优化 |
简洁 / 标准 / 严谨 三档,任选一档替换或复制 |
| 好问法归档 | 采纳时自动 | 按任务类型打标签的模板,输入时主动推荐 |
安装
桌面客户端(Electron)
桌面端读的是 desktop profile,dsh plugin 命令行按设计拒绝碰它。让宿主自己装:
请使用内置的
plugin_manager安装github:LIN-F1SH/dsh-conversation-digest。
或本地开发:
请用内置
plugin_manager安装link:<本目录绝对路径>。
Web(dsh web)
# 跟随 main(会拿到最新提交)
dsh plugin --profile web add github:LIN-F1SH/dsh-conversation-digest
# 钉住某个版本(推荐用于生产)
dsh plugin --profile web add github:LIN-F1SH/dsh-conversation-digest#v0.1.1
⚠️ 宿主代码改动后必须重启应用。插件以
link:安装时,改lib/*不会热重载(ESM 模块缓存);禁用再启用也只会重跑apply(),不会重载代码。客户端client/client.js的改动刷新页面(Ctrl+F5)即可。⚠️ 不要在
link:安装之上再试file:安装。link:在node_modules/<包名>建的是指向源码目录的 junction;pnpm 装file:时会先"移除旧包目录",它会顺着 junction 把你源码目录里的文件删掉(实测把.git元数据掏空了)。要换安装方式请先卸载并手工删掉那个 junction。
怎么用
- 先复盘:设置 → 「提示词工作台」→「开始复盘」。它读最近
reviewWindowDays天内的会话(默认 14 天、最多 8 个),只分析你自己打的字,调一次模型产出改进项。 - 再优化:回到对话,在输入框打一句话,点
✨ 优化。它拿你档案里 active 的改进项来改写,并列出「这次补了哪几条」。 - 点「替换输入框」:改写稿写回草稿,同时这条被采纳的提示词自动归档进资产库。
- 之后输入时,输入框上方会出现提示:「你上次做类似任务时补上这条约束后效果更好,要不要带上?」
设置
设置 →「提示词工作台」→ 设置 页。改完点「保存」;非法值会被自动收敛(档位过滤、数值夹到区间),不会写坏档案。
| 项 | 作用 | 范围 |
|---|---|---|
| 启用插件 | 关掉后不再自动推荐,手动优化仍可用 | 开关 |
| 生成哪几档 | 优化时生成哪些版本,档位越少越快越省 | 简洁 / 标准 / 严谨,至少留一档 |
| 默认版本 | 排在最前并标「推荐」的那一档 | 必须在已选档位内 |
| 输入时自动推荐 | 边打字边匹配历史模板与待补约束 | 开关 |
| 推荐灵敏度 | 越小越容易触发 | 0–20 |
| 复盘回看天数 | 只看最近这么多天的会话 | 1–365 |
| 单次复盘会话数 | 越多越慢、越费 token | 1–20 |
| 优化时参考哪些改进项 | 只带任务类型匹配的,或全部生效中 | matched-only / ll-active |
| 清空档案 | 删除全部改进项与资产(二次确认) | — |
设置就存在同一份档案的 settings 字段里,接口:POST /pwb/profile {"action":"update-settings","settings":{…}}。
数据与隐私
| 项 | 说明 |
|---|---|
| 档案位置 | $DSH_HOME/prompt-workbench/profile.json(默认 ~/.dsh) |
| 读取什么 | 本机 ~/.dsh/sessions/**/session.v4.jsonl.zstd,只读 |
| 过滤规则 | 只取 user/message 且 source.kind === 'user' —— 系统注入的运行时上下文、审批通知、技能目录一律排除,否则分析结论全是噪声 |
| 运行要求 | Node ≥ 22.15(会话日志是 zstd 压缩的,老版本 Node 没有 zstd API) |
| 联网 | 只有调模型时;读会话与分析不访问任何第三方接口 |
| 凭据 | 不存任何 key。模型调用走宿主 llm 服务,用你当前选择的默认模型 |
| 诊断文件 | 模型输出解析失败时,原文会落到 $DSH_HOME/prompt-workbench/last-*.txt,仅本机 |
| 写接口 | 只接受本机回环来源(127.0.0.1 / localhost / ::1),局域网写入一律 403 |
HTTP 接口
前缀 /pwb。读接口不限来源,写接口仅本机。
| 方法 | 路径 | 作用 |
|---|---|---|
| GET | /pwb/ping |
自检 |
| GET | /pwb/health |
环境体检:llm / 默认模型 / 档案 / 可复盘会话,ready 一句话回答"现在能不能跑复盘" |
| GET | /pwb/profile |
读档案(改进项 / 资产 / 复盘记录 / 设置) |
| POST | /pwb/profile |
改设置、改改进项状态、删条目(用 action 区分) |
| GET | /pwb/sessions |
列出可复盘的时间窗口 |
| POST | /pwb/review |
启动复盘,返回 reviewId(异步,避免 HTTP 超时) |
| GET | /pwb/review?id= |
轮询复盘进度与结果 |
| POST | /pwb/optimize |
按档案改写草稿,返回 3 个版本(options[],另带兼容字段 rewritten) |
| POST | /pwb/recommend |
按草稿推荐资产/改进项(纯本地匹配,不调模型) |
| POST | /pwb/assets |
把一条提示词沉淀进资产库 |
目录结构
dsh-conversation-digest/
├── package.json # dsh.bundle.patch + dsh.client(platform: web)
├── cordis.patch.yml # 挂载声明
├── lib/
│ ├── index.js # 宿主入口:装配
│ ├── routes.mjs # /pwb/* 路由与信任边界
│ ├── profile.mjs # 档案层:原子写 / 损坏保护 / 合并去重
│ ├── sessions.mjs # 读历史会话:多帧 zstd 解压 + 提问/失败提取
│ └── analyze.mjs # 提示词工程 + 模型输出校验
├── client/client.js # 客户端半区(手写、零构建)
├── scripts/ # 三套自检
└── docs/DESIGN.md # 设计文档:为什么是这些字段
开发
npm run smoke # 98 项:宿主 15 + 档案 28 + 分析 34 + 会话 9 + 客户端 12
客户端半区不需要浏览器也能验:scripts/smoke-client.mjs 桩掉 window.__ModuleLoader__、document 和 require('react'),直接跑 factory 与 apply(),断言 id 与包名一致、返回 cordis 插件、三个插槽名真实存在、组件可渲染、清理函数可用,并覆盖两种降级:语言包注册抛错时插槽仍注册、缺少 useInput/inputActions 时组件不抛。
重启宿主后,一条命令验证真机闭环:
node scripts/verify-live.mjs # 默认 http://127.0.0.1:19387
node scripts/verify-live.mjs 3080 # 或指定 dsh web 的端口
它会依次打印环境体检、跑一次真实复盘、列出改进项与改写草稿、试跑一次优化、复核档案。
三个踩过的坑(写这类插件的人会再踩一遍)
- 会话文件是
session.v4.jsonl.zstd,而且是多帧拼接的。zlib.zstdDecompressSync只解第一帧 → 你只会读到一行头部,看起来「这个会话是空的」。必须按魔数28 B5 2F FD逐帧解(见lib/sessions.mjs)。 user/message里大部分不是你打的字。实测 300 条里只有 62 条source.kind === 'user';其余是ptc-mode、runtime-context、skill-catalog等系统注入。不过滤就会把系统模板当成你的提问习惯来分析。tool/result的error字段只覆盖约 1/3 的真实失败(32/1195)。真实的内层工具失败在tool/ptc-dispatch,另外还要叠加文本启发式([exit code: N]、STDERR:、ToolCallError…)。
验证记录
在 9 个真实会话(约 9 天、8.4 MB 压缩日志)上的实测:
| 环节 | 结果 |
|---|---|
| 复盘 | 8 个会话 / 60 条真人提问 / 98 次工具失败 → 5 条改进项,每条带证据与改写草稿 |
| 重复复盘 | 第二批结果 新增 0 / 合并 5,次数累加(8/8/6/6/6),标题更新为更具体的措辞 —— 不会越跑越脏 |
| 优化 | 引用档案中全部 active 改进项改写草稿,列出本次补了哪几条,并给出任务分类与标签 |
| 资产 | 采纳后归档、按任务类型打标签;相似草稿能命中推荐 |
这套数字来自
scripts/verify-live.mjs的真实输出,脚本可随时重跑。
token 成本(实测,不是估算)
powershell node scripts/measure-tokens.mjs
它在你的真实会话上量四件事:复盘实际要发出去的材料、模型自报的历史 usage、重复提交的两种成因、以及单条提示词的增量。
本机 8 个会话 / 60 条真人提问的实测结果:
| 项 | 数字 | 含义 |
|---|---|---|
| 复盘实际发送 | 7,982 字符 ≈ 5.0 千 tokens | 只取真人提问 + 失败聚合摘要 |
| 事件全文 | 30.7 MB ≈ 2000 万 tokens | 若把整段对话直接塞给模型 |
| 压缩比 | ≈ 4000 : 1 | 这是插件最硬的省 token 点 |
| 历史总消耗 | input 2.30M + output 1.34M | 模型自报 |
| 缓存命中读取 | 179.5M | 每次请求重读上下文前缀,按缓存价计费 |
| 失败后重发 | 6 次 | 上一轮 error/borted(网络/服务故障) |
| 真·返工 | 1 次 / 60 轮 ≈ 0.1% tokens | 上一轮正常完成却要重说 |
结论要老实说:
- 省 token 的地方在复盘输入的压缩(4000:1),以及增量复盘:已经复盘过、文件之后没变的会话不再重发,重复点「开始复盘」几乎零成本(要强制重跑传 {"force":true})。
- 复盘材料从早期的 16,209 字符压到 7,982 字符(-51%):失败记录从"逐条贴原文"改成按 工具+错误码 聚合(曾占材料的 71%),连续重复的提问折叠成「同一句 ×N」,只说过一两句的会话直接跳过。
- 单条提示词会变长(加约束,通常 +30200 字 ≈ +20130 tokens),这是明面上的成本;而且它进入上下文后每一步都会被重读,所以有放大效应。
- 「更好的提示词能否省 token」取决于返工是否减少。在你这批数据里,真·返工只占 0.1% —— 你 9 天里的重复提交,6 次是 provider 502/传输错误造成的,那类 token 靠改提示词省不掉。
- 换句话说:这个插件的主要价值不是省 token,而是让问题有据可查、让约束不再漏。如果你的返工主要来自提问含糊,收益会明显;如果主要来自网络与模型能力,收益有限。
每次复盘/优化的响应里都带 okens 字段(模型自报的 input/output/cacheRead),可以在界面上核对真实开销。
DSH 升级与版本兼容
插件架在若干宿主契约上。下表是已知耦合点、升级后可能出现的症状、以及现在的兜底——不是保证永不坏,而是坏的时候你能一眼定位。
| 契约 | 用在哪 | 变了会怎样 | 现在的兜底 |
|---|---|---|---|
会话日志 session[.vN].jsonl[.zstd] |
复盘读取 | 新格式读不到 → 报「时间窗口内没有可复盘的会话」 | 按版本发现:取最高版本、压缩与否看魔数而不信后缀、未压缩也能读 |
| 多帧 zstd 拼接 | 同上 | 只读到头部 → 会话看起来「是空的」 | 按 28 B5 2F FD 逐帧解压 |
user/message.source.kind |
复盘过滤 | 系统注入被当成提问 → 结论全是噪声 | 只认 kind === 'user',未知 kind 一律排除 |
tool/ptc-dispatch、tool/result.error |
失败检测 | 失败数被低估 | 结构化字段 + 文本启发式双通道 |
llm.stream()、agentDefaultModel.currentSelection() |
复盘 / 优化 | 调用抛错 | 服务缺失时给明确提示,不崩;没选模型也提示 |
webServer.register() |
全部 API | 路由全 404 | 注入失败只报错,不拖垮宿主 |
__ModuleLoader__.load、dsh.client |
界面三处插槽 | 界面完全不出现 | bundle 内每步注册独立 try/catch,单点失败只少一块 |
插槽名 conversation.input.right 等 |
界面位置 | 按钮不出现 | 注册失败降级,不影响另外两块 |
useInput / inputActions |
读写草稿 | 按钮变灰 / 插入无效 | 类型守卫;缺失时按钮禁用而不报错 |
升级后先看体检:
curl http://127.0.0.1:19387/pwb/health
它会报 sessions.formats(实际读到的格式,如 ["v4.zstd"])、compat.zstd、compat.services(llm / agentDefaultModel / webServer 是否在位)、profile.exists、ready。ready: false 就说明某条链路断了,再按上表定位。
已知限制
- 复盘一次只发一个模型请求,材料已压缩(只取真人提问 + 失败摘要),但仍受窗口大小限制;输出被截断时插件会明确报
TRUNCATED并重试一次,而不是静默失败。 - 复盘的问题合并靠三条判据:模型复用 id(提示词里会要求)→ 标题归一化后完全相同 → 引用了同一条证据(同 session 同 seq)。纯字符串相似度阈值定得很高(0.85),因为「问题 1 / 问题 2」这种只差一个数字的标题会被误并。
- 资产推荐用字符 bigram 相似度做本地匹配,不做语义检索——够用、零成本、可预测。
- 会话压缩(compaction)后,被折叠的早期事件仍在日志里,本插件按时间顺序读取,不区分「模型当前可见」的 surface。
- 只支持
session.v4(并按最高版本发现);将来格式升到 v5,解析层会忽略未知事件类型、不会崩,但新字段的语义需要人工适配。
许可
MIT © 2026 LIN-F1SH
No comments yet. Be the first to write one.