Operational Steps
- 确认输入参数完整
- 执行核心操作(参考本目录下的 scripts/ 或 references/)
- 验证输出符合契约
- 保存结果并报告
Pitfalls
-
-
Verification
-
-
-
-
1. 2. 3.
IO_CONTRACT
- input:
request: str, context: dict— 用户请求描述、上下文信息 - output:
result: dict — 技能执行结果(结构因技能而异)
对应原则:P2(机械原子暴露输入输出规范)
MarkItDown → Markdown 转换
微软开源文档转 Markdown 工具。支持 PDF、DOCX、PPTX、Excel、图片。 安装:
uv tool install markitdown --with markitdown[pdf]
⚠️ 强制前置:PDF→MD 是下载后的标准步骤,非可选
2026-05-31 确认:所有论文管线必须将 PDF→Markdown 转换 作为下载后的强制步骤。
原因:
- Layer B 双质检需要全文文本,仅 PDF 不可靠(NotebookLM 索引 PDF 经常 error)
- Markdown 格式在 NotebookLM 中 100% 索引成功
markitdown优于pdftotext:保留数学公式(LaTeX内联)、表格结构、章节标题
标准目录结构:PDF 和 MD 共存,MD 放在 pdfs_md/ 子目录:
06-references/
├── pdfs/ # 原始 PDF(用于 D9 验证)
│ ├── Smith1988.pdf
│ └── ...
└── pdfs_md/ # 转换后的 Markdown(用于质检 & NotebookLM)
├── Smith1988.md
└── ...
批量转换参考文献 PDF(推荐脚本)
python3 << 'PYEOF'
import subprocess, os
pdf_dir = "06-ref/pdfs"
md_dir = "06-ref/pdfs_md"
os.makedirs(md_dir, exist_ok=True)
for f in sorted(os.listdir(pdf_dir)):
if not f.endswith('.pdf'): continue
bibkey = f.replace('.pdf', '')
out = f'{md_dir}/{bibkey}.md'
if os.path.exists(out) and os.path.getsize(out) > 100:
continue # 跳过已有缓存
r = subprocess.run(['uvx', 'markitdown', f'{pdf_dir}/{f}'],
capture_output=True, text=True, timeout=120)
if r.returncode == 0 and len(r.stdout) > 50:
with open(out, 'w') as fh: fh.write(r.stdout)
print(f'{bibkey} — {len(r.stdout):,} chars ✅')
else:
# Fallback: pdftotext
r2 = subprocess.run(['pdftotext', f'{pdf_dir}/{f}', '-'],
capture_output=True, text=True)
if len(r2.stdout) > 100:
with open(out, 'w') as fh: fh.write(r2.stdout)
print(f'{bibkey} — pdftotext ⚠️ ({len(r2.stdout):,} chars)')
else:
print(f'{bibkey} — ❌ 无可提取文本')
with open(out, 'w') as fh:
fh.write(f'# {bibkey}\n\n[PDF无法提取文本 — 需手动补摘要或走OCR]\n')
PYEOF
单文件转换
uvx markitdown input.pdf > output.md
实战成功率
| 类型 | 比例 | 说明 |
|---|---|---|
| 正常学术PDF | ~35/40 (87.5%) | MarkItDown 直转成功 ✅ |
| 无文本层/损坏PDF | ~5/40 (12.5%) | 需手动补摘要或走 OCR |
| arXiv PDF (旧版) | 多数 OK | 少数 2016前 PDF 无文本层 |
损坏PDF检测
部分下载PDF虽报告 %PDF- 头,但 xref 表破损/catalog 缺失,所有工具均无法提取文本:
# 检测方法
python3 -c "
import re
with open('file.pdf', 'rb') as f:
content = f.read()
text_chars = sum(1 for b in content if 32 <= b < 127)
strings = re.findall(rb'[ -~]{10,}', content)
print(f'Readable chars: {text_chars}/{len(content)} ({text_chars/len(content)*100:.1f}%)')
for s in strings[:5]: print(s.decode(errors='ignore')[:80])
"
# 损坏PDF典型表现:
# - pdftotext 返回 0 字符
# - pymupdf.get_text() 返回 0 字符
# - mutool 报 "cannot find page tree"
# - file 命令报 "PDF document" 但 ImageMagick 报 "Catalog dictionary not located"
处理策略:
- 寻找 arXiv/PMC 替代版本(多数经典论文有线上全文)
- 手动写摘要(知名论文如 SMOTE、LIME、CRISP-DM)
- 走 OCR 管线(marker-pdf,见下方)
OCR 替代(MarkItDown 不做 OCR)
扫描版/纯图像 PDF 需使用 marker-pdf(见下方):
# Tesseract OCR(英文)
pdftoppm -png -r 200 input.pdf /tmp/page
for f in /tmp/page-*.png; do
tesseract "$f" "${f%.png}" -l eng
done
cat /tmp/page-*.txt > full_text.txt
论文批量转换(含引用PDF过滤)
科学论文目录常混有自己的论文与参考文献PDF。转换时必须过滤引用,否则会转错目标。
找主论文 PDF 的策略
按优先级:
- 最大 PDF(排除明显引用:
*reference*,*template*,*graphical*) - 最新修改的 PDF(revision 日期最新的)
- 与目录名匹配的 PDF
OUTPUTS="outputs/papers"
for paper_dir in "$OUTPUTS"/*/; do
main_pdf=$(find "$paper_dir" -maxdepth 2 -name "*.pdf" \
-not -iname "*graphical*" -not -iname "*template*" \
-printf '%s\t%p\n' 2>/dev/null | sort -rn | head -1 | cut -f2)
if [ -n "$main_pdf" ]; then
uvx markitdown "$main_pdf" > "$paper_dir/paper.md" 2>/dev/null
fi
done
陷阱:引用PDF命名为 hooge2021pupil.pdf 等作者年格式,容易被当作主论文。始终用 -not -name 排除已知引用模式。
TeX 替代方案(无可用 PDF 时)
cd "$tex_source_dir"
pandoc paper.tex -f latex -t markdown --wrap=none --mathjax -o paper.md
⚠️ 从源文件目录执行 pandoc,否则 .bib 引用解析失败。
依赖
- Python 3.10+, uv
uv tool install markitdown --with markitdown[pdf]- 不加
[pdf]extra 会报MissingDependencyException
转换后处理:添加 Obsidian frontmatter
生成的 paper.md 缺少 YAML frontmatter,Obsidian 无法识别标签/别名。转换完成后补充:
python3 -c "
import os
path = 'paper.md'
with open(path) as f: content = f.read()
if not content.startswith('---'):
fm = '''---
tags: [paper, your-tags-here]
aliases: [Paper Title]
---
'''
with open(path, 'w') as f: f.write(fm + content)
"
已知限制
- 数学公式 → LaTeX 内联文本,非渲染格式
- 表格可能展平
- 多栏 PDF 需额外处理
- MarkItDown 无 OCR — 扫描版 PDF 使用 marker-pdf(见下方)
相关文件
references/synthos-paper-conversion-2026-05-27.md— 本会话的 8 篇论文转换记录
验证清单 · VERIFICATION
- 安装使用
uv tool install markitdown --with markitdown[pdf],无MissingDependencyException - 每个 PDF 均有对应
.md存在于pdfs_md/,输出 >50 chars 且非空文件 - markitdown 失败时已回退
pdftotext;仍失败则写入[PDF无法提取文本]占位而非静默跳过 - 批量转换已排除引用/模板类 PDF(
*reference*/*template*/*graphical*/作者年格式),主论文未转错目标 - 损坏/无文本层 PDF 已走替代路径(arXiv/PMC 替代版、手动摘要或 marker-pdf OCR)
- 用于 Obsidian 的
paper.md已补 YAML frontmatter(tags + aliases)
约束规则 · RULES
- 输入约束: 参数类型、范围、格式必须校验
- 输出约束: 返回值结构、编码、命名必须一致
- 异常约束: 错误信息必须包含上下文和恢复建议
- 安全约束: 不执行未验证的任意代码,不暴露内部状态
Golden 集合 · GOLDEN SET
- Golden Input: 标准输入样本(覆盖正常路径)
- Golden Output: 预期输出(精确匹配或格式校验)
- Golden Error: 预期错误信息(覆盖失败路径)
Golden 集合是测试的单一真理来源。所有改进必须通过 golden 测试。
违反规则的操作视为不安全,必须拒绝或隔离。
每项验证必须可执行、可记录、可复现。验证失败时记录原因和修复。
示例 · EXAMPLES
单文件 PDF→Markdown 转换
- 输入:
report.pdf(学术 PDF,含文本层) - 操作:
uvx markitdown report.pdf > pdfs_md/report.md - 验证:
wc -c pdfs_md/report.md输出 >50 chars,且保留 LaTeX 公式与章节标题
- 输入:
批量转换参考文献目录(含回退与缓存)
- 输入:
06-ref/pdfs/下 40 个 PDF - 操作: 运行"批量转换参考文献 PDF"脚本,
markitdown失败时回退pdftotext - 验证:
pdfs_md/中每个 PDF 均有对应.md;成功率约 87.5%,失败项写入[PDF无法提取文本]占位而非静默跳过
- 输入:
扫描版 PDF 走 OCR 替代
- 输入:
scan.pdf(纯图像,无文本层) - 操作:
pdftoppm -png -r 200+ Tesseract(-l eng)逐页提取并合并 - 验证:
full_text.txt含可读文本;markitdown对该文件返回 0 字符时即应转入此路径
- 输入:
Markitdown Convert
Genes (策略基因)
紧凑策略表示。条件→策略。需要深度时参考完整文档。
- [MARK-001] 处理学术 PDF 管线 → 必须将 PDF 转换为 Markdown 作为下载后的强制步骤,以确保全文文本可被可靠索引和质检
- [MARK-002] 执行批量 PDF 转换 → 优先使用
markitdown工具,若失败或输出过短则自动回退至pdftotext,并跳过已存在且大小有效的缓存文件 - [MARK-003] 遇到无文本层或损坏的 PDF → 依次尝试寻找 arXiv/PMC 替代版本、手动补写摘要或启动 OCR 管线(如 marker-pdf),而非直接报错终止
- [MARK-004] 在混合目录中识别主论文 PDF → 优先选择体积最大且排除引用/模板特征的 PDF,其次考虑最新修改时间或文件名匹配度
- [MARK-005] 转换结果需用于 Obsidian 笔记系统 → 检查生成的 Markdown 是否包含 YAML frontmatter,若缺失则自动注入 tags 和 aliases 字段
- [MARK-006] 安装 MarkItDown 依赖 → 必须使用
uv tool install markitdown --with markitdown[pdf]命令,缺少[pdf]extra 会导致依赖缺失异常 - [MARK-007] 处理扫描版或纯图像 PDF → 识别 MarkItDown 无 OCR 能力的限制,转而使用 Tesseract 或 marker-pdf 等专用 OCR 工具进行文本提取