# Deep Research 系统 > 生物医药行业的 AI 驱动深度研究流水线。基于 OpenCode 多 agent 协作,以麦肯锡/德勤式方法论产出专业级研究报告(PDF + DOCX)。 **当前状态**:v0.13 迭代完成。新增 Quarto/xelatex PDF 引擎(`--engine quarto`),解决 ReportLab 超宽表格渲染 bug;ReportLab 引擎保留为默认后备。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 # 默认 ReportLab uv run python scripts/build_report.py --engine quarto # Quarto/xelatex ``` 网络不稳或 API 限流时,把 `--workers` 降到 `3` 或 `1` 即可断点续跑。 ### 多平台兼容 - OpenCode:主适配器,使用 `.opencode/agents` 与 `.opencode/commands`。 - Codex:native 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 )" ``` 模型与搜索 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 ``` 统一搜索入口: ```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/ # 每个研究一个子目录 │ └── / │ ├── 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 里 `+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 引擎,按需选择: #### 引擎 A:ReportLab(默认,无额外依赖) ```bash uv run python scripts/build_report.py ``` - 字体:思源宋 + 思源黑 + 霞鹜文楷(全 SIL OFL,可商用嵌入) - 样式:集中在 `build_styles()`,所有字号行距单点维护 - 速度:30,000 字 3-5 秒出稿 - 局限:超宽表格(≥4 列且含长文本)需借助列宽 patch 或改为 bullet list 格式 #### 引擎 B:Quarto / xelatex(`--engine quarto`,推荐用于宽表报告) ```bash uv run python scripts/build_report.py --engine quarto ``` - 排版引擎:xelatex(TeX 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. 安装 TinyTeX(Quarto 内置命令) 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 双 provider(Claude 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 个命令 - [ ] 生物医药专业信源 skill:PubMed / 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 用 `+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 # Linux ~/.TinyTeX/bin/universal-darwin/tlmgr install # 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 Servers:https://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 了解完整变更历史。