系统详细设计
项目:PPT 自动生成 Agent · 赛道一:Agent 开发实战赛 · 新规项目
配套文档:PRD v1.2(项目资料/需求与思路/02-需求文档/产品需求文档_PRD.md)、设计文档(项目资料/对外资料/设计文档.md)
版本:v0.4(2026-08-25 二次同步:UI 全语言收尾 + 网络配图管线;新增 6.6,更新 5.1/6.5/十章)
前版:v0.3(2026-08-25 状态同步:Sprint 2 对话修改落地、在线预览上线、LLM 零Key 接入;新增 4.7 预览设计)
前版:v0.2(2026-08-24 引擎切换改版:第5/6章改为 aura-ppt 方案,散点同步)
初版:v0.1(第1批 · 骨架,2026-08-17)
配套选型依据:项目资料/事前调查/引擎选型对比_ppt-master_vs_aura-ppt.md
一、总体架构与分层
1.1 分层架构图
1.2 模块职责
| 模块 |
目录 |
职责 |
| Web 前端 |
src/web/static/ |
4 页面(登录/工作台/历史/设置)+ 样式 + JS |
| Flask API |
src/web/app.py |
路由注册、Session 鉴权、请求校验、错误统一处理 |
| Agent 核心 |
src/agent/ |
perception / planning / action / memory 四子模块 + chat(对话修改)/ llm(LLM 客户端) |
| 引擎桥接 |
src/engine_bridge/ |
调用 aura-ppt CLI(渲染 / 保真验证)、预览图导出(COM);ppt-master 解析脚本已接入(upload.py),搜图待接 |
| 配置 |
config.py |
引擎路径、上传限制、数据库路径、DeepSeek API 等 |
| 数据层 |
src/db/ |
SQLite 连接管理、表结构 DDL |
1.3 关键设计约束
| 约束 |
说明 |
| 引擎路径可配置 |
config.AURA_ENGINE_PATH 指向项目内 aura-ppt 副本(渲染),config.PPT_MASTER_PATH 指向 ppt-master 副本(解析/搜图),不硬编码全局路径 |
| 引擎只经 CLI 调用 |
Agent 不 import 引擎内部模块,渲染统一走 engine.py --plan/--verify + subprocess |
| 生成异步化 |
PPT 生成耗时长,采用后台任务 + 前端轮询进度(对应 US-2.7a 进度提示、US-2.11 跨页面状态) |
| 状态机驱动 |
每个生成任务有任务 ID,状态迁移:pending → analyzing → planning → rendering → done / failed |
1.4 中日文切换设计
系统支持双语言,且拆分为两个相互独立的维度:
| 维度 |
含义 |
切换入口 |
存储 |
| UI 语言 |
界面文案(按钮/标签/提示)整体切换 |
顶栏语言下拉 + 设置页 |
localStorage(未登录)→ preferences(登录后同步) |
| 生成语言 |
生成的 PPT 内容与演讲备注的语言 |
工作台「生成配置」面板下拉 |
每次生成独立选择,默认取偏好值 |
多语言实现:
- 前端 i18n 字典:
src/web/static/lang/zh.json 与 ja.json,键值一一对应,支持动态切换无需刷新
- 引擎侧:生成语言=ja 时,Agent 感知层输出的源 Markdown、执行器产生的演讲备注全部用日文,字体栈换为 Meiryo(参照试跑项目 ai-basics-jp)
- 偏好默认值:
default_language 默认 zh,用户可改
语言洁癖约束:任一语言环境下界面与生成内容均保持单一语言,禁止中日文混排。
二、REST API 规范
2.1 通用约定
| 项 |
约定 |
| 基础路径 |
/api |
| 内容类型 |
请求/响应均为 application/json(文件上传除外) |
| 认证 |
除登录/注册外,所有接口需带 session cookie;未登录返回 401 |
| 响应结构 |
成功:{"code":0,"data":{...}};失败:{"code":<错误码>,"message":"中文提示"} |
| 错误码前缀 |
10xx 认证 / 20xx 生成 / 30xx 上传解析 / 40xx 历史 / 50xx 设置 / 60xx 引擎 |
2.2 错误码表
| 错误码 |
含义 |
前端提示文案 |
| 1001 |
用户名已存在 |
"用户名已被使用" |
| 1002 |
用户名或密码错误 |
"用户名或密码错误" |
| 1003 |
两次密码不一致 |
"两次输入的密码不一致" |
| 1004 |
未登录或会话过期 |
"请先登录" |
| 2001 |
内容字数不足 20 |
"内容至少需要 20 个字" |
| 2002 |
页数范围非法(min>max) |
"最少页数不能大于最多页数" |
| 2003 |
引擎繁忙 |
"引擎繁忙,请稍后重试" |
| 2004 |
生成失败(引擎侧) |
"生成失败,请重试" |
| 3001 |
不支持的文件类型 |
"不支持的文件类型" |
| 3002 |
文件超过 20MB |
"文件大小不能超过 20MB" |
| 3003 |
文件损坏无法读取 |
"文件损坏,无法读取" |
| 3004 |
解析内容为空 |
"文件内容为空" |
| 4001 |
历史记录不存在 |
"该记录不存在或已被删除" |
| 5001 |
原密码错误 |
"原密码不正确" |
| 6001 |
引擎内部错误 |
"引擎内部异常,请联系管理员" |
2.3 接口清单
Epic 1 · 认证
| # |
方法 |
路径 |
说明 |
对应故事 |
| 1 |
POST |
/api/register |
注册 |
US-1.1 |
| 2 |
POST |
/api/login |
登录 |
US-1.2 |
| 3 |
POST |
/api/logout |
退出登录 |
US-1.3 |
| 4 |
GET |
/api/me |
获取当前用户信息 |
US-1.2 |
Epic 2 · PPT 生成
| # |
方法 |
路径 |
说明 |
对应故事 |
| 5 |
POST |
/api/generate |
触发生成,返回任务 ID |
US-2.7a |
| 6 |
GET |
/api/generate/<task_id>/status |
查询生成进度 |
US-2.7a / US-2.11 |
| 7 |
GET |
/api/generate/<task_id>/result |
生成完成后取结果 |
US-2.7b |
| 8 |
POST |
/api/title/suggest |
智能生成标题 |
US-2.4 |
| 9 |
GET |
/api/files/<record_id>/download |
下载 PPTX |
US-2.8 |
| 10 |
GET |
/api/files/<record_id>/preview |
在线预览页数据(PNG 按版本缓存) |
US-2.9 |
预览页图实际加载走 GET /api/preview-img/<record_id>/<name>(单页 PNG,归属校验 + 文件名白名单,见 4.7)。
Epic 3 · 上传解析
| # |
方法 |
路径 |
说明 |
对应故事 |
| 11 |
POST |
/api/upload |
上传文档(multipart) |
US-2.3a |
| 12 |
POST |
/api/parse |
解析上传文件为文本 |
US-2.3b |
Epic 4 · 对话修改
| # |
方法 |
路径 |
说明 |
对应故事 |
| 13 |
POST |
/api/chat |
发送修改指令 |
US-3.1 |
| 14 |
GET |
/api/chat/<record_id>/messages |
获取本轮对话记录 |
US-3.2 |
Epic 5 · 历史记录
| # |
方法 |
路径 |
说明 |
对应故事 |
| 15 |
GET |
/api/records |
历史列表(搜索/筛选/分页) |
US-4.1 / 4.2 / 4.3 |
| 16 |
GET |
/api/records/<id> |
历史详情(含版本) |
US-4.4 |
| 17 |
DELETE |
/api/records/<id> |
删除记录 |
US-4.6 |
Epic 6 · 个人设置
| # |
方法 |
路径 |
说明 |
对应故事 |
| 18 |
PUT |
/api/settings/username |
修改用户名 |
US-5.1 |
| 19 |
PUT |
/api/settings/password |
修改密码 |
US-5.2 |
| 20 |
PUT |
/api/settings/preferences |
保存生成偏好 |
US-5.3 |
| 21 |
GET |
/api/settings |
获取设置与偏好 |
US-5.1 / 5.3 |
2.4 关键接口详细定义
POST /api/generate
请求体:
成功响应:
状态迁移(US-2.7a 进度提示映射):
| 状态 |
前端提示 |
对应引擎阶段 |
analyzing |
"正在分析内容…" |
源内容处理 / 策略师分析 |
planning |
"正在规划结构…" |
策略师八大确认解析 |
rendering |
"正在排版渲染…" |
执行器 SVG 逐页生成 + 导出 |
done |
生成完成 |
导出完成 |
failed |
按错误码提示 |
任一环节失败 |
GET /api/generate/<task_id>/status
GET /api/files/<record_id>/download
Content-Disposition: attachment; filename="标题_20260817_1015.pptx",返回二进制流。
三、SQLite 数据库设计
3.1 ER 概览
3.2 表结构
users(用户表)
| 字段 |
类型 |
约束 |
说明 |
| id |
INTEGER |
PRIMARY KEY AUTOINCREMENT |
主键 |
| username |
TEXT |
UNIQUE NOT NULL |
用户名 |
| password_hash |
TEXT |
NOT NULL |
bcrypt 哈希,不存明文 |
| created_at |
TEXT |
NOT NULL |
创建时间(ISO8601) |
preferences(偏好表)
| 字段 |
类型 |
约束 |
说明 |
| id |
INTEGER |
PRIMARY KEY AUTOINCREMENT |
主键 |
| user_id |
INTEGER |
NOT NULL, FOREIGN KEY→users.id |
所属用户 |
| default_scene |
TEXT |
DEFAULT 'training' |
默认场景 |
| default_color |
TEXT |
DEFAULT 'blue' |
默认配色 |
| default_language |
TEXT |
DEFAULT 'zh' |
默认生成语言(zh/ja) |
| default_canvas |
TEXT |
DEFAULT 'ppt169' |
默认画布(ppt169/ppt43) |
| default_image_strategy |
TEXT |
DEFAULT 'web' |
默认配图策略(web/ai/off) |
| default_page_min |
INTEGER |
DEFAULT 10 |
默认页数下限 |
| default_page_max |
INTEGER |
DEFAULT 15 |
默认页数上限 |
ppt_records(PPT 生成记录表)
| 字段 |
类型 |
约束 |
说明 |
| id |
INTEGER |
PRIMARY KEY AUTOINCREMENT |
主键 |
| user_id |
INTEGER |
NOT NULL, FOREIGN KEY→users.id |
所属用户(索引) |
| title |
TEXT |
NOT NULL |
PPT 标题 |
| content |
TEXT |
NOT NULL |
用户输入的源内容 |
| scene |
TEXT |
NOT NULL |
report / training |
| language |
TEXT |
NOT NULL DEFAULT 'zh' |
生成语言(zh/ja),历史筛选依据 |
| color_scheme |
TEXT |
NOT NULL |
blue/green/purple/orange/gray |
| page_min |
INTEGER |
NOT NULL |
页数下限 |
| page_max |
INTEGER |
NOT NULL |
页数上限 |
| status |
TEXT |
NOT NULL DEFAULT 'done' |
生成状态 |
| file_size |
INTEGER |
NULL |
PPTX 文件大小(字节) |
| page_count |
INTEGER |
NULL |
实际生成页数 |
| generate_duration |
INTEGER |
NULL |
生成耗时(秒) |
| created_at |
TEXT |
NOT NULL |
生成时间(列表倒序排序依据) |
versions(版本表,对应 US-4.4 两版本策略)
| 字段 |
类型 |
约束 |
说明 |
| id |
INTEGER |
PRIMARY KEY AUTOINCREMENT |
主键 |
| record_id |
INTEGER |
NOT NULL, FOREIGN KEY→ppt_records.id |
所属记录 |
| version_no |
INTEGER |
NOT NULL |
版本号(1=第一版,2=修改后) |
| file_path |
TEXT |
NOT NULL |
PPTX 文件相对路径 |
| svg_dir |
TEXT |
NULL |
SVG 源目录相对路径 |
| change_note |
TEXT |
NULL |
本次修改说明(对话修改时记录) |
| created_at |
TEXT |
NOT NULL |
版本生成时间 |
两版本策略:当前版本 + 上一版本(决策日志 2026-07-20)。生成新版本时,旧"上一版"删除,原"当前版"降为"上一版"。
chat_messages(对话消息表)
| 字段 |
类型 |
约束 |
说明 |
| id |
INTEGER |
PRIMARY KEY AUTOINCREMENT |
主键 |
| record_id |
INTEGER |
NOT NULL, FOREIGN KEY→ppt_records.id |
关联记录 |
| role |
TEXT |
NOT NULL |
user / assistant |
| content |
TEXT |
NOT NULL |
消息内容 |
| created_at |
TEXT |
NOT NULL |
时间戳 |
3.3 索引
| 表 |
索引 |
用途 |
| users |
UNIQUE (username) |
登录查询、注册唯一性 |
| ppt_records |
(user_id, created_at DESC) |
历史列表按时间倒序 |
| ppt_records |
(user_id, scene) |
场景筛选(US-4.3) |
| versions |
(record_id) |
版本回查(US-4.4) |
| chat_messages |
(record_id, created_at) |
对话历史按时间顺序 |
3.4 SQLite 配置
四、Agent 核心模块设计
对应设计文档「感知→规划→行动→记忆」四层架构,每个模块对应一个 Python 子包。
4.1 模块划分与文件结构
4.2 感知层(perception.py)
| 方法 |
输入 |
输出 |
职责 |
parse_input(title, content) |
标题 + 正文 |
结构化内容对象 |
清洗文本、截断超长、提取行数/字数 |
resolve_config(payload, user_id) |
用户请求 |
完整生成配置 |
合并请求参数 + 用户偏好(未显式提供的项用偏好默认值) |
detect_lang_override() |
— |
语言参数 |
生成语言显式传参,否则取偏好 default_language |
校验规则(对齐 US-2.2 / US-2.6):内容 ≥ 20 字、页数 min ≤ max,不满足回传相应错误码(2001/2002)。
4.3 规划层(planning.py)
职责:把用户配置映射为引擎可执行的方案,是"包装引擎"的核心。
| 方法 |
职责 |
build_plan(cfg) |
配置 + 内容 → plan.json(Markdown 标题切块、页数预算合并/拆分、五色板/日式规格选择,详见第五章) |
4.4 行动层(action.py)
职责:编排生成任务,管理状态机,调用引擎。
4.5 记忆层(memory.py)
| 方法 |
职责 |
create_record(...) / list_records(...) |
历史记录增查(含搜索/筛选/分页) |
save_version(record_id, file_path, change_note) |
两版本策略写盘 |
load_history(record_id) |
版本回查(当前+上一版) |
record_chat(record_id, role, content) |
对话消息落库 |
read_preferences(user_id) / save_preferences(...) |
偏好读写 |
两版本策略规则(决策日志 7-20):新版本生成时,删除旧"上一版",原"当前版"降级为"上一版",新文件成为"当前版"。
4.6 对话修改流程(chat.py,Sprint 2 已实现)
| 意图类型 |
指令示例(中/日) |
动作 |
| change_color |
换成绿色 / カラーを緑に変更 |
切换 corp-* 设计系统重渲(ja 固定 report-jp,返回不支持提示) |
| change_title |
把标题改成XX / タイトルを「XX」に変更 |
更新 plan.title + 封面页 + ppt_records.title |
| edit_page |
第2页把A改成B / 第3页删除"xx" / 第2页添加"yy" |
定位 slides[n] 增删改要点 |
| unknown |
其余 |
返回帮助文案,不重渲染 |
实现说明:设计原则为"只重新生成受影响内容";aura-ppt 引擎全量重渲仅数秒,等效满足体验目标,且保证整册风格一致性(如换色必须全册生效)。plan.json 是唯一演进基准(见 6.3)。
4.7 在线预览设计(2026-08-25 上线)
| 设计点 |
说明 |
| 渲染方式 |
PowerPoint COM 自动化导出(本机 Office,WPS 兜底),零额外服务依赖 |
| 缓存策略 |
按版本缓存 PNG,同版本二次打开零等待;新版本自动增量导出 |
| 安全 |
两路由均校验 record 归属当前用户;文件名白名单(Slide.PNG),防路径穿越 |
| 前端 |
工作台结果卡片「预览」按钮弹出翻页弹层,默认展示对话修改后的最新版本 |
五、Agent 参数映射规则
2026-08-24 引擎切换后改版:原「八大确认自动应答」方案废弃,改为 用户配置 → aura-ppt plan.json 的确定性映射。规划层不再模拟人工确认,直接产出引擎可执行的结构化页面规划。
5.1 配置 → plan.json 映射总表
| 用户配置 |
plan.json 落点 |
映射规则 |
| title / content |
title + slides 结构 |
content 按 Markdown 标题切块分页(见 5.3) |
| language=ja |
design: report-jp |
日语固定走日式报告规格(法人蓝 #0B3D91,与本部长报告会母版对齐) |
| language=zh + color_scheme |
design: corp-* |
五色板设计系统(见 5.2),默认 corp-blue |
| canvas |
画布尺寸 |
当前仅支持 ppt169(16:9);ppt43 自动回退并写入任务告警(引擎待验证项) |
| page_min ~ page_max |
slides 数量预算 |
扣除封面/目次/结尾 3 页后,对内容块做合并/拆分(见 5.3) |
| scene |
ppt_records 落库字段 |
v1 分页算法与场景无关,场景值用于历史筛选,Sprint 2 增强为骨架模板 |
| image_strategy |
plan.slides[].image |
web=内容页配图(见 6.6,失败降级无图);ai/off=落库字段,暂不配图 |
5.2 五色板设计系统(对应 US-2.5)
在引擎 DESIGN_SYSTEMS 注册表扩展(继承 business-report 浅色骨架,覆写颜色令牌):
| 方案名 |
design 键 |
主色 |
辅色 |
卡片底 |
说明 |
| 商务蓝(默认) |
corp-blue |
#1565C0 |
#2196F3 |
#E3F2FD |
产品默认 |
| 清新绿 |
corp-green |
#2E7D32 |
#34A853 |
#E8F5E9 |
|
| 科技紫 |
corp-purple |
#5B21B6 |
#7C3AED |
#EDE9FE |
|
| 活力橙 |
corp-orange |
#D97706 |
#F59E0B |
#FEF3C7 |
|
| 深灰 |
corp-gray |
#374151 |
#6B7280 |
#F3F4F6 |
图表灰阶+蓝红点睛 |
日语生成走 report-jp(#0B3D91/#1976D2),即公司确认的强调色 R11 G61 B145 / R25 G118 B210。
5.3 内容分页算法(planning.build_plan)
- 无标题块回退标题:中文「要点 n」/日文「ポイント n」
- 目次条目即各 content 页标题;语言文案包内置 zh/ja 两套(目录/致谢页等)
5.4 公司母版继承策略(--template 模式)
| 配置 |
默认 |
说明 |
COMPANY_TEMPLATE |
engine/aura-ppt/assets/公司模板.pptx |
项目资产副本(技能原版只读) |
COMPANY_TEMPLATE_MODE |
ja |
always=全部用模板 / ja=仅日语生成用 / off=不用 |
| 生效行为 |
— |
继承母版背景/Logo/页脚,以「白紙」版式建页,引擎元素叠加;页面尺寸随母版(10.83×7.5in) |
5.5 语言映射
| 维度 |
zh |
ja |
| design |
corp-{color} |
report-jp(固定) |
| 回退标题 |
要点 n |
ポイント n |
| 目录/结尾 |
目录 / 谢谢聆听 |
目次 / ご清聴ありがとうございました |
| 续页标记 |
(续) |
(続き) |
5.6 LLM 智能规划模式(2026-08-25 接入,08-26 改版为无降级)
后端:默认复用 opencode serve(opencode serve --port 4096,零 Key,模型 mimo-v2.5-free 经基准选定);预留 OpenAI 兼容接口(DeepSeek 等,配 Key 即切)。配置项:LLM_BACKEND / OPENCODE_SERVE / OPENCODE_MODEL / OPENAI_API_* / PLAN_CHUNK_CHARS / PLAN_MAX_CHUNKS。
产品决策(2026-08-26):取消规则降级——要么产出总结版,要么明确报生成失败(含具体原因),绝不静默产出照搬版。规划失败抛 PlanningError → 任务 failed → 前端 toast 透传原因。
能力与流程:
| 环节 |
实现 |
失败处理 |
| 长文档两级规划 |
>6000 字先分段通读(Map:每段提炼小节摘要+关键数据)→ 汇总产出大纲(Reduce);全文覆盖,不再只读前3000字 |
单段调用重试2次,仍失败报错 |
| 短文档直通 |
≤6000 字直接出大纲 |
同上 |
| 页数硬约束 |
_validate_slides 裁剪保证最终页数不超上限;每轮尝试均为 LLM 规划,共两轮 |
两轮均败→任务失败 |
| 智能标题 |
/api/title/suggest 返回 3 个候选 |
首行截断 |
| 对话意图解析 |
parse_intent_llm + 封面替换规范化为改标题;规则句式兜底 |
返回帮助文案 |
| 数字保真 |
提示词约束 → 数字消毒器 → 引擎 --verify 门禁 |
保真不过→下一轮重新规划→仍败则报错 |
质量保障:LLM 产出经 _validate_slides 严格校验(类型白名单/长度截断/首尾页规范/页数硬上限)+ _sanitize_fidelity 数字消毒;引擎 --verify 内容保真为最终门禁。
六、aura-ppt 集成方式
2026-08-24 选型切换(对比依据:项目资料/事前调查/引擎选型对比_ppt-master_vs_aura-ppt.md)。渲染出口统一为 aura-ppt;ppt-master 降级为辅助引擎,仅复用其文档解析(source_to_md)与网络搜图(image_search)独立脚本。
6.1 渲染调用链(action.run_generation)
| 步骤 |
操作 |
实现 |
状态机 |
| ① 规划 |
GenerateConfig → plan dict |
planning.build_plan(cfg)(第五章算法) |
planning |
| ② 写盘 |
projects/<slug>_<ts>/ 建 sources/source.md + plan.json |
action 直接写文件 |
planning |
| ③ 渲染 |
engine.py --plan plan.json --output out.pptx [--template 公司模板.pptx] |
bridge.render_plan() subprocess |
rendering |
| ④ 验证 |
engine.py --verify out.pptx --plan plan.json |
bridge.verify_output(),失败重试 1 次 |
rendering |
| ⑤ 落库 |
ppt_records + versions(version_no=1) |
memory.save_generated_record |
done |
6.2 调用实现要点
| 要点 |
说明 |
| CLI 调用 |
subprocess.run([python, engine.py, ...], cwd=AURA_ENGINE_PATH),不 import 引擎内部模块 |
| 编码 |
子进程强制 PYTHONIOENCODING=utf-8 语义(bridge 以 utf-8 解码),规避 GBK 控制台报错 |
| 成功判据 |
渲染:退出码 0 且输出文件存在;验证:stdout 含「内容保真验证通过」且无「保真失败」 |
| 失败处理 |
EngineError → 任务 failed(错误码 2004);保真失败重试 1 次仍失败即终止 |
| 并发控制 |
进程内信号量(MAX_CONCURRENT_GENERATION),占满返回 2003 引擎繁忙 |
| 超时 |
渲染 600s / 验证 300s,超时抛 EngineError |
| 模板模式 |
日语生成默认继承公司母版(5.4);模板模式页面尺寸随母版 |
6.3 生成目录结构
plan.json 即「执行合同」:下载、预览、对话修改均以它为基准做增量演进(Sprint 2 局部重渲染)。
6.4 双引擎分工与配置
| 引擎 |
角色 |
路径配置 |
当前接入点 |
| aura-ppt |
主渲染引擎 |
AURA_ENGINE_PATH / AURA_ENGINE_SCRIPT |
bridge.render_plan / verify_output |
| ppt-master |
辅助:文档解析 + 网络搜图 |
PPT_MASTER_PATH |
文档解析已接入(agent/upload.py 调 source_to_md 五脚本);配图(image_search)待接 |
6.5 上传解析链路(2026-08-25 落地)
image_strategy=web → action 挂载 imaging.attach_images(plan.slides, project_dir)
→ 取前 MAX_IMAGE_SLIDES(4) 个内容页,以页面标题为关键词
→ IMAGE_SEARCH_MODE:
web = subprocess 调 ppt-master scripts/image_search.py
(openverse/wikimedia 零配置;pexels/pixabay 配 Key 即启用)
test = 本地样例图通道(IMAGE_SEARCH_TEST_DIR,e2e 确定性)
off = 禁用
→ 成图落 projects//images/slide_x.jpg,路径写入 plan.slides[].image 并随 plan.json 落盘
→ aura-ppt 渲染:content 页左文右图(文本区收窄 58%,图片等比缩放/垂直居中/细边框)
容错:单页失败仅记任务告警,全部失败降级为无图版式;verify 保真检查跳过 image 键。
现状:本机网络 openverse/wikimedia 不可达(超时/重置),管线与降级已验证,
真实搜图待更换网络环境或配置 pexels/pixabay Key 即自动启用。
6.5 引擎扩展点(已落地与待移植)
| 项 |
状态 |
| 五色板设计系统注册(corp-*) |
✅ 已落地(engine.py DESIGN_SYSTEMS) |
| 公司模板 assets 副本 |
✅ 已拷入 engine/aura-ppt/assets/ |
| KPI 卡片 / 数据源脚注 / 阴影开关 / 精选图标 |
⏳ 移植第一批(见选型对比文档第五章) |
| 幻灯片插图片(content 页右图布局) |
✅ 已落地(_place_image,见 6.6) |
| 4:3 画布 |
⏳ 待试跑验证后实现 |
| 动画 |
✕ 放弃(python-pptx 限制) |
七、异常与错误码体系
对齐 PRD 4.3「错误提示以中文展示,不显示原始异常栈」。前端直接展示 message 字段,后端日志记录完整堆栈。
7.1 错误码全景表
| 错误码 |
触发场景 |
后端处理 |
前端提示文案 |
| 1001 |
注册用户名已存在 |
唯一索引冲突捕获 |
用户名已被使用 |
| 1002 |
登录用户名或密码错误 |
哈希比对失败 |
用户名或密码错误 |
| 1003 |
注册两次密码不一致 |
请求参数校验 |
两次输入的密码不一致 |
| 1004 |
未登录访问受限接口 |
Session 校验拦截 |
请先登录 |
| 2001 |
生成内容不足 20 字 |
校验拦截 |
内容至少需要 20 个字 |
| 2002 |
页数 min > max |
校验拦截 |
最少页数不能大于最多页数 |
| 2003 |
引擎繁忙(并发上限) |
任务队列拒绝 |
引擎繁忙,请稍后重试 |
| 2004 |
生成失败(引擎已重试) |
任务标记 failed |
生成失败,请重试 |
| 2005 |
生成中断(服务重启/超时) |
任务标记 failed |
生成中断,请重新生成 |
| 3001 |
上传文件类型不在白名单 |
扩展名校验拦截 |
不支持的文件类型 |
| 3002 |
上传文件超过 20MB |
大小校验拦截 |
文件大小不能超过 20MB |
| 3003 |
文档解析失败(损坏) |
解析器异常捕获 |
文件损坏,无法读取 |
| 3004 |
解析结果为空 |
解析后空文本检测 |
文件内容为空 |
| 3005 |
文件上传失败 |
存储异常捕获 |
上传失败,请重试 |
| 4001 |
历史记录不存在/已被删除 |
查询无结果 |
该记录不存在或已被删除 |
| 4002 |
下载文件不存在 |
文件系统检查 |
文件已丢失,请重新生成 |
| 5001 |
修改密码原密码错误 |
哈希比对失败 |
原密码不正确 |
| 5002 |
用户名/密码格式非法 |
正则校验 |
用户名 3-20 位,密码至少 6 位 |
| 6001 |
引擎进程非零退出 |
subprocess stderr 解析 |
引擎内部异常,请联系管理员 |
| 6002 |
引擎配置文件缺失 |
启动自检 |
系统配置异常,请稍后重试 |
7.2 统一错误响应结构
detail 仅后端调试日志输出,永不返回前端。
7.3 引擎失败分类与重试策略
| 分类 |
判定 |
动作 |
前端码 |
| 可恢复(网络/限速/图片源超时) |
退出码非零 + stderr 匹配网络关键字 |
重试 1 次(指数退避 2s→4s) |
重试成功继续,失败 2004 |
| 不可恢复(脚本缺参/SVG 质检 error 无法修复) |
退出码非零 + 逻辑错误 |
直接失败 |
2004 / 6001 |
| 资源性(同时任务超限) |
任务队列满载 |
拒绝入队 |
2003 |
| 中断性(服务重启) |
任务表 status=processing 且服务重启 |
标记 failed |
2005 |
7.4 前端错误处理约定
| 场景 |
行为 |
| 字段校验错误 |
Toast 提示对应文案,不清空用户输入 |
| 接口 401 |
跳转登录页 |
| 联网失败(fetch 异常) |
提示"网络异常,请检查网络后重试",保留页面状态 |
| 生成中失败 |
结果卡片红色区域展示错误文案 +「重新生成」按钮(US-2.7b) |
八、安全设计
对齐 PRD 4.2。本项目为内网自用系统,采用适度防护,不做过度设计。
| 维度 |
措施 |
实现 |
| 密码存储 |
bcrypt 哈希,不存明文 |
werkzeug.security.generate_password_hash,成本因子 12 |
| 会话管理 |
Flask Session + 签名 Cookie |
SECRET_KEY 存于 config.SECRET_KEY(环境变量注入,不进仓库) |
| CSRF 防护 |
同源校验 |
所有写接口校验 Origin/Referer 头 + Session 内 CSRF Token |
| 文件上传 |
扩展名白名单 + 大小限制 |
8 种格式白名单,≤20MB,存储到非 web 根目录 |
| SQL 注入防护 |
参数化查询 |
全部 SQL 用 ? 占位符,禁止字符串拼接 |
| 路径穿越 |
下载路径校验 |
record_id 反查数据库后拼接相对路径,禁止直接拼接用户输入文件名 |
| 日志脱敏 |
不记录密码/令牌 |
统一日志过滤器屏蔽敏感字段 |
| 内网安全 |
仅监听 127.0.0.1 |
Flask 运行绑定本机回环地址,不开放公网 |
九、目录结构与部署
9.1 项目目录树
9.2 运行方式
9.3 配置项(config.py)
| 配置 |
默认值 |
说明 |
AURA_ENGINE_PATH |
engine/aura-ppt/ |
主渲染引擎目录(可配置) |
PPT_MASTER_PATH |
engine/ppt-master/ |
辅助引擎目录(解析/搜图) |
COMPANY_TEMPLATE |
engine/aura-ppt/assets/公司模板.pptx |
公司母版(--template 模式) |
COMPANY_TEMPLATE_MODE |
ja |
模板模式策略:always/ja/off |
PROJECTS_PATH |
src/web/data/projects/ |
生成任务输出根目录 |
DB_PATH |
src/web/data/ppt.db |
SQLite 文件路径 |
SECRET_KEY |
环境变量 |
Flask Session 密钥 |
MAX_UPLOAD_MB |
20 |
上传大小上限 |
ALLOWED_EXT |
8 种格式 |
扩展名白名单 |
ALLOWED_SCENE |
report/training |
场景枚举 |
ALLOWED_COLOR |
blue/green/purple/orange/gray |
配色枚举 |
ALLOWED_LANG |
zh/ja |
生成语言枚举 |
ALLOWED_CANVAS |
ppt169/ppt43 |
画布枚举 |
ALLOWED_IMAGE |
web/ai/off |
配图策略枚举 |
LLM_BACKEND |
opencode |
大模型后端:opencode(免费零 Key)/ openai(兼容接口) |
OPENCODE_SERVE |
http://127.0.0.1:4096 |
opencode serve 地址(--port 4096 常驻) |
OPENCODE_MODEL |
opencode/mimo-v2.5-free |
免费模型(三模型基准选定,44s/大纲) |
OPENAI_API_BASE / OPENAI_API_KEY / OPENAI_MODEL |
环境变量 |
DeepSeek 等 OpenAI 兼容后端切换入口(配 Key 即切) |
LLM_TIMEOUT |
180 |
LLM 请求超时(秒) |
十、里程碑映射
对齐 PRD「五、用户故事与开发阶段对应」的 3 个 Sprint,补充到接口/数据表/模块粒度。
10.1 Sprint 1(MVP:登录→生成→下载)✅ 已完成(2026-08-24)
目标:跑通"登录 → 输入文字 → 配置 → 生成 → 下载"完整链路。
| 内容 |
明细 |
| 接口 |
1-9 号(认证 4 + 生成 6) |
| 数据表 |
users + preferences + ppt_records + versions(versions 先建表,Sprint 2 启用回退) |
| Agent 模块 |
perception(基础解析)+ action(生成编排)+ orchestrator(生成流程) |
| 引擎集成 |
7 步全流程 + branding 模板(blue)+ 质检门禁 |
| 语言 |
zh / ja 生成 + UI zh/ja 双语言包(UI 语言切换第一期启用) |
10.2 Sprint 2(对话修改 + 历史闭环)✅ 已完成(2026-08-25)
目标:生成→修改→回退 完整闭环 + 在线预览。
| 内容 |
明细 |
| 接口 |
10、13-17 号(预览 + 对话 + 历史 CRUD) |
| 数据表 |
chat_messages 启用、versions 回退逻辑启用 |
| Agent 模块 |
planning(修改意图解析)+ memory(版本/对话读写) |
| 引擎集成 |
只重生成受影响页面(局部渲染) |
| 前端 |
对话弹窗接入真实轮询 + 历史两版本展示 |
完成情况与偏差:接口 13/14 号、chat_messages 落库、两版本回退均已落地,e2e_chat 16 项断言全绿;「只重生成受影响页面」调整为 plan.json 变更 + aura 全量重渲(秒级,等效满足体验且保证整册风格一致,见 4.6);在线预览以 COM 导出 PNG 实现(见 4.7);智能标题(原 Sprint 3 内容)随 LLM 接入提前完成。
10.3 Sprint 3(体验完善)
目标:上传解析 + 智能标题 + 偏好 + UI 全语言。
| 内容 |
明细 |
| 接口 |
11-12、18-21 号(上传解析 + 设置) |
| Agent 模块 |
memory 偏好读写、upload 解析链路 |
| 引擎集成 |
source_to_md/*.py 8 格式转换 + 智能标题 DeepSeek 调用 |
| 前端 |
设置页生成偏好绑定 + 历史页语言筛选(预留,本期可选) |
进度:上传解析已提前落地(2026-08-25,见 6.5,e2e_upload 21 项断言全绿);智能标题已于 LLM 接入时完成;设置偏好与历史语言筛选已落地(e2e_settings 18 项断言全绿);UI 全语言四页收尾完成(login/history 补 i18n 与切换入口);网络配图管线落地(见 6.6,e2e_image 9 项断言全绿)。Sprint 3 全部用户故事已覆盖,余一项环境依赖:真实搜图源需换网络或配 Key。
10.4 里程碑与成果物对齐
| 里程碑 |
关联成果物 |
验收口径 |
| Sprint 1 完成 |
03 源码(主体) |
US-1.1~2.8 通过测试顾问验收 |
| Sprint 2 完成 |
03 源码(完整)+ 04 实验报告起点 |
修改/回退闭环可演示 |
| Sprint 3 完成 |
04 实验报告 |
全部 23 条用户故事覆盖 |
| 全量定稿 |
05 AI使用日志 + 06 演示视频 |
整理 8 月日志 + 录制完整流程 |
全 10 章完成。v0.3 已同步 Sprint 2 落地状态(对话修改 / 在线预览 / LLM 零Key 接入),e2e_web、e2e_chat、e2e_llm 三套测试全绿。