视觉画布设计
canvas-design
基于设计原则创作静态视觉作品,用于海报与品牌图形。
ppt-generate【文档与办公】从一句话/大纲/文档生成原生可编辑的 PPT(.pptx)。项目制逐页生成:先定大纲与专属 design system,再每页独立构思版式/内容/衔接,渲染为 python-pptx 原生矢量元素——文本、形状、图表、表格、公式全部可在 PowerPoint/WPS 里二次编辑。当用户说「做PPT」「生成幻灯片」「写个汇报PPT」「把这份文档做成演示文稿」「pptx」「slides」「presentation」「课件」时触发。
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
把自然语言需求变成原生可编辑的 pptx:不是图片拼贴,每个文本框、形状、图表、表格、公式都是 PPT 原生元素,用户打开就能改。
好 deck 不是一次写出来的,是逐页设计出来的:先定全局(大纲 + 专属 design system),再每页单独构思版式、内容、和前后页的衔接,最后逐页复审返修。本技能的工作流就按这个节奏组织。
需求 → ①大纲(含衔接设计) → ②design system → ③建项目目录 → ④逐页生成
→ ⑤gen_image.py 填图 → ⑥--check 校验 → ⑦渲染 → ⑧逐页复审/单页返修
→ ⑨deliver_file 可视化交付(强制,缺此步即视为任务失败)
⑨ 不是可选的收尾动作,是本技能的终止条件:没有调用 deliver_file,这次 PPT 生成就没有完成。
slideType(cover/contents/transition/content/end)和核心内容。不要直接从预设主题里挑一个了事——每个值得认真做的 deck 都该有一套为它定制的视觉语言:
references/fonts.md:按 deck 气质(学术/商务/科技/营销)和交付平台选定中西文字体配对(中文 ea 字体 + 西文 latin 字体分离设置)。#4A5FA8,不用高饱和纯钴蓝);deck.json(结构见 schema.md 的 SlideTheme,typography 按 textType 给默认值)。预设主题(business-blue / dark-tech / fresh-green / vibrant-orange)只作为快速兜底或定制起点,可在其基础上改色改字体。⚠️ 质量红线(强制):
- 必须有主题色:禁止纯白背景 + 黑色文字的"默认"样式。每页必须有背景色/渐变 + 主题色点缀。
- 必须从预设主题起步:至少从 business-blue / dark-tech / fresh-green / vibrant-orange 中选一个作为定制起点,禁止完全自创配色(除非用户明确指定)。
- 禁止空页面:每页必须有标题 + 正文内容,不允许只有标题无内容的空白页。
- 标题必须是 action title:完整句子,表达结论或观点,不能是"概述""背景"等名词短语。
<输出目录>/<项目名>/
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": {...内联主题...}}。一次只写一页:pages/NN_slug.json(NN 两位序号保证排序,如 01_cover.json、05_attention_intro.json),文件内容是单个 Slide 对象({"id","type","background"?,"remark"?,"elements":[...]})。
每写一页之前,显式过四遍再落笔(可以在回复里用一两句话说明设计意图):
top+总高 ≤ 540。中文宽约西文 1.8 倍,字符数直觉不可信,必须按容器宽度换算。references/schema.md(元素字段、形状名表、主题结构),写之前必读。references/layout-guide.md:咨询式页面骨架、版式库、信息密度标准、衔接与设计语言规则。latex 元素(默认 OMML 引擎:真根号/真分式,PowerPoint/WPS 可再编辑;Keynote 交付时加 "engine": "runs"),不要画成图片。"src": "gen:modern office skyline"(英文搜索词效果更好)"src": "icon:mdi:rocket-launch"(Iconify 集合:名称,如 mdi/fa/carbon)remark 字段。用户可能直接给一份详细的每页规划 md。按以下映射转成逐页 JSON:
# 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 内容明显有误或遗漏时先问用户,不要擅自扩写。
python3 ~/.ethan/skills/ppt-generate/scripts/gen_image.py /path/to/<项目目录>
pages/*.json,解析后逐页原地回写,图片存到项目内 assets/。PEXELS_API_KEY)→ Unsplash(需 UNSPLASH_ACCESS_KEY)→ AI 生图(需 ETHAN_IMAGE_GEN_API_KEY)→ 纯色占位图(保底,永不失败)。image_search 工具搜图并 download=true,把返回的本地路径直接写进对应页 JSON 的 src,跳过 gen_image.py。--dry-run 可先列出待解析项。python3 ~/.ethan/skills/ppt-generate/scripts/render_pptx.py /path/to/<项目目录> --check
slides[i] 对应 pages/ 下排序后的第 i 个文件,回到那一页改。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)供程序化消费。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 光栅化)。渲染完不要直接交付。逐页过一遍复审清单,有问题的页只改那一个 page 文件再重新渲染(这就是项目制的意义):
--check 的 overflow 警告是否都已处理?转图后目检文字有没有触底/压框、表格末行有没有被裁(这三类是最影响观感的缺陷,Step 6 已给过建议值)。_k、√d_、\sqrt 字面量——展示公式都走 latex 元素、行内变量都用 sub/sup run,没有裸文本伪公式?形状内嵌文本(圆圈/步骤条/按钮)都写了 text.align: "middle"?soffice),可 soffice --headless --convert-to pdf <pptx> 再 pdftoppm -png 逐页转图,用文件读取工具看图做视觉自检,溢出/重叠/字体替换问题一目了然;没有这些工具就按清单文字审查。pages/ 下的单页文件,改完重跑 Step 7 即可(页少时秒级)。🚫 绝不允许把文件路径当纯文本吐给用户。 像「pptx 路径:/root/.ethan/output/xxx.pptx」这样直接在正文里写一行路径,用户根本点不动、看不了预览——这是失败交付。文件必须以「文件卡片」形态交付。
渲染成功后、报告最终结果前,必须先调用 deliver_file 工具,传入 pptx 的绝对路径:
deliver_file(path="/absolute/path/to/<项目目录>/<项目名>.pptx")
它会在聊天里生成可点击的文件卡片(icon + 文件名 + 页数),用户点击卡片进入逐页预览页,可在线翻页预览并选择下载 PPTX 或 PDF。
正确顺序:
deliver_file(path="<pptx 绝对路径>") —— 生成文件卡片(这一步不可省)。调用时机是 pptx 已完整落盘之后(Step 7 渲染成功、Step 8 复审通过);若 Step 8 返修后重新渲染,用最终那次渲染的 pptx 再调一次,确保卡片指向最终版本。pages/ 下单页 JSON 可改后重新渲染)、所有元素都能在 PPT 里直接二次编辑。失败必须处理,不能静默跳过:若 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)。
deliver_file:Step 9 是本技能的终止条件。渲染出 pptx 却只在文字里报路径、没生成文件卡片,视为任务失败——用户在聊天里拿不到可点击的预览/下载入口。工具报错要修正重试,不能静默跳过。fontName(中文)+ latinFontName(西文)分离设置;配对选择读 references/fonts.md。run 级显式 fontName 会同时覆盖中西文。
Noto Sans CJK SC / WenQuanYi Micro Hei,西文 DejaVu Sans。remark 字段,不要塞进页面元素。deck.json + pages/ + assets/ 别删(用户可能改单页后重新渲染);pptx 默认输出在项目目录内。deliver_file 只接受用户主目录或 /tmp 下的绝对路径,项目目录别建在别处,否则渲染完无法交付。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: 后用英文搜索词 |