大規模言語モデルとの対話や検索を、外部のクラウドAPIに依存せず家庭内で完結させる。ここでは、その中核であるOllama・Open WebUI・SearXNGの構成を記す。

OllamaOllama
SearXNGSearXNG

画像: Ollama / SearXNG ロゴ、Wikimedia Commons

Ollama: ローカルLLM実行環境

Ollamaは、大規模言語モデルをローカル環境でダウンロード・実行するためのランタイムである。GPUへの直接アクセスを単純化するため、Dockerコンテナ内ではなくWindows上にネイティブでインストールしている。これによりコンテナ経由のGPUパススルーの複雑さを避け、GPUの性能を素直に引き出せる。汎用対話にはqwen3.5:9b、検閲の少ない用途にはdolphin-llama3:8bを使い分けている。

以前は用途別に細分化した複数のモデル(分析用・経理用など)を並行運用していたが、モデル管理の手間の割に使い分けの効果が薄いと判断し、汎用モデルへの統一を進めた経緯がある。無検閲系モデルのdolphin-llama3:8bには、開発元が推奨するシステムプロンプトをそのまま設定して使っている。

Open WebUI: チャットフロントエンド

Open WebUIはOllamaへのWebベースのチャットインターフェースで、ChatGPT等の商用サービスに近い使用感を持つ。設定上はOLLAMA_BASE_URLでOllamaのAPIエンドポイントを指定するだけで接続できる、単純な構成である。

応答が遅い問題の原因調査

導入初期、1ターンの応答に10分近くかかることがあった。原因は複合的で、(1)汎用モデルがデフォルトで数千トークン規模の「思考」過程を行う仕様になっていたこと、(2)Open WebUI側がタイトル生成・タグ付け・関連質問の提案・画像生成プロンプトの自動リライトのために、本来の応答とは別に補助的なLLM呼び出しを複数回追加で行っていたことが重なっていた。対応として、思考モードを無効化し、生成トークン数に上限を設定して暴走的な長文生成を防いだ上で、上記の補助的なLLM呼び出し機能を個別に無効化した。これらの設定はモデルのパラメータテーブルに直接投入することで、チャットごとに毎回設定し直す必要がないようにしている。

もう一つ、ツール呼び出し(画像生成の起動等)がモデルによって正しく動作しない問題もあった。Ollamaのネイティブなツール呼び出し形式に対応していないモデルや、対応が不安定なモデルでは、チャット中にツールが起動しないことがある。これも、該当モデルのデフォルトパラメータに、より互換性の高い旧式のツール呼び出し形式を使うよう焼き込むことで恒久的に解決した。チャットの都度、手動で呼び出し方式を切り替える必要がなくなっている。

SearXNG: プライベート検索エンジン

SearXNGは、複数の検索エンジンの結果を横断的に集約して返すメタ検索エンジンであり、検索クエリを単一の検索事業者に直接送信しない。自分専用の単一ユーザーインスタンスとして運用しているため、一般公開インスタンス向けに必要なボット検知やレート制限機能は無効化している(これらは複数の匿名ユーザーが共有する公開インスタンスを想定した機能であり、単一ユーザー・tailnet限定アクセスの構成では不要かつ誤検知の原因になりうる)。

なお、SearXNGの内部Webサーバーには従来のuWSGIではなくGranianが採用されているバージョンを使っており、実効的なリスニングポートの環境変数名がuWSGI版のドキュメントと異なる(SEARXNG_PORTではなくGRANIAN_PORTが実際に効く)という、ドキュメントとの差異に注意が必要だった。ボット検知の誤動作についても、原因を掘り下げると構造的な理由があった。SearXNGへの到達経路はリバースプロキシを経由しないTLS終端のみの生TCP転送方式を採っているため、通常であればリバースプロキシが付与するはずのクライアント情報のヘッダーがそもそも存在しない。これを一般公開インスタンス同様のボット検知ロジックにかけると、正規のアクセスであっても異常なアクセスとして誤検知されてしまう。単一ユーザー・tailnet限定という前提を踏まえ、検知ロジック自体を無効化するという判断に落ち着いた。

ComfyUI: 画像生成は必要な時だけ起動

画像生成にはComfyUIをGPUパススルー付きで導入しているが、他のサービスと異なり常時起動はさせていない。コンテナの再起動ポリシーを「自動再起動しない」に設定し、使う時だけ手動で起動する運用にしている。GPUを使う処理はメモリ・電力消費が大きく、常時待機させておく必要性が薄い用途のため、明示的に手動起動という選択をしている(この判断に至った経緯は実行基盤の記事に譲る)。

導入時に直面した依存関係の罠

導入時のイメージに同梱されていたPyTorchのバージョンが、最新版のComfyUI本体が要求する新しい依存コンポーネントに対応しておらず、起動時にエラーとなった。対応として、コンテナ内のPyTorchを手動でより新しいバージョンへ上げている。

この過程でさらに、ブリッジ接続のネットワークモードでは、GPU関連の大容量パッケージ群のダウンロードが度々失敗する問題にも遭遇した。ホストのネットワークをそのまま共有するモードに切り替えたところ解消しており、結果として他の常時稼働サービスと同じネットワークモードに揃える形になった。

さらに、cuDNNライブラリの新旧バージョンが混在してクラッシュする問題も発生した。これは、コンテナの環境変数でライブラリの探索パスを、新しいバージョンが優先されるよう明示的に上書きすることで解決している。依存関係が複数レイヤー(イメージのベースPyTorch・アプリ本体・個別ライブラリ)にまたがって絡み合っており、1つずつ原因を切り分けていく必要があった。

Open WebUIとの統合

Open WebUI側の画像生成機能でComfyUIをバックエンドに指定することで、チャット画面から直接プロンプトを入力して生成できるようにしている。生成に使うワークフロー自体(サンプラーの種類・ステップ数・ネガティブプロンプトの既定値等を含むノード構成)は、Open WebUI内部のデータベースに直接投入する形で設定した。チャット入力欄のツールメニューから画像生成を有効にして送信するだけで、裏側でComfyUIのワークフローが呼び出される。

Jupyter Notebook: ローカルの計算・分析環境

対話的なデータ処理・分析用に、Jupyter Notebookもホストの資源を使ってコンテナ内で動かしている。ホームディレクトリの所有権をコンテナ起動時に自動調整する設定を有効にした上でroot権限で起動し、ホスト側の作業ディレクトリをそのままノートブックの作業領域としてマウントしている。ブラウザのブックマークデータを読み取り専用でマウントする設定も加えており、ブックマーク情報を使ったちょっとした個人用の分析・整理タスクにも使える環境にしている。

権限を絞り込んだ経緯

現在の構成に落ち着くまでには、権限を絞り込む作業があった。導入当初は、root権限に加えてパスワードなしでのsudo実行まで許可し、さらにブラウザの実際のプロファイルディレクトリ(Cookieや保存済みパスワードを含む)を丸ごとマウントした状態で動かしていた。これは分析タスクの都合を優先した結果だったが、後日の監査で、この状態のままサービスがループバック限定ではなく全インターフェースに公開されていたことも判明し、両方の問題が重なっていたと分かった。対応として、待受アドレスをループバック限定にした上で、sudoの無条件許可を廃止し、マウント対象もブラウザプロファイル全体からブックマークファイル1つだけに絞り込んだ。認証トークンについても、コンテナ定義に直接書いていたものを別ファイルに分離している。分析環境という「自分専用だから」という油断が、複数の過剰な権限を積み重ねさせていた典型例である。

参考リンク

#Ollama #SearXNG