Skip to content

About

论文 PDF 翻译与辅助阅读工具:保留排版的翻译 + 图内文字翻译 + 带引用的阅读助手

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

Paper Reader

论文 PDF 翻译与辅助阅读工具(自用)。

核心思路:不重造翻译内核,只补它的盲区。

  • 翻译 + 排版保留 → 复用 pdf2zh-next(BabelDOC 内核)。 它已实现正文、图注、表格、图内有文本层文字的翻译。
  • 我们的增量 → BabelDOC 处理不了的 text-as-path 图内文字(轴标签/图例/刻度), 以及它没有的 Web 阅读体验。

详见 docs/technical-design.md(含 M0/M1/M2 全部实测报告)。

功能

能力 说明
翻译 上传 PDF → 保持排版的双语/纯译文 PDF
图表 提取图表 → OCR 识别图内文字 → 擦除回填中文;原图/译文对照
助手 问答 / 总结 / 资料筛选,答案带引用编号,点击跳回原文高亮
阅读 PDF.js 虚拟滚动、三态切换(原文/纯译文/双语)、缩放
术语表 BabelDOC 自动提取,可下载
进度 翻译与图表处理都有 SSE 实时进度,可取消

助手能力

能力 用途 示例
问答 针对论文提问 「预训练用了哪两个任务?」→ 答案每个结论后带 [p3-c7]
总结 结构化摘要 一句话 / 问题 / 方法 / 结果 / 贡献 / 局限(JSON 渲染成卡片)
资料筛选 找「论文里讲 X 的部分」 按主题返回按相关度排序的段落 + 为什么相关

核心体验:答案里的 [p3-c2] 是可点击的——点一下 PDF 就滚到那段并高亮。 这是它区别于普通聊天窗口的地方:答案可验证。

实现上没有用向量检索:论文正文通常 8k–20k tokens,模型能整篇吃下, 而且看全文比看检索片段准得多(也省掉 embedding 依赖)。

快速开始

需要 uv 和 Node.js。

# 后端(首次会下载布局模型约 337MB 到 ~/.cache/babeldoc/)
uv sync --python 3.12
uv run pdf2zh_next --warmup        # 可选:预热模型
uv run uvicorn backend.main:app --host 127.0.0.1 --port 8000

# 前端(另开一个终端)
cd web && npm install
npx vite --port 5173

打开 http://127.0.0.1:5173/ ,上传 PDF,点「翻译」;翻译完成后点「图表」提取并翻译图内文字。

LLM 配置

两种方式:前端「⚙ 模型设置」直接切(推荐),或改 config.toml 手动配。

cp config.toml.example config.toml     # 两者都已被 .gitignore 排除

配置分层:

数据 存哪 说明
provider 定义(base_url / model / key) config.toml 单一配置源,含敏感信息
用户选择(翻译/问答各用哪个) SQLite 页面上改,立即生效

开箱可用:不建 config.toml 也能跑 —— 默认用 pdf2zh-next 官方免费翻译服务(免 key)。

支持的 provider 类型(只有三种):

type 覆盖 例子
openai_compat 绝大多数厂商 DeepSeek、SiliconFlow、Ollama、OpenAI、自建 vLLM
cli 订阅制工具 claude -p(Claude Code)、codex exec、任意 CLI
free_proxy 内置免费服务 pdf2zh-next 官方 chatproxy

当前默认(实测数据见技术方案 §21):

provider_translate = "siliconflowfree"   # 1-3s/条,批量场景
provider_chat      = "claude"            # 15-45s,比 codex 快且更完整
能力 Codex Claude
问答 54s 26s
总结 50s (2 条贡献) 45s (4 条贡献)
资料筛选 43s 15s

用途分离:翻译(短文本、要便宜快)和问答(长上下文、要强)可以指向不同 provider:

[llm]
provider_translate = "siliconflowfree"   # 快:1-3s/条
provider_chat      = "codex"             # 强:35-48s/条

[llm.providers.codex]                    # 已登录的 Codex 订阅
type    = "cli"
command = "codex exec --skip-git-repo-check -o {outfile}"
mode    = "arg"

实测的取舍:Codex 做图表翻译质量没问题,但一张复杂图有 100+ 条标签, 按 40s/条算要一小时以上 —— 翻译必须用轻量服务,重模型留给问答。

CLI 类 provider 的 {outfile} 技巧:codex exec 会在 stdout 打印 session id、 tokens used、warnings 等噪音。用它的 -o 选项把「最后一条消息」单独写文件即可拿到干净输出:

command = "codex exec --skip-git-repo-check -o {outfile}"

Claude Code(需要先 claude auth login):

[llm.providers.claude]
type    = "cli"
command = "claude -p"
mode    = "arg"        # prompt 自动追加到命令末尾

⚠️ 重要限制:siliconflowfree 是受限制的翻译代理,只接受特定格式的 翻译 prompt(其他内容返回 400 Keyword not allowed)。 做问答必须配真正的 LLM provider。详见技术方案 §17.4。

为什么不默认用 Google:实测会触发 HTTP 429 限流(见技术方案 §12.3)。

目录结构

backend/
├── main.py               FastAPI 端点
├── tasks.py              后台任务 + SSE 进度广播(翻译 / 图表 / 助手共用)
├── models.py / db.py     SQLModel + SQLite
├── config.py             路径与默认配置
├── ir/                   文档结构解析(M3 地基)
│   ├── parse.py          段落切分 + 章节树 + bbox
│   └── store.py          IR 落盘缓存
├── assist/               辅助阅读(M3)
│   └── service.py        问答 / 总结 / 资料筛选 + 引用解析
├── llm/                  统一 LLM 接入层
│   ├── base.py           Message / Usage / Provider 协议
│   ├── openai_compat.py  覆盖 DeepSeek/Ollama/任意自建
│   ├── cli.py            覆盖 Claude/Codex 订阅
│   ├── free_proxy.py     官方免费翻译服务
│   └── registry.py       配置加载 + 按用途解析
├── pipeline/translate.py pdf2zh_next 官方 API 封装
└── figures/              M2 图内文字翻译
    ├── detect.py         图表区域检测
    ├── ocr.py            macOS Vision OCR(分区调用)
    ├── labels.py         文字提取 + 代码块过滤
    ├── render.py         擦除 + 回填
    ├── validate.py       翻译结果校验闸门(数字/相似度/代码)
    ├── translate.py      图表翻译(走 LLM 层)
    ├── service.py        编排
    └── store.py          JSON 索引 + 图片存储

web/
├── src/App.tsx           主界面
├── src/api.ts            API 客户端 + SSE 订阅
└── src/components/
    ├── PdfViewer.tsx     PDF.js 渲染(虚拟滚动 + 引用高亮)
    ├── FigurePanel.tsx   图表面板
    └── AssistPanel.tsx   助手面板(问答/总结/筛选)

config.toml.example       LLM 配置模板
docs/technical-design.md  技术方案与实测报告(§1-19)

关键实现笔记

几个踩过的坑,改代码前值得先看:

  1. ConfigManager.initialize_config() 会解析 sys.argv —— 在 uvicorn 进程里会 SystemExit。 pipeline/translate.py 里做了临时遮蔽,别删。
  2. FastAPI 同步端点里不能调度 asyncio 任务 —— /translate 必须保持 async def。
  3. OCR 必须分区 —— 整张大图识别率只有分区的 1/12(技术方案 §14.2)。
  4. 去重不能只看 bbox —— 必须配合文本相关性判断,否则会误删大量真实短标签(§14.3)。
  5. 擦了没填最危险 —— 所有回填路径都保证「有译文 → 才擦 → 才填」(§5.4.5)。
  6. 翻译结果必须过校验闸门 —— 数字一致性 / 相似度 / 代码模式,任一不过就保留原文 (§16.1)。闸门放在 figures/validate.py,改动那块务必跑一下 test_validate 的用例。
  7. 回填中文不要手工算坐标 —— CJK 字体 ascender 留白会让中文系统性偏下; 字号也不能直接用 bbox 高(英文 bbox 含行距,中文是方块字)。(§16.2)
  8. PDF.js 文本层有三个隐式依赖,少一个就"框选对不上字" —— --scale-factor(不设则 span 的字号声明整条失效、退回 body 的 14px)、 lang(不设则浏览器给「量宽度」和「渲染」选两套字体,实测宽度差 5.9%)、 以及字号必须是整数像素(非小数会让 Chromium 的跨元素拖选失效,译文页整页拖不动)。 排查与验证数据见技术方案 §24、§26。

已知问题

见技术方案 §16.6。主要剩余限制:

  • OCR 漏检/误识仍存在 —— 校验保证了「不乱写」,但不保证「全覆盖」。 未被识别或被拒绝的标签会保留英文原文。
  • 部分轴标题被 OCR 切成多段时,可能只有一段被翻译。

已修复(见 §16):数字被改写、中文叠字、字号偏大、图表任务无取消入口。

许可证

AGPL-3.0 —— 与所依赖的 pdf2zh-next / BabelDOC 保持一致。

本项目调用 pdf2zh-next 的公开 Python API,没有复制它的源码; 选同一个许可证是为了消除「分发一个 AGPL 依赖」这件事上的任何争议。 如果你把它跑成对外的网络服务,同样需要公开你的修改。

About

论文 PDF 翻译与辅助阅读工具:保留排版的翻译 + 图内文字翻译 + 带引用的阅读助手

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages