v0.13: add Quarto/xelatex PDF engine and fix ReportLab wide-table rendering

build_report.py:
- add --engine quarto option: Quarto 1.9 + xelatex pipeline with
  CJK font setup (Source Han Serif/Sans CN via fontspec),
  automatic {.landscape} wrapping for wide tables (>=8 cols),
  TOC/references placeholder replacement, sources.jsonl backfill
- prepare_qmd(): converts Markdown to .qmd with proper YAML front matter,
  writes _preamble.tex for longtable/pdflscape/lscape packages
- _detect_wide_tables(), _build_references_block(): helper functions
- ReportLab path unchanged (remains default)

report-template.py:
- render_table(): force equal-width column distribution for tables
  with >=4 cols or any cell >30 chars, preventing negative availWidth
  crash on mixed CJK/English content
- render_table_blocks(): split long tables (>25 rows) into chunks to
  avoid NoneType comparison crash in ReportLab splitByRow logic

.gitignore:
- add rules for LaTeX temp files (*.aux, xetest.*, *.qmd, _preamble.tex)
- add projects/ to gitignore (research data, not source code)

README.md:
- update status to v0.13
- rewrite PDF section as dual-engine guide with install steps,
  comparison table, and landscape table chunking guidance
- add Quarto troubleshooting (font italic mapping, tlmgr path, param_size)
- add v0.13 to changelog
This commit is contained in:
Deep Research System
2026-05-05 11:50:32 +08:00
parent ddaa6730bc
commit d1169646b8
7 changed files with 464 additions and 105 deletions
+114 -92
View File
@@ -2,7 +2,7 @@
> 生物医药行业的 AI 驱动深度研究流水线。基于 OpenCode 多 agent 协作,以麦肯锡/德勤式方法论产出专业级研究报告(PDF + DOCX)。
**当前状态**v0.12 迭代完成。OpenCode 全流程可用(Phase 1-4),搜索网关、模型预设与 Phase 4 统一 pipeline 已落地;Codex native adapter 与 OpenCode 保持并列入口
**当前状态**v0.13 迭代完成。新增 Quarto/xelatex PDF 引擎(`--engine quarto`),解决 ReportLab 超宽表格渲染 bugReportLab 引擎保留为默认后备。Quarto 依赖独立安装,不影响现有环境
详见 `PLAN.md` 了解完整方案、版本记录与迭代路径。
---
@@ -87,94 +87,8 @@ opencode # 启动 TUI
**跑单个 Python 脚本**(不用先激活):
```bash
uv run python .opencode/templates/report-template.py --input ... --output ...
```
**加新依赖**
```bash
uv add <package> # 自动更新 pyproject.toml 和 uv.lock
```
**同步到最新锁定版本**(新 clone 或切分支后):
```bash
uv sync
```
如果你用 [direnv](https://direnv.net/),可在项目根目录建 `.envrc`
```bash
source scripts/activate.sh
```
这样 `cd` 进项目目录会自动激活,`cd` 出去会自动卸载。
---
## 可用命令
| 命令 | 功能 | 状态 |
|---|---|---|
| `/dr-init <主题>` | 初始化新研究,启动访谈 | ✅ 可用 |
| `/dr-frame [slug]` | Phase 1:生成 8-15 章双语研究框架 | ✅ 可用 |
| `/dr-research [slug]` | Phase 2:并行深度研究 | ✅ 可用 |
| `/dr-review [slug]` | Phase 3:总编审校 | ✅ 可用 |
| `/dr-finalize [slug]` | Phase 4:英文合稿 → 中文翻译/术语核查/润色 → PDF+DOCX | ✅ 可用 |
| `/dr-models [profile]` | 解析模型预设(simple / medium / premium 等) | ✅ 可用 |
| `/dr-apply-models <profile>` | 把模型预设写入 OpenCode/Codex agent 文件 | ✅ 可用 |
| `/dr-glossary [slug]` | 术语表事实核查 | ✅ 可用 |
| `/dr-status [slug]` | 查看进度 | ✅ 可用 |
### 典型流程
```
1. /dr-init GLP-1 减重药物市场
→ dr-plan 向你提 8 个访谈问题(研究类型、受众、时间范围等)
→ 你回答后,生成 projects/glp1-obesity-market-2026/manifest.json
2. /dr-frame
→ dr-plan 调用 skill:search-strategy
→ 委派 3-4 个 dr-searcherHaiku,轻量)并行初扫
→ 生成 8-15 章框架到 phase1/framework.md
→ 暂停等你确认
3. 你审核框架,或提修改意见,或直接确认
→ 确认后,manifest.phase1.approved = true
4. /dr-research
→ dr-pm 分批并行调度 dr-analyst 深研
→ dr-verifier 做反方验证
→ 产出 phase2/drafts、evidence、sources.jsonl
5. /dr-review
→ dr-chief-editor 通读审校,产出 phase3/critique.md
6. /dr-finalize
→ dr-editor-in-chief 合并英文终稿
→ Python 脚本执行 translate → glossary → apply_glossary → polish → build_report
→ 产出 final_zh_polished.md、PDF、DOCX
```
### Phase 4 Python 流水线
Phase 4 已切到统一 pipeline(替代式):由 Python 控制切块、并发、重试与断点续传:
```bash
uv run python scripts/phase4_pipeline.py <slug>
# 等价入口(支持模型预设)
uv run python scripts/dr.py finalize <slug> --model-profile medium
```
默认行为:
- 自动估算 translate/polish 并发(`--translate-workers 0` / `--polish-workers 0`
- glossary 仅核查低置信度术语(`--glossary-mode low-confidence`
你也可以手动分步执行:
```bash
uv run python scripts/translate.py <slug> --workers 4
uv run python scripts/build_glossary.py <slug> --workers 4
uv run python scripts/apply_glossary.py <slug> --input phase4/final_zh.md --dry-run
uv run python scripts/apply_glossary.py <slug> --input phase4/final_zh.md
uv run python scripts/polish.py <slug> --workers 4
uv run python scripts/build_report.py <slug>
uv run python scripts/build_report.py <slug> # 默认 ReportLab
uv run python scripts/build_report.py <slug> --engine quarto # Quarto/xelatex
```
网络不稳或 API 限流时,把 `--workers` 降到 `3``1` 即可断点续跑。
@@ -318,12 +232,71 @@ OpenCode 的常见陷阱:AI 在主会话里装样子地"委派"子 agent,实
Phase 1 分配章节配额,Phase 2 自检,不足返工。见 `skills/length-budget/SKILL.md`
### 4. 中文 PDF 无坑
### 4. 中文 PDF 双引擎
`build_report.py` 现在支持两套 PDF 引擎,按需选择:
#### 引擎 AReportLab(默认,无额外依赖)
```bash
uv run python scripts/build_report.py <slug>
```
- 字体:思源宋 + 思源黑 + 霞鹜文楷(全 SIL OFL,可商用嵌入)
- 样式:集中在 `build_styles()`,所有字号行距单点维护
- 引擎:ReportLab(纯 Python30,000 字 3-5 秒出稿
- 图表:matplotlib 预渲染 300 DPI PNG 嵌入
- 速度:30,000 字 3-5 秒出稿
- 局限:超宽表格(≥4 列且含长文本)需借助列宽 patch 或改为 bullet list 格式
#### 引擎 BQuarto / xelatex`--engine quarto`,推荐用于宽表报告)
```bash
uv run python scripts/build_report.py <slug> --engine quarto
```
- 排版引擎:xelatexTeX Live / TinyTeX),LaTeX 级排版质量
- 字体:同样使用思源宋 + 思源黑,通过 fontspec 加载
- 宽表支持:超宽表通过 `longtable` + `tbl-colwidths` 精确指定列宽比例,不溢出
- 横向页面:通过 `{.landscape}` div 包裹超宽表,自动插入 `pdflscape` 代码(注意:101 行以上的 landscape longtable 可能触发 TeX `param_size` 上限,建议拆成 ≤20 行的子表块)
- 图表:暂不嵌入 matplotlib 图表(使用文字描述代替)
**安装 Quarto 引擎**(一次性,系统级):
```bash
# 1. 安装 Quarto CLI
# 下载页:https://github.com/quarto-dev/quarto-cli/releases/latest
# Linux 选 .deb 安装包,macOS 选 .pkg
# 2. 安装 TinyTeXQuarto 内置命令)
quarto install tinytex
# 3. 安装中文 LaTeX 支持包
~/.TinyTeX/bin/x86_64-linux/tlmgr install ctex xecjk cjk xetex
# macOS 路径通常为:~/.TinyTeX/bin/universal-darwin/tlmgr
# 4. 注册思源字体到 fontconfig
# (先确认字体已下载:bash .opencode/templates/fonts/download-fonts.sh
mkdir -p ~/.fonts
cp .opencode/templates/fonts/*.otf ~/.fonts/
cp .opencode/templates/fonts/*.ttf ~/.fonts/
cp .opencode/templates/fonts/ttf/*.ttf ~/.fonts/
fc-cache -fv ~/.fonts
# 5. 验证
quarto --version # 应输出 1.x.x
fc-list | grep "Source Han" # 应看到思源字体条目
```
**两引擎对比**
| 指标 | ReportLab | Quarto/xelatex |
|------|-----------|----------------|
| 安装复杂度 | 无额外依赖 | 需安装 Quarto + TinyTeX |
| 渲染速度 | 3-5 秒 | 30-90 秒(LaTeX 编译) |
| 宽表格处理 | 需 workaround | longtable 原生支持 |
| 横向页面 | 不支持 | 支持(≤20 行/块) |
| 字体嵌入 | OTF 直接嵌入 | fontspec 系统字体 |
| 输出体积 | ~1.2 MB/100页 | ~0.9 MB/100页 |
| 目录生成 | 自定义实现 | LaTeX 自动 \tableofcontents |
### 5. zenmux 双 providerClaude cache 关键)
@@ -394,6 +367,51 @@ ls .opencode/templates/fonts/*.otf | wc -l # 应为 6+
python .opencode/templates/report-template.py --help
```
### Quarto PDF 生成失败
**字体找不到(`Could not resolve font "Source Han Serif CN/I"`**
CJK 字体没有斜体变体,fontspec 默认会找 `/I` 导致报错。`build_report.py --engine quarto` 已通过 `mainfontoptions: [ItalicFont=...]` 自动绕开,无需手动处理。若自行编写 `.qmd`,需在 YAML 里加:
```yaml
format:
pdf:
pdf-engine: xelatex
CJKmainfont: "Source Han Serif CN"
mainfontoptions:
- BoldFont=Source Han Serif CN
- ItalicFont=Source Han Serif CN
- BoldItalicFont=Source Han Serif CN
```
**`tlmgr` 找不到**
TinyTeX 不在系统 PATH,用完整路径:
```bash
~/.TinyTeX/bin/x86_64-linux/tlmgr install <package> # Linux
~/.TinyTeX/bin/universal-darwin/tlmgr install <package> # macOS
```
**`TeX capacity exceeded [parameter stack size]`**landscape 大表):
pdflscape 的 `\LS@makefcolumn` 在 101 行以上的 longtable 里递归过深,耗尽 TeX 的 `param_size`。解决方法:把超大表拆成每块 ≤20 行的子表,每块都包在 `{.landscape}` div 里:
```markdown
::: {.landscape}
| 列1 | 列2 | ... |
|---|---|---|
| 第1-20行 | ... |
:::
::: {.landscape}
| 列1 | 列2 | ... |
|---|---|---|
| 第21-40行 | ... |
:::
```
若使用 `build_report.py --engine quarto`,可通过传入预处理好的 `.md`(宽表已拆块)来避免此问题。
### uv 安装后找不到
uv 官方脚本把 uv 装到 `~/.local/bin/`。若终端里 `which uv` 找不到:
```bash
@@ -442,6 +460,9 @@ direnv allow
- Skill 配置:https://opencode.ai/docs/skills
- MCP Servershttps://opencode.ai/docs/mcp-servers
- ReportLab 文档:https://docs.reportlab.com
- Quarto 文档:https://quarto.org/docs/output-formats/pdf-basics.html
- Quarto PDF 引擎:https://quarto.org/docs/output-formats/pdf-engine.html
- Quarto 表格文档:https://quarto.org/docs/authoring/tables.html
- 思源字体:https://github.com/adobe-fonts
- 霞鹜文楷:https://github.com/lxgw/LxgwWenKai
@@ -452,5 +473,6 @@ direnv allow
- **v0.1** (2026-04-20) — MVP 路径 2 完成:dr-plan + dr-pm 两主 agent、4 个核心 skill、2 个命令、ReportLab 模板基础版、字体下载脚本
- **v0.2** (2026-04-20) — 双 provider 架构(zenmux-anthropic + zenmux),解决 Claude prompt cache 生效问题
- **v0.3** (2026-04-20) — 修正 v0.2 模型名(回到 Opus 4.7 / Sonnet 4.6 / Gemini 3.1 Pro / GPT-5.4 Pro 等真实 slug);改 venv + requirements.txt 跨平台方案(macOS + Debian);新增 `scripts/setup.sh``scripts/activate.sh`
- **v0.13** (2026-05-02) — `build_report.py` 新增 `--engine quarto` 选项:Quarto 1.9 + xelatex 引擎,解决 ReportLab 超宽表格渲染 bug`negative availWidth`/`NoneType` 问题);`report-template.py` 同步修复(`render_table_blocks` 分块 + 等宽列强制分配);README 补充双引擎安装指南与排错
`PLAN.md` §12 了解完整变更历史。