v0.10: add native Codex adapter for deep research

This commit is contained in:
kai
2026-04-24 10:48:14 +08:00
parent c93fce5078
commit 77df1838b1
48 changed files with 3354 additions and 48 deletions
+303
View File
@@ -0,0 +1,303 @@
---
name: pdf-reportlab
description: 用 ReportLab 生成专业中文 PDF 研究报告。集中样式管理、紧凑分页(widows/orphans/keepWithNext)、颜色层次、封面保密标识、页眉页脚简洁化。基于 9MW1911 综合战略报告的编排参考。
---
# ReportLab 中文 PDF 模板使用指南(v0.5)
## 一、为什么是 ReportLab
- **完全可控**:每个字号、行距、颜色由代码说了算,不被引擎意外改动
- **中文字体一次搞定**`pdfmetrics.registerFont` 注册后全局可用,子集嵌入 PDF,无授权问题
- **分页规则精确**:支持 widows/orphans、keepWithNext、splitByRow 等避免孤行/寡行
- **图表嵌入高质量**matplotlib 300 DPI PNG,速度快
- **样式集中在 StyleSheet**:避免字号不一
---
## 二、模板入口
脚本:`.opencode/templates/report-template.py`
调用:
```bash
uv run python .opencode/templates/report-template.py \
--input projects/<slug>/phase4/final.md \
--manifest projects/<slug>/manifest.json \
--output projects/<slug>/phase4/final.pdf \
--fonts-dir .opencode/templates/fonts
```
首次使用前:
```bash
bash .opencode/templates/fonts/download-fonts.sh
```
---
## 三、字体注册(7 个字重)
```
SrcSerif-Regular 思源宋体 Regular 正文
SrcSerif-Bold 思源宋体 Bold 正文粗体
SrcSans-Light 思源黑体 Light 页眉页脚
SrcSans-Medium 思源黑体 Medium 三级标题/图表
SrcSans-Bold 思源黑体 Bold 一二级标题
SrcSans-Heavy 思源黑体 Heavy 封面大标题
Kai 霞鹜文楷 Regular 摘要/引文
```
---
## 四、样式表(StyleSheet,集中管理)
| 样式名 | 字体 | 字号 | 行高 | 颜色 | 备注 |
|---|---|---|---|---|---|
| `body` | SrcSerif | 10.5 | 18 | `#1a1a1a` | 正文,首行缩进 21pt |
| `body-bold` | SrcSerif-Bold | 10.5 | 18 | `#1a1a1a` | 行内加粗 |
| `h1` | SrcSans-Bold | 18 | 28 | `#1e3a8a` | 章标题,前强制分页 |
| `h2` | SrcSans-Bold | 14 | 22 | `#2c5282` | 节标题 |
| `h3` | SrcSans-Medium | 12 | 18 | `#374151` | 小节标题 |
| `quote` | Kai | 10.5 | 18 | `#4b5563` | 引文 |
| `caption` | SrcSans-Medium | 9 | 13 | `#6b7280` | 图表标题 |
| `footnote` | SrcSerif | 9 | 13 | `#374151` | 脚注/参考文献 |
| `header-footer` | SrcSans-Light | 8 | 12 | `#9ca3af` | 页眉页脚 |
| `cover-title` | SrcSans-Heavy | 28 | 40 | `#0f172a` | 封面主标题 |
| `cover-subtitle` | SrcSans-Medium | 15 | 24 | `#475569` | 封面副标题 |
| `cover-confidential` | SrcSans-Bold | 11 | 16 | `#dc2626` | 封面保密标识(红色)|
| `cover-meta` | SrcSerif | 11 | 18 | `#334155` | 封面元信息 |
| `summary` | SrcSerif | 11 | 20 | `#1a1a1a` | 执行摘要 |
---
## 五、分页规则(关键升级点)
### 章(h1
- `pageBreakBefore=1`(每章新起一页)
- `keepWithNext=1`(标题和下一段不分离)
### 节(h2
- **禁止单独触发分页**
- `keepWithNext=1`(标题紧跟内容)
### 小节(h3
- 同 h2`keepWithNext=1`
### 段落
- `widows=2, orphans=2`(避免寡行/孤行)
- 每段之间 `spaceBefore=6, spaceAfter=6`
### 表格
- `TableStyle` 中启用 `splitByRow=True`(长表格按行分页)
- `repeatRows=1`(表头在分页后重复)
- 单元格 padding 统一 4-6pt
### 摘要/术语表/目录/参考文献
- 每个独占起始页(用 `PageBreak`
---
## 六、封面模板(参考 9MW1911)
封面独立一页,无页眉页脚,布局:
```
(上 30% 空白)
主标题(cover-title,黑色,居中)
副标题(cover-subtitle,深灰,居中)
(中部 40% 空白)
[机密 | 仅供 XX 内部决策使用] cover-confidential,红色,居中)
(下部 20%
类型:研究类
作者:Deep Research 系统 / <公司名>
编制日期:YYYY 年 M 月
版本:v1.0
```
字段来源:
- `manifest.report_title` / `report_subtitle`
- `manifest.confidentiality` (如 "机密 | 仅供迈威生物内部决策使用")
- `manifest.author` / `manifest.date` / `manifest.version`
---
## 七、页眉页脚(简洁化)
### 页眉
左边:报告简称(从 `manifest.report_title` 取前 15 字)
右边:章节名(动态,从当前 h1 内容取)
底线:`#e5e7eb` 浅灰分隔线
### 页脚
居中:页码(格式 `— X —`
字号:8pt`#9ca3af` 浅灰
### 特殊页
- 封面:无页眉页脚
- 免责声明:无页眉,仅页脚
- 其他(摘要/术语表/目录/正文/附录/参考文献):有页眉页脚
---
## 八、报告结构(11 件套)
ReportLab 按以下顺序组装:
1. **封面**cover PageTemplate
2. **免责声明**normal PageTemplate,单页)
3. **Executive Summary / 执行摘要**summary PageTemplate1-2 页)
4. **Abstract / 摘要**normal,单页)
5. **Glossary / 术语表**normal
6. **Table of Contents / 目录**TOC,自动生成)
7. **正文各章**(normal,每章 h1 强制分页)
8. **结论与建议**(正文的一部分)
9. **附录**normal
10. **参考文献**bibliography PageTemplatefootnote 样式)
11. **版本信息**normal,单页)
---
## 九、Markdown 支持范围
| Markdown | ReportLab 渲染 |
|---|---|
| `# 第 X 章 ...` | h1(新起一页,深蓝色)|
| `## X.Y ...` | h2(节,蓝色,不分页)|
| `### X.Y.Z ...` | h3(小节,深灰)|
| `**粗体**` | inline `<b>` |
| `*斜体*` | inline `<i>` |
| `` `代码` `` | 等宽字体 |
| `> 引文` | quote 样式(楷体,浅底色)|
| `- 项` / `1. 项` | 项目符号列表 |
| 表格 `\| \| \|` | Table,自动列宽 + splitByRow |
| `![caption](path)` | 图片 + caption 样式 |
| `[src_001]` | 上标引用 |
| `---` | 分页符 |
**不支持**:HTML 标签、数学公式、代码块高亮。
---
## 十、图表嵌入
不用 ReportLab 原生绘图,全部预渲染为 PNG:
```python
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
font_path = '.opencode/templates/fonts/SourceHanSansSC-Medium.otf'
fm.fontManager.addfont(font_path)
plt.rcParams['font.family'] = 'Source Han Sans SC'
plt.rcParams['axes.unicode_minus'] = False
fig, ax = plt.subplots(figsize=(6, 4), dpi=300)
# ...
plt.savefig('projects/<slug>/phase4/figures/fig_01_XXX.png', dpi=300, bbox_inches='tight')
```
Markdown 中引用:`![图 1-12020-2025 GLP-1 市场规模(数据来源:[src_042]](figures/fig_01_XXX.png)`
---
## 十一、manifest 必需字段
```json
{
"slug": "...",
"report_title": "自研 O-糖苷酶立项可行性研究报告",
"report_subtitle": "对标 NEB 与 Merck 经典产品的技术路径、IP 壁垒与差异化战略",
"confidentiality": "机密 | 仅供内部决策使用",
"author": "Deep Research 系统",
"date": "2026-04-21",
"version": "1.0",
"type": "研究类",
"disclaimer": "本报告基于公开信息与 AI 辅助研究生成,仅供参考..."
}
```
---
## 十二、常见坑与对策
| 坑 | 对策 |
|---|---|
| 中文字号不一 | 集中 StyleSheet,不在 Paragraph 里 inline 改 fontSize |
| 行距太挤 | 行高 = 字号 × 1.5~1.7 |
| 换行断错 | `wordWrap='CJK'` 必设 |
| 表格被截断 | `splitByRow=True, repeatRows=1` |
| 标题孤行(页末一个标题后直接新页)| `keepWithNext=1` |
| 段落寡行(末段只剩一行在下页)| `widows=2, orphans=2` |
| 图片变形 | 先 matplotlib 出 300 DPI PNG,再 `Image(path, width=..., kind="proportional")` |
| 生成慢 | matplotlib 图表预渲染,不要在 PDF 生成阶段现算 |
| 参考文献丢失 | dr-reporter 出稿前检查:读 citations.md,确认内容已写入 final.md |
---
## 十三、dr-reporter 调用流程
```
1. 环境检查
- 字体 ≥6 个 OTF 文件
- final.md 存在
- manifest.json 有必需字段
2. 回填参考文献(关键步骤,修复 v0.4 的 bug)
- 读 citations.md 内容
- 在 final.md 中找到"## 参考文献"段落
- 如果段落内容是占位符(如 "[由 dr-reporter 自动生成]" 或为空)
→ 替换为 citations.md 的完整内容
- 写回 final.md
3. 图表检查
- 扫描 final.md 中所有 ![...](path) 图片引用
- 验证每个 path 在 figures/ 目录下存在
- 缺失图片 → 警告并继续,但汇报中注明
4. 生成 PDF
uv run python .opencode/templates/report-template.py \
--input projects/<slug>/phase4/final.md \
--manifest projects/<slug>/manifest.json \
--output projects/<slug>/phase4/final.pdf \
--fonts-dir .opencode/templates/fonts
5. 生成 DOCX(可选)
pandoc projects/<slug>/phase4/final.md \
--from markdown --to docx \
--output projects/<slug>/phase4/final.docx \
--toc --toc-depth=3
6. 验证
- PDF 文件大小 > 500KB(太小说明字体没嵌)
- PDF 页数合理(按字数估算)
- "参考文献"章节存在且非空
7. 汇报
```
---
## 十四、输出卫生检查(必跑)
生成 PDF 前:
```bash
# 加载 skill:output-hygiene
python3 .opencode/templates/hygiene_check.py projects/<slug>/phase4/final.md
```
禁止词残留 → 抛回 dr-polisher 再润色一轮。