skills+general_v1: ppt 歧义反问 + 路由产物形式歧义先问

skills/ppt/SKILL.md:3 上次收紧白名单+反例后,"MES 汇报方案" 这种请求
还是被路由命中 —— 反例列表只列了 "生成方案/写报告/出文档/做纪要",
"汇报方案" 未列入,而 "汇报" 在 LLM 语义里本就有强烈的 PPT 联想
(工作汇报/季度汇报多以幻灯片形式),足以压过 "必须明确点名 PPT"
的硬约束。

修法:
- ppt SKILL.md description 改三段( 触发白名单 /  不触发 [只留
  "报告/文档/纪要" 明确指向文档的词] / ⚠️ 歧义先反问)。把 "汇报/
  方案/材料" 从反例摘出来,改成 "先反问 'PPT 还是 Word/Markdown 文档'
  再决定 load",把判断权还给用户而不是赌 LLM 路由词典。
- prompts/system/general_v1.md Skill 机制段加 "产物形式歧义时先问"
  通用原则,跨 skill 生效(imagegen/videogen 各自 skill 内本来就有
  '问清楚再画' 逻辑,抽到 system prompt 让新加 skill 也继承)。

否决:
- 继续往反例堆 "汇报方案/汇报材料/汇报内容":堆词典治标不治本,
  下次 "做个 Q4 总结" 又得加。
- 路由层加 required_keywords 结构化字段,在 discovery_block 之前
  grep 兜底:跨多 skill 都得补字段,工程量大,短期 LLM 反问范式
  收益已够。
- ppt skill load 后再反问:路由命中就已是误触发,要在路由阶段拦。

代价:用户心里已经清楚要 PPT 但没说时会多一轮反问;缓解靠反问句式短
+ 暗示默认选项,一个字 "PPT" 就能过,比生成完整 deck 后推翻代价小
一个数量级。

热更新无需重启服务:agent_builder.py:197 每次 build_agent 现读
general_v1.md;SkillRegistry 也每次 build_agent 重建。DESIGN/RUN 不动。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
caoqianming 2026-05-27 15:36:25 +08:00
parent 8109f20345
commit 0b7c084458
3 changed files with 5 additions and 2 deletions

View File

@ -2,7 +2,7 @@
> 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9`
最后更新:2026-05-27(ppt skill description 收紧路由,避免 "生成方案" 被误命中)
最后更新:2026-05-27(ppt skill 歧义反问 + general_v1 加"产物形式歧义先问"通用原则)
---
@ -23,6 +23,7 @@
### 2026-05-27
- **ppt skill 歧义反问 + general_v1 加"产物形式歧义先问"通用原则**:上次 8109f20 把 ppt description 收紧成"白名单 + 反例"后,实测"MES**汇报方案**"这种请求还是被路由命中 —— 反例列表只覆盖"生成方案 / 写报告 / 出文档 / 做纪要"几个组合,但"汇报方案"未列入,而"汇报"在 LLM 语义里就有强烈的 PPT 联想重力(工作汇报 / 季度汇报多以幻灯片形式)足以压过"必须明确点名 PPT"的硬约束。**修法**:① `skills/ppt/SKILL.md:3` description 改三段(✅触发白名单 / ⛔不触发[只留明确指向文档的"报告 / 文档 / 纪要"] / ⚠️ 歧义先反问)—— 把"汇报 / 方案 / 材料"从反例摘出来,改成"先反问用户'PPT 还是 Word/Markdown 文档'再决定 load",把判断权还给用户而不是赌 LLM 路由词典;② `prompts/system/general_v1.md` Skill 机制段加一条系统级原则"产物形式歧义时先问",升格为跨 skill 通用约束(imagegen / videogen 各自 skill 内本来就有"问清楚再画"逻辑,现在抽到 system prompt 让新加 skill 也能继承)。**否决**:(a) 继续往反例里堆"汇报方案 / 汇报材料 / 汇报内容"—— 堆词典治标不治本,下次"做个 Q4 总结"又得加;(b) 路由层加 `required_keywords` 结构化字段,在 discovery_block 之前 grep 用户原话兜底 —— 跨多 skill 都得补字段,工程量大,短期 LLM 反问范式收益已够;(c) ppt skill load 后再反问 —— 路由命中后再反问就是已经误触发了,要在路由阶段拦。代价:用户已经心里清楚要 PPT 只是没说时,会觉得多一轮反问啰嗦;缓解靠反问句式短 + 暗示默认选项,一个字"PPT"就能过,比生成完整 deck 后推翻代价小一个数量级。`DESIGN.md` 不动(无架构变化);`RUN.md` 不动(纯 skill 元数据 + system prompt 文案)。
- **ppt skill description 收紧路由**:`skills/ppt/SKILL.md:3` 原文 "做汇报 PPT、把材料/会议纪要/方案转为幻灯片、生成演示稿" 含 "方案" / "生成" 字样,Claude 路由时把 "生成一个方案" 也命中到 PPT skill。改成显式白名单(PPT/幻灯片/演示文稿/.pptx/slide/deck)+ 显式反例("生成方案 / 写报告 / 出文档 / 做纪要" 不触发 —— 那是文档任务)。`DESIGN.md` 不动;`RUN.md` 不动(纯 skill 元数据)。
- **skill 热更新:`/v1/skills` 每次现扫**:此前 `web/app.py` lifespan 启动时 `app.state.skill_registry = SkillRegistry(...)` 扫一次,`GET /v1/skills` 从这份静态快照读 → 加新 skill 目录(放到 `skills/<name>/SKILL.md`)必须重启 web 才能在 dev SPA 新建任务弹窗下拉看见,为未来"允许用户安装自己 skill"埋了一刀。改法:删 lifespan 那行 + 注释,`/v1/skills` 路由内每次 `SkillRegistry(ROOT / cfg["skills_dir"])` 现扫。实测 SkillRegistry 构造 ~3ms / 次(9 个 skill,iterdir + 9 次 read_text + yaml frontmatter),整个 HTTP e2e ~20ms 完全淹没在 JWT + DB 噪声里,且 `/v1/skills` 只在"新建任务弹窗打开"触发,非热路径。**`core/agent_builder.py::build_agent` 早已是每次新建 SkillRegistry**(每发新消息重扫),所以 agent 内部 `load_skill` 工具与 system prompt discovery block 一直是热的;此次仅修补前端下拉这一处静态快照。Smoke 验证:`skills/_smoke_hot_reload/SKILL.md` 临时创建 → `/v1/skills` 9→10 看见、删除 → 10→9 消失,全程未重启进程。否决:(a) 加 `POST /v1/skills/reload` 显式触发 —— 多 API + 用户得记得调,3ms / 次的优化收益为 0;(b) watchdog 文件系统监听 —— 加依赖 + 容器 bind mount inotify 偶尔不稳 + 工程量过重,与方案 A 在用户体感上无差异;(c) `SkillRegistry` 加 mtime cache —— 智能化复杂度换 ms 级 IO 节省,§7.9 "不为不存在的瓶颈预付架构成本"同款判定。**未来"用户自带 skill"独立维度**(届时 `workspace/users/<uid>/.skills/` 与全局 `skills/` 多 root 叠加),跟当前热更新不耦合,等真做时再加多 root 支持。`DESIGN.md` 不动(无架构变化);`RUN.md` 不动(无 CLI / env 变化)。
- **dev SPA 「导出对话记录」/「清空对话」按钮 disable 逻辑改成只要选中 task 就常亮**:`web/static/dev.html` `renderChatMeta` 里原本按 `t.n_messages === 0` 一并禁用两键(`:1812`/`:1815`)。bug:用户「清空对话」→ `clearMessages` 返回 `n_messages=0` → 两键 disable;之后发新消息走 SSE 流(`sendMessage` `:2210`),后端 task.n_messages 累加但前端 `state.taskMeta.n_messages` 没刷,renderChatMeta 也不会再跑,两键一直灰。改法:不按 n_messages 门禁,导出常亮、清空仅在 run running/cancelling 期间禁(后端 409,confirm 后再报错 UX 差);0 条时点导出生成空 docx、点清空 confirm 显 0 条 —— 都不会出错,语义一致更省心。`deleteTask` 路径里把"无 task 选中时两键显式 disable"逻辑保留(那时 chat-meta 退到"未选中任务"占位,常亮反而误导)。否决:(a) 修真正的 n_messages 同步问题(SSE 收 done 时回拉 taskMeta) —— 一次额外 GET,且 streaming 期间频繁拉一致性更易飘;(b) 把 export 也按 running 禁 —— export 是只读快照,run 中导出当前可见的部分对话完全合理。`DESIGN.md` 不动(无架构变化);`RUN.md` 不动(无 CLI/env 变化)。

View File

@ -23,6 +23,8 @@
简单问答、读代码、改 bug、文件操作这类通用任务,直接用通用工具就够,不必为每个
任务硬套 skill。一旦决定要用,**不要凭印象推测**怎么用 —— load 一下。
**产物形式歧义时先问**:用户请求里产物**内容**清楚了、但**形式**(PPT / 文档 / 视频 / 图)还模糊时(只说"汇报 / 方案 / 材料 / 报告"等通用词、没明确说成品形式),先用一句话反问确认形式,再决定 load 哪个 skill。例:用户说"做一个 XX 汇报方案",反问"要做成 PPT 演示稿,还是 Word/Markdown 文档?"。歧义反问的代价 ≪ 误选 skill 后整份产物推翻的代价。
## 工作原则
- 动手前先看: 用 read/grep/glob 摸清现状,再 edit
- 改动最小化: edit 工具的 old_str 必须唯一匹配,不够唯一就多带上下文

View File

@ -1,6 +1,6 @@
---
name: ppt
description: 生成 PowerPoint 演示文稿 (.pptx) 文件。**仅当**用户明确点名 PPT / 幻灯片 / 演示文稿 / .pptx / slide / deck 之一时才用。⛔ 不要触发:用户只说"生成方案 / 写报告 / 出文档 / 做纪要"而没明确要 PPT 形式 —— 那是文档任务,不是 PPT 任务
description: 生成 PowerPoint 演示文稿 (.pptx) 文件。✅ 触发:用户明确点名 PPT / 幻灯片 / 演示文稿 / .pptx / slide / deck 之一。⛔ 不触发:用户明确说要"报告 / 文档 / 纪要"等指向纯文档形式的产物。⚠️ 歧义先反问:用户说"汇报 / 方案 / 材料"等产物形态不明的词、且没说成品形式时,不要直接 load 本 skill 也不要假定走文档,先反问一句"这份要做成 PPT 演示稿,还是 Word/Markdown 文档?" 用户确认 PPT 后再 load
---
# PPT