Files
Deep Research System d1169646b8 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
2026-05-05 11:50:32 +08:00

479 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Deep Research 系统
> 生物医药行业的 AI 驱动深度研究流水线。基于 OpenCode 多 agent 协作,以麦肯锡/德勤式方法论产出专业级研究报告(PDF + DOCX)。
**当前状态**v0.13 迭代完成。新增 Quarto/xelatex PDF 引擎(`--engine quarto`),解决 ReportLab 超宽表格渲染 bugReportLab 引擎保留为默认后备。Quarto 依赖独立安装,不影响现有环境。
详见 `PLAN.md` 了解完整方案、版本记录与迭代路径。
---
## 快速开始
> 项目在 **macOS** 与 **Debian/Ubuntu** 上均通用。Python 包管理用 [**uv**](https://docs.astral.sh/uv/)Rust 写的 Python 包管理器,比 pip 快 10-100 倍,Astral 出品)。
### 1. 一键初始化(推荐)
```bash
bash scripts/setup.sh
```
这个脚本会自动:
- 检查并安装 **uv**(没有会交互询问,走官方 `curl -LsSf https://astral.sh/uv/install.sh` 脚本)
- 调用 `uv sync``pyproject.toml` 创建 `.venv/` 并装所有依赖(ReportLab、matplotlib、biopython 等)
- uv 会自动管理 Python 版本(>=3.10),不依赖系统 Python
- 检查并提示缺失的系统二进制(pandoc、opencode
**为什么选 uv 而不是 pip**
- macOS Homebrew Python、Debian 12+ 默认 PEP 668 保护,`pip install` 到系统会被拒
- uv 把 venv + 版本管理 + 依赖解析一次搞定,不需要手动 `python -m venv` + `source activate` + `pip install`
- `uv sync` 10-30 秒装完一整个科学计算栈(pip 要 2-5 分钟)
-`uv.lock` 锁定精确版本,mac 和 debian 装出来的环境完全一致
### 2. 安装系统二进制(setup.sh 不装这些)
```bash
# macOS
brew install pandoc
curl -fsSL https://opencode.ai/install | bash
# Debian/Ubuntu
sudo apt update && sudo apt install -y pandoc curl
curl -fsSL https://opencode.ai/install | bash
```
> uv 会帮你装 Python 本身,不需要再装 `python3-venv` / `python3-pip`。
### 3. 配置密钥
```bash
cp secrets.env.example secrets.env
# 编辑 secrets.env,填入:
# - ZENMUX_API_KEY(必填,格式 sk-ai-v1-xxx
# - TAVILY_API_KEY / BRAVE_API_KEY / EXA_API_KEY
# - NCBI_API_KEY(可选,PubMed 高频查询时用)
```
### 4. 下载中文字体
```bash
bash .opencode/templates/fonts/download-fonts.sh
```
下载思源宋体 + 思源黑体 + 霞鹜文楷(SIL OFL 许可,约 140MB)。
### 5. 验证 zenmux 端点与 cache(强烈推荐)
```bash
source scripts/activate.sh # 一键激活 venv + 加载 secrets
bash scripts/verify-zenmux.sh # 3 步自检
```
`verify-zenmux.sh` 会:
1. 测 OpenAI 兼容端点(Gemini 3.1 Pro Preview
2. 测 Anthropic 兼容端点(Claude Haiku 4.5
3. 测 Claude prompt cache 两次调用命中(Opus 4.7 cache 读取仅 0.5 USD/M tokens
若第 3 步 `cache_read_input_tokens` 始终为 0,参见 `AGENTS.md` §6.5 诊断步骤。
### 6. 日常使用
```bash
cd ~/Documents/Projects/deep_research
source scripts/activate.sh # 激活 venv + 载入 secrets
opencode # 启动 TUI
```
**退出 venv**`deactivate`
**跑单个 Python 脚本**(不用先激活):
```bash
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` 即可断点续跑。
### 多平台兼容
- OpenCode:主适配器,使用 `.opencode/agents``.opencode/commands`
- Codexnative adapter,使用 `.codex/config.toml``.codex/agents``.codex/commands``.agents/skills``scripts/dr.py` 独立运行;主入口是 `dr-run`,由 Codex 主线程承担 PM 调度并主动 spawn subagents,详见 `docs/codex-usage.md`
- Gemini CLI / Claude Code:暂不做强适配,后续以同一套脚本与配置为基础扩展。
安装 Codex adapter
```bash
uv run python scripts/install_codex_adapter.py --force
```
Codex adapter 默认面向自动化研究:workspace 可写、命令不逐次审批、实时 web search 与脚本网络访问开启;Tavily / Brave / Exa MCP 会默认启用但不设为必需服务。
部署到新环境后自检:
```bash
uv run python scripts/deploy_check.py
uv run python scripts/deploy_check.py --repair --force
```
运行 Codex 总调度:
```bash
codex exec "$(uv run python scripts/dr.py prompt dr-run <slug-or-topic>)"
```
模型与搜索 API 选择见:
- `docs/model-playbook.md`
- `docs/search-playbook.md`
模型预设配置文件:
- `configs/models.yaml`(统一预设,支持 `simple / medium / premium / cn_heavy / codex_native`
推荐时机:在 `/dr-init` 访谈阶段就确定 `model_profile`,并立即执行 `apply-models`,保证 plan→pm→analyst→verifier→editor→polisher 的全流程策略一致。
命令行查看解析后的模型映射:
```bash
uv run python scripts/dr.py models
uv run python scripts/dr.py models --list
uv run python scripts/dr.py models --profile premium
uv run python scripts/dr.py models --profile medium --model-override dr_verifier=zenmux/openai/gpt-5.4
# apply profile to agent files
uv run python scripts/dr.py apply-models --profile medium --target both --dry-run
uv run python scripts/dr.py apply-models --profile medium --target both
```
Sprint 5 回归检查(一键):
```bash
uv run python scripts/sprint5_regression.py <slug>
```
统一搜索入口:
```bash
uv run python scripts/search.py "dual-target RNAi 2024" --route scholar --year-low 2023
uv run python scripts/search.py "dual-target siRNA GalNAc" --route patents
```
---
## 项目结构
```
deep_research/
├── PLAN.md # 完整方案(中断续接从此读起)
├── AGENTS.md # 研究方法论与规则(OpenCode 自动加载)
├── README.md # 本文件
├── secrets.env.example # 密钥模板
├── secrets.env # 你的密钥(gitignore
├── .opencode/
│ ├── opencode.json # MCP 配置 + 权限
│ ├── agents/ # Agent 定义
│ │ ├── dr-plan.md # [MVP] 框架规划师 Opus 0.7
│ │ └── dr-pm.md # [MVP] 项目经理 Sonnet 0.2
│ ├── skills/ # 可复用技能
│ │ ├── search-strategy/ # [MVP] 检索策略总纲
│ │ ├── source-quality/ # [MVP] 信源评级
│ │ ├── length-budget/ # [MVP] 字数预算
│ │ └── pdf-reportlab/ # [MVP] PDF 模板使用
│ ├── commands/
│ │ ├── dr-init.md # [MVP] /dr-init
│ │ └── dr-frame.md # [MVP] /dr-frame
│ └── templates/
│ ├── report-template.py # [MVP] ReportLab PDF 生成器
│ └── fonts/
│ ├── download-fonts.sh
│ └── README.md
├── projects/ # 每个研究一个子目录
│ └── <slug>/
│ ├── manifest.json
│ ├── phase1/
│ ├── phase2/
│ ├── phase3/
│ └── phase4/
└── archive/ # 完成项目归档
```
---
## 关键设计要点
### 1. 防止"多 agent 变单模型跑"
OpenCode 的常见陷阱:AI 在主会话里装样子地"委派"子 agent,实际还是主模型在跑。本项目通过 3 道保险避免:
1. **命令 `subtask: true`** — 强制走 Task 工具起子会话
2. **Agent 强绑 `model`** — 每个 subagent 锁死具体模型
3. **`permission.task` 白名单** — 精确限定调用关系
验证方法:TUI 里 `<Leader>+Right` 切入子会话,能看到真实在跑的模型名。
### 2. 信源分级(Tier 1-4 + 黑名单)
详见 `AGENTS.md` §4 与 `skills/source-quality/SKILL.md`
- **Tier 1**PubMed、顶刊、FDA/NMPA 监管、ClinicalTrials、专利
- **Tier 2**:权威咨询、系统综述、行业协会
- **Tier 3**:预印本、券商研报、会议摘要(需 Tier 1-2 支撑)
- **Tier 4**:通用搜索(仅做发现入口,不做证据)
- **黑名单**:自媒体、撤稿论文、软文
### 3. 字数硬性要求
| 类型 | 最小字数 |
|---|---|
| 综述 | 10,000 |
| 研究 | 30,000 |
| 投资 | 20,000 |
| 管理 | 15,000 |
Phase 1 分配章节配额,Phase 2 自检,不足返工。见 `skills/length-budget/SKILL.md`
### 4. 中文 PDF 双引擎
`build_report.py` 现在支持两套 PDF 引擎,按需选择:
#### 引擎 AReportLab(默认,无额外依赖)
```bash
uv run python scripts/build_report.py <slug>
```
- 字体:思源宋 + 思源黑 + 霞鹜文楷(全 SIL OFL,可商用嵌入)
- 样式:集中在 `build_styles()`,所有字号行距单点维护
- 速度: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 关键)
Deep Research 大量使用**相同的长 system prompt + skill 内容**连续调用 Claude,如果 prompt cache 没生效,Opus/Sonnet 成本会翻 5-10 倍。所以本项目:
- **Claude 系列** → `zenmux-anthropic/claude-opus-4.7`(走 `https://zenmux.ai/api/anthropic``@ai-sdk/anthropic` 原生支持 `cache_control`
- **非 Claude 系列** → `zenmux/google/gemini-3.1-pro-preview` 等(走 `https://zenmux.ai/api/v1`,隐式缓存自动生效)
Opus 4.7 cache 读取价格 0.5 USD/M tokens(对比输入 25 USD/M,节省 98%)。
**验证 cache 是否生效**
1. 在 https://zenmux.ai/settings/logs 打开 API Call Logging
2. 运行 `/dr-frame` 让 dr-plan 连续调用 2 次
3. 第 2 次的 `cache_read_input_tokens` 字段应 > 0
4. 若始终为 0,检查 agent 的 `model:` 是否以 `zenmux-anthropic/` 开头(详见 `AGENTS.md` §6.5
---
## 已知待办
### 用户侧
1. [x] ~~在 zenmux 后台确认模型 slug,更新 `AGENTS.md` §6 映射表~~(已在 v0.2 完成,使用双 provider 架构)
2. [ ] 填写 `secrets.env`
3. [ ] 运行 `download-fonts.sh` 下载字体
4. [ ] 用一个小主题(如"5000 字 PD-1 综述")跑通 MVP 流水线
### 系统侧(下一阶段)
- [ ] dr-chief-editor / dr-searcher / dr-analyst / dr-verifier / dr-polisher / dr-reporter 6 个 subagent
- [ ] `/dr-research` `/dr-review` `/dr-finalize` `/dr-status` 4 个命令
- [ ] 生物医药专业信源 skillPubMed / ClinicalTrials / openFDA / 专利 / 金融
- [ ] citation-manager / evidence-table / mckinsey-method / docx-pandoc / report-template 5 个辅助 skill
- [ ] Pandoc reference-doc 模板(中文 DOCX
---
## 排错
### 字体下载失败
```bash
# 检查网络访问 GitHub
curl -I https://github.com
# 用镜像手动下载(见 .opencode/templates/fonts/README.md
```
### MCP Server 启动失败
```bash
# 检查 npx 可用
which npx
# 验证 MCP server 可独立运行
npx -y tavily-mcp@latest
```
### subagent 没被真正调度
1. 检查 agent frontmatter 的 `mode` 字段是否为 `subagent`
2. 检查命令 frontmatter 是否有 `subtask: true`
3. 检查主 agent 的 `permission.task` 是否允许目标 subagent
4. 在 TUI 用 `<Leader>+Right` 看是否有独立子会话
### ReportLab PDF 中文乱码
```bash
# 确认字体已注册(venv 里)
source scripts/activate.sh
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
export PATH="$HOME/.local/bin:$PATH"
# 永久生效:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc # macOS zsh
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc # debian bash
```
### Python 依赖安装报 externally-managed-environment
不要用系统 pip!改用 uv(本项目标准方案):
```bash
bash scripts/setup.sh # uv sync 会自建 .venv 并装依赖
```
### uv sync 很慢 / 下载超时
国内网络下,可用镜像加速:
```bash
export UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
# 或
export UV_INDEX_URL=https://mirrors.aliyun.com/pypi/simple
uv sync
```
### 每次开终端都要手动 source
`source scripts/activate.sh` 一次搞定。或装 [direnv](https://direnv.net/)
```bash
# macOS
brew install direnv
# Debian
sudo apt install direnv
# 都装完后在项目根目录
echo 'source scripts/activate.sh' > .envrc
direnv allow
```
之后 `cd` 进项目目录就会自动激活,不用再想。
---
## 参考链接
- OpenCode 文档:https://opencode.ai/docs
- Agent 配置:https://opencode.ai/docs/agents
- 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
---
## 变更记录
- **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 了解完整变更历史。