社内ツールやPoCにローカルLLM(手元のマシンで動かす大規模言語モデル)を組み込む構成を検討している方に向けて書きます。Ollama(ローカルでLLMを動かすためのランタイム)とFastAPI(Pythonの軽量Webフレームワーク)を組み合わせた構成は手軽に見えますが、可用性設計の観点では見落としやすい前提がいくつもあります。
個人のタスク整理をAIでクラスタリングするOSSアプリ「ErrandQuest」は、この構成の典型例です。llama3.2:1bやqwen2.5:1.5bといった軽量モデルをOllama経由でローカル実行し、さらにOllama未導入やメモリ不足の環境向けに、決定論的な(入力が同じなら必ず同じ結果を返す)Pythonロジックへフォールバックする設計を持っています。個人利用のツールとしては妥当な工夫ですが、これをチーム内の共有サービスや本番相当の運用に転用しようとすると、SREの視点では複数の落とし穴が顔を出します。
何が起きるか:ローカルAI依存が可用性の盲点になる
最初に起きやすいのは、推論バックエンドの単一障害点化です。
Ollamaはデフォルトで1プロセスとしてホスト上に起動し、HTTPのAPIエンドポイント(通常はlocalhostの11434番ポート)でリクエストを受けます。このプロセスが落ちる、あるいはモデルのロードに失敗すると、アプリ全体のAI機能が止まります。
クラウドAPI(OpenAIやAnthropicのAPIなど)であればプロバイダー側がSLA(サービス品質保証)とスケーリングを担保しますが、ローカルLLMはホストマシンの空きメモリとCPU/GPUリソースにそのまま依存します。複数ユーザーが同時アクセスする環境で負荷試験をせずに展開すると、推論待ちのリクエストがキューに溜まり、タイムアウトが連鎖する事象が起きます。
もう一つの盲点は、フォールバック機構があることで「障害に強い」と誤解してしまう点です。ErrandQuestのようにAI応答が得られない場合は決定論的エンジンに切り替える設計は、確かにクラッシュを防ぎます。ただしフォールバック後は抽出精度や分類ロジックが変わるため、ユーザー体験が劣化したことに誰も気づかないまま運用され続けるリスクがあります。
なぜ起きるか:設計思想とインフラ要件のギャップ
根本的な原因は、個人利用を前提にした設計と、チーム・組織利用で求められる可用性要件の間にギャップがあることです。段階的に分解します。
1つ目は、モデルのメモリ常駐コストです。llama3.2:1bのような軽量モデルでも、ロード時にはGBオーダーのRAMを消費します。これは「ノートPCでもGPUなしで動く」ことを売りにした設計ですが、同じホストで複数リクエストを捌こうとすると、OSのスワップが発生して応答が極端に遅くなります。
2つ目は、プロセス監視の仕組みが前提に入っていないことです。OllamaはSystemdのユニットやDockerコンテナとして動かせますが、クラッシュ時の自動再起動やヘルスチェックの設定は利用者側が別途用意する必要があります。個人のスクリプトとして動かしている分には気にならなくても、チームで共有するなら必須の設定です。
3つ目は、スキーマ検証(Pydanticによる構造化出力の型チェック)が成功したかどうかと、推論自体が正常に完了したかどうかが別々の失敗モードだという点です。LLMの出力がJSON形式として妥当でもビジネスロジック上は不適切な値を返すケースがあり、どちらの失敗かを区別できるログ設計がないと障害対応の初動が遅れます。
自分のプロジェクトが該当するか確認する方法
まず、自分の環境がローカルLLM依存の構成かどうかをチェックします。
curl http://localhost:11434/api/tagsこのコマンドでOllamaが応答し、ロード済みモデルの一覧が返ってくれば、ローカル推論に依存した構成です。応答がない、または接続拒否になる場合は、フォールバックロジックの有無を確認してください。
次に、フォールバック時の動作がログで判別できるかを確認します。アプリのログ出力設定(Pythonであればloggingモジュールの設定箇所)を開き、Ollama呼び出しの成功・失敗、フォールバック発動の有無がそれぞれ別のログレベルやメッセージで出ているか見てください。
grep -i "ollama\|fallback" app.log | tail -n 50これで区別できないログ構成であれば、障害発生時にユーザー体験が劣化していることに気づけません。
最後に、プロセス監視の設定ファイルを確認します。docker-compose.ymlやsystemdのユニットファイルにrestart: alwaysやRestart=on-failureのような自動復旧設定が入っているかを見てください。入っていない場合、Ollamaプロセスが落ちたまま誰も気づかない状態が続く可能性があります。
対策の手順
対策は大きく4つに分けられます。
- ヘルスチェックの導入:
/api/tagsなどの軽量エンドポイントを定期的にポーリングし、応答時間としきい値をSLO(サービスレベル目標)として定義する。たとえば「95パーセンタイルで2秒以内に応答」のような具体的な数値を決める - プロセス監視の自動化: Docker Composeで動かす場合は
restart: unless-stoppedを設定し、Kubernetesで動かす場合はLiveness/Readinessプローブを/api/tagsに向けて設定する - フォールバック発動の可視化: フォールバックが発動したイベントをメトリクスとして計測し、Prometheusなどの監視基盤に送る。発動頻度が増えた場合はアラートを出す仕組みにする
- リソース上限の明示: モデルサイズとホストのメモリ量から、同時に処理できるリクエスト数の上限を見積もり、アプリ側でキューイングやレート制限(リクエスト数の制御)を入れる
IaC(Infrastructure as Code、インフラ構成をコードで管理する手法)を使っている場合は、TerraformやPulumiのモジュールにOllama用のホストサイズやヘルスチェック設定をパラメータ化しておくと、環境ごとの差異が追いやすくなります。たとえばGPUなしの検証環境とGPUありの本番相当環境を、同じモジュールの変数だけで切り替えられる構成にしておくと、障害対応時の切り分けが速くなります。
まとめ
ローカルLLMを組み込んだアプリは、プライバシー保護やオフライン動作という利点がある一方、可用性設計の責任が利用者側に完全に移っている点を見落としがちです。
まずはcurl http://localhost:11434/api/tagsでOllamaの応答を確認し、ログにフォールバック発動の記録があるかをチェックしてください。
そのうえで、ヘルスチェック・プロセス監視・フォールバック可視化・リソース上限の4点を順に整備すれば、個人のPoCからチーム利用への移行時に起きやすい障害を事前に減らせます。