太陽がまぶしかったから

C'etait a cause du soleil.

Gemma 4のVision機能でPDFを画像のまま読み解くローカルPDFチャットツールを作ってAPI課金恐怖症から解放される

ローカルLLM実践入門

Gemma 4 でローカル Vision LLM の実用化

Google が Gemini 3 の研究をベースにした Gemma 4 をリリースした。ライセンスが Apache 2.0 に変わり、何より大きいのが Vision 対応だ。26B-A4B は MoE アーキテクチャで実質 4B 程度のアクティブパラメータしか使わないのに、テキストだけでなく画像の理解能力が実用レベルに達しているとのこと。

画像処理などはバッチ処理で大量に行う必要が出てくることもあり、その場合にAPIをガンガン叩く作りは課金額やレートリミットやポリシー違反等によるBANリスクなど怖くなってしまうポイントが多いので、ローカルで完結できると安心感がある。Claude Codeの定額内でやれないこともないが、大量処理をしようとすると嫌がって途中打ち切りや今日はやめますか?となるシステムプロンプトが組まれていると思われる挙動をされがちだったりもする。

そんなわけで、PDFファイルを画像ファイルとして切り出して、それをRAGして会話したり、文字起こしできたりするツールを作ってみた。

PDF をテキスト化せずに画像のまま Vision LLM に読ませる

LM Studio の組み込み RAG は PDF をテキスト化しようとする。しかし PDF には図表やレイアウトに意味がある文書も多く、テキスト抽出の段階で情報が欠落してしまう。特にNotebook LMで生成したスライド資料はテキスト情報を持っておらず、画像を画像のまま認識して会話する必要性がある。

構成は React のフロントエンド、FastAPI のバックエンド、MCP サーバーの3層になっている。バックエンドで PyMuPDF を使って PDF の各ページを PNG 画像にレンダリングし、base64 エンコードして LM Studio の Vision モデルに渡す。

LM Studio は OpenAI 互換のエンドポイントを持っているため、フロントエンドからのリクエストをバックエンドがリバースプロキシとして中継し、SSE ストリーミングでリアルタイムに応答を返す。MCP サーバー経由で Claude Desktop や Cursor からも PDF の画像を引き出せるようにもしている。OpenAI 互換 API がローカル LLM のデファクトになっていることで、モデルの差し替えが簡単になっていのがありがたい。

ローカルで「見える」LLM の衝撃

実際に手元の PDF を読ませてみると、テキスト主体のページはもちろん、図表やフローチャートを含むページでも内容を構造的に理解して回答してくれる。試しに技術書の見開きをそのまま画像にして投げたところ、コードブロックの中身まで拾って解説を返してきた。テキスト抽出 → RAG のパイプラインではこうはならない。

技術的に面白いのはビジョンエンコーダの設計だ。Gemma 3 の SigLIP から MobileNet-v5 ベースに移行し、画像トークン予算が 70、140、280、560、1120 の5段階で調整できる。これはゲームのグラフィック設定で解像度とフレームレートをトレードオフするのに似ていて、分類やキャプション生成なら低トークンで回し、OCR やドキュメント解析なら高トークンに振るといったバジェット戦略が取れるとのこと。

API 課金の問題が電気代の問題に変わる

ローカル LLM の活用先は少しずつ広がってきた。コードレビューの lint 的な用途、ブラウザ組み込みの要約、アンビエントエージェントの判定処理。そして今回の PDF の画像認識。共通しているのは、API を叩くほどではないが人間がやるには面倒な処理をローカルで黙々と回すという使い方だ。

大量処理が必要な場面では「API 課金がいくらになってしまうのか」という問題が「現実的な時間で終わるか」と「電気代はいくらか」の問題に変わり、大抵は後者のほうが圧倒的に安い。unsloth が公開している gemma-4-26B-A4B-it-GGUF の 4bit 量子化版は 18GB 程度、31B の Dense モデルですら Q4_K_M なら 20GB 弱程度のマシンで動く。もっと小さなモデルはスマートフォン上でも動いている。

ナレッジカットオフがある以上はどの道 RAG で外部知識を注入することになるのだから、個別具体的な知識を持たせる部分にパラメータを使う必要はあまりない。推論能力と Vision の認識精度にパラメータを集中させ、知識は外から渡す。この割り切りが MoE による軽量化と噛み合って、ローカルで動かせるサイズに収まっているのだろう。

何にせよ、ちょっとしたバッチ処理だからこそローカルLLMの利用が選択肢に入っていく時代になったのかもしれないと改めて思った。