- name
- ppt-generate
- description
- 从一句话/大纲/文档生成原生可编辑的 PPT(.pptx)。项目制逐页生成:先定大纲与专属 design system,再每页独立构思版式/内容/衔接,渲染为 python-pptx 原生矢量元素——文本、形状、图表、表格、公式全部可在 PowerPoint/WPS 里二次编辑。当用户说「做PPT」「生成幻灯片」「写个汇报PPT」「把这份文档做成演示文稿」「pptx」「slides」「presentation」「课件」时触发。
- trigger
- PPT|ppt|pptx|幻灯片|演示文稿|slides|presentation|deck|做PPT|生成PPT|汇报PPT|课件|keynote
- version
- 2.1.0
- display_name
- PPT 生成器
- platforms
- ["macos","linux","windows"]
- metadata
- {"openclaw":{"requires":{"bins":"[Truncated]"}}}
# PPT 生成器(项目制逐页生成 · PPTist schema · python-pptx 渲染)
把自然语言需求变成**原生可编辑**的 pptx:不是图片拼贴,每个文本框、形状、图表、表格、公式都是 PPT 原生元素,用户打开就能改。
好 deck 不是一次写出来的,是**逐页设计**出来的:先定全局(大纲 + 专属 design system),再每页单独构思版式、内容、和前后页的衔接,最后逐页复审返修。本技能的工作流就按这个节奏组织。
## 工作流(严格按顺序)
```
需求 → ①大纲(含衔接设计) → ②design system → ③建项目目录 → ④逐页生成
→ ⑤gen_image.py 填图 → ⑥--check 校验 → ⑦渲染 → ⑧逐页复审/单页返修
→ ⑨deliver_file 可视化交付(强制,缺此步即视为任务失败)
```
⑨ 不是可选的收尾动作,是本技能的**终止条件**:没有调用 `deliver_file`,这次 PPT 生成就没有完成。
### Step 1:规划大纲(含衔接设计)
- 先输出大纲给用户(除非用户说直接生成):每页定 `slideType`(cover/contents/transition/content/end)和核心内容。
- **叙事按金字塔原理**:全 deck 一个核心结论(写进封面副标题),每章一个分结论,每页一个 action title(**完整观点句,带数字或机制名**,不是名词短语)。动机页用 SCQA(情境-冲突-问题-答案)。
- **整体↔细节结构**:机制/架构类主题必须有「总览页」——全景图 + 编号圆圈 ①②③④;后续细节页带同编号锚点,细节讲完放「回扣页」闭环(总-分-总)。
- **衔接设计(逐页生成质量的源头)**:大纲里每页除了 action title、2-4 个支撑要点(含具体数字/机制)、页面角色(总览/细节①/对比/结论)、锚点编号,还要写一条**衔接备注**:
- 承上:本页回收/回答上页留下的什么钩子;
- 启下:本页给后面哪页埋什么钩子(如「先记住这个公式,第 9 页我们亲手算一遍」)。
前后页的显式引用(页码、章节名)会让 deck 读起来是一个整体而不是一摞单页。
- **只给主题、没给素材时**:大纲内容来自模型自身知识;若主题涉及最新资讯/实时数据/具体数字(如「2026 年行业趋势」「某公司最新财报」),先用 web_search 检索再写大纲,并在交付时说明哪些内容来自检索。
- 页数:默认 6-10 页;用户没说要目录/过渡页就不加。
### Step 2:定制本 deck 的 design system
不要直接从预设主题里挑一个了事——每个值得认真做的 deck 都该有一套**为它定制的视觉语言**:
1. **读 `references/fonts.md`**:按 deck 气质(学术/商务/科技/营销)和交付平台选定中西文字体配对(中文 ea 字体 + 西文 latin 字体分离设置)。
2. **给这套设计语言起个名字、定一组规则**,在大纲确认时一并告知用户,例如「地图策略:纸白底 + 深海军蓝主色 + 灰调皇家蓝强调 + 朱红警示 + 路线/坐标装饰语法」。规则至少包括:
- 主色 / 强调色(≤1 个)/ 语义色(如「Encoder 蓝、Decoder 粉」全 deck 一致)——**主色往灰调一档更雅致**(如灰调皇家蓝 `#4A5FA8`,不用高饱和纯钴蓝);
- 装饰语法:编号圆圈、章节导航点、分隔线、卡片形态(圆角?描边?投影?)——全 deck 统一;
- 字体配对与字号阶梯(标题/正文/注释)。
3. **落成内联 theme 对象**写进项目 `deck.json`(结构见 schema.md 的 SlideTheme,`typography` 按 textType 给默认值)。预设主题(business-blue / dark-tech / fresh-green / vibrant-orange)只作为快速兜底或定制起点,可在其基础上改色改字体。
> ⚠️ **质量红线(强制)**:
> 1. **必须有主题色**:禁止纯白背景 + 黑色文字的"默认"样式。每页必须有背景色/渐变 + 主题色点缀。
> 2. **必须从预设主题起步**:至少从 business-blue / dark-tech / fresh-green / vibrant-orange 中选一个作为定制起点,禁止完全自创配色(除非用户明确指定)。
> 3. **禁止空页面**:每页必须有标题 + 正文内容,不允许只有标题无内容的空白页。
> 4. **标题必须是 action title**:完整句子,表达结论或观点,不能是"概述""背景"等名词短语。
### Step 3:建项目目录
```
<输出目录>/<项目名>/
deck.json # version / canvas / theme(Step 2 的内联主题),不含 slides
pages/ # 每页一个 JSON,Step 4 逐页写入
```
- **默认输出目录钉在 `~/.ethan/output/`**(即 `$HOME/.ethan/output/<项目名>/`),除非用户明确指定别的位置。这一步不能用 cwd 相对路径:ethan 可能从 home 外的目录启动,相对路径建的目录渲染虽成功,但 Step 9 的 `deliver_file` 会因「路径必须在用户主目录或 `/tmp` 下」而报错,整份 deck 得挪目录重渲一遍。钉到 `~/.ethan/output/` 从源头避免这轮返工。
- 项目名用人类可读命名(如 `Transformer详解课件/`),最终项目目录形如 `~/.ethan/output/Transformer详解课件/`。
- `deck.json` 骨架:`{"version": 1, "canvas": {"width": 1000, "height": 562.5}, "theme": {...内联主题...}}`。
- ≤5 页的小 deck 可以走旧的单文件模式(一个含 slides 的 deck.json),但逐页生成 + 复审的效果更好,默认用项目制。
### Step 4:逐页生成(本工作流的核心)
**一次只写一页**:`pages/NN_slug.json`(NN 两位序号保证排序,如 `01_cover.json`、`05_attention_intro.json`),文件内容是单个 Slide 对象(`{"id","type","background"?,"remark"?,"elements":[...]}`)。
每写一页之前,显式过四遍再落笔(可以在回复里用一两句话说明设计意图):
1. **版式**:本页从 layout-guide 版式库选哪个骨架?为什么适合这段内容?(三卡片 / 左右论点-证据 / 图表页 / 公式页 / 流程图页…)
2. **内容**:action title 是不是观点句?2-4 个区块形态是否错开?每条 bullet 有没有数字/机制/对比?密度够不够(构件清单见 layout-guide)?
3. **高度预算**:多行文本按 layout-guide「宽度与行数估算」核一遍——中文字 ≈1 个字号宽(270px 卡片 @14px 每行只装 17 字)、行高 ≈1.36×字号、表格总高 ≈ Σ行 max(cellMinHeight, 行数×13×1.36+8) 且 `top+总高 ≤ 540`。**中文宽约西文 1.8 倍,字符数直觉不可信,必须按容器宽度换算**。
4. **衔接**:kicker 与章节导航点对不对?总览锚点编号是否全局一致?本页是否兑现了大纲里的承上/启下钩子(该引用的页码要写进文案)?
- **Schema 全文见 `references/schema.md`**(元素字段、形状名表、主题结构),写之前必读。
- **排版必读 `references/layout-guide.md`**:咨询式页面骨架、版式库、信息密度标准、衔接与设计语言规则。
- 画布固定 1000×562.5;文本用结构化 runs,**不写 HTML**;形状只用预设名,**不写 SVG path**。
- 公式页用 `latex` 元素(默认 OMML 引擎:真根号/真分式,PowerPoint/WPS 可再编辑;Keynote 交付时加 `"engine": "runs"`),不要画成图片。
- 图片先用占位符:
- 照片/配图 → `"src": "gen:modern office skyline"`(英文搜索词效果更好)
- 图标 → `"src": "icon:mdi:rocket-launch"`(Iconify 集合:名称,如 mdi/fa/carbon)
- 用户提供的图 → 直接写本地路径
- 演讲者备注写进该页 JSON 的 `remark` 字段。
### Markdown 输入约定(用户给 md 大纲时)
用户可能直接给一份详细的每页规划 md。按以下映射转成逐页 JSON:
```markdown
# PPT 主题:大模型时代的搜索架构
主题:dark-tech ← 可选,映射 theme(此时可不做 Step 2 定制)
页数:8 ← 可选
## 第1页 [封面]
标题:大模型时代的搜索架构
副标题:从倒排索引到向量召回
## 第2页 [目录]
- 检索范式的三次迁移:关键词→语义→生成式
- 向量召回的工程落地:HNSW 与 IVFFlat
## 第3页 [正文] 检索范式对比
版式:三卡片 ← 可选,映射 layout-guide 版式
- 卡片1 icon:mdi:magnify 关键词检索:倒排+BM25,精确强、语义弱
- 卡片2 icon:mdi:vector-point 向量检索:Embedding+ANN,语义强
- 卡片3 icon:mdi:brain 生成式:RAG,成本高
## 第4页 [正文] IVFFlat 原理
公式:\mathrm{Recall@K} = \frac{|S_K \cap S_K^*|}{K} ← 映射 latex 元素
要点:
- nlist 取 √N 量级
- nprobe 是召回/延迟旋钮
表格: ← 映射 table 元素
| nprobe | Recall@10 | P99 |
| 8 | 0.86 | 6ms |
| 64 | 0.97 | 21ms |
## 第5页 [正文] 上线效果
图表:柱状图 ← 映射 chart 元素,数据必须给出
| 月份 | nDCG@10 | 召回率 |
| 1月 | 0.61 | 0.72 |
配图:gen:server room data center ← 映射 gen: 占位符
备注:强调延迟只涨 8ms ← 映射 slide.remark
## 第6页 [结尾]
谢谢观看
```
映射规则:`[封面/目录/过渡/正文/结尾]`→slideType;`公式:`→latex;`表格:`后的 md 表格→table;`图表:`+数据表→chart;`gen:`/`icon:`→图片占位;`备注:`→remark。用户没写页类型时按内容推断(第 1 页默认封面、最后默认结尾)。md 里没给的细节(精确坐标、字号)按 layout-guide 补齐。
**忠实原则**:md 里写明的页数、页序、文案、公式、表格/图表数据必须原样进入页面 JSON,不增页、不减页、不改写观点、不编造 md 里没有的数据。可自由发挥的只有视觉层:版式选择、坐标、字号微调、装饰元素、配图选词。md 内容明显有误或遗漏时先问用户,不要擅自扩写。
### Step 5:填充图片
```bash
python3 ~/.ethan/skills/ppt-generate/scripts/gen_image.py /path/to/<项目目录>
```
- 传项目目录即可:自动合并 `pages/*.json`,解析后**逐页原地回写**,图片存到项目内 `assets/`。
- 瀑布流:Pexels(需 `PEXELS_API_KEY`)→ Unsplash(需 `UNSPLASH_ACCESS_KEY`)→ AI 生图(需 `ETHAN_IMAGE_GEN_API_KEY`)→ 纯色占位图(保底,永不失败)。
- Iconify 图标无需任何 key。
- **没有配任何 key 时**:改用 ethan 内置 `image_search` 工具搜图并 `download=true`,把返回的本地路径直接写进对应页 JSON 的 `src`,跳过 gen_image.py。
- `--dry-run` 可先列出待解析项。
### Step 6:校验
```bash
python3 ~/.ethan/skills/ppt-generate/scripts/render_pptx.py /path/to/<项目目录> --check
```
- 有 error 必须修到 0 个再渲染;warning 尽量修。报错信息里的 `slides[i]` 对应 `pages/` 下排序后的第 i 个文件,回到那一页改。
- **文字溢出检测**(overflow.*)分级:
- `overflow.fixable`(warn):渲染时会自动缩字兜底(不小于原字号 80% 且 ≥12px),但建议按报错里的「建议高度/删减字数」改文案——自动缩字会让该页字号与别页不一致。
- `overflow.unfixable` / `overflow.nofit`(error):缩字也救不了,**必须**删字或加高,error 清零前不许渲染。
- `overflow.table-canvas`(error):表格末行会被画布裁掉——删行/降 cellMinHeight/表格上移。
- `overflow.table-grow`(warn):表格行会被内容撑高、可能压住下方元素,核对下方留白。
- 加 `--json` 可拿到结构化 issues(severity/code/message)供程序化消费。
### Step 7:渲染
```bash
python3 ~/.ethan/skills/ppt-generate/scripts/render_pptx.py /path/to/<项目目录>
# 默认输出 <项目目录>/<项目名>.pptx;也可 -o 指定;--theme 可临时覆盖主题
```
- 首次运行会自动 `pip install python-pptx latex2mathml mathml2omml`(纯 Python 依赖);用到 icon: 图标时还会自动装 `pymupdf`(SVG→PNG 光栅化)。
### Step 8:逐页复审,单页返修
渲染完**不要直接交付**。逐页过一遍复审清单,有问题的页**只改那一个 page 文件**再重新渲染(这就是项目制的意义):
1. 每页 action title 都是观点句?有没有名词短语漏网?
2. 密度:每页 2-4 个区块、形态错开?有没有纯文字堆砌页或空洞页(<60 字)?
3. 衔接:锚点编号全 deck 一致?承上/启下钩子都兑现了?章节导航点逐页正确?
4. 视觉纪律:无越界/贴边、语义色一致、装饰语法统一?主色是否灰调雅致、大面积填充是否「深色字+浅色底」(白字深底只留给小徽章)?
5. 数据页有结论栏和来源行?公式符号逐一解释了?
6. **溢出复查**:`--check` 的 overflow 警告是否都已处理?转图后目检文字有没有触底/压框、表格末行有没有被裁(这三类是最影响观感的缺陷,Step 6 已给过建议值)。
7. **公式纪律**:grep 一遍页面 JSON 里的 `_k`、`√d_`、`\sqrt` 字面量——展示公式都走 latex 元素、行内变量都用 sub/sup run,没有裸文本伪公式?形状内嵌文本(圆圈/步骤条/按钮)都写了 `text.align: "middle"`?
- 若本机装了 LibreOffice(`soffice`),可 `soffice --headless --convert-to pdf <pptx>` 再 `pdftoppm -png` 逐页转图,用文件读取工具看图做视觉自检,溢出/重叠/字体替换问题一目了然;没有这些工具就按清单文字审查。
- 返修只动 `pages/` 下的单页文件,改完重跑 Step 7 即可(页少时秒级)。
### Step 9:可视化交付(强制 · 违反即失败)
> 🚫 **绝不允许把文件路径当纯文本吐给用户。** 像「pptx 路径:/root/.ethan/output/xxx.pptx」这样直接在正文里写一行路径,用户根本点不动、看不了预览——这是**失败交付**。文件必须以「文件卡片」形态交付。
渲染成功后、报告最终结果前,**必须先调用 `deliver_file` 工具**,传入 pptx 的**绝对路径**:
```
deliver_file(path="/absolute/path/to/<项目目录>/<项目名>.pptx")
```
它会在聊天里生成可点击的文件卡片(icon + 文件名 + 页数),用户点击卡片进入逐页预览页,可在线翻页预览并选择下载 PPTX 或 PDF。
正确顺序:
1. 先调 `deliver_file(path="<pptx 绝对路径>")` —— 生成文件卡片(这一步不可省)。**调用时机**是 pptx 已完整落盘之后(Step 7 渲染成功、Step 8 复审通过);若 Step 8 返修后重新渲染,用最终那次渲染的 pptx 再调一次,确保卡片指向最终版本。
2. 卡片发出后,再用文字补充说明:页数、design system 名称与要点、哪些图是占位图(若有)、项目目录位置(`pages/` 下单页 JSON 可改后重新渲染)、所有元素都能在 PPT 里直接二次编辑。
3. **文字说明里不要再重复粘贴那条绝对路径**——路径已经在卡片里,重复只会把 AI 味写回来。
**失败必须处理,不能静默跳过**:若 `deliver_file` 返回 `Deliver failed: ...`,说明路径不合法(必须在用户主目录或 `/tmp` 下,见 Step 3 的默认落点)、文件不存在或扩展名不支持。此时**修正问题后重试**——例如把项目输出目录挪到用户主目录下再重新渲染。重试仍失败时,明确告知用户「文件已生成但卡片交付失败」并附上原因和路径,不要假装交付成功。
自检:回复发出前问自己「我调 deliver_file 了吗?」没调就是没交付完,回去补。
## 预设主题(快速兜底 / 定制起点)
| 主题 | 风格 | 适用 |
|---|---|---|
| `business-blue`(默认) | 白底商务蓝 | 汇报/总结/通用 |
| `dark-tech` | 深色科技 | AI/技术分享/发布会 |
| `fresh-green` | 清新绿 | 教育/环保/健康 |
| `vibrant-orange` | 活力橙 | 营销/活动/路演 |
正式 deck 应在预设基础上走 Step 2 定制(内联 theme 对象覆盖,结构见 schema.md 的 SlideTheme)。
## 关键约束(违反必然翻车)
1. **渲染完必须 `deliver_file`**:Step 9 是本技能的终止条件。渲染出 pptx 却只在文字里报路径、没生成文件卡片,视为任务失败——用户在聊天里拿不到可点击的预览/下载入口。工具报错要修正重试,不能静默跳过。
2. **元素可编辑是底线**:禁止把整页渲染成一张大图;禁止 SVG path 形状(用预设形状名);禁止 HTML 文本(用 runs)。
3. **gen:/icon: 占位符必须先跑 gen_image.py**,否则渲染器直接报错退出。
4. **中西文字体**:主题 `fontName`(中文)+ `latinFontName`(西文)分离设置;配对选择读 `references/fonts.md`。run 级显式 `fontName` 会同时覆盖中西文。
- **渲染机不需要装字体**:渲染器只把字体名写入 pptx,字体解析发生在打开文件的机器上。
- **查看端是 Linux(WPS/LibreOffice)时**:雅黑/Verdana 通常都没有,会被替换成默认字体。预先知道的话把主题改成 Linux 常见自带字体:中文 `Noto Sans CJK SC` / `WenQuanYi Micro Hei`,西文 `DejaVu Sans`。
5. **坐标纪律**:元素不越界(右 ≤940、下 ≤540)、不贴边、页边距 60/40;字数按容器宽度核(左栏 430px 一行 ≤29 个中文字,全栏 880px ≤61 字;西文字符按 0.6 个中文字折算),速查表见 layout-guide。
6. **图表用原生 chart 元素**(数据可编辑),不要用 image_search 找图表截图。
7. **演讲者备注**写进该页 JSON 的 `remark` 字段,不要塞进页面元素。
8. 项目目录整体交付与保留:`deck.json` + `pages/` + `assets/` 别删(用户可能改单页后重新渲染);pptx 默认输出在项目目录内。
9. **输出目录要落在可交付范围内**:`deliver_file` 只接受用户主目录或 `/tmp` 下的绝对路径,项目目录别建在别处,否则渲染完无法交付。
## 参考文档(按需 skill_read 加载)
- `references/schema.md` — deck/页 JSON 完整字段定义(写页前必读)
- `references/layout-guide.md` — 页面骨架、版式库、信息密度、衔接与设计语言规则
- `references/fonts.md` — 中西文字体配对与平台适配(Step 2 必读)
- `examples/demo.json` — 覆盖全部元素类型的示例 deck(单文件模式,可当元素写法参考)
## 故障排查
| 症状 | 原因 | 处理 |
|---|---|---|
| `deliver_file` 报 path must be under the user home directory or /tmp | 项目目录建在了主目录/`/tmp` 之外 | 把项目目录移到主目录下(如 `~/Downloads/`)重新渲染再交付 |
| `deliver_file` 报 file not found | pptx 还没落盘或路径拼错 | 确认 Step 7 渲染成功、用渲染输出的实际绝对路径 |
| 用户说「没看到文件 / 收不到」 | 漏了 Step 9,只在文字里报了路径 | 补调 `deliver_file` 传 pptx 绝对路径 |
| 渲染报「图片占位符未解析」 | 跳过了 Step 5 | 跑 gen_image.py 或把 src 改成本地路径 |
| 渲染报「项目目录缺少 deck.json」 | deck 参数传了目录但没有元信息文件 | 在项目目录补 deck.json(version/canvas/theme) |
| 渲染报「页文件应为单个 Slide 对象」 | pages/*.json 里写成了数组或包裹层 | 每页文件直接是 `{"id","type","elements":[...]}` |
| pip 自动安装失败 | 无网络/权限 | `pip3 install --user python-pptx latex2mathml mathml2omml` 后重试 |
| 中文变方框/宋体 | 用户机器无该字体 | 换主题 fontName(Windows: 微软雅黑,macOS: PingFang SC),详见 fonts.md |
| Linux/WPS 打开字体被替换、版式跑偏 | Linux 无雅黑/Verdana | 主题改 `fontName: Noto Sans CJK SC`(或 WenQuanYi Micro Hei)+ `latinFontName: DejaVu Sans` 后重新渲染 |
| 公式变成一行源码文本 | latex 依赖缺失或语法错 | 看 stderr 的 [warn],检查 LaTeX 语法(latex2mathml 子集) |
| Pexels 搜不到中文词 | API 对中文支持差 | gen: 后用英文搜索词 |
在 GitHub 查看