paper-summarize-pdf-to-feishu

GitHub 作者 yy-fan v1.0.1

总结论文 PDF 为飞书文档(含图表)。当用户发送 PDF 文件并要求总结、阅读、提取内容, 或要求将 PDF 内容写入飞书文档时激活。支持学术论文、技术报告、一般 PDF 文档。 自动检测扫描版 PDF 并回退 OCR,支持提取并上传论文图片到飞书文档。 含多模型自审核机制:生成 → 配图 → 审核 → 人工确认 → 完善。 **支持去重系统**:自动识别重复 PDF、同文章不同版本、补充材料,智能合并处理。 触发场景:发送 PDF 附件、"总结这个 PDF"、"帮我读一下这个论文"、"把 PDF 写成飞书文档"、 "论文总结"、"PDF 摘要"、"阅读 PDF 并输出到飞书"。

安装 / 下载方式

TotalClaw CLI推荐
totalclaw install github:LeoYeAI~openclaw-master-skills~paper-summarize-pdf-to-feishu
cURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/github%3ALeoYeAI~openclaw-master-skills~paper-summarize-pdf-to-feishu/file -o paper-summarize-pdf-to-feishu.md
# paper-summarize-pdf-to-feishu

将 PDF 文件完整阅读后生成结构化总结,写入飞书文档,并将论文 Figure 精确插入对应章节。
**含多模型审核 + 配置确认 + 人工确认机制**,确保最终输出质量。

## 前置依赖

### 系统工具
| 工具 | 用途 | 版本要求 |
|------|------|----------|
| `pdftotext` | PDF 文本提取 | poppler-utils ≥ 0.86 |
| `pdfinfo` | PDF 元信息查看 | poppler-utils ≥ 0.86 |
| `pdfimages` | PDF 图片提取 | poppler-utils ≥ 0.86 |
| `pdftoppm` | PDF 转图片(截图/OCR) | poppler-utils ≥ 0.86 |
| `tesseract` | OCR 识别 | ≥ 4.1 |
| `jq` | JSON 处理 | ≥ 1.6 |

### OpenClaw 插件
| 插件 | 用途 | 版本 |
|------|------|------|
| `feishu` | 飞书文档操作 | 2026.3.13¹ |
| `feishu_doc` | 文档读写/图片上传 | 内置 |

> ¹ OpenClaw 官方插件与主程序同步发布,版本号一致

检查依赖:
```bash
# 检查系统工具
which pdftotext pdfinfo pdfimages pdftoppm tesseract jq || \
  sudo apt-get install -y poppler-utils tesseract-ocr tesseract-ocr-eng tesseract-ocr-chi-sim jq

# 检查版本
pdftotext -v  # 应显示 poppler-utils 版本
tesseract --version  # 应显示 tesseract 版本
jq --version
```

## 完整工作流程(六阶段)

### 阶段零:去重检查

**目标**:避免重复处理,智能识别补充材料并合并

#### 0.1 提取元数据

```bash
scripts/extract_metadata.sh <input.pdf> "$TEMP_DIR/metadata.json"
```

提取内容:
- DOI(优先,用于唯一标识)
- 标题、作者、发表年份
- PDF 文件哈希(用于精确去重)
- 生成 `paper_id`:`<DOI>` 或 `hash_<指纹>`

#### 0.2 检查是否已处理

```bash
scripts/check_duplicate.sh "$TEMP_DIR/metadata.json" "$PAPERS_DIR"
```

**判断逻辑**:
```
收到 PDF → 计算 paper_id → 查询 papers/ 目录
  ├─ 不存在 → 新论文,创建文件夹,进入阶段一
  ├─ 存在 + PDF 哈希相同 → 完全重复,跳过并告知用户
  ├─ 存在 + DOI 相同但哈希不同 → 同文章不同版本,询问是否更新
  └─ 存在 + 判断为补充材料 → 合并到 supplements/,追加到飞书文档
```

#### 0.3 补充材料识别规则

文件名包含以下关键词视为补充材料:
- `supplement`, `suppl`, `_si_`, `supporting`, `appendix`

DOI 包含 `.supp` 或 `supplementary` 也视为补充材料。

#### 0.4 文件夹结构

```
papers/
├── 10.xxxx-xxxxxx/                      # DOI 作为 ID(优先)
│   ├── metadata.json                    # 元数据(DOI、标题、作者等)
│   ├── paper.pdf                        # 主文章
│   ├── paper.txt                        # 提取的全文文本
│   ├── feishu_doc_token.txt             # 飞书文档 token
│   ├── summary.md                       # 总结文档
│   ├── versions.json                    # 版本历史(如有更新)
│   ├── images/                          # 提取的 Figure/Table
│   └── supplements/                     # 补充材料
│       ├── 20260326_120000_suppl1.pdf
│       ├── 20260326_120000_suppl1_meta.json
│       └── 20260326_120000_suppl1.txt
│
└── hash_xxxxxxxxxxxx/                   # 无 DOI 时用指纹哈希
    └── ...
```

---

### 阶段一:生成

#### 1. 创建论文专属文件夹

```bash
PAPER_DIR=<OpenClaw 工作目录>/papers/<paper_id>
mkdir -p "$PAPER_DIR"/{images,supplements}
cp <input.pdf> "$PAPER_DIR/paper.pdf"
cp "$TEMP_DIR/metadata.json" "$PAPER_DIR/metadata.json"
```

#### 2. 智能提取 PDF 文本

```bash
scripts/extract_pdf_text.sh "$PAPER_DIR/paper.pdf" "$PAPER_DIR/paper.txt"
```

策略:pdftotext → 检测字符密度(≥50 字符/页正常,<50 走 OCR 回退)

#### 3. 分段完整阅读

用 `read` 工具每次 500 行,直到读完全文。

**关键要求:必须读完全文再总结,不要只读摘要或部分内容。**

#### 4. 生成结构化总结

**学术论文**结构:

```markdown
# 总结:<论文标题>

> 原文标题 / 发表日期 / 机构

---

## 📊 论文统计
- 总字数 / 总页数
- Figure(正文):X 张
- Figure(附录):X 张
- Table(正文):X 张
- Table(附录):X 张

---

## 一、研究背景与动机
## 二、研究设计
## 三、方法/系统架构
## 四、核心结果
### 4.1 结果 A
### 4.2 结果 B
## 五、讨论与局限性
## 六、结论
## 七、关键数据速览
```

#### 5. 创建飞书文档并写入

```json
{
  "action": "create",
  "title": "总结:<文档标题>",
  "owner_open_id": "<用户的 open_id>"
}
```

```json
{
  "action": "write",
  "doc_token": "<doc_token>",
  "content": "<Markdown 格式总结>"
}
```

保存 `feishu_doc_token.txt` 以便后续补充材料合并时使用。

---

### 阶段一(补充):补充材料合并

**如果阶段零判断为补充材料**,执行以下流程:

```bash
# 读取已有的飞书文档 token
DOC_TOKEN=$(cat "$PAPER_DIR/feishu_doc_token.txt")

# 步骤 1:合并补充材料(文件层面)
scripts/merge_supplement.sh "$PAPER_DIR" "<supplement.pdf>" "$DOC_TOKEN"

# 步骤 2:追加到飞书文档(调用 feishu_doc 工具)
feishu_doc action=append doc_token="$DOC_TOKEN" content="
## 📎 补充材料:$(basename $SUPPLEMENT_PDF)
- 添加时间:$(date +%Y-%m-%d %H:%M)
- 摘要:$(cat $SUPP_TXT | head -20)
"
```

**合并逻辑**:
1. `merge_supplement.sh` 负责文件层面操作:
   - 复制补充材料到 `supplements/` 目录(带时间戳命名)
   - 提取补充材料的元数据(`_meta.json`)
   - 提取简要摘要(`.txt`)
2. **Agent 调用 `feishu_doc` 工具**追加内容到飞书文档
3. 更新 `versions.json` 记录(待实现)

**注意**:`merge_supplement.sh` 不直接操作飞书文档,仅准备文件和数据。飞书文档更新由上层 Agent 调用 `feishu_doc` 工具完成。

---

### 阶段二:配图(Figure/Table 提取与验证)

#### 6. 定位 Figure/Table 页码

```bash
scripts/locate_figures.sh "$PAPER_DIR/paper.pdf" "$PAPER_DIR/paper.txt" "$PAPER_DIR/images"
```

脚本会:
1. 用 `grep` 找到所有 Figure/Table 标题行
2. 根据行号估算页码
3. 对估算页码 ±2 页范围截图(候选页面)

**⚠️ 注意:行号→页码是粗略估算,必须经过审核验证!**

#### 7. 验证截图(关键步骤)

对每个 Figure 的候选截图逐张审核:

```
for each Figure:
  1. read 候选截图
  2. 判断:图中是否包含目标 Figure?
     - ✅ 包含 → 记录正确页码,复制为 Figure_XX_full.png
     - ❌ 不包含 → 检查相邻页面
  3. 如果所有候选页面都不对 → 扩大搜索范围
```

**验证标准**:
- ✅ 截图中必须可见 "Figure X" 或 "Table X" 标题文字
- ✅ 截图中必须包含图表内容(非纯文字页面)
- ✅ 复合图(多子图拼合)应作为完整页面保留

**如果截图是纯文字**:
1. ❌ 不要使用该截图
2. 检查相邻页面(±3 页范围)
3. 检查文本提取是否有误(Figure 标题可能在图片中无法提取)
4. 手动浏览 PDF 定位:`pdftoppm -f X -l X paper.pdf output`

#### 8. 插入图片到对应章节

**精确定位**:

```json
{
  "action": "upload_image",
  "doc_token": "<doc_token>",
  "file_path": "<图片路径>",
  "parent_block_id": "<doc_token>",
  "index": <目标索引>
}
```

**技巧**:从文档末尾往前插(倒序),避免索引偏移。

---

### 阶段三:审核(多模型审核)

**核心思想**:直接使用 fallback 模型审核 → 告知用户 → 主模型审查 → 人工确认

#### 9. 读取模型配置并启动审核

```bash
# 读取 OpenClaw 配置文件
CONFIG_FILE=<OpenClaw 配置文件路径>

# 提取 fallback 模型列表(取第一个作为审核模型)
FALLBACK_MODEL=$(jq -r '.agents.defaults.model.fallbacks[0]' "$CONFIG_FILE")

# 确认配置并启动审核
if [ -z "$FALLBACK_MODEL" ] || [ "$FALLBACK_MODEL" = "null" ]; then
  echo "⚠️ 未配置 fallback 模型,将使用主模型自审"
  # 降级方案:使用主模型重新阅读 PDF + 文档进行自审
  sessions_spawn task="请审核这份飞书文档与原始 PDF 的一致性..."
else
  echo "✅ 使用 fallback 模型进行审核:$FALLBACK_MODEL"
  # 告知用户审核模型
  echo "📋 已启动审核流程,使用模型:$FALLBACK_MODEL"
  sessions_spawn task="请审核这份飞书文档与原始 PDF 的一致性..." \
    model="$FALLBACK_MODEL"
fi
```

**注意**:
- 优先使用配置中的 fallback 模型
- **不需要用户确认**,直接启动审核
- 审核前告知用户使用的模型即可

**审核内容**:
1. 文档章节完整性
2. Figure 是否正确显示(非纯文字)
3. 关键数据准确性(百分比、p 值、置信区间)
4. 格式和错别字检查

#### 10. 生成审核报告

审核报告包含:
- 字数对比(原始 PDF vs 飞书文档)
- 章节完整性检查
- Figure/Table 清单核对
- 关键数据提取(百分比、p 值、样本量等)
- **修改建议清单**(逐条列出)

#### 11. 主模型审查审核意见

**主模型审查流程**:
```
1. 阅读审核报告
2. 逐条审查修改建议:
   - ✅ 合理建议 → 标记为"采纳"
   - ❌ 错误建议 → 标记为"拒绝"并说明原因
   - ⚠️ 需确认 → 标记为"待用户确认"
3. 生成最终修改方案
```

**注意**:
- 不照单全收审核意见
- 主模型对最终质量负责
- 有争议的建议提交用户确认

---

### 阶段四:人工确认

#### 12. 提交用户确认

向用户发送:
- 飞书文档链接(初版)
- 审核报告摘要
- 修改建议清单(标注采纳/拒绝/待确认)
- **确认提示**:

```
📋 文档已完成初稿和审核

✅ 已完成的修改:X 处
⚠️ 待您确认的修改:Y 处
❌ 拒绝的修改:Z 处(原因:...)

请查看文档后回复:
- "确认" → 应用所有修改,输出最终版
- "修改 XXX" → 指定需要调整的内容
- "跳过" → 直接输出当前版本
```

#### 13. 等待用户确认

**用户回复处理**:
- ✅ **"确认" / "没问题" / "可以"** → 进入阶段五(完善)
- ✏️ **"修改 XXX"** → 根据用户要求修改后重新提交确认
- ⚠️ **"跳过" / "直接输出"** → 跳过修改,进入阶段五

---

### 阶段五:完善

#### 14. 应用最终修改

根据用户确认的修改方案:
- 补充遗漏的章节
- 修正错误的数据
- 添加缺失的 Figure/Table
- 优化格式和表述

**格式标准化检查清单**(必须逐项核对):
- [ ] 文档开头:引用块包含标题、期刊、DOI、作者、接受日期
- [ ] 论文统计:使用表格格式,包含所有必填指标
- [ ] 章节标题:使用统一的标题层级(H1 → H2 → H3)
- [ ] 关键数据:加粗重要数值,补充置信区间
- [ ] 表格:所有数据表格使用统一样式
- [ ] 图片:Figure 插入到对应章节后
- [ ] 相关链接:包含原文、补充材料、数据平台、预注册链接
- [ ] **署名信息**:文档末尾必须包含撰写人和审核人(见步骤 17)

#### 15. 最终检查

- 通读飞书文档,检查格式、错别字
- 确认所有链接可点击
- 确认图片显示正常
- **核对格式检查清单**(见步骤 15)

#### 16. 添加署名信息(强制)

**在文档末尾添加署名块**(必须包含):

```markdown
---

## 📝 文档信息

| 项目 | 信息 |
|------|------|
| 撰写人 | <Agent 名字>(<主模型名称>) |
| 审核模型 | <审核模型名称> |
| 审核状态 | ✅ 已通过 |
| 生成时间 | YYYY-MM-DD HH:MM |
| 文档版本 | v1.0 |

---

*本总结由 AI 助手自动生成,如有问题请指出。*
```

**示例**:
```
撰写人:Lux(qwen3.5-plus)
审核模型:kimi-k2.5
审核状态:✅ 已通过
生成时间:2026-03-26 17:13
文档版本:v1.0
```

**注意**:
- 撰写人 = 当前 Agent 的名字(从 IDENTITY.md 或会话上下文获取)
- 主模型 = 生成文档使用的模型(如 `qwencode/qwen3.5-plus`)
- 审核模型 = fallback 模型(如 `qwencode/kimi-k2.5`)
- 如果跳过审核,标注"审核状态:⏭️ 已跳过"

#### 17. 返回最终文档

向用户发送:
- 飞书文档链接(最终版)
- 修改摘要(可选)
- 使用说明:"如有问题请随时指出,我可以进一步修改"

---

## 脚本说明

### 去重系统

| 脚本 | 功能 | 输出 |
|------|------|------|
| `extract_metadata.sh` | 提取 PDF 元数据(DOI、标题、作者、页数),生成 paper_id | JSON:`paper_id`, `doi`, `title`, `pdf_hash` |
| `check_duplicate.sh` | 检查是否已处理,判断重复/版本更新/补充材料 | JSON:`action`, `file_type`, `message` |
| `merge_supplement.sh` | 复制补充材料到 `supplements/`,提取元数据和摘要 | JSON:文件路径 + 摘要,**不操作飞书文档** |

### 原有脚本

| 脚本 | 功能 |
|------|------|
| `extract_pdf_text.sh` | 智能文本提取(pdftotext + OCR 回退) |
| `extract_pdf_images.sh` | 提取嵌入图片 + 生成清单 |
| `locate_figures.sh` | 定位 Fi