gpt-image2-ppt -- Generate PPT with gpt-image-2
Feed a markdown outline (or slides_plan.json) + a visual style directly to OpenAI's official Images API (gpt-image-2), generate images page by page, and finally package them into a 16:9 .pptx.
Available Styles
| Style ID | One-line positioning | Use cases |
|---|---|---|
gradient-glass |
Apple Vision OS / Spatial Glass | AI product launches, tech sharing, creative proposals |
clean-tech-blue |
Stripe / Linear-grade blue and white | Funding pitches, business plans, corporate strategy |
vector-illustration |
Retro vector illustration + black outlines | Education and training, brand stories, community sharing |
editorial-mono |
Kinfolk / Monocle editorial design | Brand launches, cultural interviews, book sharing |
dark-aurora |
Linear / Vercel dark neon | AI products, developer tools, tech sharing |
risograph |
Riso dual-color printing + halftone texture | Creative studios, cultural and creative brands, independent zines |
japanese-wabi |
MUJI / Kenya Hara-style wabi-sabi | Tea ceremony, lifestyle, luxury goods, cultural lectures |
swiss-grid |
Bauhaus / Vignelli International Style grid | Academic reports, museum exhibitions, serious presentations |
hand-sketch |
Sketchnote / whiteboard hand-drawn | Workshops, product brainstorming, training |
y2k-chrome |
Y2K millennium liquid metal + butterfly stickers | Streetwear, entertainment, brand collaborations, Gen Z marketing |
abstract-art-showcase |
Black-and-white minimalism, art exhibition feel, oversized typography juxtaposed with abstract imagery | Art curation, portfolios, brand tone display |
coal-industry-business-company-profile |
Industrial brown and black, heavy headlines, structural lines, and hard-edged icons | Energy, manufacturing, heavy-asset company introductions |
college-candy-aesthetics-infographics |
Candy colors, campus feel, rounded infographics, and light decorations | Education, campus events, lightweight data popularization |
creative-agency |
Creative agency temperament, strong visual collage, distinctive layout rhythm | Agency proposals, brand plans, creative presentations |
culinary-innovation |
Culinary innovation feel, food photography, warm color blocks, and magazine-style typography | Food and beverage brands, food innovation, menu/new product launches |
data-science-consulting |
Data consulting blue-gray, modular layout, charts, and tech-flavored information hierarchy | Data analysis, AI consulting, enterprise digitalization |
mindfulness-in-the-classroom-breathing-techniques |
Soft mental health color palette, negative space, rounded blocks, and a quiet illustration feel | Mental health, classroom activities, breathing training courses |
mind-maps-workshop-professional |
Professional workshop style, mind map nodes, clear process structure | Training workshops, methodologies, team co-creation |
meeting-agenda |
Meeting agenda feel, clean grid, strong information grouping, and business headlines | Regular meetings, project syncs, management reports |
investment-company-business-plan |
Investment institution quality, dark-light contrast, steady business layout | Investment plans, fund introductions, business plans |
indigenous-cultures |
Cultural patterns, natural colors, handmade texture, and narrative composition | Cultural courses, historical themes, public welfare education |
health-disparities-and-social-determinants-of-health-doctor-of-philosophy-phd-in-health-behavior-and-health-education |
Public health academic style, rational grid, soft medical colors and paper-like hierarchy | Medical thesis defense, public health reports, education research |
geometric-duotone-thesis |
Two-color geometry, thesis defense feel, angled shapes and strong titles | Academic defense, research reports, chapter-based content |
geometric-clinical-case |
Geometric medical style, calm color palette, case cards and clear columns | Clinical cases, medical training, diagnosis and treatment reports |
geometric-business |
Business geometric blocks, steady blue-green tones, concise chart language | Business plans, team reports, product strategy |
formal-lavender-portfolio |
Light purple formality, portfolio whitespace, elegant thin lines and soft layouts | Personal portfolios, design resumes, professional showcases |
flowery |
Floral decorations, soft color blocks, romantic yet orderly typography | Lifestyle, women's brands, event introductions |
first-impressions |
First-impression theme, strong cover visuals, dramatic relationship between person/title | Interview training, personal branding, communication courses |
final-year-project-thesis-defense |
Graduation project defense, academic grid, clear chapters and data pages | Graduation defense, project completion, research showcases |
fashion-business-consulting-toolkit-aesthetic |
Fashion consulting feel, high-end collage, magazine typography and neutral colors | Fashion business, brand consulting, trend reports |
economic-impact-of-coronavirus |
Economic impact report style, serious infographics, calm colors and data storytelling | Macroeconomics, policy analysis, risk reports |
eco-green-business-plan |
Sage green, natural material photography, eco-friendly business and minimalist split screens | Sustainable business, eco-friendly brands, healthy lifestyle |
All available styles are uniformly placed under styles/ and grouped by source, used in exactly the same way:initial/ contains the initial 10 sets,featured/ contains 22 curated sets,xiamulingzi/ contains 233 sets provided by designer @夏目玲子. For the directory index see styles/README.md; for curated style cover showcases see docs/distilled-styles.md.
Style selection principle: first choose the closest set in
styles/based on the content scenario. For technical topics, prioritizedark-aurora/gradient-glass/data-science-consulting; for business topics, prioritizeclean-tech-blue/editorial-mono/eco-green-business-plan/investment-company-business-plan; for culture and lifestyle topics, prioritizejapanese-wabi/vector-illustration/culinary-innovation/flowery; for academic topics, prioritizeswiss-grid/geometric-duotone-thesis/final-year-project-thesis-defense; for workshops and training, prioritizehand-sketch/mind-maps-workshop-professional/mindfulness-in-the-classroom-breathing-techniques.
Scenario recipes (optional starter templates)
examples/ is not a new skill, nor is it a required runtime input; it is the scenario starter template library for the current skill, used to help the agent write the first version of slides_plan.mdfaster when the user only gives a vague request.
Trigger rules:
- When the user has already provided a complete outline / complete
slides_plan.md/ completeslides_plan.json, do not apply a recipe; directly follow the user's content through the generation process. - When the user only says something like "make a product launch PPT / fundraising pitch / weekly report / courseware / thesis defense / book sharing" and other common scenarios, and has not given a clear page structure, first check
examples/Is there a matching recipe. - The recipe serves only as a structural reference: read
examples/<id>/recipe.mdto understand the scenario, recommended styles, and considerations, then refer toexamples/<id>/slides_plan.md's page-order structure and rewrite it with the user's own topic and content. - Do not treat the fictional products, companies, projects, or data in the examples as the user's finished work; they must be replaced with information provided by the user, or clearly marked as placeholder content and await user confirmation.
- If the user provides real images, logos, screenshots, paper figures, or product UI, still handle them according to the "external real image insertion" rules; the recipe is only responsible for content structure and does not replace the material fidelity process.
Currently built-in recipes:
| User scenario | recipe directory | Recommended style |
|---|---|---|
| Product launch, new feature launch, AI product introduction | examples/product-launch/ |
gradient-glass |
| Financing roadshow, business plan, investor report | examples/investor-pitch/ |
clean-tech-blue |
| Project weekly report, monthly report, regular meeting sync | examples/weekly-report/ |
meeting-agenda |
| Courseware, training, knowledge popularization | examples/courseware/ |
vector-illustration |
| Thesis defense, graduation project defense, final project presentation | examples/thesis-defense/ |
final-year-project-thesis-defense |
| Book sharing, cultural interview, viewpoint sharing | examples/book-sharing/ |
editorial-mono |
How to use:
- Determine whether the user's need matches a recipe.
- Read the corresponding
recipe.mdandslides_plan.md. - Based on the user's topic, rewrite a new
slides_plan.md, do not directly modify the recipe source file. - Confirm with the user the page count, title of each page, and key content.
- After the user confirms, execute
md_to_plan.pyto convert to json, and continue with the specified style or template cloning process below.
Layout bank sidecar for built-in styles (the only runtime format)
Built-in styles use a dual-file structure of "MD for humans, JSON for machines":
styles/<collection>/<style-id>.md # 风格说明、设计令牌、基础提示词
styles/<collection>/<style-id>.layouts.json # 必需;每页 layout bank,供自动分配页面形态
generate_ppt.py will use the .layouts.json of the same name as the RuntimeProfile without a reference image: assign different layouts via assign_layouts() , write visual_signature / content_capacity / best_for / avoid_for / variation_tags into the prompt, and write the condensed information of the matched layout into metadata.json.
Currently all styles/**/*.md must be paired with a .layouts.jsonof the same directory and name. Old styles that only have Markdown and lack a sidecar will directly report an error before image generation, and will no longer silently use the old Prompt; first migrate them to the paired format. In the future, when distilling public templates or adding built-in styles, a JSON sidecar must also be produced; do not compress multi-page layouts into only a "layout system" text paragraph in a single MD.
Unified RuntimeProfile execution core
Strict template cloning and structured style sidecars are both first compiled into the same RuntimeProfile, then uniformly processed through assign_layouts(), page Profile attachment, prompt compilation, and metadata recording. The entry adapter only retains the necessary differences:
template-clone: comes from--template-profileor template vision analysis; layout can carryreference_image, only--template-strictis actually passed into image generation.distilled-style: comes from<style>.md+<style>.layouts.json; uses content routing and multiple layouts, and does not depend on the original template images.
RuntimeProfile uniformly records source_kind, fixed prompt_strategy=layout-fields、layouts and capabilities(routing / evidence / reference / portability). The priority is fixed as: valid template Profile > style RuntimeProfile; when the template analysis has no layouts, it must truly fall back to the structured style, rather than only printing a hint. The runtime no longer includes legacy-freeform or the synthetic layout branch.
Template clone mode
Give the skill a .pptx template directly, and all subsequent pages will imitate this template.
# 一行:自动渲染 + 模板分析 + 出图。需本机有可用 PPTX 渲染后端
python3 scripts/generate_ppt.py \
--plan slides_plan.json \
--template-pptx ./company-template.pptx \
--template-strict
--template-strict means that for each page, the corresponding template page is fed to gpt-image-2 as an image reference, giving the highest fidelity.
Template rendering: no need to operate PowerPoint on this machine
The skill includes render_template.py, which automatically renders the .pptx into one PNG per page, saved to <cwd>/template_renders/<stem>/page-NN.png.
Agent pre-check (mandatory when cloning a template)
Before running any --template-pptx command, you must first check whether this machine has an available PPTX rendering backend.
How to check:
- Preferred: run
python3 scripts/render_template.py --checkin the skill directory. It verifies whether the backend is actually executable, rather than only checking whether the path exists. - macOS: first check
/Applications/Keynote.appand whether AppleScript is executable; otherwise checklibreoffice --version || soffice --version - Windows: first check whether the local PowerPoint COM can start; otherwise check
libreoffice --version/soffice --version - Linux / compatibility layers: check
libreoffice --version || soffice --version, do not rely only onwhich
Note: HarmonyOS / Termux / container / special architecture environments may look like Linux, but you cannot assume that the Linux aarch64 LibreOffice binary is runnable; you must rely on the actual execution results of render_template.py --check or soffice --version . Do not treat aspose-slides as the default fallback; it has no installable wheel in many mobile/special Python environments.
If no available backend exists, first tell the user that template rendering requires installing an executable LibreOffice, or have the user manually export each template page as page-01.png、page-02.png on desktop and pass it in via --template-images . Optional installation commands:
| Platform | Installation command |
|---|---|
| Windows | winget install LibreOffice.LibreOffice |
| macOS | brew install --cask libreoffice |
| Linux (Debian/Ubuntu) | sudo apt-get install -y libreoffice |
| Linux (Fedora/RHEL) | sudo dnf install -y libreoffice |
| Linux (Arch) | sudo pacman -S --noconfirm libreoffice-fresh |
After installation, check again and confirm that an available rendering backend exists before continuing the subsequent process.
Note: On Windows,
wingetis built into Win10/11 and will pop up a UAC confirmation dialog, which requires the user to click confirm; on macOS,brewrequires installing Homebrew first.
render_template.py 's rendering backend is automatically selected by priority:
- Windows: PowerPoint COM (preferred when Office is installed locally, directly outputs PNG and skips the PDF step) > LibreOffice
- macOS: Keynote AppleScript (preferred when Keynote is installed locally, directly outputs PNG) > LibreOffice
- Linux / compatibility layers: a LibreOffice / soffice command confirmed to be runnable via
--versiondetection - PDF -> PNG goes through
pymupdf(already in requirements); if not installed, usepdf2image+ poppler
Run generate_ppt.py --template-pptx ... when omitting --template-images will automatically trigger one render; you can also manually run it once first:
python3 scripts/render_template.py company-template.pptx
# -> <cwd>/template_renders/company_template/page-01.png ... page-NN.png
Two-layer cache for template mimicking
| Material | Path | Purpose |
|---|---|---|
| PNG for each template page | <cwd>/template_renders/<stem>/page-NN.png |
Long-term reuse of one render from the local rendering backend |
| Template style analysis | <cwd>/template_cache/<sha256>.json or hand-written template_profile.json |
Generated by the multimodal agent itself by looking at the images; only text-only agents need an external vision setup |
| Generated output | <cwd>/outputs/<timestamp>/ |
A new directory for every new run |
All three live under the caller's cwd and naturally rise and fall together with the project; it is recommended to add template_renders/、template_cache/、outputs/ to the project's .gitignore.
Template image analysis (let the agent decide for itself whether VISION_*is needed):
- The current code agent is itself a multimodal model (for example Claude Code's multimodal Claude, Codex's multimodal GPT): no additional
VISION_*configuration is needed. The agent directly readstemplate_renders/<stem>/page-*.png, generatestemplate_analyzer.py, then passes it toTemplateProfilestructure oftemplate_profile.jsonaccording to the--template-profile template_profile.json. If it needs to work withgenerate_ppt.pyusing--template-strict, each layout must includereference_image(the absolute path or accessible path of the template PNG). - The current code agent is a text-only model (for example, connected only to a DeepSeek text model): it cannot view template screenshots and needs additional
VISION_BASE_URL/VISION_API_KEY/VISION_MODEL_NAMEconfiguration so thattemplate_analyzer.pycalls a separate OpenAI-compatible multimodal endpoint to do template analysis.
vision analysis and image generation are always decoupled via gpt-image-2 —switching the vision provider does not affect the image output path.
Installation
git clone git@github.com:JuneYaooo/gpt-image2-ppt-skills.git
cd gpt-image2-ppt-skills
bash install_as_skill.sh --target claude # Claude Code
# 或
bash install_as_skill.sh --target codex # Codex
# API 直连所需密钥优先通过 agent 配置 / 系统环境变量注入
Environment variable injection (for direct API connection)
Do not write this skill's keys into .envin the caller's business project root directory, and do not read the generic .envin the user's project just to generate images. Environment variables should be injected in the standard way for the agent framework:
- Generic / CI / server: inject via system environment variables, Docker Compose
environment/env_file, Kubernetes Secret, CI Secret, etc. - Claude Code: inject environment variables via the user-level
~/.claude/settings.jsonor project-level.claude/settings.local.json; command-line environment variables have the highest priority. - OpenClaw / custom Agent: use
apiKey/ env reference in the framework configuration to reference system environment variables, avoiding writing keys in plaintext into the project configuration. - Local standalone CLI fallback: you can set
GPT_IMAGE2_PPT_ENV=/path/to/private.env, or use.envunder the skill installation directory; this is only a fallback method, not the business project.env.
A direct API connection requires these variables:
OPENAI_BASE_URL=https://api.openai.com # 或任意 OpenAI 兼容中转站
OPENAI_API_KEY=sk-...
GPT_IMAGE_MODEL_NAME=gpt-image-2
GPT_IMAGE_QUALITY=high # low / medium / high / auto
# 可选:模板克隆模式的 vision 分析 backend。
# 多模态 agent / 原生 Codex 可自己看图生成 --template-profile,不需要下面这组。
# 只有纯文本 agent(如 DeepSeek 文本模型)才需要外挂下面这组。
# 不内置默认 endpoint,请填你自己信任的服务,否则就别填。
# VISION_BASE_URL=https://your-openai-compatible-relay.example.com/v1
# VISION_API_KEY=sk-...
# VISION_MODEL_NAME=gemini-3.1-pro-preview # 或 gpt-4o / claude-3.5-sonnet 等任意多模态 SKU
The configuration priority is fixed as: current process environment variables > platform-injected gpt-image2-ppt_* variables > GPT_IMAGE2_PPT_ENV / under the skill directory .env;JULING_GPT_IMAGE2_* Only used as a compatible fallback when there is no corresponding OPENAI_* configuration; it will not override explicit configuration.
Security note: the script only reads the current process environment, platform-injected
gpt-image2-ppt_*variables, explicitGPT_IMAGE2_PPT_ENV, and the.envfallback under the skill installation directory. The script does not recursively read.envfrom the caller's project directory, to avoid accidentally consuming business project secrets.python3 scripts/render_template.py --checkwill perform a minimal real conversion to verify the re-rendering backend.
If you are the Codex agent (native image_generation for image output -- recommended)
If you yourself are Codex (the agent running this skill is Codex CLI / Codex TUI), and the current environment provides the image_generation tool and a ChatGPT login state, then do not use generate_ppt.py or --backend codex to handle image output; directly use the native tool to generate images, and at the end just reuse this repository's md conversion / PPTX packaging logic.
Key boundary: the Python script runs in a subprocess and cannot access the native tool in the current agent session.generate_ppt.py --backend codex can only start another codex exec subprocess to have another Codex generate images; it is not "reusing the current Codex's image_generation tool". Therefore, when the current agent can already generate images natively, the image generation action must be performed by the agent itself, not delegated to generate_ppt.py.
How to determine
You can access the image_generation tool, and you can generate images without manually configuring OPENAI_API_KEY -- if these two conditions are met, take the native path. If the current Codex session does not have this tool, handle it as an ordinary agent: go through the API direct connection, the--backend codex fallback backend, or have the user fill in the environment.
Image generation flow (Codex native path)
1. Prepare slides data
If there is no slides_plan.jsonyet, first write slides_plan.md → python3 scripts/md_to_plan.py ... to json according to steps 2-3 of "Generation flow" below.
2. Prepare prompts with the unified runtime
Do not manually replicate generate_prompt(). Run --prepare-onlyso that the API direct connection and the Codex native path share the same RuntimeProfile, layout routing, and prompt compiler:
python3 scripts/generate_ppt.py \
--plan slides_plan.json \
--style styles/<collection>/<id>.md \
--prepare-only \
--output outputs/<timestamp>
This command does not call the image API or package a PPTX; it generates prompts.json, per-page prompt text, and metadata.json. For a single-page smoke test, also pass --slides 1.
3. Read the compilation result for each page
From outputs/<timestamp>/prompts.json , read each page's prompt、reference_image、asset_reference_image and layout_id. Do not reassemble a Prompt based on the Markdown, otherwise it will bypass the structured layout bank.
4. Call the image_generation tool to generate images
For each page, call your image_generation tool:
prompt:prompts.jsonthe complete prompt already compiled for that pageoutput_format:png- If
reference_image/asset_reference_imagewas recorded, pass it in the original order as the image reference - Save the returned image to
outputs/<timestamp>/images/slide-NN.png(NN is the two-digit page number)
Concurrency is allowed (≤4 concurrent recommended, to avoid rate limiting).
5. Package the PPTX
If this deck has no external real image objects, you can use the simple full-page PNG packaging below. If any page has external_image / image_overlay / external_image_placeholder and it points to a real image, you cannot use this simple packaging snippet, otherwise the real image will be merged into the full-page background PNG and the user will not be able to select and drag it separately in PowerPoint. In that case you must use generate_ppt.py 's standard packaging logic, or call generate_pptx(..., metadata=metadata)in an existing session, so that the real image is overlaid on the background as an independent picture object.
python3 -c "
from pptx import Presentation
from pptx.util import Inches
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
blank = prs.slide_layouts[6]
import os, glob
for p in sorted(glob.glob('outputs/<timestamp>/images/slide-*.png')):
slide = prs.slides.add_slide(blank)
slide.shapes.add_picture(p, 0, 0, width=prs.slide_width, height=prs.slide_height)
prs.save('outputs/<timestamp>/<title>.pptx')
print('done')
"
The correct PPTX structure for a page with an external real image should be:
- Layer 1:
images/slide-XX.pngas the full-page background image (including the model-generated background and text). - Layer 2:
sourceas an independent PPT picture object, placed according toslide_speccoordinates on the background, selectable, draggable, and resizable in PowerPoint.
Template cloning mode (Codex native path)
You are yourself a multimodal agent -- directly Read extract the visual style from each page PNG of the template, write it into template_profile.json(for the schema see template_analyzer.py in TemplateProfile, write reference_imagefor each layout), then use --template-profile template_profile.json --template-strict --prepare-only to compile each page's Prompt and reference; do not manually choose another Prompt assembly logic.
No need to configure VISION_* -- you are the vision.
Difference from the "--backend codex" below
| Native path (this section) | --backend codex | |
|---|---|---|
| Applicable scenario | You are the Codex agent | You are Claude Code / another agent, borrowing the local codex CLI |
| Invocation method | Directly call the image_generation tool |
spawn codex exec --full-auto subprocess |
| Image generation layers | 1 layer | 2 layers (agent → python → codex exec) |
| Speed | A few seconds per image | 30-60s per image |
| Reliability | Precise tool parameters | Natural language relay, occasional failures |
| Requires API Key | No | No |
Optional: generate images via codex CLI (--backend codex, for non-Codex callers)
If you are a Codex agent, do not take this path -- use the "native path" in the previous section instead.
When you run this skill with Claude Code / OpenClaw / another agent, but the local machine has codex CLI installed and logged in (codex login), you can borrow its credentials to generate images, saving the need to configure OPENAI_API_KEY:
python3 scripts/generate_ppt.py --plan slides_plan.json --style styles/initial/editorial-mono.md --backend codex
The default backend is still openai(direct API calls, fast, stable concurrency, 3-10s per page).--backend codex is an escape hatch, suitable for scenarios where "you only want to run 1-2 images to test the waters and don't want to configure a key".
Tradeoffs:
- ✅ No need to configure in this skill
OPENAI_API_KEY - ⚠️ Slow: each page has an extra agent loop layer, 30-60s+ per page, 10 pages may take 5-10 minutes
- ⚠️ Billing unchanged: gpt-image-2 is billed per image, not included in the ChatGPT subscription; codex is just spending your quota on your behalf
- ⚠️ Poor controllability: aspect_ratio / quality / reference_image rely on natural language instructions for codex to forward, occasional failures
Related envs (all optional):
CODEX_CMD="codex exec --full-auto" # 覆盖 codex 调用方式(默认这串)
CODEX_IMAGE_MODEL=gpt-image-2 # 传给 codex 的目标模型
CODEX_TIMEOUT_SECS=900 # 单页超时
GPT_IMAGE_BACKEND=codex # 不想每次敲 --backend 就设这个
The same applies to vision analysis for template cloning -- when the caller agent itself is multimodal (Claude Code / multimodal codex), it can directly Read Extract the style from the template PNG, without configuring VISION_*; only when the caller agent is a pure text model is an external vision provider needed.
Generation flow (specified style)
md first, then json: md is for humans to read, easy to diff / review / edit copy; json is derived from md, fed to generate_ppt.py, marked as generated, not hand-edited.
- The user provides an outline / existing slides_plan.json; if the user only gives a common scenario and theme, first choose one according to the "scenario recipes" above
examples/<id>/as the structural reference - The Agent writes a new one according to the md spec below
slides_plan.md, confirms the copy with the user:--- title: MediWise Health Suite 商业计划书 --- ## 1. [cover] MediWise Health Suite 副标题:家庭健康管理智能平台 年份:2026 ## 2. [content] 市场痛点:健康管理的两类割裂 痛点一:高频无深度 ... ## 6. [data] 效率对比:使用 MediWise 前后 ...- h2 format:
## N. [page_type, layout=layout-05] 本页标题行 N.optional (auto-numbered by order of appearance);[page_type]optional (defaultcontent);layout=only needed in template cloning modepage_type:cover/agenda/section/content/data/quote/closing/other- h2 title line → in json
contentfirst line; the body below → body
- h2 format:
- After the user OKs it, convert to json:
python3 scripts/md_to_plan.py slides_plan.md -o slides_plan.json - Choose a style: from
styles/initial/、styles/featured/orstyles/xiamulingzi/, pick one, corresponding tostyles/<collection>/<id>.md; if a recipe was used, prefer therecipe.md/ in the frontmatter'srecommended_style, when a visual preview is needed first look atdocs/distilled-styles.md - Construct slide_spec (Agent step): read
styles/<collection>/<id>.mdvisual spec, forslides_plan.jsonconstruct each page'sslide_spec(each element's type, content, position, style), write into each page'sslide_specfield. Format see the "point and edit" section below - Call the script:
python3 scripts/generate_ppt.py --plan slides_plan.json --style styles/initial/editorial-mono.md - Artifacts are in
<cwd>/outputs/<timestamp>/:images/slide-XX.png-- each page's PNG (16:9, 1536x864)prompts.json-- the full prompt used for each page (for review / secondary fine-tuning)metadata.json-- slide_spec version history (supports precise editing and rollback)<title>.pptx-- 16:9 PPTX; by default the background and text are full-page images, viaexternal_imageReal images placed in will be overlaid as independent PPT image objects
Editable Mode (disabled by default)
Normal mode still prioritizes the full-page aesthetics of gpt-image-2, outputting backgrounds and text as full-page images. Only enable editable mode when the user explicitly requests "editable PPTX / text can be changed / elements can be split / images can be moved / native shapes"; do not enable it by default on your own based on content type.
Core Principle
Do not prohibit gpt-image-2 from generating titles, body text, numbers, tables, logos, or key charts in the initial visual draft. The model still first generates a complete finished page, to preserve the overall composition, materials, lighting effects, and the relationship between text and visuals; editable mode is a post-generation reconstruction step.
Effect Priority and Round Control
Editable mode takes final visual effect and object-level editable quality as its primary goals, and does not force completion in a single round; but it must distinguish low-cost inspection rounds from high-cost generation rounds:
- Inspection rounds can be multiple: scene schema, font availability, text overflow, object out-of-bounds, image aspect ratio, black-and-white background edges, object movement, PPTX re-rendering, and manual visual inspection can all be repeated, and must not be skipped in pursuit of fewer rounds.
- Generation rounds escalate level by level: first adjust deterministic parameters such as fonts, coordinates, cropping, rounded corners, and z-order; next use A1 original-pixel extraction and A2 occlusion completion; then only perform B AI separation/regeneration for failed complex assets; only when the overall composition, visual hierarchy, or style is clearly unacceptable may the entire page be regenerated.
- Local problems only fix local areas: when one layer, one text box, or one slot fails, do not by default regenerate other content that has already passed inspection.
- Keep the current best version each round: in
quality-report.jsonrecord the problems of this round, the repair scope, the route used, and the result; stop when the new version brings no visible improvement, and do not let the layout drift randomly just to "try one more time." - Real assets still prioritize fidelity: logos, product UI, medical imaging, paper charts, financial data, and evidence screenshots must not be switched to AI redrawing just to reduce rounds.
Recommended order:
完整视觉稿 / 用户参考图
-> 一次性 scene 规划与对象分层
-> 原生对象重建 + A1/A2 素材处理
-> 多轮低成本预检与回渲染
-> 仅对失败范围做局部修复或 B 路由
-> 只有结构性失败才重生整页
-> 选择历史最佳版本交付
Pre-check for Re-rendering in Editable Mode (required)
An editable PPTX must be able to be re-rendered into images, for a multimodal agent to read page by page and for manual acceptance; the requirements are the same as template cloning mode. Before running any --editable command, you must first check whether this machine has an executable PPTX rendering backend:
python3 scripts/render_template.py --check
- Windows: PowerPoint COM > LibreOffice
- macOS: Keynote AppleScript > LibreOffice
- Linux / compatibility layer: actually executable LibreOffice /
soffice
You cannot check only whether file paths or installation packages exist; the actual results of --check, PowerPoint COM startup, Keynote AppleScript detection, or libreoffice --version must be used as the standard. HarmonyOS, Termux, containers, and special architectures likewise must not assume that LibreOffice can run.
If no backend is available, stop editable mode and inform the user to install PowerPoint, Keynote, or LibreOffice; you must not generate a -editable.pptx that has not undergone re-render inspection and claim success. The installation method is the same as the rendering backend description in "Template Cloning Mode" above.
generate_ppt.py --editable will run an equivalent precheck before starting generation; after the build completes, it automatically sends -editable.pptx back-rendered to <session>/editable_renders/page-XX.png. The agent must read these PNGs page by page and check for font substitution, line breaks, object misalignment, edges and visual differences. When a text-only agent cannot complete this step, it must explicitly require the user or another multimodal agent to inspect the images for acceptance; it must not treat the automated report as manual acceptance.
When the user explicitly requests editability, the agent must:
- First run
python3 scripts/render_template.py --checkto confirm that the back-rendering backend is actually available; - Normally complete
slides_plan.md→slides_plan.jsonand the single-page visual smoke test; - Save the full visual draft of each page as
visual-master; - Establish for each page
slide-XX.scene.json, clean plate, independent assets and QC evidence; - Invoke the explicit
--editablemode; - Read
<session>/editable_renders/page-XX.pngand manually inspect page by page; do not just look at the automated report.
python3 scripts/generate_ppt.py \
--plan slides_plan.json \
--style styles/initial/dark-aurora.md \
--editable \
--editable-scenes editable_scenes/
--editableis off by default; when not passed, the existing generation, editing, rollback and normal PPTX packaging behavior is unchanged.--editable-scenespoints to a directory containingslide-01.scene.json、slide-02.scene.jsonand other files.- When
--editable-scenesis omitted, it will attempt<session>/editable_scenes/. - The CLI will reject an unavailable back-rendering environment before generation, and will automatically generate
<session>/editable_renders/page-XX.pngafter the build. - When a scene is missing pages, assets are lost or the format is wrong, it must not silently degrade into full-page images and claim editability; it should preserve the normal PPTX and intermediate evidence, then fail explicitly.
- On success, retain both
<title>.pptxand<title>-editable.pptx.
Scene Elements
Each scene uses real pixel canvas coordinates, and at minimum declares slide_number、canvas、clean_plate and z_index -sorted elements. Supports:
| type | Purpose |
|---|---|
native_text |
Titles, body text, dates, numbers, labels, badge text; outputs native PowerPoint text boxes |
image_layer |
Photos, key visuals, illustrations, complex textures and objects that cannot reasonably be converted into shapes; outputs independent image layers |
native_shape |
Rectangles, rounded rectangles, circles, five-pointed stars and lines; outputs native PowerPoint shapes |
connector |
Straight connector lines and arrows for architecture diagrams and flowcharts |
For paths in a scene, prefer writing relative paths relative to the scene JSON, to make it easy to move examples and sessions as a whole. For a complete example, see examples/editable-pptx/case05-summer-poster/slide-01.scene.json.
A1 → A2 → B routing for overlapping assets
- A1 direct original-pixel extraction (default): extract directly from the complete visual comp when the contour is complete, occlusion is minimal, and edges are clean. Multiple mutually overlapping assets are by default extracted as one connected combined layer, without forcibly splitting them into incomplete objects.
- A2 original pixels + occlusion completion: keep the visible original pixels, and complete the back of the object or the clean plate exposed after the object is moved away.
- B AI separation or regeneration: enabled only when A1/A2 results are unsatisfactory for fur, plush, semi-transparent, glass, white subjects, complex watercolor edges, or occlusion completion, or when the user explicitly requests design mode.
Do not skip A1 just because B is more convenient. Every escalation must be recorded in quality-report.json . In Case 05, the plush character, white ice cream, and watercolor clouds are mixed, and A1/A2 edges are unstable, so B is used to generate a combined asset on a monochrome key background, then background removal is done locally.
Clean plate and page types
- Save
visual-master.png, do not overwrite the original finished page. - Text and standalone image objects must be removed from
clean-plate.png; after moving an object, a second copy of the same object must not be exposed. - API edit may only composite within an explicit repair mask, and pixels outside the mask must be locked.
- Simple gradients, neon light bands, and solid-color cards may use deterministic interpolation; ghost text, color blocks, dark circles, or obvious patches must be rejected.
- For data pages, build titles, labels, and numbers separately as
native_text, do not treat the entire data card as a non-editable screenshot. - Architecture diagrams, flowcharts, and rule infographics should preferably be rebuilt as
native_shape+native_text+connector, do not merely overlay text on a screenshot.
Delivery threshold
Each page must retain at least:
editable/slide-XX/
├── visual-master.png
├── clean-plate.png
├── repair-mask.png # 使用局部修复时
├── layers/*.png
├── edge-check-white.png # 有透明图片层时
├── edge-check-black.png
└── quality-report.json
Before delivery, must check: scene schema, PPTX object names and counts, pixel changes outside masks, black/white background edges, text modifications, image moves,editable_renders/page-XX.png , and the human visual effect. The initial report status is rendered_pending_manual_review; it can be judged as passing only after a multimodal agent or the user visually inspects it page by page.
Report to the user the plain PPTX,-editable.pptx, the output directory, and the editable_renders/ path, and explain which visuals still exist as standalone image layers.
Inserting real external images (recommended precise workflow)
Default rule: when the user provides a real image, prioritize pasting it faithfully as the original image; do not let gpt-image-2 redraw this image. Use slide_spec to declare external image slots:
This workflow is enabled only when an element declares type: "external_image" / image_overlay / external_image_placeholder and source can resolve to a real local image file. Ordinary generation without a real image source, template cloning, pure placeholder layouts, and old free-style generation are unaffected.
If the user explicitly says "I care more about the visual blending effect, it doesn't have to paste the original image / redrawing is fine / image-to-image is fine", you may use reference image mode: input the image to the model as a generation reference, rather than as a final standalone pasted image. In this case the layout is usually more blended, but pixel-level fidelity is not guaranteed, and there will be no individually selectable original image object in the PPT.
Reference image mode may use type: "image_reference", or in external_image explicitly write on render_mode: "reference" / preserve_original: false:
{
"elements": {
"mood_reference": {
"type": "image_reference",
"source": "/absolute/path/to/photo.png",
"purpose": "只作为视觉参考,允许模型融合重绘,不作为独立 PPT 图片对象后贴"
}
}
}
Do not use reference-image redrawing for high-precision assets: medical imaging, pathology images, diagnostic evidence, experimental/engineering readings, financial tables, paper charts, legal evidence screenshots, exact product UI screenshots, etc. should all by default go through external_image to paste with fidelity, and prompt the user to verify before delivery.
{
"elements": {
"hero_photo": {
"type": "external_image",
"source": "/absolute/path/to/photo.png",
"layout_intent": "auto",
"tailor_to_asset": true,
"slot_strategy": "fit-within",
"fit": "contain",
"slot": {
"padding": 0.012,
"bleed": 0,
"fill": "#F7F7F5",
"mask_placeholder": false,
"sanitize_background": false,
"draw_frame": false,
"outline_width": 0,
"skeleton_canvas_fill": "transparent",
"skeleton_fill": "transparent",
"skeleton_shape": "corners",
"skeleton_outline": "#000000",
"skeleton_outline_width": 2,
"skeleton_ticks": false
}
}
}
}
During generation, the script automatically does four things:
- Plan slots first, then generate the skeleton. The script will preferentially read the
external_image_slotsin the template profile, or infer candidate regions such as "image left, text right / image right, text left / chart at bottom / central main visual" from the template summary; then combine the page's text volume, title length, number of real images, real image aspect ratios, and asset categories (photo / chart / document / architecture diagram, etc.) to score and select positions, and first produceposition/computed_bbox/auto_layout_reason/layout_planning_profile. The skeleton only draws this planning result for the model to see; it is not responsible for improvising positions on the fly. - Read the
sourcereal image dimensions. Iftailor_to_asset: trueorslot_strategy: "fit-within"is declared, the script will treatpositionas an "available area" and calculatecomputed_bboxwithin it according to the real image aspect ratio; this bbox will be used simultaneously in the prompt, the skeleton reference image, and the final PPTX image placement. This is not resizing after generation, but tailoring beforegpt-image-2image generation. - In
outputs/<timestamp>/references/slide-XX-asset-skeleton.png, generate a transparent-canvas corner-marker skeleton reference image, mark out thefinal_image_rect_pxthat the final real image will cover, and pass it as a reference image togpt-image-2. This is only used to guide the model not to place key information in that area; only callgpt-image-2once per page, not generate one first and then regenerate using the skeleton. - When packaging the PPTX, use
python-pptxwith the same bbox to paste the real image pointed to bysourceas an independent image object. By default, do not draw extra frames or lay down masks; also do not by default clean upgpt-image-2generated images. Real images should not be composited intoimages/slide-XX.png, otherwise the user cannot drag them separately in the PPT.
If after generation you find that the real image slot presses into a large area of text or graphics, prioritize the following two methods:
- Fine-tune the slot before pre-generation: change
slide_spec.elements.<id>.position(oranchor/padding), let the real asset move to a cleaner area, then regenerate that page. As long as the slot position changes, the background must be regenerated; do not just move the final image in the PPTX, otherwise the background content may still press on the new position. - Secondary layout repair: when the overall style of the first page is already satisfactory and only local content presses into the slot, use
--edit SLIDE --external-slot-repair. This mode will pass both the current page and the newasset-skeletonas reference images, requiring the model to keep the original style but rearrange text/graphics so that the slot is left empty.
Example: move the real image area to the right and rearrange the current page:
python3 scripts/generate_ppt.py \
--session outputs/20260529_120000 \
--edit 3 \
--external-slot-repair \
--element-updates '{"hero_photo":{"position":[0.60,0.16,0.32,0.60],"anchor":"center"}}'
At the same time, every page containing an external real image will be included in outputs/<timestamp>/external_image_trace/slide-XX/ Record the full intermediate pipeline:
step1-real-on-blank.png: paste the real images onto a blank page at their final coordinates and sizes first, to confirm "the real image should ultimately appear here".step2-reference-outline-blank.png: remove the real images and keep only the corner-marker positioning reference image forgpt-image-2; by default a transparent canvas, with no white background laid down. The positioning area usesfinal_image_rect_px, i.e. the pixel rectangle that the final real image will actually cover, not the outer slot. This image is also copied toreferences/slide-XX-asset-skeleton.pngand used as an image reference input.step3-generated-background.png:gpt-image-2the background image generated from the step2 reference, with the real images not yet pasted in.step3-image2-raw.png/step3-sanitized-background.png: appears only whensanitize_background: trueis explicitly set, used as a fallback to clean up placeholder blocks the model has already drawn; disabled by default.step4-final-overlay-preview.png: a preview image with the real images pasted back onto step3 at the same coordinates as step1, used to compare against the final PPTX result.manifest.json: record each external image'ssource、slot_bbox_norm、inner_rect_norm、reference_rect_px、final_image_rect_px, padding, bleed, asset dimensions and aspect ratio.
Key principles:
- The reference skeleton is responsible for "telling the model where not to put key information", not for asking the model to draw white empty boxes.
- When template cloning /
--template-strictand external real-image slots exist at the same time, the generation stage passes in two references at once: the template page for learning the style, andasset-skeletonfor marking the area to be covered by the pasted image; do not choose only one, otherwise the model looking only at the template page will not know the final image position. - External real-image pages cannot simply stack a "template photo/image area prompt" and a "leave blank prompt". Before constructing the prompt, conflicts must be resolved: the template only provides color scheme, fonts, grid, rhythm and decorative language; the template's photo areas, image frames, full-bleed images, cropped images, etc. are all regarded as already replaced by the real-image slots.
- When constructing
slide_spec,positioncannot be chosen arbitrarily, and must not default to a fixed right side. In template cloning mode, preferably let the template profile provideexternal_image_slots, or infer candidate image areas from the template layout summary, then score them based on this page's text volume, number of real images, real image aspect ratios and page type: when there is a lot of text, prioritize securing the title/body reading area; when there are many images or extreme aspect ratios, prioritize using the template's original column/split or top-bottom layout; when they cannot coexist, reduce decoration and fake visual subjects rather than letting the real images squeeze the content. - It is recommended to write
layout_intent: "auto"first rather than hand-writingposition. The script will read the template candidate slots, real image dimensions, text volume, image count and aspect ratios to choose the position and write it toposition/computed_bbox/auto_layout_reason; only when automatic planning is unsatisfactory should a manualpositionoverride be used. - When using
layout_intent: "auto",slide_spec.layoutTry to clearly describe the image area direction and structure, for example "text on left, image on right / right image / right landscape photo / bottom image / portrait rail". Automatic planning will prioritize inferring the real image area from these directional descriptions and template candidate slots; when the description is too vague, text-heavy pages may degrade to conservative small image slots. positionBy default can serve as an "allowed area";computed_bboxis the final real image slot calculated by the script.- If you want to fully fix the coordinates, do not tailor them; directly write
bbox, or setslot_strategy: "exact"/tailor_to_asset: false. - Final precision is guaranteed by the
python-pptxcoordinates, not by the model drawing boxes. skeleton_outline_widthonly controls the skeleton reference image shown to the model;outline_width/draw_framecontrols whether a visible box appears in the final PPT.- Do not write normalized coordinates in the prompt; position is controlled by the transparent corner-marker reference image, avoiding the model misinterpreting numeric coordinates and also avoiding closed boxes being understood as real image frames.
skeleton_canvas_fill/skeleton_fill/skeleton_outline/skeleton_outline_width/skeleton_shapeonly affects the reference skeleton image. By defaultskeleton_canvas_fill: "transparent"andskeleton_shape: "corners", only at thefinal_image_rect_pxfour corners draw short corner markers, do not draw a closed rectangle, do not lay down a white background, to avoid the model interpreting the reference as a real image frame or white placeholder block. When the old behavior is needed, explicitly setskeleton_shape: "outline"。sanitize_background/mask_placeholderis not the recommended path; they are only suitable for clearing extremely slight placeholder traces, not for solving the problem of text or graphics covering the slot over a large area. When content is covered, handle it as "fine-tune the slot and regenerate" or "secondary layout repair".- By default, do not draw an outer frame in the final output, do not insert any background-color rectangle, only paste the real image;
mask_placeholderwill be ignored, to avoid producing a draggable white background under the real image. Only when explicitly settingdraw_frame: trueandoutline_width > 0will an unfilled border be additionally drawn. - Recommended default:
tailor_to_asset: true+slot_strategy: "fit-within"+fit: "contain"+ a small amount ofpadding. This fully preserves the original image and makes the skeleton image reserved according to the asset aspect ratio from the start. fit: "contain"preserves the full image;fit: "cover"center-crops the image to fill the slot.- If you want a "perfect fit" with no white edges, use
fit: "cover"、padding: 0、outline_width: 0, and set a very smallbleed(for example0.0015-0.003) to make the image extend about 1-3px beyond the slot, offsetting rounding and anti-aliasing seams in PowerPoint / Quick Look rendering. - If you want to "reserve a little but not have strange gaps", do not rely on later
containto force it into a large frame with a mismatched aspect ratio; instead usefit-withinto first calculate a slot with matching aspect ratio, then use a very smallpaddingfor design whitespace. - Before delivery, you must spot-check
external_image_trace/slide-XX/manifest.json: focus on whetherfinal_image_rect_pxmatches visual expectations, and whetherauto_layout_reasonselected the correct left/right or top/bottom area. If a landscape image is calculated as a small thumbnail, a portrait image is too narrow, or the position covers content, first clarify the directional intent ofslide_spec.layout, or explicitly setposition, then regenerate that page's background and repackage the PPTX.
The overall schematic is saved at docs/external_image_overlay_logic.txt; when modifying the external real-image pipeline, first check against this diagram to confirm the order is still "template/page/asset profiling -> candidate slot scoring -> transparent skeleton -> background generation -> paste real images afterward -> quality check/limited repair".
Generation flow (template cloning)
-
Obtain the template .pptx (user-provided / internal template library / downloaded from the web)
-
(Optional) Render separately and manually select first----for large templates (>15 pages), it is recommended to first
python3 scripts/render_template.py xxx.pptx, then fromtemplate_renders/<stem>/pick 8-12 representative pages and copy them totemplate_renders/<stem>_curated/, for vision analysis. The more precise the page count, the more accurate the layout match. -
Generate slides_plan.md → convert to slides_plan.json (see steps 2-3 of the specified style flow). Each page
slide_number/page_type(cover/agenda/section/content/data/quote/closing/other) /content; for precise alignment, add in the h2layout=layout-NN(NN = template page N / the template page number you expect it to correspond to) -
Image generation smoke test. For API direct connection / non-Codex native path, run
generate_ppt.py:python3 scripts/generate_ppt.py \ --plan slides_plan.json \ --template-pptx xxx.pptx \ --template-images template_renders/xxx_curated \ --template-strict --slides 1If the current agent is itself a multimodal model, you can also first look at the template PNGs and write out
template_profile.json, then run it this way, without needingVISION_*:python3 scripts/generate_ppt.py \ --plan slides_plan.json \ --template-profile template_profile.json \ --template-strict --slides 1First
--slides 1to smoke-test the cover; if the result is OK, then run the full batch.If the current agent is Codex with native image generation capability, do not use the above
generate_ppt.pycommand to handle image generation; first generate / readtemplate_profile.json, then follow the "Codex native path" to directly call the current session's image generation tool to output page 1 PNG, and after the user confirms, generate all pages and package them. -
Tell the user the artifact paths
Template page selection / reuse principles
Core principle: strive for 1 page : 1 layout----in the same deck, use a different template page as reference for each slide, and the audience will feel that every page is new content; if the same unique layout appears 2-3 times, the audience will subconsciously think "why is this page here again".
During vision analysis, each layout is tagged reuse_friendly:
For each layout, TemplateProfile, in addition to id / page_type / summary / json_schema / reference_image, also tries to save:
visual_signature: the most obvious visual differentiator of this page, e.g. "image on the right, text on the left", "numbered timeline", "three-card grid".content_capacity: the information density it is suitable for carrying, to avoid cramming long text into a strongly visual page.best_for/avoid_for: content structures it is suitable or unsuitable for.variation_tags: short English labels, used to help compare and stagger layout forms.
During generation, assign_layouts() is used to prioritize unused layouts; even if the plan does not hand-write slide_spec, the matched template layout will also be written into template_layout_profile as a simplified version, metadata.json, for subsequent editing, image slot planning, and review.
| reuse_friendly | typical layout | cost of multiple uses |
|---|---|---|
false(not reusable, (!) strong warning) |
Cover, 3 named character illustration pages, unique scene images (snow mountain / broadcast tower / retro radio), 5-step zigzag with a unique icon per step, novelty data central device | Visual repetition is very obvious, the audience will be confused |
true(reusable, but still recommend staggering, (i) weak hint) |
Plain text, card grid, generic list, section subheadings | Not fatal, but it plainly wastes the other good layouts in the template |
When building the plan, the Agent's execution strategy:
- Prioritize assigning the template's N different layouts to N slides (if N is not enough, look in the SKILL at the reuse_friendly=true parts and pick the ones that can be reused)
- If some page in the plan has a very similar content structure (for example multiple "5-step processes"), first try rewriting the content to express it with a different layout (use different process pages for 4 steps + 5 steps), instead of using the same zigzag twice
- After the smoke run, look at the
Layout 复用检测output: (!) must be changed, (i) change depending on the situation; just change the corresponding slide'slayout_idin the plan - After reading the profile JSON, choose the layout:
cat <cwd>/template_cache/<sha256>.json | jq '.layouts[] | {id, page_type, reuse_friendly, visual_signature, content_capacity, summary}'; if it is atemplate_profile.jsongenerated by a multimodal agent itself, then read that file.
generate_ppt.py will automatically run a reuse check once before dispatching the task, print the warnings to the terminal, and not block execution.
Skill invocation conventions
When the user says "make a PPT" / "generate slides":
- First ask three things (do not start directly):
- Content / number of pages / who is the audience?
- Style preference? Based on
styles/anddocs/distilled-styles.mdscenario category mappings, recommend 1-2; or the user uploads their own .pptx template (go through--template-pptx, automatically rendered) - Whether a single-page test image is needed first to see the effect (for direct API use
--slides 1; for the Codex native path, directly generate page 1 PNG)
- First write slides_plan.md to let the user confirm the copy (md is the source of truth, human-review friendly)
- Convert to slides_plan.json:
python3 scripts/md_to_plan.py slides_plan.md -o slides_plan.json(json is marked as generated, do not hand-edit; to change the copy, go back to the md, change it, then convert) - Build slide_spec (Agent step): read
styles/<collection>/<id>.mdto understand the visual conventions, then forslides_plan.jsonbuildslide_specfor each page, and write it into each page'sslide_specfield (format see the "change exactly where you point" section). This step makes later modifications precise down to each element - Image-generation smoke test:
- Direct API / non-Codex native path: run
generate_ppt.py --slides 1to produce a cover smoke test, and if the effect is OK then run the full batch - If the current agent is Codex with native image-generation capability: follow the "Codex native path" above and directly call the current session's
image_generationtool to generateoutputs/<timestamp>/images/slide-01.png; do not usegenerate_ppt.py --backend codex
- Direct API / non-Codex native path: run
- Tell the user the artifact paths, the artifacts are in
outputs/<timestamp>/,<title>.pptxand can be opened directly
User-facing expression conventions
When reporting to ordinary users, by default do not explain slide_spec、metadata.json、element-updates, JSON Schema, pytest commands, and other internal implementation, unless the user explicitly asks about technical details.
What users care about most is:
- Whether the resulting PPT looks good and can be used directly.
- Which scenarios are stable and which scenarios require manual acceptance.
- Whether only the specified pages / specified content were changed.
- Where the final output directory and PPTX file are.
- What the current shortcomings are, for example the background/text is still a full-page image, and small numbers/text need to be reviewed; real logos/product images require provided assets before they can be placed as independent image objects.
If you need to introduce the editing capabilities, prioritize citing docs/edit_guide.md scenario tiers, before / after cases, and current shortcomings; do not put the implementation chain in front of the user.
When the user says "change XX on page X":
- Find the session: first use
--list-sessionsto list existing sessions, and determine which one is to be edited - Read metadata.json: check the slide_spec of the corresponding slide, and find the target element
- Confirm the modification content: tell the user the current content and ask for the new content
- Construct the edit instruction: use
--element-updatesto specify the element to change and the new content - Run --edit:
python3 scripts/generate_ppt.py --edit X --session <ts> --element-updates '{"elem_id": {"content": "new"}}' - Report the result: a new version has been generated, and the PPTX has been updated
Generate only some pages
python3 scripts/generate_ppt.py --plan my_plan.json --style styles/initial/dark-aurora.md --slides 1,3,5
When pages that have already been run have a PNG with the same name, they are automatically skipped, making page-by-page iteration convenient.
"Edit exactly what you point to" PPT editing workflow
This section only keeps the information needed for the agent to execute; for the complete structure, version chain, and data security details, see docs/workflow.md. When explaining the capabilities to ordinary users, see docs/edit_guide.md.
Structural requirements during generation
When generating a new PPT, the agent should write a concise slide_specfor each page, to facilitate subsequent precise modifications by title, subtitle, card, metric, and other elements. Minimum requirements:
layout: a one-sentence description of the layoutelements: a semantic element dictionary- Common element IDs:
title、subtitle、card_1、card_2、metric_1、date_line、footer - For element fields, prefer writing
type、contentorheading/body、position、style、color
Do not write a very long spec just for the sake of completeness; as long as it enables subsequent locating and editing, that is enough.
Modify an existing slide
- Use
--list-sessionsto find the target session. - Read the target session's
metadata.json, and locate the page number and element ID. - If the user has not given the new content, first ask, "The current content is X; what should it be changed to?"
- Use
--element-updatesto describe the modification; when stronger constraints are needed, add--edit-instruction, clearly stating "do not change other content, layout, or color scheme." - After running
--edit, check the target page image; the rebuilt PPTX will be updated in sync.
Common commands:
python3 scripts/generate_ppt.py \
--edit 3 \
--session 20240523_143052 \
--element-updates '{"subtitle": {"content": "医疗数据碎片化"}}' \
--edit-instruction "将副标题从'健康管理的两类割裂'改为'医疗数据碎片化'"
python3 scripts/generate_ppt.py \
--edit 3 \
--session 20240523_143052 \
--edit-prompt "在参考图基础上,只修改标题下方副标题的文字,从'健康管理的两类割裂'改为'医疗数据碎片化',保持位置、字体、颜色、大小完全不变。" \
--element-updates '{"subtitle": {"content": "医疗数据碎片化"}}'
Modify after ingesting an external PPTX
An external PPTX can first be ingested as an image session, and then a multimodal agent can look at the images to fill in each page's slide_spec. Before the specs are filled in, do not promise to "precisely modify a certain object."
python3 scripts/generate_ppt.py --ingest-pptx path/to/deck.pptx
python3 scripts/generate_ppt.py --ingest-pptx path/to/deck.pptx --session my_deck_2024
Rollback and session list
python3 scripts/generate_ppt.py \
--rollback 3 \
--to-version 1 \
--session 20240523_143052
python3 scripts/generate_ppt.py --list-sessions
File structure
gpt-image2-ppt-skills/
|---- SKILL.md # 本文件(Claude Code skill 入口)
|---- AGENTS.md # codex / aider / cursor 等 agent 的薄索引,指向本文件
|---- README.md # 项目说明
|---- scripts/ # 所有 Python 脚本
| |---- generate_ppt.py # 主入口(CLI)
| |---- runtime_profile.py # 模板克隆 / 结构化 style sidecar 的统一运行时适配器
| |---- md_to_plan.py # slides_plan.md -> slides_plan.json 转换器(CLI)
| |---- render_template.py # PPTX -> 每页 PNG 的辅助脚本(CLI + library)
| |---- image_generator.py # gpt-image-2 wrapper(支持 reference image,openai backend)
| |---- codex_backend.py # 可选:走 codex CLI 出图(--backend codex)
| \---- template_analyzer.py # PPT 模板剖析器(vision + 缓存)
|---- styles/ # 所有可用风格,每个 .md 配同名 .layouts.json
| |---- initial/ # 初始 10 套
| |---- featured/ # 精选 22 套
| |---- xiamulingzi/ # 设计师 @夏目玲子 提供的 233 套
| \---- README.md # 目录说明与调用示例
|---- examples/ # 场景 recipes:常见 PPT 的 slides_plan.md 起步模板
| |---- product-launch/ investor-pitch/
| |---- weekly-report/ courseware/
| |---- thesis-defense/ book-sharing/
|---- docs/README.en.md # 英文 README
|---- install_as_skill.sh # 一键安装到 agent skills 目录
|---- requirements.txt # requests + python-dotenv + python-pptx + jsonschema + pymupdf
\---- .env.example
The runtime directories generated when invoked are all under <cwd> :
<your-project>/
|---- template_renders/<stem>/page-NN.png # PPTX 渲染(render_template.py)
|---- template_cache/<sha256>.json # 外挂 vision 风格分析缓存(纯文本 agent 路径)
|---- template_profile.json # 多模态 agent 可手写/生成的模板 profile(可选)
\---- outputs/<timestamp>/ # 每次生成产物
License
Apache License 2.0.