OllamaでローカルLLMを運用に組み込む — 使いどころと限界
GRAXELがローカルLLMをどのようにコスト削減と自動化に使うかを整理します。
ローカルLLMを本番環境で運用する — 高額なAPI請求からの脱却
高額なOpenAI APIの請求書を見て、息を呑んだ経験はありますか?私はあります。わずか数週間のテスト運用で、個人開発者としては無視できない数百ドルの請求が発生した時、私はローカルLLMの本格的な導入を決意しました。Ollamaを活用して、deepseek-r1:14bやnomic-embed-textを本番環境で安全に運用する方法について、私の実践的なアプローチを共有します。
なぜOllamaを選択したのか?
純粋なllama.cppを直接ビルドして運用することも検討しましたが、1人開発者にとってメンテナンスのオーバーヘッドは最大の敵です。その点、Ollamaはollama pullコマンド一つでモデルを管理でき、標準でHTTP 11434ポートを通じたREST APIを提供してくれます。この直感的なDX(開発者体験)こそが、Ollamaを採用した最大の理由でした。私たちのサービスでは、検索用の768次元のエンベディングと、夜間のバッチ解析タスクの双方でOllamaに強く依存しています。
3-Tier Fallback(3層フォールバック)アーキテクチャの構築
ローカルLLM最大の弱点は、単一障害点(SPOF)になりやすいことです。これを克服するため、私は3つの物理的なノードを束ねたフォールバック構造を設計しました。
- 第1層(Primary): Oracle Cloud ARM(24GB RAM)。バッチクローラーと同じネットワーク内にあり、ゼロレイテンシを目指します。
- 第2層(Secondary): 自宅のOld Mac(M4 Pro 24GB)。Thunderbolt 5によるプライベートネットワークを経由して呼び出します。
- 第3層(Tertiary): 開発用メインマシンのNew Mac(M4 Pro 64GB)。究極のバックアップです。
リクエストはタイムアウトを3秒に設定し、失敗すれば即座に次の層へルーティングされます。この構造により、過去半年の運用でAPIの完全なダウンタイムは0回を記録しています。より詳しいネットワーク構成については、ブログ一覧のインフラ関連記事でも触れています。
実際に直面したOOM(メモリ枯渇)の失敗談
もちろん、全てが順調だったわけではありません。導入初期、Oracle ARMサーバー上でエンベディングのバッチ処理を回した際、突然OllamaプロセスがOOM(Out of Memory)で強制終了される事件が発生しました。ログを辿ると、Ollamaのデフォルトの並列処理設定(num_parallelが4)が原因でした。
14Bモデルをロードした状態で、同時に複数のリクエストを処理しようとすると、24GBのメモリでは一瞬で枯渇してしまいます。この苦い経験から、私は環境変数でOLLAMA_NUM_PARALLEL=2に制限し、キューイングシステムを自作して同時リクエスト数を厳密にコントロールするようにしました。公式のAPIドキュメントに記載されているパラメータチューニングの重要性を身をもって学んだ瞬間です。
具体的なパフォーマンスと限界
Oracle ARM環境におけるdeepseek-r1:14bのトークン生成速度は、実測で毎秒4〜6トークン程度です。これはユーザーとリアルタイムで対話するチャットボットとしては致命的に遅いですが、裏側で動作する文書要約や非同期のタグ付けバッチとしては全く問題ありません。一方、nomic-embed-textによるエンベディング生成は1件あたり約50〜120msと非常に高速です。適材適所で使い分けることが、コスト0円運用を成立させる鍵です。
今後も継続的にモデルの最適化を進める予定です。このインフラ構築の背景にある私の開発哲学については、著者プロフィールやお問い合わせページを通じて、ぜひご意見をお聞かせください。
共有
関連記事
同じテーマやタグに基づき、GRAXELの運用文脈を続けて確認できます。
Next.js 15とnext-intlで韓国語・英語・日本語ページを運用する
GRAXELポータルの多言語ルーティング、メタデータ、検索エンジン向け整備についてまとめます。
韓国語政策データのハイブリッド検索 — pgvectorと全文検索を組み合わせる
MyHyetaekで意味検索とキーワード検索を組み合わせる理由を説明します。
Rust Axum + Cloudflare Tunnelでpolicy-api.graxel.aiを運用する
MyHyetaekの背後にある政策検索APIを安全に公開するための構成を解説します。