モチベーション
論文を読む際はxxxのようなPDF翻訳サービスを使って読むことも多いと思います(サービスのネガキャンになってしまうので名前は伏せます)。私自身xxxをサービスができた初期の頃からProブランを契約してずっと使っていました。
しかし、ページの境目や文章の改行、間の図表の挿入などによって、翻訳がおかしくなることが頻繁にあったのと、論文は専門用語が多いためか、翻訳自体の精度もあまり満足できるものではありませんでした。そのため、翻訳した文章は頑張れば読めるが、読むに耐えないレベルの文章になることがしばしばでした。
そのサービスはPDFのレイアウトを保ったまま翻訳できるということを売りにしていましたが、正直レイアウトが保たれるかどうかはどうでもよくて、論文の内容がきちんと翻訳されてくれればそれでいいわけです。
そのサービスだけが特に質が悪いというわけでもなく、似たようなサービスはいくつもありますが、どれも同様の問題を抱えていました。PDFというものがあまりにも機械処理しづらい形式であるということが全ての元凶だということです。
PDFの内容をマークダウン形式に正しく変換できれば、ブラウザやエディタなど様々なツールで容易にレンダリングできて、処理しやすい文書形式で手元に保持できるため、翻訳をかけやすくなります。例えばブラウザ上でレンダリングされた状態で表示できれば、Google翻訳などの好きな翻訳ツールでページ翻訳できます。
なんとかPDFをMrkdown形式に変換しようと小1時間試みた結果、最終的にはClaude Codeでやるのが一番快適だったので、その話を共有できればと思います。
試したこと
最初はPDFをMarkdownに変換するライブラリをいくつか試してみました。PyMuPDFやpdfplumberなどを使って簡単なPythonスクリプトを書いたり、Microsoftが出しているMarkitdownなんかを使って、The design of a practical system for fault-tolerant virtual machinesという論文のPDFをMarkdownに変換してみましたが、論理構造が正しく保持されなかったり、文章が二重に表示されたり、不自然な改行が挟まったり、図表で使われている文字やフッターが悪さをしてしまったりと、あまり満足できる結果にはなりませんでした。この状態の文章に対して翻訳をかけても読むに耐えない文章しか生成されないことは目に見えています。
Claude Codeを使って変換
そもそもPDF自体が文章の論理構造情報を正しく保持していないため、単純な機械処理で変換を行うのは限界があります。人間のように意味を解釈して変換を行う必要があるのです。そのため、少しコストはかかりますがLLMを用いて変換を行うことにしました。10ページ程度のフルペーパーであれば最近のLLMのコンテキストに収まるのでさほど苦労せずにできるはずです。
すでに言及したように変換にはClaude Codeを用いたのですが、その理由としては生成されるMarkdownが長くなるので出力結果をファイルに書き込んでくれるのが嬉しい、そのままGitHubにpushしてMarkdownをレンダリングしてブラウザで表示できる、Claude CodeはProプランを契約しているので追加コストがかからないというのが挙げられます。
下記のようにカスタムスラッシュコマンド(.claude/commands/pdf2md.md
)を作成して対象のPDFのパスを指定して実行してみました。Markdownのリンターにはmarkdownlintを使用しています(一行の長さが80文字以上になるとリントエラーになるMD013ルールはあらかじめ無視するように設定)。
# PDFをマークダウン形式に変換する
1. 引数で指定されたPDFと同じディレクトリに、同じファイル名で.mdファイルを作成する。
2. PDFを読んでセクション構造をマークダウン形式でマークダウンファイルに出力する。セクション番号はPDFの番号に従うこと。
3. セクションごとに、「このセクションの内容をマークダウン形式に変換し、マークダウンファイルの該当のセクションの部分に挿入する。段落ごとに空白行で区切ること。」というサブタスクを生成する。
4. 生成したサブタスクを順番に実行する。
5. 全てのセクションを1つずつ確認し、空白のセクションがないかを確認する。空白のセクションがあれば修正する。
6. `pnpx markdownlint-cli2 <マークダウンファイル名>`を実行してフォーマットをチェックし、エラーがあれば修正する。
結果
5分弱で全体の処理が終わり、Markdown形式に綺麗に変換することができました。GitHubでレンダリングすると下記のようになります。論理構造がきちんと保持されていて、不自然に文章が分割されるようなこともありません。
気軽にGoogle翻訳でページ翻訳できるのでとても扱いやすいです。またはさらにLLMを使ってより良い翻訳をさせることも可能だと思います。
ちなみに参考までに某xxxというサービスを使って翻訳した結果です。読むのが大変なほど翻訳がひどいのがわかります、、。
追記:画像の挿入について
何度か試しましたが、結局はClaude CodeはPDFから図表を正しく抽出して載せるということが苦手なようです(多分画像の正確な座標位置を把握することができない)。なので私は図表があるページ全体を画像としてマークダウンに挿入することにしました。カスタムスラッシュコマンドの内容は下記のようになります。気になるようなら手動でページ全体の画像から図表部分のみを切り取って画像を修正すればいいだけなので、そこまで手間ではないと思います。
pdftoppm
コマンドはbrew install poppler
でインストールできます。
# PDFをマークダウン形式に変換する
1. 引数で指定されたPDFと同じディレクトリに、同じファイル名で.mdファイルを作成する。
2. PDFを読んでセクション構造をマークダウン形式でマークダウンファイルに出力する。セクション番号はPDFの番号に従うこと。
3. セクションごとに、「このセクションの内容をマークダウン形式に変換し、マークダウンファイルの該当のセクションの部分に挿入する。段落ごとに空白行で区切ること。」というサブタスクを生成する。
4. 生成したサブタスクを順番に実行する。
5. 全てのセクションを1つずつ確認し、空白のセクションがないかを確認する。空白のセクションがあれば修正する。
6. 図表の挿入: PDFに図表(Figure、Table、Chart等)が含まれている場合は以下の手順で処理する:
- `pdftoppm`を使用してPDFの各ページをPNG画像として抽出し、`images/`ディレクトリに保存する
- 各図表が含まれるページを特定し、ページ全体の画像を適切な箇所にマークダウン形式で挿入する
- 図表の参照は `` の形式で行う
- 図表の切り取りは行わず、ページ全体の画像をそのまま使用する
- 使用しないページの画像は削除する。また使用するページの画像については名前に図表の名前をつける(例: `images/figure-1.png`)。
7. `pnpx markdownlint-cli2 <マークダウンファイル名>`を実行してフォーマットをチェックし、エラーがあれば修正する。
おわりに
今回はClaude Codeを使って快適な論文読みをする方法を共有しました。PDF自体が魔境なので、最終的にはLLMのような意味を解釈して変換する形でないと綺麗にMarkdown形式に変換することは難しいと思います。10ページ程度のPDFであれば5分程度で気軽に処理できますし、何よりも高いサブスク費用を払わずにすむというのがとてもありがたいです。興味のある方はぜひ試してみてください。