Ubuntu サーバで LLM 構築へ:(1)事前学習
だいぶ生成 AI を使うことに慣れてきたので,そろそろ自前で LLM サービスを構築することを考えてみる。
いや,既にもうメジャーな AI サービスプロバイダってメタクソ化(enshittified)し始めてるぢゃん。 企業サービスに完全にロックインされないうちに自前で構築できるようになっておかないと,と思ってさ。
今回は,以下の要求で Kagi Assistant にサービス構成を提案してもらった。
- 家庭内 LAN 上の Ubuntu サーバ機に LLM サービスを構築する
- クライアントは Windows 機と Ubuntu 機を想定
- 主な用途はプログラミング支援とブログ作成補助
- VS Code で使えるようにする
以降に Kagi Assistant からの提案を載せるけど,まだ内容の検証をしていない。 なので嘘や間違いが紛れている可能性があるのでご注意を。 私としては,この提案を学習の起点(trigger)とするつもりである。
アーキテクチャ
Kagi Assistant が最初に推奨してきた構成:
:11434
(推論エンジン)"] LiteLLM["LiteLLM
:4000
(API Proxy)"] Nginx["Nginx
:443
(Reverse Proxy)"] Embed["nomic-embed-text
(Embedding / RAG用)"] PG["PostgreSQL
(LiteLLM 用)"] Ollama ---> LiteLLM LiteLLM --- PG LiteLLM ---> Nginx Ollama --- Embed end subgraph ClientUbuntu["Ubuntu PC"] VSCodeU["VS Code + Continue"] end subgraph ClientWin["Windows PC"] VSCodeW["VS Code + Continue"] end Nginx -- "LAN (HTTPS)" --> ClientUbuntu Nginx -- "LAN (HTTPS)" --> ClientWin
推論エンジンとして Ollama を提案した理由は以下の通りらしい:
個人〜小規模LAN利用ではOllamaが最適。セットアップが最も簡単で、OpenAI互換APIを標準提供し、モデル管理が容易です。
- vLLMは同時接続ユーザーが多い(5人以上)本番運用向けで、単一ユーザーには複雑さが増すだけ
- llama.cppは低レベルすぎて管理が煩雑
LiteLLM は Ollama の前に置く OpenAPI 互換 API プロキシ。 Ollama だけでなく OpenAI や Anthropic などの外部 API も統一的に扱えるらしい。 図では LiteLLM に PostgreSQL がぶら下がっているが,これは API キー管理・使用量トラッキング用とのこと。
Nginx はリバースプロキシとして HTTPS 終端,セキュリティ(Ollama/LiteLLM への直結ポートをサーバの外に晒さない),ストリーミング対応を担っている。 注意点は以下の通り:
- LAN 内のみの利用でもHTTPS推奨(Continue.dev が API キーを送るため)
- Let’s Encrypt 証明書か自己署名証明書を使用
- ストリーミング(SSE)対応のため proxy_buffering off が必須
nomic-embed-text については後述する。
LiteLLM と Nginx は入れなきゃダメ? と訊いてみたら,もう少し簡単な構成もあるらしい。
:11434
(推論エンジン)"] OpenWebUI["Open WebUI
:8080
(GUIチャット)"] Embed["nomic-embed-text
(Embedding / RAG用)"] Ollama --- Embed Ollama ---> OpenWebUI end subgraph ClientUbuntu["Ubuntu PC"] VSCodeU["VS Code + Continue
ollama run (CUI)
ブラウザGUIチャット"] end subgraph ClientWin["Windows PC"] VSCodeW["VS Code + Continue
ollama run (CUI)
ブラウザGUIチャット"] end Ollama -- "Ollama API
:11434" --> ClientUbuntu OpenWebUI -- "Web UI
:8080" --> ClientUbuntu OpenWebUI -- "Web UI
:8080" --> ClientWin Ollama -- "Ollama API
:11434" --> ClientWin
クライアントの用途ごとの使い分けは以下の通り。
| アクセス先 | ポート | 用途 | クライアント |
|---|---|---|---|
| Ollama API | :11434 |
VS Code + Continue(コーディング支援) | Ubuntu / Windows |
| Ollama API | :11434 |
ollama run(CUIチャット) |
Ubuntu / Windows |
| Open WebUI | :8080 |
ブラウザ GUI チャット(ブログ執筆・雑談) | Ubuntu / Windows |
VS Code の拡張機能である Continue は Ollama API に対応しているそうなので(セキュリティの問題を除けば)直結で OK。 ターミナルエミュレータ等で CUI チャットを行う場合はクライアント側にも Ollama をインストールして接続先をサーバ機に向ければいいらしい。
OLLAMA_HOST=http://192.168.x.x:11434 ollama run qwen3.5:9b
さらに簡単に Ollama API を直に叩く方法もある(自作ツール向け?)。 こんな感じ。
# ワンショット質問
curl http://192.168.x.x:11434/api/chat -d '{
"model": "qwen3.5:9b",
"messages": [
{"role": "user", "content": "ブログのタイトル案を5つ提案して"}
],
"stream": false
}'
# ストリーミング(リアルタイム出力)
curl http://192.168.x.x:11434/api/chat -d '{
"model": "qwen3.5:9b",
"messages": [
{"role": "user", "content": "PythonでFizzBuzzを書いて"}
]
}'
Ollama API って素の RESTful API でやり取りするのか。 確かにこれは(セキュリティ的に)ヤバいな。 LiteLLM/Nginx を噛ませろって言う筈だわ。 LAN 内に他人(のデバイス)が入ってくる余地がないならギリ大丈夫かな。 まぁ,どのみち malware に侵入されたらアウトだけど。
Open WebUI は Web ベースのチャットインターフェースで,以下の特徴があるらしい1。
| 機能 | 説明 |
|---|---|
| ChatGPT 風 UI | ブラウザでチャット、使い慣れたインターフェース |
| 会話履歴 | すべての会話を保存・検索可能 |
| モデル切替 | ドロップダウンでモデル切替 |
| ドキュメント RAG | ファイルをアップロードして対話 |
| ユーザー管理 | 複数ユーザー・アクセス制御 |
| 完全オフライン | 外部へのデータ送信なし |
OpenAI の API キーを持っていれば Open WebUI から OpenAI のモデルも使えるそうな(以下は Docker 上に Open WebUI をインストールした場合の起動例)。
# Open WebUI起動時にOpenAI APIも設定
docker run -d \
--name open-webui \
--network host \
-v open-webui:/app/backend/data \
-e OLLAMA_BASE_URL=http://127.0.0.1:11434 \
-e OPENAI_API_KEY=sk-your-openai-key \
--restart always \
ghcr.io/open-webui/open-webui:main
用途別の使い分けについてまとめてもらった。
| 用途 | インターフェース | 理由 |
|---|---|---|
| ブログ執筆・雑談 | Open WebUI(ブラウザ) | ChatGPT風で直感的、会話履歴管理 |
| プログラミング支援 | VS Code + Continue | コード補完・エディタ統合 |
| サクッと質問 | ollama run(CUI) |
ターミナルから即座に |
| スクリプト・自動化 | curl / Python API | バッチ処理やパイプライン |
普段の調べ物は Kagi Assistant で必要十分なので Open WebUI はあまり使わないかもしれないけど。 Open WebUI が不要なら入れない構成もありだな。
モデル選択
Ollama で選択可能な LLM モデルで Kagi Assistant が勧めてきたのは以下のもの1。
| 用途 | 推奨モデル | 役割 |
|---|---|---|
| チャット・コーディング対話 | Qwen 3.6-27B または 35B-A3B | chat, edit, summarize |
| コード自動補完(FIM) | Qwen 2.5-Coder(7B/14B/32B) | autocomplete(タブ補完) |
| Embedding(RAG用) | nomic-embed-text | codebase検索 |
| Reranker(RAG精度向上) | Qwen3-Reranker-8B | 検索結果の再順位付け |
GPU VRAM別のモデル構成
| VRAM | チャット用モデル | 自動補完用モデル | 備考 |
|---|---|---|---|
| 8GB | Qwen 3.5-9B (~6.6GB) | Qwen 2.5-Coder 7B (~5GB) | 1モデルずつ切り替え運用 |
| 16GB | Qwen 3.6-35B-A3B (~16-22GB) | Qwen 2.5-Coder 14B (~9GB) | 同時稼働は量子化調整が必要 |
| 24GB | Qwen 3.6-27B (~17GB) | Qwen 2.5-Coder 32B (~20GB) | ★最も推奨される構成 |
| 32GB+ | Qwen 3.6-27B (Q6/Q8) + Qwen 2.5-Coder 32B | 同時稼働余裕あり | RTX 5090等 |
💡 24GB VRAM(RTX 3090/4090)の構成が最もバランスが良い: Qwen 3.6-27Bでチャット・エージェント的コーディング、Qwen 2.5-Coder 32Bでタブ補完。ただし同時稼働はVRAM的に厳しいため、Ollamaはモデルを自動でアンロード/ロードするので、交互に使う運用になります。
あー。 そういや,サーバ機のスペックを教えてなかった。 手持ちの空いてるミニ PC をサーバ機にする予定なのでスペックは高くないのよ。
というわけで Ryzen 5 7430U, RAM 16GB, 外付け GPU なしの構成で再提案してもらった。
| 役割 | 推奨モデル | RAM使用量 | 予想速度 | 理由 |
|---|---|---|---|---|
| チャット・ブログ・コーディング対話 | Qwen 3.5-9B (Q4) | ~6 GB | ~5-8 tok/s | 9Bで品質最優、ブログ執筆に十分な表現力 |
| コード自動補完(FIM) | Qwen 2.5-Coder 3B (Q4) | ~2.5 GB | ~15-20 tok/s | 補完は高速が命、3Bで品質も十分 |
| Embedding(RAG用) | nomic-embed-text | ~0.3 GB | 高速 | コードベース検索用 |
💡 合計RAM使用量: ~9 GB(OS等の予約分を含めても16GB内に余裕あり)
チャット用を軽くして速度を稼ぐ構成:
| 役割 | モデル | RAM | 予想速度 |
|---|---|---|---|
| チャット | Qwen 3.5-4B (Q4) | ~3 GB | ~12-18 tok/s |
| 自動補完 | Qwen 2.5-Coder 1.5B (Q4) | ~1.2 GB | ~30+ tok/s |
| Embedding | nomic-embed-text | ~0.3 GB | 高速 |
合計 ~4.5 GB。速度は快適ですが、ブログ執筆の品質は9Bに劣ります。
🌟 注目の選択肢:Gemma 4 26B-A4B(MoE)
GoogleのGemma 4 26B-A4Bは 総パラメータ26B・推論時アクティブ3.8B のMoEモデルです。 Q4量子化で ~15 GB のRAM使用量。
- ✅ 品質: 3.8B活性化で26Bクラスの表現力(Qwen 3.5-9B以上の可能性)
- ⚠️ RAM: ~15 GBで16GBギリギリ。OSの予約分と競合する可能性
- ⚠️ 速度: MoEはアクティブパラメータが少なくても全パラメータのメモリアクセスが必要なため、DDR4帯域幅がボトルネックになり 予想3-6 tok/s
結論: 試す価値はありますが、16GBではスワップ発生のリスクが高く、安定性に欠ける可能性があります。まずはQwen 3.5-9Bで安定運用し、余裕があればGemma 4 26B-A4Bも試すのがおすすめ。
⚡ パフォーマンスを引き上げるTips
| 施策 | 効果 | 詳細 |
|---|---|---|
num_ctxを小さく |
速度向上 | 4096→2048にするとコンテキスト処理が高速化。ブログ執筆なら2048で十分な場面も |
| モデルを1つずつロード | RAM節約 | OLLAMA_MAX_LOADED_MODELS=1で未使用モデルを自動アンロード |
| Q3量子化を試す | RAM削減・速度UP | ollama run qwen3.5:9b-q3_K_MでRAM~4.5GB、品質は若干低下 |
| スワップの無効化 | 安定性向上 | RAM不足時のスワップは極端な低速化の原因。/etc/fstabでswapを0に |
| 将来的にGPU追加 | 劇的改善 | Thunderbolt/OCuLink外付けGPUエンクロージャーでRTX 3060(12GB)等を追加すれば、一気に実用的に |
Ryzen 5 7430U には内蔵 GPU (Radeon Graphics) があるが LLM 推論には非力なので CPU-only 推論となる。 そうなるとメモリ帯域幅が重要になるんだけど DDR4-3200 デュアルチャネルは DDR5 半分以下の帯域幅(〜51GB/s)しかない。 RAM のサイズも 32GB 以上は欲しいらしい。
| サーバRAM | 推奨構成 | 備考 |
|---|---|---|
| 8GB | Qwen 3.5-4B (チャット) + Qwen 2.5-Coder 1.5B (補完) | 1モデルずつ切り替え |
| 16GB | Qwen 2.5-Coder 7B (チャット) + Qwen 2.5-Coder 3B (補完) + nomic-embed | ★最も現実的 |
| 32GB | Qwen 3.5-35B-A3B (チャット) + Qwen 2.5-Coder 7B (補完) + nomic-embed | ★★最高の体験 |
| 64GB | Qwen 3.5-35B-A3B + Qwen 2.5-Coder 14B + nomic-embed | 余裕あり |
なかなかに貧弱な構成と言われてしまった(笑)
しょうがないぢゃん orz
nomic-embed-text について
nomic-embed-textはOllama上で動く Embeddingモデル です。テキストを数値ベクトル(768次元)に変換するだけで、それ自体にデータベースは必要ありません 。
テキスト入力 → nomic-embed-text → 768次元ベクトル出力
ベクトルデータはデータベース化して RAG (Retrieval-Augmented Generation; 検索拡張生成) に使用する1。 Open WebUI および Continue は自前でベクトルデータベースを持っている。 規模が大きくなれば PostgreSQL + pgvector などのベクトルデータベースが別途必要になる。
🏗️ RAGの規模別アーキテクチャ
| 規模 | ベクトル保存先 | 構成 |
|---|---|---|
| 小規模(個人・Continue.dev) | ローカルファイル(Continue内蔵) | Ollama + nomic-embed-text のみ |
| 中規模(チーム・Open WebUI) | Open WebUI内蔵のChromaDB | Ollama + Open WebUI |
| 大規模(組織・自作パイプライン) | PostgreSQL + pgvector / Qdrant / Milvus | Ollama + 独自バックエンド |
今回はここまで
とりあえず Ollama と RAG についてはちゃんと勉強せなあかんなぁ,というのは分かった。 あとは実際に組んでみて評価していく感じかな。
薄々わかってはいたが,どうも手持ちの環境は貧弱すぎるみたいだけど,どの程度足らないのかの感覚がわからない。 これは使ってみて確かめるしかないだろう。
仕事が絡むなら vLLM も気になるところだが,そういう仕事が貰えるなら考えるということで(笑)
