Mac ローカル RAG 環境構築手順のメモ（Ollama x LlamaIndex）


構築時のメモです

## 前提条件
- macOS（Intel／Apple Silicon 問わず）
- Homebrew がインストール済み  

---

## 1. 開発ツールのインストール

### 1.1 pyenv & pyenv-virtualenv
```bash
# Homebrew でインストール
brew update
brew install pyenv pyenv-virtualenv

# シェル初期化ファイルに pyenv 設定を追加
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init --path)"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.zshrc
source ~/.zshrc
```

### 1.2 Ollama（ローカル LLM サーバー）
```bash
# Homebrew でインストール（Intel/macOS向け）
brew install ollama

# llama3:instruct イメージを取得
ollama pull llama3:instruct

# サーバー起動（別ターミナルで実行）
ollama serve
# デフォルトで http://localhost:11434 で待ち受け
```

---

## 2. Python 3.11.9 環境の作成
```bash
# pyenv でインストール済みの Python 3.11.9 を仮想環境としてセットアップ
pyenv install 3.11.9            # 未インストールの場合のみ
pyenv virtualenv 3.11.9 rag-local
# プロジェクトディレクトリで環境を有効化
cd rag-demo
pyenv local rag-local
```

---

## 3. 依存ライブラリのインストール
```bash
pip install --upgrade pip

pip install \
  chromadb==0.5.23 \
  tokenizers==0.15.2 \
  transformers==4.38.2 \
  sentence-transformers==2.6.1 \
  llama-index-core==0.12.37 \
  llama-index-vector-stores-chroma==0.4.1 \
  llama-index-llms-ollama \
  unstructured \
  pdfminer.six \
  python-docx \
  python-pptx \
  openpyxl \
  bitsandbytes accelerate
```

---

## 4. バージョン確認
下記コマンドで主要パッケージのバージョンが揃っていることを確認します:
```bash
python - <<'PY'
import importlib.metadata as m
for p in (
    "chromadb",
    "tokenizers",
    "transformers",
    "sentence-transformers",
    "llama-index-vector-stores-chroma",
    "llama-index-core"
):
    print(p, ":", m.version(p))
PY
```
期待される出力:
```
chromadb                         : 0.5.23
tokenizers                       : 0.15.2
transformers                     : 4.38.2
sentence-transformers            : 2.6.1
llama-index-vector-stores-chroma : 0.4.1
llama-index-core                 : 0.12.37
```

:::note warn
バージョン周りでかなりハマった
:::

---

## 5. プロジェクト構成
```
rag-demo/
├── docs/      ← テキスト／PDF等を配置
└── main.py    ← 実行スクリプト
```

---

## 6. `main.py` の作成
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from llama_index.core import (
    Settings,
    VectorStoreIndex,
    StorageContext,
    SimpleDirectoryReader,
)
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.ollama import Ollama

import chromadb
from llama_index.vector_stores.chroma import ChromaVectorStore

# モデル設定
Settings.embed_model = HuggingFaceEmbedding("BAAI/bge-small-en-v1.5")
Settings.llm         = Ollama(model="llama3:instruct")

# ドキュメント読み込み
docs = SimpleDirectoryReader("./docs").load_data()

# 永続化付き ChromaVectorStore 初期化
vector_store = ChromaVectorStore.from_params(
    collection_name="rag-demo",
    persist_directory="./chroma_db",
)

# インデックス作成
index = VectorStoreIndex.from_documents(
    docs,
    storage_context=StorageContext.from_defaults(vector_store=vector_store),
)

# 質問応答ループ
query_engine = index.as_query_engine()

if __name__ == "__main__":
    print("✅ setup 完了。'exit' で終了")
    while True:
        q = input("❓ 質問 > ").strip()
        if q.lower() in ("exit", "quit"):
            break
        resp = query_engine.query(q)
        print("💬 回答:", str(resp))
```

---

## 7. 実行と確認
```bash
# docs フォルダを作成し、サンプルテキストを配置
mkdir -p docs

cat <<EOF > docs/example.txt
## 社員のプロフィール
- 山田たろう
    - 年齢: 30歳
    - 職業: エンジニア
- 田中はなこ
    - 年齢: 25歳
    - 職業: デザイナー
EOF

# スクリプト実行
python main.py
```
プロンプトに質問し、回答を確認します:
```
❓ 質問 > 社員の人数は？
💬 回答: 2人です。
```

---