【脱クラウド】OllamaとChromaDBで作る、完全ローカル&無料の「自分専用AI」構築ガイド

OllamaとPythonでローカルRAG構築!ChromaDB実践ガイド AI開発(自作AI)
【脱クラウド】OllamaとChromaDBで作る、完全ローカル&無料の「自分専用AI」構築ガイド

クラウドにお金を払い続けるのは、もう終わりにしませんか?

こんにちは、AIデベロッパーのケンジです。

「ChatGPTのAPI料金がじわじわ上がって怖い」「社外秘のドキュメントをクラウドに投げるのは抵抗がある」……そんな悩みを持っていませんか?

もしあなたが、「完全無料」かつ「オフライン」で、しかも「自分の手元のデータを知っている」AIを作れるとしたらどうでしょう? それが今回解説する、ローカルRAG(Retrieval-Augmented Generation)の世界です。

この記事では、現在最もホットなツールである OllamaChromaDB を組み合わせ、Pythonを使ってわずか数10行のコードで「自分専用AI」を構築する手順を解説します。LangChainのような複雑なラッパーライブラリをあえて使わず、技術の「中身」が完全に理解できる形で実装します。

読み終える頃には、あなたのPCの中に、あなただけの専属アシスタントが住み着いているはずです。

なぜ「Ollama × ChromaDB」なのか?

ローカル環境でAIを動かすためのツールは山ほどありますが、現時点で私が「最強の組み合わせ」と断言するのがこれです。

ツール名 役割 選定理由 (Why)
Ollama LLMの実行エンジン Llama 3やMistralなどの高性能モデルを、コマンド1つでダウンロード・実行できる。Dockerのような手軽さが革命的。
ChromaDB ベクトルデータベース セットアップ不要でPythonから即利用可能。軽量かつ高速で、プロトタイピングから小規模プロダクションまで対応。
Python 接着剤 AI開発の共通言語。今回はあえてLangChainを使わず、OllamaとChromaDBの公式ライブラリを直接制御して軽量化を図ります。

RAG(検索拡張生成)の仕組みを3行で解説

AIに独自の知識を与える「RAG」の仕組みはシンプルです。

  1. 検索 (Retrieval): ユーザーの質問に関連する情報を、手元のデータベース(ChromaDB)から探し出す。
  2. 拡張 (Augmented): 探し出した情報を「カンニングペーパー」としてプロンプトに貼り付ける。
  3. 生成 (Generation): AI(Ollama)がそのカンニングペーパーを見ながら回答を作成する。

これにより、AIは学習していない社内マニュアルや個人的なメモについても回答できるようになります。

実践ガイド:やってみよう

ここからは、実際に手を動かして環境を構築します。エンジニアらしく、無駄を削ぎ落とした最短ルートを進みます。

前提条件

  • OS: Windows, macOS, Linux (いずれも可)
  • Python: 3.8以上
  • 推奨スペック: メモリ16GB以上(8GBでも動きますが、モデル選びに制限が出ます)

Step 1: Ollamaのインストールとモデル準備

まず、Ollama公式サイトからインストーラーをダウンロードして実行してください。

インストール完了後、ターミナル(コマンドプロンプト)を開き、以下のコマンドでモデルをダウンロードします。今回は軽量かつ高性能な Llama 3.2 と、文章をベクトル化するための nomic-embed-text を使用します。

# 会話用モデル (数GBのダウンロードが発生します)
ollama pull llama3.2

# 埋め込み用モデル (非常に軽量です)
ollama pull nomic-embed-text

ollama serve がバックグラウンドで動いていることを確認してください(通常、インストール後に自動起動しています)。

Step 2: Python環境のセットアップ

プロジェクト用フォルダを作成し、必要なライブラリをインストールします。

pip install ollama chromadb

Step 3: 「自分専用AI」のコード実装

以下のコードを local_rag.py という名前で保存してください。これは、ドキュメントの読み込みから検索、そして回答生成までを一気通貫で行うスクリプトです。

import ollama
import chromadb
import sys

# --- 設定 ---
# 会話に使用するLLMモデル
CHAT_MODEL = "llama3.2"
# テキストをベクトル化する埋め込みモデル
EMBED_MODEL = "nomic-embed-text"

def main():
    print("🚀 システムを初期化しています...")

    # 1. ベクトルデータベース(ChromaDB)の初期化
    # ここではメモリ上で動作させますが、persist_directoryを指定すれば保存も可能です
    client = chromadb.Client()
    try:
        collection = client.create_collection(name="my_knowledge_base")
    except Exception:
        # 既に存在する場合は取得
        collection = client.get_collection(name="my_knowledge_base")

    # 2. 知識データの準備 (本来はPDFやテキストファイルから読み込みます)
    print("📚 知識データを学習中...")
    documents = [
        "Ollamaは、ローカル環境でLLMを簡単に実行・管理できるツールです。Mac, Linux, Windowsに対応しています。",
        "ChromaDBは、AIアプリケーション向けのオープンソースベクトルデータベースです。設定不要でPythonからすぐに使えます。",
        "ケンジはAIデベロッパーで、現在はローカルLLMの普及活動に力を入れています。好きな飲み物はブラックコーヒーです。",
        "RAG (Retrieval-Augmented Generation) は、外部データを検索してLLMに与えることで、回答の精度を向上させる技術です。"
    ]

    # 3. データをベクトル化してDBに保存
    for i, doc in enumerate(documents):
        # Ollamaを使ってテキストをベクトル(数字の列)に変換
        response = ollama.embeddings(model=EMBED_MODEL, prompt=doc)
        embedding = response["embedding"]
        
        # ChromaDBに登録
        collection.add(
            ids=[str(i)],
            embeddings=[embedding],
            documents=[doc]
        )
    print(f"✅ {len(documents)}件のデータを学習しました。")

    # 4. ユーザーからの質問
    user_query = "ケンジって誰?"
    if len(sys.argv) > 1:
        user_query = sys.argv[1]
    
    print(f"\n🤔 質問: {user_query}")

    # 5. 検索 (Retrieval)
    # 質問文をベクトル化
    query_embed = ollama.embeddings(model=EMBED_MODEL, prompt=user_query)["embedding"]
    
    # 類似度が高い情報を検索 (ここではトップ1件を取得)
    results = collection.query(
        query_embeddings=[query_embed],
        n_results=1
    )
    
    # 検索結果を取り出す
    if not results['documents'][0]:
        print("関連情報が見つかりませんでした。")
        return

    retrieved_info = results['documents'][0][0]
    print(f"💡 検索された関連情報: {retrieved_info}")

    # 6. 生成 (Generation)
    # 検索結果をコンテキストとしてプロンプトに埋め込む
    prompt = f"""
    以下の情報を参考にして、質問に簡潔に答えてください。
    
    [参考情報]
    {retrieved_info}
    
    [質問]
    {user_query}
    """

    print("\n🤖 回答生成中...")
    response = ollama.generate(model=CHAT_MODEL, prompt=prompt)
    
    print("=" * 30)
    print(response['response'])
    print("=" * 30)

if __name__ == "__main__":
    main()

実行結果

ターミナルで以下のように実行してみましょう。

python local_rag.py "ケンジの好きな飲み物は何?"

出力例:

💡 検索された関連情報: ケンジはAIデベロッパーで、現在はローカルLLMの普及活動に力を入れています。好きな飲み物はブラックコーヒーです。

🤖 回答生成中...
==============================
ケンジの好きな飲み物はブラックコーヒーです。
==============================

成功です! モデル自体(Llama 3.2)はケンジのことを知りませんが、ChromaDBから取得した情報を元に正しく回答できています。

プロフェッショナルのためのTips & 注意点

実運用を考える際に知っておくべきポイントをまとめました。

⚠️ LangChainを使わない理由
多くのチュートリアルではLangChainを使いますが、学習段階ではおすすめしません。LangChainは抽象度が高く、エラーが起きたときに「どこで何が起きているか(OllamaのエラーかDBのエラーか)」が分かりにくくなるからです。まずは上記のように直接APIを叩くことで、RAGの本質的な仕組みを理解しましょう。
🔧 PDFやMarkdownを読み込ませるには?
実際のアプリでは、documents リストの中身をファイルから読み込む必要があります。Pythonの pypdf や標準の open() 関数を使ってテキストを抽出し、リストに追加してください。
💻 ハードウェアのリスク
ローカルLLMはPCのリソース(特にメモリとGPU)を激しく消費します。動作が重い場合は、より小さなモデル(例: llama3.2:1b)を試すか、生成時に他のアプリを閉じてください。

まとめ:あなただけの情報の城を築こう

たったこれだけのコードで、外部にデータを漏らすことなく、あなた専用の知識検索システムが完成しました。これを応用すれば、自分の日記、技術メモ、あるいは大量の顧客データを読み込ませて、一瞬でインサイトを引き出すことも可能です。

情報は現代の「石油」です。それを他人のタンク(クラウド)に預けるのではなく、自分の城(ローカル環境)で精製する技術を持つこと。それこそが、AI時代を賢く生き抜くエンジニアの戦略だと私は考えます。

さらに高度な情報管理術については、情報洪水に溺れないために。多忙なサラリーマンがAIと「自分専用の全自動メディア群」を構築した全記録でも解説していますので、ぜひ参考にしてください。

コメント

タイトルとURLをコピーしました