Part of NEURA Office: native Word, PowerPoint and Excel for Open WebUI.
A Open WebUI Tool that generates
native PowerPoint (.pptx) presentations from a JSON spec produced by the model.
It doesn't export HTML or images: it builds the slides directly with python-pptx,
with a coherent visual system, layered decorative shapes, native charts, icons
inside circles and rich layouts.
The resulting file is saved through Open WebUI's Files API (with a /cache/files
fallback) and a clickable download link appears in the chat.
License: MIT · Author: IANUSTEC
Slides generated from the example examples/deck.json → examples/demo_tech_deck.pptx.
- Native, editable .pptx (text, charts and shapes are editable in PowerPoint/Keynote/LibreOffice).
- Native Office charts:
bar,line,area,pie,doughnut,radar,stacked_bar. - ~25 ready-made layouts: cover, sections, bullets, columns/comparison, KPIs, timeline, process flow, icon lists, icon grids, pillars, quote, alert, tables, diagrams (funnel, pyramid, cycle, quadrant, bullseye) and image layouts.
- Curated themes + custom accent (
theme:"auto"infers the theme from the content). - Lucide-style icons bundled in the file (no network dependency for icons).
- Optional images from Unsplash (with a key) or generated via Open WebUI.
- Template Mode: build a deck by cloning shapes from a user
.pptxtemplate and overlaying content in the template safe zone. inspect_slides: JSON inventory of the template for the model: text, table and picture ids per slide, and every image inside the.pptx(slides, backgrounds, layout/master logos) with arefthe model can place on new slides.- Single-file: one self-contained
.py, ready to paste into the Tools registry.
See CHANGELOG.md for release notes.
- Open WebUI
>= 0.4.0 - Python:
python-pptx,pillow(declared in the frontmatter → Open WebUI installs them automatically) - Optional:
httpx(fetch images from URL/Unsplash)
- Open the tool page on the Open WebUI community site.
- Click Get / Import to your instance.
- In your Open WebUI instance go to Workspace → Tools → +.
- Paste the contents of
generate_slides.py. - Save. The declared dependencies are installed on first use.
- Enable the tool for the model (or chat) that should use it.
The model calls generate_slides(content), where content is a single JSON string.
Minimal structure:
{
"title": "Presentation title",
"subtitle": "Optional subtitle",
"author": "Author / company",
"theme": "auto",
"footer": "Footer label",
"slides": [
{ "layout": "cover", "title": "...", "subtitle": "...", "icon": "cpu" },
{ "layout": "kpi_row", "title": "...", "stats": [ { "value": "-40%", "label": "..." } ] }
]
}See the full example in examples/deck.json.
Works on the standard theme engine (no reference_file_id required):
| Field | Effect |
|---|---|
palette.primary, palette.dark, palette.accent, palette.light_accent |
Override named theme colors |
accent, primary (top-level) |
Shortcuts for accent / primary |
heading_font, body_font |
PowerPoint font names (e.g. "Calibri", "Arial") for titles and body text |
{
"title": "Branded deck",
"theme": "ocean",
"palette": { "accent": "C99A3B", "primary": "1E3A5F" },
"heading_font": "Calibri Light",
"body_font": "Calibri",
"slides": [{ "layout": "title_bullets", "title": "Hello", "bullets": ["One"] }]
}Use this when the user attaches a template .pptx and wants the output to keep its look (backgrounds, logos, decorative shapes) while replacing slide content.
- Step 1 —
inspect_slides— Pass the Files APIfile_id(or rely on chat attachment auto-detection only in this tool). Returns a compact JSON for the model: per slide the text, table and picture ids with their verbatim text, andimages[](ref, size, slides,on). Decorations, bbox and safe zones stay server-side: decorations are cloned and safe zones applied by the tool. - Step 2 — Model — Builds the content JSON plus the same
reference_file_id. Prefer per-slidereuse(slide,keep_ids,drop_ids,textfrom inspect shape"id") when mirroring each template slide; otherwisetemplate_mapping+template_edits. - Step 3 —
generate_slides(content)— Re-downloads the reference, clones allowed shapes, overlays layouts in the safe zone, saves the.pptx. Requires admin valvetemplate_mode_enabled=true.
Important: generate_slides does not infer the template from chat attachments. Only an explicit reference_file_id in the JSON enables Template Mode.
Example spec: examples/template-deck-with-reference.json. Deep dive: doc/template-mode-implementation-plan.md. Model instructions (Neura): doc/neura-template-mode-model-hints.md.
| Field | Description |
|---|---|
reference_file_id |
Files API id of the template .pptx |
slides[].reuse |
Per output slide: clone template slide index + shape ids + in-place text (see examples/template-reuse-slide.json). Template tables (kind: "table") are refilled in place with text["<id>"] = {"headers": [...], "rows": [[...]]} keeping cell formatting |
template_mapping |
Fallback: maps layout role → reference slide index (cover, section, content, closing, default, …) |
template_edits.defaults |
Clone policy: drop_text, drop_placeholders, drop_offslide (conservative defaults; set drop_text: true only when the user wants template wording removed) |
template_edits.slides[] |
Per reference slide: index (0-based in the template file), drop_ids, optional keep_ids |
With template_mode_enabled=false (default), reference_file_id is ignored and a classic deck is generated (same behavior as v1.0.3).
Separate from Template Mode’s 3-step workflow: after the user opens a deck from generate_slides, they may ask for small fixes (title too large, text overlap, split title vs body). Neura should call edit_presentation with a JSON content string — not rerun generate_slides for those tweaks.
Flow: user feedback → Neura → optional inspect_slides on the output file UUID → edit_presentation with presentation_file_id + operations[] (set_text, shrink_font, …).
Requires admin valve presentation_edit_enabled=true (default off; independent of template_mode_enabled). Input must be a Files API UUID from the last generate/edit response, not the template reference_file_id.
Docs: doc/presentation-edit-implementation-plan.md · Model hints: doc/neura-presentation-edit-hints.md · Chat examples: doc/neura-presentation-edit-chat-examples.md.
Minimal payload shape:
{ "presentation_file_id": "<uuid>", "operations": [{ "op": "set_text", "slide": 1, "shape_id": 1, "text": "..." }] }v2 ops (same JSON): enable_autofit, replace_text_and_fit, split_text (from_shape_id, to_shape_id, mode), resize_shape (delta_height_in), set_table_cell (row, col, text), set_font_pt (font_pt or font_pt_delta). shrink_font optional "mode": fit (default), to_min, target (+ target_pt). JSON "slide" uses PowerPoint numbering when EDIT_SLIDE_INDEX_ORIGIN=1 in generate_slides.py.
auto (default, inferred from content) · midnight · forest · ocean · coral
· terracotta · teal · berry · sage · cherry · charcoal · slate.
You can force the accent with "accent": "#C99A3B".
| Layout | Main fields |
|---|---|
cover |
title, subtitle, author, eyebrow, icon, date, chips[] |
section |
number ("01"), eyebrow, title, lead |
title_bullets |
title, eyebrow, bullets[] |
title_body |
title, eyebrow, body (paragraphs separated by \n) |
two_column_text / comparison_two |
left{}, right{} or columns[] (heading, icon, points[], highlight, badge) |
kpi_row |
stats[] with {value, label, change} |
timeline_horizontal / process_flow |
steps[] with {when, title, description} |
icon_list_vertical |
items[] with {icon, title, description} |
icon_grid_2x2 / icon_grid_3 / pillars |
items[] with {icon, title, description} |
chart |
chart_type, labels[], values[] or datasets[]{label,data[]}, insight[] |
funnel / pyramid / cycle / quadrant / bullseye |
nodes[] with {label, description} |
quote |
quote, author, role |
alert |
title, level (info|tip|warning|danger), body or bullets[] |
table |
headers[], rows[] |
text_image_right / image_left_text_right |
title, bullets[]/body, image_hint or image_url or base64 |
image_full_caption |
title, subtitle, image_hint/image_url |
closing |
title, eyebrow, takeaways[], contact |
| Cover | KPI row |
|---|---|
![]() |
![]() |
| Native chart | Funnel |
![]() |
![]() |
| Valve | Default | Description |
|---|---|---|
default_theme |
auto |
Default theme when the spec doesn't set one |
footer_label |
"" |
Default footer (overridden by spec.footer) |
unsplash_access_key |
"" |
Unsplash key for stock images (optional) |
image_generation |
false |
Enable AI image generation via Open WebUI |
max_image_px |
1600 |
Maximum image width |
emit_status |
true |
Emit status events in chat |
pptx_export_dir |
/app/backend/data/cache/files |
Fallback directory for saving |
template_mode_enabled |
false |
Enable reference download + template clone in generate_slides |
inspect_slides_enabled |
true |
Allow the inspect_slides tool |
inspect_extract_images |
true |
Upload the template images to the Files API cache on inspect (images[] is returned either way) |
template_strict_mode |
false |
Fail generate when reference safe_zone is not computed or is too small |
presentation_edit_enabled |
false |
Enable edit_presentation (post-generate fixes on an existing output UUID) |
presentation_edit_min_font_pt |
14 |
Floor for shrink_font when op omits min_pt |
presentation_edit_shrink_step_pt |
2 |
Step for shrink_font when op omits step_pt |
presentation_edit_progress_every |
5 |
Emit progress every N ops (0 = off) |
presentation_edit_warn_noop |
false |
Status hint when all ops complete but none mutated the deck |
Deferred post-v1: auto-inject inspect on .pptx upload (Open WebUI/Neura integration), optional inspect thumbnails, PNG/JPG background-only templates.
- Keep
template_mode_enabled=falseon customer instances until Template Mode is explicitly rolled out. - Enable
template_mode_enabled=trueonly on internal pilot workspaces. - Presentation Edit: keep
presentation_edit_enabled=falseby default; enablepresentation_edit_enabled=trueonly on internal pilot workspaces where post-generate fixes are tested. Independent of template mode. Rollout checklist and log monitoring: doc/neura-presentation-edit-hints.md — Rollout pilot Neura. - After deploy: Workspace → Tools → paste the updated
generate_slides.pyand save (same Files API workflow as v1.0.3). - Rollback: turn the valve off instantly (
template_mode_enabledand/orpresentation_edit_enabled), or pin the previous tool version.
- For a custom template, the model may call
inspect_slidesfirst, thengenerate_slideswith the samereference_file_id. - The model produces the JSON spec and calls
generate_slides(classic or template path). - The engine resolves theme/accent, prefetches images (if any image layouts are present), and for each slide invokes the corresponding layout renderer (template path clones reference shapes first).
- Shapes, text and charts are written as native OOXML objects.
- The
.pptxis saved via the Files API (fallback/cache/files) and the link is returned in chat.
Requires python-pptx and (optionally) pillow/httpx:
pip install -r examples/requirements-dev.txt httpx
python examples/build.py # → examples/demo_tech_deck.pptx
python examples/check_baseline.py # NF5 golden regression smoke
python examples/fixtures/build_fixtures.py # template-mode dev fixtures
python examples/parse_template_fixtures.py # Fase 1 template parse smoke
python examples/inspect_template_fixtures.py # Fase 2 inspect JSON (offline)
python examples/inspect_extract_media_fixtures.py # Fase 3.1 media extract (offline)
python examples/inspect_shape_kinds.py # Fase 3.2 kind + cloneable (offline)
python examples/inspect_online_templates.py # real Slidesgo decks in doc/online_templates/
python examples/clone_template_fixture.py # Fase 3 clone smoke → examples/output/
python examples/generate_slides_async_smoke.py # NF9 / NF5 / F9 / F10 async smoke
python examples/template_mode_nf6_15_slides.py # NF6: 15-slide template deck
python examples/run_production_checks.py # full local batteryOptional: open examples/output/clone_corners.pptx in LibreOffice for a visual check.
inspect_slides in Open WebUI needs the Files API runtime; the scripts above test parse/JSON locally.
See examples/fixtures/README.md for fixture types.
Local dev was verified with Python 3.11 (Docker python:3.11-slim) and pinned deps in examples/requirements-dev.txt. Record the Open WebUI Neura container Python version on deploy (≥3.10).
The file is designed to run inside Open WebUI: the open_webui.* imports are optional
and the tool degrades gracefully when they're missing (handy for isolated render tests).
Issues and PRs welcome. Please keep the file single-file and free of mandatory network dependencies for the core features.
MIT © IANUSTEC




