スマートフォン・タブレットからインターネットサーバーオペレーション
RAGは、ユーザーの質問に対して、まず関連する文書をベクトル検索で取得し、その文書を大規模言語モデル(LLM)に渡して回答を生成する手法です。これにより、モデル単体では持ち得ない最新情報やドメイン知識を活用した高精度な応答が可能になります。
RAGの基本構成は以下の通りです。
依存パッケージのインストール
必要なパッケージをインストールします。
sudo apt update && sudo apt install -y build-essential cmake git python3-pip python3-venv
llama.cppのビルド
LLMをCPUで動かすための軽量フレームワーク「llama.cpp」をビルドします。
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
cmake -B build
cmake --build build --config Release -j3
Python仮想環境の作成と必要ライブラリのインストール
python3 -m venv rag-env
source rag-env/bin/activate
pip install llama-cpp-python sentence-transformers chromadb
Hugging Face CLIを使って、実験用のLLMモデル(例:Gemma)をダウンロードします。
pip install huggingface-hub
hf download unsloth/gemma-4-E2B-it-GGUF gemma-4-E2B-it-Q4_K_M.gguf --local-dir ~/models
解説:モデルは用途やVPSのスペックに合わせて選択してください。
主要ライブラリのインポートと設定
python3 -m venv rag-env
source rag-env/bin/activate
pip install llama-cpp-python sentence-transformers chromadb
llama-cpp-pythonでLLMを、sentence-transformersで埋め込みモデルを、chromadbでベクトルDBを扱います。
サンプルコードのポイント:
# rag.py
from llama_cpp import Llama
from sentence_transformers import SentenceTransformer
import chromadb
import numpy as np
# ---- 設定 ----
MODEL_PATH = "(#MODELのPATH#)/gemma-4-E2B-it-Q4_K_M.gguf"
N_CTX = 2048
N_THREADS = 3 # CPUのコア数
# ---- 初期化 ----
# LLM(llama.cpp)
llm = Llama(
model_path=MODEL_PATH,
n_ctx=N_CTX,
n_threads=N_THREADS,
n_gpu_layers=0, # CPU only
verbose=False
)
# 埋め込みモデル(軽量なものを選ぶ)
embedder = SentenceTransformer("intfloat/multilingual-e5-small")
# ベクトルDB(ChromaDB をローカルで使用)
chroma_client = chromadb.PersistentClient(path="./chroma_db")
collection = chroma_client.get_or_create_collection("documents")
def chunk_text(text: str, chunk_size: int = 300, overlap: int = 50) -> list[str]:
"""長文を重複付きで分割"""
words = text.split()
chunks, i = [], 0
while i < len(words):
chunk = " ".join(words[i:i + chunk_size])
chunks.append(chunk)
i += chunk_size - overlap
return chunks
# ---- ドキュメント登録 ----
def add_documents(docs: list[dict]):
texts = [d["text"] for d in docs]
ids = [d["id"] for d in docs]
# 空の場合は source キーをデフォルトで入れる
metas = [d.get("metadata") or {"source": "unknown"} for d in docs]
embeddings = embedder.encode(texts, normalize_embeddings=True).tolist()
collection.upsert(documents=texts, embeddings=embeddings,
ids=ids, metadatas=metas)
print(f"{len(docs)} 件登録完了")
# ---- 検索 ----
def retrieve(query: str, top_k: int = 3) -> list[str]:
q_emb = embedder.encode([query], normalize_embeddings=True).tolist()
results = collection.query(query_embeddings=q_emb, n_results=top_k)
return results["documents"][0] # テキストのリスト
# ---- RAG 推論 ----
def rag_query(question: str) -> str:
# 1. 関連文書を取得
contexts = retrieve(question)
context_text = "\n\n".join(f"[{i+1}] {c}" for i, c in enumerate(contexts))
# 2. プロンプト構築
prompt = f"""以下のコンテキストを参考に質問に答えてください。
### コンテキスト
{context_text}
### 質問
{question}
### 回答
"""
# 3. LLM で生成
output = llm(
prompt,
max_tokens=512,
temperature=0.1,
stop=["###", "\n\n\n"]
)
return output["choices"][0]["text"].strip()
# ---- メイン ----
if __name__ == "__main__":
# サンプルドキュメント登録
sample_docs = [
{"id": "1", "text": "ConoHa VPS の CPU 3 コア / メモリ 2GB のプランを利用している。",
"metadata": {"source": "rpi_doc"}},
{"id": "2", "text": "llama.cpp は CPU のみでも LLM を動かせる軽量フレームワークだ。",
"metadata": {"source": "llamacpp_doc"}},
{"id": "3", "text": "RAG はベクトル検索で関連文書を取得し、LLM に渡す手法だ。",
"metadata": {"source": "rag_doc"}},
]
add_documents(sample_docs)
# 質問
question = "ConoHa VPS で LLM を動かすには何が必要ですか?"
answer = rag_query(question)
print(f"\nQ: {question}\nA: {answer}")
解説:
add_documents関数で文書をベクトルDBに登録retrieve関数で質問に関連する文書を検索rag_query関数でプロンプトを組み立て、LLMで回答生成仮想環境の有効化と実行
source rag-env/bin/activate
python rag.py
出力例:
Q: ConoHa VPS で LLM を動かすには何が必要ですか?
A: ConoHa VPS で LLM を動かすには、以下の要素が必要です。
1. **ハードウェアリソース**:
* **CPU**: 3 コア
* **メモリ**: 2GB
2. **ソフトウェア**:
* **軽量フレームワーク**: `llama.cpp` のような、CPU のみで動作可能な軽量フレームワーク。
3. **LLM モデル**:
* 実行したいLLMモデル。
4. **(オプション)高度な手法**:
* **RAG**: ベクトル検索を用いて関連文書を取得し、LLM に渡す手法を利用する場合。
**まとめると、ConoHa VPS 上でLLMを動かすためには、VPSのスペック(CPU/メモリ)を考慮し、`llama.cpp`などの軽量なフレームワークを選び、実行したいモデルを用意することが必要です。**