1实现原理 · 为什么它能做到
管线是 extract → look → (translate) → build → verify,中间『看』与结尾『验』被定为忠实度的真正来源——PDF 是版式不是文本流。
The pipeline is **extract → look → (translate) → build → verify**. The middle "look" and final "verify" steps are where faithfulness actually comes from: a PDF is a layout, not just a text stream, so you read the rendered pages before building and the rendered HTML before delivering.
extract_pdf.py 产出可复核中间态:structure.json(每页文本块带 bbox+最大字号,图片块带 decorative 标记)+ images/ + 每页渲染 PNG,阅读顺序沿用 PyMuPDF 的 get_text('dict') 块序。
The point of a separate extraction step is a *verifiable intermediate output*: structure.json is the plan. Inspect it (and the rendered page PNGs) before building, instead of going PDF -> HTML in one opaque jump.
build_html.py 是数据驱动通用构建器:从字号统计推断标题层级(最常见字号=正文,更大逐级升 h3/h2/h1),去掉 decorative 图,内容图压成 base64 内联——单文件可双击打开。
`build_html.py` is **data-driven**: it infers heading levels from font size (most common size = body; larger steps up to h3/h2/h1), drops decorative images, and inlines content images as compressed base64 → one portable file. It is not hand-tuned to any document.
翻译分支不走『整文机器翻译』,而是 agent 按 references/translation_workflow.md 用 Dynamic Workflow 并行翻页、图表图注单独成文、术语统一,产出 units.json/caps.json 两个 overlay 交给 build 消费。
It produces two overlay files (`units.json`, `caps.json`) that step 4 consumes. **Do not** hand-translate inline for anything longer than a page — the workflow keeps terminology consistent and is far faster.
强制视觉验证:verify_render.py 用 headless Chrome 截图并按 ~2600px 切片(先 1x 探真实内容高、再选最大 device-scale-factor 避开 16384px 截图上限),agent 必须逐张 Read seg-*.png。
```bash uv run --with Pillow --with numpy python scripts/verify_render.py output.html ``` Then **Read every `seg-*.png`** and check: fonts render (no tofu boxes), no clipped tables/figures, headings/lists look right, all expected images present.
忠实度铁律写在 references/failure_cases.md:绝不给人名/专名推断翻译、每个数字/专名逐字照抄(failure_cases #6),翻译前必读。
The one that bites hardest: **never give a real person an inferred translated name, and copy every number/proper-noun verbatim** (failure_cases #6). Read that file before any translation run; skim it before any run.
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| package | PyMuPDF (fitz)(extract_pdf.py,uv run --with pymupdf) |
| cli | Google Chrome / Chromium(headless 视觉验证) |
| package | Pillow / numpy(build 与 verify,uv --with) |
4风险提醒 风险提醒:蓝色 · 知晓即可
- 复杂版式(多栏表格/图文混排)会被摊平 — SKILL 自述 PyMuPDF 把表格当文本块读,列对齐会丢失;像素级还原不在承诺内。需要表格网格时应转 doc-to-markdown。
- 扫描件必须先行 OCR — 无文本层 PDF 直接跑会失败/空提取,需 ocrmypdf 前置——依赖链加长。
- 翻译质量依赖模型与人工把关 — Dynamic Workflow 是 agent 编排,无独立翻译 API;专名/数字铁律要靠执行者遵守,交付前必须读图核对。
- 视觉验证需要 GUI/Chrome 环境 — 无头服务器需装 Chrome;verify 环节依赖截图工具链(--no-sandbox 无沙箱运行)。
5第二遍独立确认
- [ok] extract→look→build→verify 管线 — SKILL 三步命令与三个脚本一一对应;structure.json 字段(bbox/字号/decorative)在 extract_pdf.py 实现。
- [ok] 字号推断标题层级 — build_html.py 从 font size 推断 h3/h2/h1 的逻辑在 docstring 与代码中均有('larger sizes step up to h3/h2/h1')。
- [ok] base64 内联单文件 — build_html.py data_uri():压缩→JPEG/PNG→base64;'single portable .html you can double-click' 相符。
- [ok] decorative 判定启发式 — extract_pdf.py:DECORATIVE_MAX_BYTES=3000 + bbox 重复 > 半数页面(max(2, npages//2))。
- [ok] 强制视觉验证 headless Chrome 分片 — verify_render.py:1x 探高 + device-scale-factor 选择 + SEGMENT_PHYSICAL 分片;SKILL 要求 Read every seg-*.png。
- [ok] 翻译 overlay 机制 — translation_workflow.md 存在且描述 units.json/caps.json 产出;build_html.py 接受 --translation/--captions 参数。
- [ok] 无网络外发/转义防注入 — 三脚本无 requests/urllib/http;build_html.py md() 对段落文本 html.escape;--no-proxy-server 防代理泄漏。
- [ok] 元数据 — GitHub API:MIT / 1385 stars / pushed 2026-09-09T12:33:29Z;本地 HEAD==pin d5c4678。
6结论
a8f3ffec2f8cdcaa…d5c4678cb5