日本語AIチャットボットを月額1,000円以下で自前運用する方法【2026年版】LFM2.5-1.2B-JP × llama.cpp × DockerによるRAG構築ガイド
この記事でわかること
- なぜ Dify・n8n・Transformers を使わず「コードベース構築」が最強なのか(比較つき)
- LFM2.5-1.2B-JP が CPU 推論で最速クラスになる理由
- Contabo VPS S(月額約1,000円)で動く最小構成と Docker Compose による構築手順
- 実運用で詰まりやすいポイントと高速化チューニング
Python の基礎があり、VPS 上で API サーバーを動かしたい個人開発者・スタートアップエンジニア
なぜ今「自前ローカル RAG」なのか
ChatGPT API を使って社内ドキュメントを検索させようとすると、月額コストは利用量に比例して膨らみ、機密データが外部に出るリスクもつきまとう。かといって GPU 付きクラウドはコスパが悪すぎる。
そこで注目されているのが、軽量な日本語 LLM を CPU のみで動かし、自前の RAG(Retrieval-Augmented Generation)サーバーを持つという構成だ。2026年現在、LFM2.5 シリーズの登場でこの選択肢は一気に現実的になった。
1. モデル選定:なぜ LFM2.5-1.2B-JP なのか
LFM2.5 アーキテクチャの特徴
LFM2.5 は Liquid AI が開発した「ハイブリッドモデル」で、Transformer の注意機構に加えて短いたたみ込み層を組み合わせたアーキテクチャを採用している。これが CPU 推論に特に効く。
公式ベンチマークによると、LFM2.5-1.2B は AMD CPU で 239 tok/s のデコード速度を達成し、1GB 未満のメモリで動作し、llama.cpp・MLX・vLLM に初日からネイティブ対応している。また、LFM2 ファミリーは Qwen3 と比べて CPU での decode・prefill が 2 倍高速という実績を持つ。
日本語特化版の LFM2.5-1.2B-JP は、LFM2.5 のハイブリッドアーキテクチャをベースに、日本語テキスト生成・補完向けに最適化されたモデルだ。
RAG・エージェントタスクとの相性
LFM2.5-1.2B は RAG、データ抽出、エージェントタスクに推奨されており、1B スケールにおいてベストインクラスの性能と高速な CPU 推論・低メモリプロファイルを提供する。ただし知識集約タスクやプログラミングは不得手なため、RAG で外部ドキュメントを参照する設計との組み合わせが本来の使い方に最も合致している。
量子化サイズの比較
| 量子化 | ファイルサイズ | CPU 速度感 | 推奨用途 |
|---|---|---|---|
| Q2_K | 483 MB | 最速 | PoC・検証のみ |
| Q4_K_M | 731 MB | 高速・バランス良好 | 本番推奨 |
| Q5_K_M | 843 MB | やや遅い | 回答品質重視 |
| Q8_0 | 1.25 GB | 遅い | 精度最重視 |
Q4_K_M が CPU 推論のスイートスポット。 メモリ消費は 1GB 未満、速度と品質のバランスが最も良い。
2. 推論エンジン選定:llama.cpp 一択である理由
比較:Python(Transformers)vs llama.cpp
「Python だけで完結したほうが軽いのでは?」という疑問は自然だが、実際は逆だ。
| 比較項目 | Transformers のみ | llama.cpp(推奨) |
|---|---|---|
| CPU 推論速度 | 遅い(インタープリタのボトルネック) | 爆速(AVX2/AVX512 直叩き) |
| メモリ消費 | 多い(PyTorch が数 GB 占有) | 少ない(モデル本体のみ) |
| 起動時間 | 遅い(ライブラリロードが重い) | 速い |
| 依存ライブラリ数 | 多い | 最小限 |
llama.cpp は x86 アーキテクチャ向けに AVX・AVX2・AVX512・AMX をサポートしており、依存ライブラリなしの Pure C/C++ 実装によって最小セットアップで最高レベルのパフォーマンスを実現することを主目標にしている。
Python から使いたい場合も、llama-cpp-python というバインディングを使うことで「操作は Python・計算は C++」のいいとこ取りが可能だ。
Ollama を挟まない理由
Ollama は llama.cpp をバックエンドに使っているため推論速度自体は同等だが、REST API 層・モデル管理デーモンが常駐する分、メモリに 200〜400 MB 余計に使う。リソースが潤沢なら問題ないが、VPS S クラスでは削れるオーバーヘッドはすべて削る。
3. ノーコードツール vs コードベース:Dify・n8n を使わない理由
Dify のメリットとデメリット
Dify は確かに強力だ。PDF・Word・Web ページ・Notion など手元の資料をアップロードするだけでナレッジベースを作成でき、専門的なプログラミング知識なしでエンジニア 1 名でも RAG を活用した AI アプリを作れる。
2025 年 2 月にリリースされた Dify v1.0.0 では、プラグインシステムが正式導入され、120 以上のプラグインを提供する Marketplace が開設された。
しかし、自前VPSでローカルLLM を動かす場合、Difyは重すぎる。
Dify を快適に運用するには最低 4GB のRAM が必要で、複数コンテナを立ち上げる場合や他のアプリと同時使用する際は 16GB 以上が望ましい。つまり Dify 自体で 2〜4 GB を消費し、その上にローカル LLM を乗せると VPS S(8GB)ではほぼメモリが尽きる。スワップが発生した瞬間に推論速度は致命的に遅くなる。
n8n の立ち位置
n8n は業務自動化ツールとしては優秀だが、「ユーザーの質問に即座に答える API サーバー」としてはオーバーヘッドが大きい。ストリーミング出力への対応も限定的で、チャットボット API 用途には向いていない。
構築手法の最終比較
| 項目 | コードベース(FastAPI + llama.cpp) | Dify + Ollama | n8n + Ollama |
|---|---|---|---|
| メモリ消費 | 最小(約 1.5 GB 全体) | 多い(4 GB 以上) | 普通 |
| 推論速度 | 最速 | 普通 | 普通 |
| RAG 構築難度 | やや手間 | 簡単(GUI) | 中程度 |
| カスタマイズ性 | 自由 | 制限あり | 限定的 |
| VPS S での動作 | ◎ | △(ギリギリ) | ○ |
| API 拡張性 | ◎ | ○(組み込み API) | △ |
結論:メモリ 8GB 以下なら迷わずコードベース。 Difyが真価を発揮するのはメモリが 16 GB 以上あり、ドキュメントの更新を非エンジニアが行うケースだ。
4. インフラ選定:Contabo VPS S を選ぶ理由
Contabo のコスパ
Contabo の VPS は「スペックの割に安い海外系 VPS」で、例えば Cloud VPS 10 が月額 €4.50 で 4vCPU / 8GB RAM / 75GB NVMe といった構成を提供している。
Contabo は Vultr と月額わずか 2.25 ドルの差額で、CPU が 4 倍・メモリ 6 倍・ストレージ 16 倍という驚異的なコスパを発揮する。
日本リージョンも選択可能で、予算と通信量に不安がないなら日本リージョンが選択肢として挙げられる。
LFM2.5-1.2B-JP に必要なリソースと VPS プランのマッピング
| Contabo プラン | vCPU | RAM | 月額目安 | LFM2.5-1.2B 用途 |
|---|---|---|---|---|
| VPS 10 | 4 | 8 GB | ~€4.50 | 本番推奨(余裕あり) |
| VPS 20 | 6 | 16 GB | ~€7.50 | 複数モデル同時稼働 |
| VPS 30 | 8 | 24 GB | ~€12 | 8B モデルへの移行視野 |
LFM2.5-1.2B-JP Q4_K_M は モデル本体 731 MB。VPS 10(8GB)なら、OS・ベクトル DB・API サーバーを合わせても余裕のある構成が組める。
Docker vs ベアメタル展開
ストレージ差は 500 MB〜1 GB 程度で誤差の範囲。一方で Docker を使うメリットは大きい。
- 環境の分離: llama.cpp のビルドに必要な
g++・cmake等がホスト OS を汚染しない - 再現性: 「手元では動いたのに VPS で動かない」問題を完全回避
- アップデート容易:
docker compose pull一発で llama.cpp の最新最適化の恩恵を受けられる
メモリのオーバーヘッドは Docker エンジンの常駐分で 20〜50 MB 程度。仮想マシンとは異なりカーネルを共有するため、数 GB 余分に食うことはない。
5. 構築手順:ゼロから動かすまで
ステップ 1:VPS の準備
# Ubuntu 24.04 LTS を選択して VPS を立ち上げる
# SSH 接続後、まず Docker をインストール
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# 再ログイン後に確認
docker --version
ステップ 2:モデルのダウンロード
mkdir -p ~/rag-server/models
cd ~/rag-server/models
# Hugging Face CLI でダウンロード(pip install huggingface_hub)
pip install huggingface_hub
python3 -c "
from huggingface_hub import hf_hub_download
hf_hub_download(
repo_id='LiquidAI/LFM2.5-1.2B-JP-GGUF',
filename='LFM2.5-1.2B-JP-Q4_K_M.gguf',
local_dir='.'
)
"
# ダウンロード後の確認(約 731 MB)
ls -lh LFM2.5-1.2B-JP-Q4_K_M.ggufステップ 3:プロジェクト構成の作成
rag-server/
├── docker-compose.yml
├── models/
│ └── LFM2.5-1.2B-JP-Q4_K_M.gguf
├── api/
│ ├── Dockerfile
│ ├── main.py # FastAPI アプリ
│ ├── rag.py # RAG パイプライン
│ └── requirements.txt
└── qdrant_data/ # ベクトル DB の永続化領域
ステップ 4:docker-compose.yml
services:
# LLM 推論エンジン(llama-cpp-python の OpenAI 互換サーバー)
llm:
image: ghcr.io/abetlen/llama-cpp-python:latest
ports:
- "8001:8000"
volumes:
- ./models:/models
environment:
MODEL: /models/LFM2.5-1.2B-JP-Q4_K_M.gguf
HOST: 0.0.0.0
PORT: 8000
N_THREADS: 4 # VPS の物理コア数に合わせる
N_CTX: 4096 # コンテキスト長(RAG には 4096 で十分)
CHAT_FORMAT: chatml # LFM2.5 は ChatML フォーマット
restart: unless-stopped
# ベクトルデータベース
qdrant:
image: qdrant/qdrant:latest
ports:
- "6333:6333"
volumes:
- ./qdrant_data:/qdrant/storage
restart: unless-stopped
# RAG API サーバー(FastAPI)
api:
build: ./api
ports:
- "8000:8000"
depends_on:
- llm
- qdrant
environment:
LLM_URL: http://llm:8000/v1
QDRANT_URL: http://qdrant:6333
restart: unless-stopped
ステップ 5:RAG パイプライン(api/rag.py)
from sentence_transformers import SentenceTransformer
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
import uuid
# 軽量日本語 Embedding モデル(CPU でミリ秒単位で動く)
EMBED_MODEL = SentenceTransformer("intfloat/multilingual-e5-small")
COLLECTION = "documents"
def init_collection(client: QdrantClient):
"""コレクションが存在しなければ作成する"""
if COLLECTION not in [c.name for c in client.get_collections().collections]:
client.create_collection(
collection_name=COLLECTION,
vectors_config=VectorParams(size=384, distance=Distance.COSINE),
)
def add_documents(client: QdrantClient, texts: list[str]):
"""テキストをベクトル化して Qdrant に登録する"""
vectors = EMBED_MODEL.encode(
).tolist() points = [ PointStruct(id=str(uuid.uuid4()), vector=v, payload={"text": t}) for v, t in zip(vectors, texts) ] client.upsert(collection_name=COLLECTION, points=points) def search(client: QdrantClient, query: str, top_k: int = 3) -> list[str]: """クエリに関連するチャンクを検索して返す""" vector = EMBED_MODEL.encode(f"query: {query}").tolist() results = client.search( collection_name=COLLECTION, query_vector=vector, limit=top_k, ) return [r.payload["text"] for r in results]ステップ 6:FastAPI エンドポイント(api/main.py)
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from openai import AsyncOpenAI
from qdrant_client import QdrantClient
import os
from rag import init_collection, search, add_documents
app = FastAPI()
llm = AsyncOpenAI(base_url=os.getenv("LLM_URL"), api_key="no-key")
qdrant = QdrantClient(url=os.getenv("QDRANT_URL"))
init_collection(qdrant)
class ChatRequest(BaseModel):
message: str
class IngestRequest(BaseModel):
texts: list[str]
@app.post("/ingest")
async def ingest(req: IngestRequest):
"""ドキュメントをベクトル DB に登録する"""
add_documents(qdrant, req.texts)
return {"status": "ok", "count": len(req.texts)}
@app.post("/chat")
async def chat(req: ChatRequest):
"""RAG を用いてストリーミングで回答する"""
# 1. 関連ドキュメントを検索
contexts = search(qdrant, req.message)
context_text = "\n\n".join(contexts)
# 2. プロンプトを構築
system_prompt = f"""あなたは親切な日本語アシスタントです。
以下の参考情報をもとに、質問に正確に答えてください。
参考情報に答えが見つからない場合は「わかりません」と答えてください。
【参考情報】
{context_text}"""
# 3. LLM にストリーミングリクエスト
async def generate():
stream = await llm.chat.completions.create(
model="local-model",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": req.message},
],
stream=True,
temperature=0.1,
max_tokens=512,
)
async for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
yield delta
return StreamingResponse(generate(), media_type="text/plain")ステップ 7:起動と動作確認
cd ~/rag-server
docker compose up -d
# ログで LLM が正常にロードされたか確認
docker compose logs -f llm
# ドキュメントを登録
curl -X POST http://localhost:8000/ingest \
-H "Content-Type: application/json" \
-d '{"texts": ["弊社の返品期限は購入から30日以内です。", "返品には領収書が必要です。"]}'
# チャットで動作確認
curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"message": "返品はいつまでできますか?"}'
6. CPU パフォーマンス最適化:速くするための 3 つのチューニング
チューニング 1:スレッド数の設定
N_THREADS は物理コア数と同じか、1〜2 少ない値が最速になることが多い。Contabo VPS S(4 vCPU)なら N_THREADS=4 から試して docker stats でCPU 使用率を見ながら調整する。
チューニング 2:コンテキスト長を必要最低限に
N_CTX を大きくするほどメモリ消費と処理時間が増える。RAG では検索したチャンクをシステムプロンプトに入れるだけなので 4096 もあれば十分。8192 以上は不要だ。
チューニング 3:Embedding モデルの選択
intfloat/multilingual-e5-small は 384 次元・117 MB と非常に軽量で、CPU で 1 クエリ数ミリ秒で処理できる。品質を上げたい場合は intfloat/multilingual-e5-base にアップグレードするが、速度とのトレードオフになる。
7. リソース消費の実測値(VPS S 想定)
| コンポーネント | メモリ消費 | CPU(アイドル/推論時) |
|---|---|---|
| LFM2.5-1.2B-JP Q4_K_M | ~900 MB | 0% / 90〜100% |
| Qdrant | ~200 MB | ほぼ 0% |
| FastAPI(api) | ~300 MB | 0% / 5% |
| OS + Docker エンジン | ~500 MB | 数% |
| 合計 | ~1.9 GB | 推論時 ~95% |
8 GB の VPS に対して約 2 GB の消費で、残り 6 GB は余裕。docker stats で確認しながら運用すること。
8. よくある失敗と対処法
モデルが遅い・タイムアウトする
→ N_THREADS が多すぎる場合がある。4 コア環境では 3〜4 が最適。また初回リクエストはモデルの KV キャッシュ生成で遅い。2 回目以降は大幅に速くなる。
Qdrant に接続できない
→ docker compose up の起動順序の問題。api サービスに depends_on: qdrant を設定し、さらに wait-for-it スクリプトかヘルスチェックを追加するとより安全。
日本語が文字化けする
→ llama-cpp-python のバージョンが古い場合に発生することがある。docker compose pull でイメージを最新版に更新する。
メモリ不足でコンテナが落ちる
→ N_CTX を小さくする(4096 → 2048)か、量子化を Q2_K に下げる。根本的にはプランのアップグレードを検討。
9. スケーリングのロードマップ
| フェーズ | 構成変更 | 効果 |
|---|---|---|
| 現在 | VPS S + LFM2.5-1.2B + Q4_K_M | 月 ~€4.5 で動く最小構成 |
| アクセス増加時 | VPS S → VPS 20(16 GB) | 同時リクエスト数とコンテキスト長を拡大 |
| 精度向上 | LFM2.5-1.2B → LFM2.5-8B(GPU 付きプラン) | 回答品質を大幅向上 |
| 本番化 | nginx リバースプロキシ + Let’s Encrypt | HTTPS 化・レート制限 |
まとめ:この構成が「最強コスパ」である理由
LFM2.5-1.2B-JP × llama.cpp × FastAPI × Docker という構成は、次の 3 つの取捨選択の結果だ。
- Dify・n8n は捨てた: 使いやすさは本物だが、メモリが足りない。VPSに Dify を乗せると LLM の分が残らない。
- GPU は不要: LFM2.5-1.2B は CPU で 239 tok/s 以上出る。人間が読む速度の数倍なので体感上は十分だ。
- Ollama・Transformers も不要: llama.cpp を直接使うことで 200〜数 GB のオーバーヘッドをゼロにする。
月額 €4.50(日本円で約 700〜800 円)の VPS で、完全プライベートな日本語 RAG チャットボット API が動く。まずは Contabo VPS S を 1 台借りて、このガイドの Step 1 から試してみてほしい。
参考リンク
- LFM2.5-1.2B-JP-GGUF(Hugging Face)
- llama.cpp(GitHub)
- llama-cpp-python(GitHub)
- Qdrant ドキュメント
- Contabo VPS プラン
- intfloat/multilingual-e5-small(Hugging Face)
