本文へスキップ
RAG開発

Ollama + ChromaDB で、データを外に出さないローカルRAGを作る

機密文書を扱うなら、データを社外に出さないローカル完結のRAGが現実解。OllamaのローカルLLMとChromaDBで構築する流れと、選定の理由を解説します。

2分で読めます

「RAGを作りたいが、社内文書を外部APIに送るのは許可が下りない」。機密情報を扱う現場では、これが最大の壁になります。答えは、データを一切外に出さないローカル完結の構成です。ここでは Ollama と ChromaDB を使った実装の勘所を紹介します。

なぜローカル構成を選ぶのか

クラウドのLLM APIは精度・手軽さで有利ですが、機密文書の送信が許容されないケースでは選べません。ローカルLLM(Ollama)とローカルのベクトルDB(ChromaDB)なら、データはネットワークの外に出ません。「精度」と「機密保持」を天秤にかけ、後者が要件なら迷わずローカルです。

構成要素

  • Ollama:ローカルでLLMを動かすランタイム。ollama run でモデルを手元で実行できる
  • ChromaDB:埋め込みベクトルを保存・検索する軽量なベクトルDB
  • 埋め込みモデル:チャンクをベクトル化するモデル(Ollama経由でも利用可)

取り込み:ドキュメントをベクトル化する

ドキュメントを意味のまとまりで分割し、ベクトル化してChromaDBに格納します。

import chromadb
from chromadb.utils import embedding_functions

client = chromadb.PersistentClient(path="./store")
collection = client.get_or_create_collection("docs")

# チャンク(事前に分割したテキスト)を格納
collection.add(
    documents=chunks,
    ids=[f"doc-{i}" for i in range(len(chunks))],
)

検索 → 生成:根拠付きで答える

質問が来たら、関連チャンクを検索し、それを根拠としてOllamaのLLMに渡します。

import ollama

hits = collection.query(query_texts=[question], n_results=4)
context = "\n\n".join(hits["documents"][0])

prompt = f"""次の資料だけを根拠に、日本語で答えてください。
資料にない場合は「分かりません」と答えること。

# 資料
{context}

# 質問
{question}
"""

res = ollama.chat(model="llama3", messages=[{"role": "user", "content": prompt}])
print(res["message"]["content"])

ポイントは、プロンプトで**「資料にないことは答えない」**と明示すること。これだけでハルシネーションがかなり抑えられます。さらに、検索でヒットしたチャンクの出典を回答に添えれば、利用者が根拠を確認できます。

つまずきやすいところ

  • チャンク分割が粗いと検索が外す:意味のまとまりを意識して分割する
  • 検索件数が多すぎると文脈が薄まる:まずは3〜5件から調整する
  • モデル選定は速度とのバランス:ローカルはマシン性能に依存するため、用途に合うサイズを選ぶ

まとめ

  • 機密要件があるなら、Ollama + ChromaDB のローカル完結が現実解
  • プロンプトで「資料にないことは答えない」と縛る
  • 検索の作り込みが回答品質を決める

自社データでのローカルRAG構築、設計から対応できます。

タグ:#RAG#Ollama#ChromaDB#ローカルLLM

Fiidia

AI・RAG・Flutter・Web を横断する個人開発者。プロフィール →

関連サービス

RAG活用のAI開発

社内ドキュメント検索・問い合わせ対応・ナレッジ活用を、RAG(検索拡張生成)で実装。根拠付きで答えるAIを構築します。