所要時間: 約40分 | 難易度: ★★★☆☆

この記事で作るもの

  • 手元のPDFドキュメントの内容を、完全にオフラインで解析・回答する「ローカルRAG(検索拡張生成)システム」
  • 前提知識:Pythonの基本的な文法(変数、関数)がわかり、ターミナルでコマンド操作ができること
  • 必要なもの:メモリ32GB以上のPC(GPUはRTX 3060 12GB以上推奨。MacならM2/M3搭載機)、Python 3.10以上

📦 この記事に関連する商品

NVIDIA GeForce RTX 3090

32Bモデルを快適に動かすには24GBのVRAMが最もコストパフォーマンスに優れています

Amazonで見る 楽天で見る

※アフィリエイトリンクを含みます

なぜこの方法を選ぶのか

これまでローカルLLMの世界では「軽量だが賢くない7B」か「賢いが動かすのが困難な70B」の二択でした。しかし、Qwen2.5で登場した「32B」というウェイトクラスは、この常識を破壊しました。RTX 3090や4090といった消費者向けハイエンドGPUの24GB VRAMに、4-bit量子化なら余裕で収まりつつ、性能は旧世代の70Bモデルを凌駕します。

クラウドAPIを使えば数分で実装できますが、業務データや機密文書を扱う場合、データ流出のリスクをゼロにはできません。本記事では、推論エンジンに「Ollama」、オーケストレーションに「LangChain」を採用します。この組み合わせは、現在最もエコシステムが成熟しており、一度構築すればモデルを入れ替えるだけで最新の技術を追いかけられるからです。

Step 1: 環境を整える

まずは、推論エンジンであるOllamaをインストールし、32Bモデルをダウンロードします。

# Ollamaのインストール(公式サイトからダウンロードも可能)
# macOS/Linuxの場合
curl -fsSL https://ollama.com/install.sh | sh

# Qwen2.5 32Bモデルのプル(ダウンロード)
# 4-bit量子化版であれば約19GBの容量が必要です
ollama pull qwen2.5:32b

# 動作確認
ollama run qwen2.5:32b "AIのウェイトクラスについて3行で説明して"

Ollamaは内部でllama.cppを動かしており、OSやハードウェアに合わせて最適な命令セット(AVX2やCUDAなど)を自動選択してくれます。自分自身でビルドする手間を省きつつ、最高速の推論環境を手に入れられるのが最大のメリットです。

⚠️ 落とし穴: VRAMが16GB以下のGPUで32Bモデルを動かそうとすると、処理が極端に遅くなる(1トークン/秒以下)ことがあります。これはVRAMから溢れたデータがメインメモリ(RAM)にスワップされるためです。その場合は、モデルを「qwen2.5:14b」や「qwen2.5:7b」に下げて試してください。

Step 2: Python環境とライブラリの設定

次に、RAGを構成するためのPythonライブラリをインストールします。仮想環境(venvやconda)を作成してから実行することを強く推奨します。

# ライブラリのインストール
pip install langchain langchain-ollama langchain-community pypdf faiss-cpu

Pythonコードを作成します。APIキーを直書きする必要はありませんが、ライブラリのバージョン依存が激しいため、最新版を入れるようにしてください。

import os
from langchain_ollama import OllamaEmbeddings, ChatOllama
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain.chains import RetrievalQA

# モデル名の定義。Ollamaでプルした名前と一致させる
MODEL_NAME = "qwen2.5:32b"

# 1. LLMの初期化
# temperature=0にするのは、RAGにおいてモデルの「創作」を抑え、事実に忠実にさせるためです
llm = ChatOllama(model=MODEL_NAME, temperature=0)

# 2. 埋め込みモデル(Embedding)の初期化
# 本来は専用モデルが良いですが、今回は手軽にOllamaのモデルを流用します
embeddings = OllamaEmbeddings(model=MODEL_NAME)

「なぜ埋め込みモデルも32Bにするのか」と疑問に思うかもしれません。本来はmxbai-embed-largeなどの軽量な専用モデルを使うのが定石ですが、最初は同じモデルで完結させたほうが設定ミスが減り、ベクトル空間の整合性も取りやすいためです。

Step 3: PDFを読み込んでベクトル化する

RAGの肝となる、ドキュメントの「ベクトル化」と「保存」を行います。

# PDFの読み込み(カレントディレクトリに sample.pdf を置いてください)
loader = PyPDFLoader("sample.pdf")
docs = loader.load()

# テキストの分割
# chunk_sizeは、一度にLLMに渡す情報の塊のサイズです
# 32Bモデルは文脈理解が強いため、少し大きめの1000トークン程度に設定します
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
splits = text_splitter.split_documents(docs)

# ベクトルストア(FAISS)の構築
# ここでPDFの内容が数値化され、検索可能な状態になります
vectorstore = FAISS.from_documents(documents=splits, embedding=embeddings)

期待される出力

このコードを実行すると、バックグラウンドでOllamaが動き出し、GPUの使用率が跳ね上がります。数秒から数十秒で完了し、エラーが出なければ成功です。

Step 4: 実用レベルのQAシステムにする

最後に、ユーザーの質問に対して「関連情報を検索し、それを踏まえて回答する」処理を実装します。

# 検索機能の作成
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})

# チェーン(一連の処理)の構築
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=retriever,
    return_source_documents=True
)

# 実際の質問
query = "この資料に記載されている主なリスクと対策は何ですか?"

try:
    response = qa_chain.invoke(query)
    print("--- 回答 ---")
    print(response["result"])
    print("\n--- 参照元ドキュメント ---")
    for doc in response["source_documents"]:
        print(f"ページ: {doc.metadata['page']} / 内容の一部: {doc.page_content[:50]}...")
except Exception as e:
    print(f"エラーが発生しました: {e}")
    print("Ollamaが起動しているか、VRAMが不足していないか確認してください。")

実務で使えるレベルにするために、return_source_documents=Trueを設定しています。これにより、AIが「どこを読んでそう答えたか」の根拠を表示でき、ハルシネーション(嘘)のチェックが容易になります。

よくあるトラブルと解決法

エラー内容原因解決策
ConnectionError: Ollama not foundOllamaサービスが未起動ollama serve を実行するかアプリを起動
OutOfMemoryError (CUDA)VRAM容量不足14bや7bなど、より小さいモデルに変更する
回答が英語になるシステムプロンプトが未設定プロンプトに「日本語で答えて」と明示的に追加

次のステップ

ここまでの内容で、32Bモデルという「新しい武器」を使ったローカルRAGの基礎は完成です。次は、以下のステップに挑戦してみてください。

  1. プロンプトエンジニアリングの最適化: PromptTemplateを使い、AIに対して「あなたはプロの法務担当者です」といった役割を与えると、回答の精度が劇的に向上します。
  2. 高速化(GGUF量子化の検討): Ollamaは標準で4-bitですが、さらに軽量な3-bitや2-bitの量子化モデルを自作して読み込むことも可能です。
  3. UIの実装: Streamlitを使えば、このPythonコードをわずか10行程度の追加でブラウザから使えるウェブアプリに進化させられます。

32Bクラスの登場により、もはや「個人や小規模チームでは性能不足」という言い訳は通用しなくなりました。実務で使えるAIは、今やあなたのローカルPCの中にあります。

よくある質問

Q1: 32Bモデルを動かすのにRTX 4090は必須ですか?

必須ではありません。RTX 3060(12GB)でも、4-bit量子化なら14Bモデルまでは快適に、32Bモデルも低速(数トークン/秒)ながら動作します。実務的な速度を求めるなら、VRAM 16GB以上のRTX 4080や、24GBの3090/4090が推奨されます。

Q2: PDFが100ページ以上ある場合でも動きますか?

動きますが、ベクトル化(Step 3)に時間がかかります。大規模なドキュメントを扱う場合は、一度構築したFAISSのインデックスを vectorstore.save_local("faiss_index") で保存し、次回からロードするようにコードを修正すると効率的です。

Q3: 会社の機密書類を読み込ませても本当に安全ですか?

本記事の手順通り、OllamaとローカルのPython環境で完結していれば、データが外部サーバー(OpenAI等)に送信されることはありません。ただし、ライブラリの更新チェックなどでインターネット通信が発生する場合があるため、完全なエアギャップ環境(ネット遮断)で運用する場合は、依存関係をすべてオフラインでインストールする必要があります。


あわせて読みたい