Node.jsとWASM製ライブラリでPDFからテキスト抽出・画像変換CLIツールのプロトタイプ開発
近年、ドキュメントの内容をAIで活用するRAG (Retrieval-Augmented Generation) などの技術が注目されています。その前処理として、PDFファイルからテキストや画像を抽出し、ベクトル化する需要が高まっています。
今回は、この前処理の第一歩として、Node.jsで動作するPDF処理CLIツールをプロトタイプ開発しました。
この記事では、開発の背景、特にWebAssembly (Wasm) を採用した技術選定の理由、そして実装したツールの概要についてご紹介します。
最終的な目標は、ユーザーがアップロードしたPDFを処理し、その内容(テキストや画像)をベクトル化してデータベースに保存するWebアプリケーションを構築することです。開発スタックとしては、VercelとNext.jsを想定しています。
ここで課題となるのが、PDF処理ライブラリの依存関係です。多くのPDF処理ライブラリは、poppler
やImageMagick
といったネイティブバイナリに依存しています。これらのバイナリは、Vercelのようなサーバーレス環境では簡単に利用できず、追加のビルド設定や環境の制約が発生しがちです。
そこで、プラットフォームに依存しないWebAssembly (Wasm) でビルドされたライブラリに着目しました。WASMであれば、特別な環境構築なしにNode.jsランタイムで直接実行できるため、サーバーレス環境との相性が抜群です。
今回のプロトタイプでは、以下のWASMベースのパッケージを採用しました。
@hyzyla/pdfium
: GoogleがメンテナンスするPDFレンダリングエンジン「PDFium」のWASMビルドです。PDFの読み込み、テキスト抽出、ページごとのレンダリングなど、強力な機能を提供します。@jsquash/png
: 高速な画像コーデックライブラリlibspng
をWASM化したものです。PDFiumでレンダリングしたビットマップデータをPNG形式にエンコードするために使用します。これらのライブラリはnpm install
するだけで必要なWASMアセットがダウンロードされ、追加のビルドステップなしで利用できる手軽さも魅力です。
開発したCLIツール pdf-tool
は、指定されたPDFファイルに対してテキスト抽出と画像変換を実行できます。
# 基本的な使い方
node ./bin/pdf-tool.mjs <pdf-path> [options]
主な機能は以下の通りです。
--text-out
, --text-format
)--text-join
)--png-dir
)--scale
, --width
, --height
)1,3-5
) (--pages
)--password
)いくつか具体的なコマンド例を見てみましょう。
1〜3ページ目を対象に、テキストをJSON形式で output/sample.json
に、ページ画像を2倍の解像度で output/images/
ディレクトリに出力します。
node ./bin/pdf-tool.mjs ./docs/sample.pdf \
--pages 1-3 \
--text-out output/sample.json \
--text-format json \
--png-dir output/images \
--scale 2
PDF内のすべてのテキストを抽出し、改ページを無視して1つのテキストファイルとして保存します。LLMへの入力データ作成などに便利です。
node ./bin/pdf-tool.mjs ./docs/sample.pdf --text-out output/sample.txt --text-join
ソースコードは機能ごとにモジュール化しています。
src/pdfium/
: PDFiumの初期化やドキュメント読み込みに関するヘルパー関数src/text/
: テキスト抽出処理のロジックsrc/image/
: ページのレンダリングとPNGエンコード処理のロジックbin/pdf-tool.mjs
: 上記モジュールを束ね、コマンドライン引数を解釈するエントリーポイントこのように関心を分離することで、将来的にNext.jsのAPI Routesなどに機能を移植しやすくなります。
今回は、Vercel + Next.js環境での利用を見据え、WASMベースのライブラリを活用してPDF処理CLIツールのプロトタイプを開発しました。これにより、環境依存を気にすることなく、堅牢なPDF前処理基盤の実現可能性を確認できました。
今後は、このプロトタイプをベースに、
といった機能拡張を進めていく予定です。
WASMのおかげで、これまでサーバーサイドで扱いにくかった処理も、JavaScript/Node.jsエコシステムの中で完結させられるようになり、開発の幅が大きく広がったと感じます。
以上、現場からお送りしました。