Files
PlantAI-rag-new/docs/pr-reports/2026-10-14-p5-ppt-assistant.md
T
2026-10-15 19:35:51 +08:00

9.0 KiB
Raw Blame History

P5 科研汇报助手 — PR 报告(2026-10-14,v4 更新 2026-10-15)

概要

新增「科研汇报助手」(P5):论文 PDF/粘贴文本 → vstore 解析 → map-reduce LLM 大纲 (5 场景 × 4 时长 × 14 版式,逐条证据可溯)→ 逐页编辑 → python-pptx 本地生成 16:9 PPTX 初稿(论文真图卡片化嵌入、分隔页主副标题、讲者备注携带证据引用)。 全程只新增 review_service/ 内代码 + BFF 既有 REVIEW_ENABLED 条件反代, 禁区(RAG 核心、既有服务、前端 router/db)零改动。

v4 迭代(2026-10-15):① 副标题风格数改为动态读取 GET /ppt/styles(缺数据回落 「多风格·图文混排」)② 章节分隔页加副标题(prompt 强制 subtitle、渲染 40pt 主标题 + 20pt muted 副标题 + 底部 accent 装饰线、编辑器可改)③ 论文白底原图与页面底色融合 (surface_2 圆角卡片 + 图注 + 宽/高上限 + 单图页居中留白)。

修改内容

后端(review_service/)

类别 文件 说明
改 app/config.py +ppt_jobs_dir / ppt_styles_dir 及 abs 属性(+14 行)
改 app/main.py 导入 ppt 路由、lifespan ppt_ensure_table()、挂载(+8 行)
改 tooling/requirements.lock +3 行:pillow==12.3.0 / python-pptx==1.0.2 / xlsxwriter==3.2.9(三者均已实装于统一 venv)
改 .gitignore +9 行:ppt_jobs/ 运行数据、prewarm.log、data/compile_jobs/、scripts/、data/review.db
新 app/routers/ppt.py(317 行) 9 端点:GET /styles、POST /jobs、POST /jobs/pdf、GET/PATCH /jobs/{id}、POST /jobs/{id}/build、GET /jobs/{id}/pptx、GET /jobs/{id}/preview/{page}、DELETE /jobs/{id}
新 app/services/ppt_outline.py(917 行) map-reduce 大纲核心(索引/配额/重验/裁剪/膨胀回修/分隔页 subtitle 规则)
新 app/services/ppt_build.py(1176 行) python-pptx 生成器(14 版式 token、字体栈、真图卡片容器、分隔页主副标题、讲者备注)
新 app/services/ppt_figure_index.py(264 行) 论文真图索引(para/图号 → 图片落盘与状态)
新 app/services/ppt_preview.py(230 行) 逐页 PNG 预览(供面板缩略图,失败不阻断)
新 app/services/ppt_store.py(155 行) ppt_jobs SQLite 持久化(约定 DDL 逐字实现)
新 data/ppt_styles/*.json(14 个) 版式 token 源码资产(随 git 走,GET /styles 的唯一数据源)
新 tests/test_ppt_*.py(6 个 / 102 例) outline / build / figure_index / preview / router / store

前端(ui/ + tests/)

类别 文件 说明
改 ui/src/api/review.js(+50 行) PPT API 段 + pptStyles()
改 ui/src/stores/edu.js(+147 行) ppt 状态块 + actions + pptLoadStyles + SECTIONS 增列
改 ui/src/components/edu/EduSideNav.vue / EduWorkspace.vue 菜单项 + PptPanel 注册(各 +2 行)
新 ui/src/components/edu/panels/PptPanel.vue(578 行) 生成表单 + 编辑器(动态风格数、分隔页副标题输入、逐页预览)
新 ui/src/components/edu/panels/ppt-styles.css(40 行) 面板样式
新 ui/src/assets/ppt-style-cards/*.png(14 个,约 21KB/个) 版式卡面截图
新 tests/frontend/unit/edu/ppt.panel.test.js(12 例)/ ppt.store.test.js(7 例) P5 前端单测
改 tests/frontend/unit/b2/components.test.js、b3/benchpanel.test.js、bioflow/benchpanel.bioflow.test.js、tests/e2e/bench.spec.js 预存失败清零:① tab 文案「提取任务」→「上传文献」(对齐 51532a3)② 模式 pill 断言改为「已随 43a7c6c 移除」

依赖偏差声明:python-pptx==1.0.2(PyPI 最高 1.0.2;需求中 1.1.2 实为 python-docx 版本,系记混,已在实现时更正)。xlsxwriter==3.2.9 当前无代码直接引用, 属统一 venv pip freeze 的真实记录,一并同步锁文件——合并前仍需人工确认这 3 行锁变更。

DDL(与约定逐字一致):

ppt_jobs(id, status /*outline_ready|building|done|error*/, source_kind, filename,
         raw_text, scenario, minutes, style_id, pages_json, pptx_path,
         warnings_json, created_at, updated_at)

API 前缀 /api/review/ppt(9 端点;业务错误一律 200 信封 {ok:false, error:{code,message,degraded}};二进制下载缺失时回同款信封 JSON)。

关键渲染约定(v4)

  • 分隔页:section_bg 底(缺则 surface_2→cover_bg→bg),40pt 居中粗体主标题 + 20pt muted 副标题(bullets[0] → subtitle → 该章第一页 title 三级兜底,浅底自动换深字)+ 底部 30% 宽 accent 短线。
  • 真图卡片:surface_2 圆角矩形(8px)容器 + 5mm 内边距,图居中、图注 Fig N(论文 S?P?) 10–12pt muted、与图区留 3mm;混排页图区 ≤55% 页宽且 ≤60% 页高, 单独图页居中、上下留白 ≥5%。

测试结果(2026-10-15)

pytest(review_service 全库): 215 passed in 13.7s   (P5 新增 102 → 113 + 102)
vitest edu(tests/frontend/unit/edu): 43 passed      (P5 新增 19:panel 12 + store 7)
vitest 全量(tests/frontend/unit): 32 files / 421 passed / 0 failed
  —— 修掉 b2/b3/bioflow 共 5 个预存失败(文案改名 + 模式按钮移除)
npm run build: ✓ built(chunk > 500kB 警告为预存)
版式目检: 3 风格 × 10 页预览 PNG 渲染核对(分隔页主副标题/对比度回退、
          混排图卡 ≤55%、单独图页居中留白)均符合预期

真实 e2e(v1 阶段记录:官方 MDPI 模板实例 PDF,16813 字符,真实 DeepSeek)

PDF 模式创建:   21.77s → 12 页(目标 [11,14])warnings=0 llm_calls=7 unverified_evidence=0
PATCH 编辑:     改写要点 + 新增无证据行 → evidence 同长重验、结构清洗 ✓
build:          0.13s → 12 slides / 64157 B / 16:9(13.33×7.50in)逐页讲者备注 ✓
python-pptx 回读: 12 页,S3 首条 = 人工改写文本 ✓
编辑后下载:     ok=false NOT_FOUND(盘上旧文件存在但拒发,pptx_path 清空生效)✓
text 模式:      15.0s → 9 页(目标 [8,10])group_meeting / 10min / botanic-forest ✓
短文本:         200 信封 VALIDATION「正文过短(<300 字),无法生成汇报大纲」✓
清理:           双 DELETE → ppt_jobs 0 行、产物目录空 ✓

部署验证步骤

  1. 依赖:同步 tooling/requirements.lock(+3 行)并安装到统一 venv。
  2. 重启服务:cd review_service && bash restart.sh(8100)。
  3. 健康检查:curl http://127.0.0.1:8100/health → status=ok、vstore connected=true。
  4. 路由:curl .../openapi.json 确认 9 个 /api/review/ppt/* 路径在列(含 /styles)。
  5. BFF:sdk/.env 确认 REVIEW_ENABLED=1,走 8090 反代冒烟 POST /api/review/ppt/jobs(短文本应得 200 VALIDATION 信封,不打 LLM)。
  6. 真实链路:上传一篇论文 PDF → 出大纲 → 编辑分隔页副标题并保存 → build → 下载 PPTX → 用 python-pptx 核对页数、16:9 尺寸与分隔页副标题文本。
  7. 回归:cd review_service && <venv>/bin/python -m pytest -q; cd ui && npx vitest run + npm run build。

部署决策

建议:只合并,下次批量部署。 本次改动对存量服务零影响(纯新增模块 + 开关化反代),无数据迁移、无 schema 破坏性变更;单点重启 8100 即可生效, 不值得为它单独发版,随下一次批量部署一并上即可。

风险与回滚

风险 影响 缓解 / 回滚
python-pptx==1.0.2 版本与需求(1.1.2)不一致 依赖锁未按原文落库 已声明偏差,合并前人工确认 3 行锁变更;如需回退直接还原 lock
xlsxwriter==3.2.9 无代码引用 锁文件带入未用依赖 venv 实况记录,可保留;若要求最小化可单独剔除该行
LLM 大纲偶发超时/无效 JSON 创建接口报 LLM_ERROR/LLM_INVALID 已分片 reduce + 单次膨胀回修 + 警告降级;前端可重试,无脏数据落库
quote 反查失败残留 evidence(2 条) 个别要点 unverified Phase 2:最长公共子串(≥20 字符)匹配补 para_id,失败保持 unverified(边际价值低,v4 不做)
编辑后旧 PPTX 残留盘上 无(pptx_path 清空后拒发,仅占磁盘) 删除 job 时 rmtree 一并清理
回滚 — 反向还原 12 个已跟踪文件改动 + 删除 44 个新增文件(后端 26 + 前端 18)即可;ppt_jobs 表与产物目录可留可删,不被其他模块引用

与 feature/p3b-compile-ui#4f9c077 的关系

v1 版报告曾以同一路径提交于该分支(docs: add P5 PR report),内容停留在 3 版式 / 7 端点 / 208 pytest 阶段。本文件为 v4 权威版本;若两分支先后合入,同路径会产生一次 文本冲突,取本文件(v4)内容即可。