# AI PPT Maker 两种任务来源 · 完整业务流程

> 任务来源入口：`https://xybcloud.online/chat/`（Claude AI 对话界面）
> 业务系统：AI PPT Maker（`https://xybcloud.online/aippt/`，服务端口 7860，systemd 服务 `ai-ppt-maker.service`）
> 梳理日期：2026-08-27 · 依据源码：`/root/ai-ppt-maker/`（V5.x 双轮闭环导出）
> 用途：完整理解「从文本生成」与「从已有原稿图继续」两种方式从创建到交付的全链路

---

## 0. 总览

系统在 Web 创作工作区的「创建任务」表单里，通过 **任务来源** 切换两种建任务方式：

| 任务来源 | source_mode | 走完整规划生图 | 需要 | 产出 |
|---|---|---|---|---|
| **从文本生成** | （缺省 / 空） | ✅ 规划 → 原稿图 → 元素图 → 导出 | 长文 `content`（必填）+ 可选风格参考图 | 原稿图 / 元素图 / 可编辑 PPT / 高清+解说词 |
| **从已有原稿图继续** | `external_reference` | ❌ 跳过规划与原稿图生成，**从元素图阶段继续** | ≥1 张整页原稿图（PNG/JPG/WEBP） | 可编辑 PPT（或只登记原稿图） |

两条路最终汇聚到 **导出阶段（ppt_export）**，共用同一套「双轮闭环导出」：

```
原稿图 + 元素图 ──▶ 首轮 AI 文字脚本 ──▶ 脚本渲染预览 PPT ──▶ Office 真实导出 PNG
                                                              │
                                                              ▼
可编辑分层 PPTX ◀── 最终脚本执行 ◀── AI 回看修正文字/样式 ◀── 原稿图 + 真实导出图对比
```

---

## 1. 方式一：从文本生成

### 1.1 前端用户操作

在「创建任务」中选择 **从文本生成**（`SOURCE_MODES.PROMPT`），填写：

| 字段 | 表单参数 | 说明 |
|---|---|---|
| 任务内容 | `content` | **必填**，长文 / 大纲 / Brief，将拆成 N 页 |
| 页数 | `page_count` | 1 ~ `max_pages`（默认 10，未填取 `default_pages`=4） |
| 画幅 | `image_preset` | 如 `landscape_2k`(16:9 2048×1152) |
| 图像质量 | `image_quality` | `low / medium / high / auto` |
| 风格说明 | `style_notes` | 附加风格约束文本 |
| 风格参考图 | `style_images` | 可选，多图上传，预览后可增删 |
| 语言 | `language` | `zh` / `en` |
| 讲解词 | `narration_length` | `0`=无；`200~1000`字/页（>0 时启用） |
| 输出模式 | `job_target` | `editable_ppt`(可编辑元素) / `reference_only`(图片版 PPT) / `hd_narration`(高清图+解说词) |
| 工作流模式 | `workflow_mode` | `auto` / 分步规划（规划后暂停等确认） |
| 封面页 / 内容丰富度 | `include_cover_page`、`page_richness_*` | 规划增强选项 |

### 1.2 提交与任务登记

```
POST /api/jobs   (source_mode 缺省，走文本路径)
   │  jobs_api_service.py: api_create_job
   ├─ 校验 content 非空、page_count 在 [1, max_pages]
   ├─ 创建任务目录 output/<job_id>/
   │    ├─ style_refs/            ← 保存 style_images（无可复制上一个任务的）
   │    ├─ 01_reference_pages/
   │    └─ 02_elements_pages/
   ├─ build_job_state → state.json + jobs.sqlite3 建记录
   └─ JOB_EXECUTOR.submit(run_job_pipeline, …)   ← 异步后台执行
```

### 1.3 流水线五阶段（run_job_pipeline）

```
┌─ Stage 1  planning ────────────────────────────────────────────────
│  对话模型 build_content_plan(content, page_count, …)
│    → style_guide（风格指南）+ 每页 {title, summary, bullets,
│       layout_family, image_prompt, elements_prompt}
│   → 设计语法保证版式家族 ≥3 种、相邻页不重复
│   → 页面质量评估 evaluate_plan，总分 <0.7 自动重试（上限 page_evaluation_retry_count）
│   → 分步规划模式下暂停，等用户确认规划后继续
├─ Stage 2  reference_generation ────────────────────────────────────
│  逐页并发生成「带文字完整页面视觉稿」（stage1_concurrency）
│    → 01_reference_pages/page_NN_reference.png + prompt.txt
│   job_target = reference_only / hd_narration 时在此阶段后结束：
│     · reference_only → 导出 result.reference_only.pptx（原稿图拼 PPT）
│     · hd_narration   → 高清 JPG + 解说词 Word，打包 export/hd_narration.zip
├─ Stage 3  elements_generation ─────────────────────────────────────
│  逐页两步生图（stage2_concurrency）：
│    A. 先出「去文字背景图」  → 03_textless_background_pages/page_NN_textless_background.jpg
│    B. 再基于背景图出「纯元素图」→ 02_elements_pages/page_NN_elements.png
│    + 生成整本共用母版背景 → 04_master_background/page_01_master_background.jpg
│    （背景底色按 prompt 判定 light/dark，深色背景走黑底抠图）
└─ Stage 4  ppt_export ──────────────────────────────────────────────
   双轮闭环导出（详见 §3）→ 可编辑分层 PPTX
```

### 1.4 交付物

| job_target | 交付 |
|---|---|
| `editable_ppt`（默认） | 可编辑分层 PPTX（元素资源页 + 可编辑文本框页成对）+ bundle 缓存 |
| `reference_only` | 图片版 PPT（每页一张原稿高清单图） |
| `hd_narration` | `hd_narration.zip` = 高清 JPG 全套 + 每页解说词 Word |

---

## 2. 方式二：从已有原稿图继续

### 2.1 前端用户操作

在「创建任务」中选择 **从已有原稿图继续**（`SOURCE_MODES.EXTERNAL_REFERENCE`）：

1. **上传 1~N 张整页原稿图**（`reference_images`，支持 PNG/JPG/JPEG/WEBP，上限 `max_pages`）
   - 每张显示预览卡片，虚线加号框可继续追加；多图**按上传/追加顺序**生成多页任务
2. 配置参数：

| 字段 | 表单参数 | 说明 |
|---|---|---|
| 画幅 | `image_preset` | 目标页面尺寸，导入图先规范到该画幅 |
| 图片适配 | `external_reference_resize_mode` | `stretch` 拉伸填满 / `contain` 等比留白 / `cover` 等比裁切 |
| 图像质量 | `image_quality` | 影响后续元素图转换质量与耗时 |
| 只登记原稿图任务 | `external_reference_create_only` | 勾选 → 任务停在「原稿图完成」态，稍后从任务中心继续 |

### 2.2 API 与登记逻辑

```
POST /api/jobs   (source_mode = external_reference)
   │  jobs_api_service.py: _api_create_external_reference_job
   ├─ 校验：至少 1 张图；格式后缀合法；数量 ≤ max_pages
   ├─ 保存到 external_reference_uploads/
   └─ create_external_reference_job()   ← external_reference_job.py
       逐张处理：
         normalize_image_canvas(原图 → 01_reference_pages/page_NN_reference.png)
           · resize_mode=stretch/contain/cover 规范到 image_preset 画幅
           · 默认白底 flatten
       生成每页任务数据：
         · reference_prompt = “外部导入原稿图，跳过一阶段原稿图生成…”
         · elements_prompt  = build_elements_prompt()
         · 页面 title = 文件名 / 自定义 page_title
       状态标记：
         · planning            → completed（跳过模型规划）
         · reference_generation → completed（原稿图已登记）
```

### 2.3 分支走向

```
create_external_reference_job()
   │
   ├─ create_only = true ──▶ 状态 completed，停在 reference_generation
   │      产物：result.reference_only.pptx（原稿图拼 PPT）
   │      之后可从任务中心「继续生成可编辑元素」→ 走 Stage 3
   │
   └─ create_only = false ──▶ JOB_EXECUTOR.submit(run_job_pipeline)
           run_job_pipeline 检测到已有规划 + 原稿图，自动跳过 Stage 1/2
             │
             ├─ Stage 3  elements_generation（与文本方式相同）
             │    A. 去文字背景图 → 03_textless_background_pages/
             │    B. 纯元素图     → 02_elements_pages/
             │    + 母版背景     → 04_master_background/
             └─ Stage 4  ppt_export（与文本方式相同，双轮闭环）
                  → 可编辑分层 PPTX
```

> 注意：外部原稿图导入的 `job_target` 只允许 `reference_only`（登记态）或 `editable_ppt`（继续转换态），不支持 `hd_narration`。

---

## 3. 导出阶段：双轮闭环（两种方式共用）

入口：`run_job_pipeline → export_web_job_to_pptx → prepare_editable_delivery_bundle → generate_direct_project_text_script`

### 3.1 资产准备（prepare_direct_project_assets）

| 步骤 | 说明 |
|---|---|
| 元素图增强 | 透明度 / 边缘处理 |
| 抠图 / 透明化 | 白底黑底参数化（`alpha_threshold` 等），深色底走 `black_key_*` 参数 |
| 连通域分割 | 把整页元素图拆成独立视觉资源 |
| 文字占位检测 | `text_placeholders` 供首轮脚本定位文字位置 |

### 3.2 单页双轮文字脚本（_generate_direct_project_page_script）

```
① 首轮：原稿图 + 元素图 ──▶ AI 生成文字层布局脚本
        _generate_page_script_from_images(原稿图, 元素图, 文字占位)
        产出 page_script（文字框位置/字号/颜色/对齐）

② 验证：写入预览脚本 → 执行生成预览 PPT → PowerPoint 真实渲染首帧 PNG
        render_pptx_first_slide_to_png（office_render_available）
        · Office 真渲染不可用 → 跳过二轮，直接采用首轮脚本

③ 二轮：原稿图 + 真实导出图 ──▶ AI 回看修正文字位置与样式
        _revise_page_script_with_rendered_preview
        若修正结果与当前脚本相同 → 提前停止（保留当前）
        否则更新脚本与资产微调（asset_adjustments）

④ 循环 refine_rounds 次（默认 1 轮），逐页并行（page_concurrency）
```

### 3.3 整套装配

```
汇总所有 page_scripts → 生成 generated_text_layout.py
执行脚本 → 最终可编辑分层 PPTX
   · SEPARATE_LAYER_MODE：元素资源页 + 可编辑文本框页 成对分层
   · 写 editable_delivery.bundle.json（可缓存、可重新导出不同 layer_mode）
   · 可选「高清图 + 解说词」：generate_narrations_batch 批量生成 → export/hd_narration.zip
```

---

## 4. 两种方式对比速查

| 维度 | 从文本生成 | 从已有原稿图继续 |
|---|---|---|
| 前端入口 | 创建任务 → 从文本生成 | 创建任务 → 从已有原稿图继续 |
| 核心输入 | 长文 `content`（必填） | ≥1 张原稿图（必填） |
| 是否调用规划模型 | ✅ 拆页 + 风格指南 + 质量评估重试 | ❌ 跳过，直接按图建页 |
| 是否调用原稿图生图 | ✅ 逐页生成带文字原稿图 | ❌ 外部图登记为原稿图 |
| 是否调用元素图生图 | ✅ 去文字背景 + 纯元素图 | ✅ 相同 |
| 是否双轮闭环导出 | ✅ | ✅ |
| 多页来源 | 内容拆页 | 多图按上传顺序各成一页 |
| 画幅适配 | 按 image_preset 直接生成 | 外部图 normalize（拉伸/留白/裁切）到画幅 |
| 特有参数 | style_images / page_richness / workflow_mode | resize_mode / create_only / page_title |
| 中断续跑 | 全阶段断点续跑 | 同左；create_only 登记态可稍后续跑 |

---

## 5. 产物目录结构

```
output/<job_id>/
├── external_reference_uploads/      # 仅导入方式：原始上传图
├── style_refs/                      # 仅文本方式：风格参考图
├── 01_reference_pages/              # 原稿图（文本=生成；导入=规范化登记）
│   └── page_NN_reference.{png,prompt.txt}
├── 02_elements_pages/               # 去文字纯元素图
│   └── page_NN_elements.{png,prompt.txt}
├── 03_textless_background_pages/    # 去文字背景图
├── 04_master_background/            # 整本母版背景
├── 03_ppt_build/
│   ├── page_NN/{assets/, previews/}
│   ├── editable_delivery.bundle.json
│   └── generated_text_layout.py
├── export/{hd_narration.zip, hd_images.zip, narration.docx}
├── config.snapshot.json
├── job.json / state.json / status.json
├── project.generated.json
└── result.reference_only.pptx / result.editable.*.pptx
output/jobs.sqlite3                  # 全局任务清单
```

---

## 6. 关键源码指引

| 文件 | 作用 |
|---|---|
| `ppt_system/web/services/jobs_api_service.py` | `api_create_job` / `_api_create_external_reference_job`：两种方式的 API 入口与参数校验 |
| `ppt_system/web/services/external_reference_job.py` | 外部原稿图登记：画布规范、页数据构建、create_only 分支 |
| `ppt_system/web/services/job_pipeline_runner.py` | `run_job_pipeline`：五阶段主调度，两种方式在此汇合 |
| `ppt_system/generation/content_agent.py` | `build_content_plan`：文本方式规划拆页 |
| `ppt_system/generation/page_image_pipeline.py` | 原稿图/元素图并发调度（stage1/stage2） |
| `ppt_system/export/export_pipeline.py` | `export_web_job_to_pptx`：导出装配入口 |
| `ppt_system/export/direct_project_script.py` | `generate_direct_project_text_script`：双轮闭环主流程 |
| `ppt_system/export/direct_page_script.py` | 单页首轮 / 二轮脚本生成 |
| `ppt_system/export/ppt_calibration_renderer.py` | PowerPoint 真实渲染首帧（二轮回看的依据） |
| `ppt_system/image/splitter.py` | 连通域分割 |
| `web_ui/src/components/Workspace/CreationForm.jsx` | 前端任务来源切换与表单 |
