zcbot/skills/ppt/SKILL.md

231 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: ppt
description: 生成 PowerPoint 演示文稿 (.pptx) 文件。✅ 触发:用户明确点名 PPT / 幻灯片 / 演示文稿 / .pptx / slide / deck 之一。⛔ 不触发:用户明确说要"报告 / 文档 / 纪要"等指向纯文档形式的产物。⚠️ 歧义先反问:用户说"汇报 / 方案 / 材料"等产物形态不明的词、且没说成品形式时,不要直接 load 本 skill 也不要假定走文档,先反问一句"这份要做成 PPT 演示稿,还是 Word/Markdown 文档?" 用户确认 PPT 后再 load。
---
# PPT
把材料变成可演示的 .pptx。**先定调(spec + 逐页大纲),再出稿(一个脚本建整 deck),再验收(quality_check)** —— 方向在大纲阶段对齐,不在逐页阶段反复来回。
进度展示建议:多页 deck 任务用 `task_progress` 标记「摄取素材 / 八条对齐 + 逐页大纲 / 图标预取 / 脚本建 deck / 质量检查 / 交付」等关键阶段;不要把每一页的内部写入都作为进度步骤。
## 资源
- `scripts/pptx_helpers.py` —— **卡片式视觉工具箱模块**:配色/字体常量 + 派生明暗色阶(`PRIMARY_WASH/SOFT/DARK`)+ 语义色 `GOOD/BAD` + `new_presentation`/`set_palette` + **组合版式件**(一个函数摆一整块):`add_card_grid`(均衡网格)/`add_timeline`(时间轴)/`add_cycle`(流程闭环)/`add_toc`(目录)/`add_kpi`(数字卡,带 baseline+delta)/`add_takeaway`(结论框)/`add_source`(数据来源)+ 质感件 `add_card`(圆角卡,**默认平卡**)/`add_gradient_rect`/`add_icon_tile`/`add_pill`/`add_eyebrow`/`add_picture_bg`(混合背景)+ `add_notes`(演讲者备注)+ 基础件 `add_textbox`/`page_title`/`apply_brand`。`import pptx_helpers as P` 调用,**不默写源码**。⚠️ helper 的 `name=` 会写进形状名,quality_check 靠它判标签/bullet
- `references/design_principles.md` —— **§信息设计纪律(论断标题/Takeaway/数据语境化/page_rhythm)** + 画布/字号/配色/投影克制/字数预算等硬规则。**先读这节**
- `references/layouts.md` —— 13+ 版式与组合件调用示例 + helper API 速查 + 安全区保护
- `references/icons.md` —— 业务图标两层:Iconify (在线/本地缓存) / unicode 字形兜底
- `assets/icons/` —— **只读**种子图标库 (商务红 tabler 集,见 `INDEX.md`;新拉的图标写 `<task_dir>/assets/icons/`)
- 素材摄取: 用 `markitdown` CLI 把 PDF/DOCX/PPTX/XLSX/HTML/URL 转干净 Markdown,落到 `<task_dir>/source/<name>.md`
- `scripts/fetch_icon.py` —— 从 Iconify CDN 拉 SVG/PNG (染主题色;**PNG 转换需 cairosvg/svglib,没装会只出 SVG** —— 优先用种子库现成 PNG)
- `scripts/render_icon.py` —— unicode 字形 → 透明 PNG (Iconify 没有时兜底)
- `scripts/render_bg.py` —— 无头 Chrome 把主题化 HTML 渲成**杂志级背景 PNG**(混合方案:封面/章节背景图 + 其上原生可编辑文字)
- `scripts/pptx_preview.py` —— **把 .pptx 渲成 PNG 预览**(无头 Chrome),交付前**肉眼验收版面**(quality_check 查结构,预览查观感;能抓到多行不上色这类渲染 bug)
- `scripts/quality_check.py` —— 产物 .pptx 结构验收 (越界 / 文本溢出 / 按列 bullet / 按色系三色制 / 重叠)
## 默认主题 — 商务红 (硬约束)
**主色 `#C00000` / 辅色 `#E15554` / 强调色 `#FFC107`。**
**不允许擅自换色**。除非满足以下任一条件,否则 spec 必须填这套红色:
- 用户在请求里**明确**点名其它配色 (例:"做成蓝色"、"用我们公司的紫色")
- 用户提供素材里有明确的 brand guideline / 配色卡
**禁止的自我合理化**(都属违规):
- "这个场景蓝色更专业" / "学术汇报红色不合适" / "财务用蓝更稳重"
- "我觉得 XX 主题更适合"
要换色,**先问用户**,不要在 spec 里塞自己的偏好。其它备选见 `design_principles.md §2`
## 两阶段工作流
### 阶段一: 策略 (Strategist) — 八条对齐
产物:**task 级 spec 文件** —— 整个 deck 的"宪法",阶段二每页前都要重读。文件路径按 system prompt 的《task 级「宪法」文件命名约定》:
<task_dir>/<today>-<task_short_id>-<task_name>.spec.md
`<today>` / `<task_short_id>` / `<task_name>` 用 system prompt 注入的实际值替换。
**0. 先检测已有 spec**:
```
glob <task_dir>/*-<task_short_id>-*.spec.md → 按文件名字典序排,取最大者作 current
```
(按 short_id 主锚,name 部分不参与匹配 — 用户改过 task name 时旧文件仍能定位)
- 有 current(当前 task 已有 spec) → 展示给用户,问「**沿用进阶段二** / **重定调**(以 today 写新版,旧版保留)」,⛔ BLOCKING 等用户决定
- 仅有其它 task 的(`*-<别的 short_id>-*.spec.md`)→ 不当 current 用,继续走下面流程
- 完全没有 → 直接走下面流程
按下表**一次性给出推荐方案**,然后 ⛔ **BLOCKING:等用户确认/修改后才能进阶段二**。不要一条一条问。
| # | 项 | 默认值 |
|---|----|-------|
| 1 | 画布 | **16:9** (13.33×7.5 in) |
| 2 | 页数 | **封面 + 5-8 页正文 + 尾页(Q&A)** = 共 7-10 页。**封面 / 尾页强制必有**,不在 5-8 页预算里 |
| 3 | 受众 | 看材料推断:领导汇报 / 同行评审 / 客户 pitch |
| 4 | 风格 | **现代简约** (白底 + 细线 + 留白) |
| 5 | 配色 | **商务红** `#C00000` `#E15554` `#FFC107` (见上"默认主题") |
| 6 | 字体 | **微软雅黑 + Arial** |
| 7 | 图标 | **Iconify `tabler` 集** (描边商务图标,主色染色;`fetch_icon.py` 拉到 `<task_dir>/assets/icons/`;业务概念页用 `add_icon_tile` 配图标底块) |
| 8 | 图表 / 配图 | 数据 ≥ 3 个点 → matplotlib 图(或 ≤4 个数字直接上 KPI 卡 L10);**真实配图 opt-in**:封面/章节/图片页可走 imagegen 生图(**每张 ¥0.22**,默认不开,要用在大纲里标 `[img]` 并经用户确认) |
把这 8 项写进上面那个 task 级 spec 文件,以表格形式给用户预览,问一句"按这个开干?"。**spec 写定后不再改**(要改就走 §0 的「重定调」分支,以 today 为前缀写新版,旧版保留)。
**8 项之外,spec 还要含一张「逐页大纲」表** —— 阶段二一个脚本建整 deck 的输入,也是替代"逐页确认"的前置 checkpoint。**标题写论断、每页标节奏**(见 design_principles §信息设计纪律):
| 页 | 节奏 | 版式 | **论断式标题** | 核心信息 / Takeaway | 图标 / 图表 / 配图 |
|---|---|---|---|---|---|
| 1 | anchor | L1 封面 | <主标题> | <副标题 / 定位> | 可选 `[img]` 主图 |
| 2 | anchor | 目录 | 目录 | <5 + 各一句副标> | — |
| 3 | dense | 卡片网格 | "大模型靠规模涌现出通用智能" | <3-5 概念 + 一句 takeaway> | `brain`/`cpu`/… |
| 4 | dense | 时间轴 | "六年能力指数跃迁" | <里程碑 + takeaway + 来源> | — |
| 5 | **breathing** | 大字页 | "2 个月,月活破亿" | <单个大数字 + 一句语境对比> | — |
| … | … | … | … | … | … |
| N | anchor | 尾页 | 致谢 / Q&A | <联系方式> | — |
> **三条硬纪律(大纲阶段就定死)**:
> - **论断标题**:标题列写"结论"不写"主题"("渗透率破 60%" 不是 "行业背景");
> - **节奏不雷同**:相邻内容页不同版式;**每隔 2-3 页插一个 `breathing` 页**(大字/金句/整图,禁卡片网格)打破"全卡 = AI 味";**卡片网格全 deck ≤2 次**;
> - **内容→版式映射**:历程→时间轴、循环→闭环、2-4 数字→KPI 卡(带对比基准)、并列概念→均衡网格、单震撼数字→breathing 大字。
>
> 内容页正文优先压成一句 **Takeaway 结论**;含数据的页要有**对比基准 + 来源**。版式见 layouts.md §选版式速查。配图页标 `[img]` + 一句画面。
大纲连同 8 项一起给用户预览,**BLOCKING 等用户确认整份结构**(页数、每页讲什么、节奏、版式)后再进阶段二。用户在这一步推翻方向 = 改表格文字,零 slide 返工。
### 阶段二: 执行 (Executor) — 一个脚本建整 deck
方向已在阶段一的「逐页大纲」里跟用户对齐过,执行阶段就是把大纲机械落成 slide。**不逐页 run_python**(每页一轮来回烧轮数/token);整 deck 在一个脚本、一个进程内构建,坐标天然一致(`pptx_helpers` 已把画布常量统一,漂移问题已解决)。
流程:
1. **读 current spec**(按 §0 的 glob 规则拿字典序最大那份),含 8 项 + 逐页大纲;只用里面定的颜色/字体/图标/页结构,**不凭记忆发挥**。
2. **图标批量预取(全 deck 一次,不逐页)**: 把大纲里所有页需要的图标概念汇总,`glob` 两处看现成 —— 种子库 `<skill_dir>/assets/icons/`(只读)+ 本 task `<task_dir>/assets/icons/`;缺的在**一个 `run_python` 里批量** `fetch_icon.py <name> --set tabler --color C00000 --size 128 -o <task_dir>/assets/icons/...` 拉齐。**几何形状(圆点/徽章/装饰线)不算图标,走 layouts.md helper**。
3. **真实配图(opt-in,仅当大纲标了 `[img]`)**: 把标 `[img]` 的页(封面/章节/图片页)汇总,**load `imagegen` skill 走它自己的确认流程**逐张生成(每张 ¥0.22,有强制确认门,不要绕过),产物落 `<task_dir>/figures/`;build_deck 里 `add_picture(<figures 路径>)` 引用。**没标 `[img]` 的 deck 跳过这步**,图标/卡片/渐变已足够撑视觉。
4. **混合背景(opt-in)**:封面/章节想要杂志级背景时,`run_python` 调 `render_bg.py --out <task_dir>/figures/cover_bg.png --kind cover --primary <主色>`(+ section),build_deck 里 `P.add_picture_bg(slide, bg)` 铺底再叠**白色**文字。**背景图不可编辑、文字可编辑**——这是 editable 前提下的最高观感。
5. **写 `build_deck.py` 到 `<task_dir>`,一次建整 deck**: 顶部 `import pptx_helpers as P``P.new_presentation``P.set_palette(spec_path=...)`**按大纲循环每页**(每页一个小函数)→ 末尾 `prs.save`。落实**信息内功**(见 design_principles §信息设计纪律):
- **论断式标题**(写结论)+ 内容页 `P.add_takeaway(slide, "<一句话结论>")`;
- 含数据用 `P.add_kpi(..., baseline=, delta=)` + `P.add_source`;**数字别孤立**;
- **节奏**:按大纲的 anchor/dense/breathing 落版式,breathing 页走大字/金句/整图(**禁卡片网格**);
- **投影克制**:平铺网格卡用 `add_card`(默认平卡),投影只给悬浮/被挑出的卡,每页 ≤2-3 个;
- 每页 `P.add_notes` 写 2-4 句**结论先行的口语**演讲稿。
helper 一律 `P.xxx` 不默写源码;版式见 layouts.md。先 `write` 脚本再 `run_python(script_path=...)`
6. **quality_check + 预览双验收**(见阶段三)→ 按报告**改 `build_deck.py` 重跑**(不逐页 edit 成品)。
7. 报整份 deck:页数、各页版式/节奏、用到的图标/配图;问用户要不要改。
8. 用户确认了**实质改动**后,追加一行到 `<task_dir>/REVISIONS.md` —— 见 §修订日志。
**风格探针(可选,降视觉返工险)**: 用户对观感没底、或这是全新风格时,可先只建**封面 + 1 内页**给用户看一眼,确认后把 `build_deck.py` 的页范围放开重跑补齐其余页 —— 仍是改一个脚本,不退回逐页。用户要快("直接全做")就跳过探针,整 deck 一把出。
**为什么不再逐页?** 逐页的两个理由都已消解:① 防坐标漂移 → `pptx_helpers` 模块化已解决;② 早发现方向问题 → 前移到阶段一「逐页大纲」确认(改文字比改 slide 便宜),视觉观感由可选探针 + 整 deck 后批改兜底。代价是放弃"逐页即时纠错",换来 N 页从 ~2N 轮降到 ~3-4 轮。
### 阶段三: 验收 (结构 + 观感 双验)
**① 结构验收** `quality_check.py`(越界/溢出/三色/重叠):
```bash
python <skill_dir>/scripts/quality_check.py <task_dir>/<output.pptx> --spec <task_dir>/<today>-<task_short_id>-<task_name>.spec.md
```
**② 观感验收** `pptx_preview.py`(渲成 PNG **肉眼看版面**)—— quality_check 查不出"好不好看 / 文字层级 / 留白 / 多行文本掉色"这类问题,**交付前必须渲几页关键页用 `read` 亲眼过**:
```bash
python <skill_dir>/scripts/pptx_preview.py <task_dir>/<output.pptx> -o <task_dir>/preview --pages 1,3,5
```
看封面、一个内容页、breathing 页是否如预期(标题层级、卡片是否过挤/过空、文字是否都正常上色、节奏是否单调)。
两项不通过的,**改 `build_deck.py` 重跑**(改源脚本可复现;不要直接 edit 成品 .pptx)。
## 设计原则 (硬规则速查)
- **每页一个核心信息**: 一页讲一件事,塞两件就拆页
- **内容装进卡片**: 内容页主力容器是 `add_card`(圆角+柔和投影),白底之上靠卡片浮起分层,别让元素裸贴白纸
- **概念配图标底块**: 业务概念(能力/模块/策略)用 L11 卡片网格 + `add_icon_tile`,**别只摆圆点 bullet**(视觉太单薄)
- **数字上 KPI 卡**: 2-4 个关键数字用 L10 `add_kpi`,优先于硬画柱状图;单个震撼数字用 L13
- **bullet ≤ 5 条/列**: 单列超过就拆页或改卡片网格;双栏对比左右各 ≤5
- **正文不写完整段落**: 列要点;长句留给演讲者口述(写进 `add_notes`)
- **数据 ≥ 3 个点应有图表**: matplotlib 生成 .png 嵌入(或转 KPI 卡)
- **中文标题 ≤ 30 字**
- **配色三色封顶 + 派生阶**: 主 + 辅 + 强调三色系,浅底/卡片底走 `set_palette` 自动派生的 `PRIMARY_WASH/SOFT`,不算新色
- **渐变只用在大色块**: 封面/章节用 `apply_brand` 内置渐变;渐变深底上文字一律用白/`ACCENT_SOFT`
- **每页演讲者备注**: `add_notes` 写 2-4 句口述要点(正式产物标配)
- **Shape 不能越界**: helper 内置 `assert_inside` 生成时即报错
- **字数按预算来**: 写 bullet 前查 `design_principles.md §4.1` 字数预算表;卡片内按"卡宽 - 0.8"算框宽
- 详细规则见 `references/design_principles.md`
## 工作目录约定
下文 `<task_dir>` = system prompt 里「task_dir」给的**绝对路径**(host 下形如 `…/workspace/users/<uid>/<wd>/`,docker 沙盒里是 `/workspace/<wd>/`)。**所有产物都写到 task_dir 下**,不要写到 cwd / `skills/` / repo 根;图标分两处:skill 自带的**只读种子库**走 `<skill_dir>/assets/icons/`(docker 沙盒里 skills 只读,只读不写),`fetch_icon.py` 新拉的图标写 `<task_dir>/assets/icons/`(详见 references/icons.md §A)。
```
<task_dir>/
├── source/ # markitdown 转出的素材(同 working_dir 多 task 共享;用 markitdown -o <task_dir>/source/<name>.md)
├── <today>-<task_short_id>-<task_name>.spec.md # 八条对齐落定,task 级宪法;命名见 system prompt 约定;按 short_id 主锚,重定调时写新日期,旧版保留
├── slides/ # 各页 matplotlib 图表 (chart_p3.png 等),多 task 时文件名前缀区分
├── figures/ # imagegen 生成的真实配图 (opt-in;封面/章节主图),由 imagegen skill 落盘
├── assets/icons/ # fetch_icon.py 新拉的主题色图标(种子库在 skill 只读侧)
├── build_deck.py # 整 deck 构建脚本(一次建完所有页);改稿/修 quality_check 项都改它重跑
├── REVISIONS.md # 修订日志:每次卡点用户确认的实质改动,见 §修订日志
└── <topic>.pptx # 最终产物 (按主题命名,多 task 时主题必须不同)
```
## 修订日志 (REVISIONS.md)
`<task_dir>/REVISIONS.md` 是产物迭代过程的紧凑可读 changelog。**spec 是宪法(定调一次),REVISIONS 是实施日志(每次卡点累加)** —— 两份独立但互参,后期 review / 复盘 / 跨周回看"上周这页为啥改成这样"靠这份。
### 何时记 / 何时不记
| 情形 | 记? |
|---|---|
| 用户确认改**版式 / 主色 / 字体方向** | ✅ 必记 |
| 用户确认换 / 增 / 删**页 / 关键图标 / 数据图表** | ✅ 必记 |
| 用户确认改**文案要点 / 核心信息 / 受众定位** | ✅ 必记 |
| 自查阶段发现版式越界 / 颜色不一致后的修正 | ✅ 必记(说明触发 quality_check 项) |
| 页首次起草(从 0 加出来) | ❌ 不记(初稿不是改动) |
| 字号 / 间距 / 对齐微调 | ❌ 不记 |
| 模型自己改改撤撤、用户没明确确认 | ❌ 不记 |
> 拿不准 → 倾向不记。`REVISIONS.md` 是"用户与 LLM 共同沉淀的实质决策",不是流水账(那是对话历史的事)。
### 格式
文件首次创建时写头(只写一次):
```markdown
# 修订日志
> 产物迭代过程中每次用户确认的实质改动,按时间倒序追加(最新在上)。spec 是宪法定调,本文件是实施日志。
```
每次记一笔追加在头注释之后、最新一笔的顶部(一行 = 一次改动):
```
- `<YYYY-MM-DD HH:MM>` | <第 N 页 / spec §X> | <一句话改了什么> — <为什么>
```
### 实例
```
- `2026-03-12 16:20` | 第 5 页 | 版式从 layouts.md "两栏文+图"改为"单栏图占主体" — 用户反馈原版式右侧文字太挤,核心数据需放大
- `2026-03-12 14:05` | 第 3 页 | 删 chart 图,换成 3 个 KPI 数字块 — 数据点只有 3 个,bar chart 浪费版面
- `2026-03-11 10:30` | spec §5 配色 | 主色 `#C00000` → `#1F4E79` — 用户给的品牌指南要求蓝色,商务红默认被覆盖
```
### 操作
每次卡点用户确认后,用 `edit` 在头注释之后插入新一行(不要 append 到文件末尾 —— 倒序读才能秒看最新)。文件不存在就 `write` 创建带头注释的新文件。
## 反模式
- 用户没给材料就开始硬编内容
- 八条没对齐就跑 python-pptx
- **基于"场景判断"自行换配色**(见上"默认主题"违规清单)
- **缺封面 / 缺尾页(Q&A)** —— 两端都是强制项,不算在正文页数预算内
- **裸白纸版式** —— 所有版式起手都必须 `apply_brand(slide, kind)`,见 layouts.md
- **业务概念页只用几何形状 / 裸圆点 bullet** —— "战略目标 / 三大能力"这类页摆光圆点没图标没卡片,视觉太单薄;用 L11 卡片网格 + `add_icon_tile`,图标按 §阶段二第 2 步先拉
- **数字页硬画柱图** —— 只有 2-4 个数字却画 bar chart 浪费版面,用 L10 KPI 卡
- **元素裸贴白纸不进卡片** —— 内容页一坨文字/图标直接铺白底,显扁平;装进 `add_card`(自带投影)分层
- **演讲者备注全空** —— 正式产物每页应有口述要点,`add_notes` 顺手写,别交白板
- **逐页 run_python 建 deck**(每页一轮来回烧轮数;改用一个 `build_deck.py` 整建,方向风险靠阶段一大纲 + 可选探针兜)
- **没经阶段一大纲对齐就直接整建** —— 大纲是替代逐页确认的 checkpoint,跳过它整建才会"改方向全推翻"
- 跑完不做 `quality_check.py` 就交付
- 起名 `output.pptx` / `untitled.pptx` —— 务必按主题给文件名
## 输出
完成后告诉用户:文件路径、页数、用到的版式列表、是否有未满足的 spec 项。问一句要不要再改。