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

この記事で作るもの

  • RTX 3090/4090を活用し、OllamaとPythonを連携させて「社外秘ドキュメントを高速に要約する自前AIツール」を作ります
  • 外部API(OpenAI等)を一切使わず、完全にオフラインで動作するため機密情報の漏洩リスクがゼロになります
  • 必要なもの:Windows(WSL2)またはLinux、VRAM 12GB以上のGPU(24GB推奨)、Python 3.10以上

📦 この記事に関連する商品(楽天メインで価格確認)

RTX 3090 24GB

VRAM 24GBを最も安価に確保でき、ローカルLLM実務において現役最強のコスパを誇るため

楽天で価格を見る Amazonでも確認

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

先に確認するスペック・料金

今のGPU市場は異常です。リークされているRTX 5090の価格を追いかけるより、実務家なら「VRAM 24GB」をいかに安く確保するかを考えるべきです。私は現在RTX 4090を2枚刺しで運用していますが、これから組むなら中古のRTX 3090(10万円〜12万円程度)が最もコスパが良いと断言できます。

なぜなら、LLMの推論において重要なのは「チップの計算速度」よりも「VRAMの容量と帯域」だからです。5090がどれだけ速くても、VRAMが32GBに届かないのであれば、動かせるモデルのサイズは4090と大差ありません。

もしあなたがMacユーザーなら、メモリ(ユニファイドメモリ)を64GB以上積んだMac Studioを検討してください。推論速度はGPUに劣りますが、巨大なモデルを動かせるメリットは大きいです。Windows派なら、迷わずVRAM 24GBのモデルを探してください。16GB(RTX 4080等)は、今のLLM開発においては中途半端で、すぐに買い替える羽目になります。

なぜこの方法を選ぶのか

クラウドAPI(GPT-4等)は便利ですが、実務で使うには「従量課金のコスト」と「セキュリティ」が常に壁になります。特にSIer時代の経験から言えば、顧客データを外部サーバーに送る許可を取るだけで数ヶ月かかることも珍しくありません。

ローカルLLM、特に「Ollama」を使った環境構築を選ぶ理由は、そのセットアップの速さと、量子化モデル(GGUF形式)の扱いやすさにあります。llama.cppを直接ビルドするのも手ですが、仕事で使うなら「一瞬で立ち上がり、APIサーバーとしても機能する」Ollamaが現状のベストプラクティスです。この記事では、Ollamaをバックエンドに、Pythonで実用的なラッパーを作る手順を解説します。

Step 1: 環境を整える

まずはバックエンドとなるOllamaをインストールし、モデルをロードします。

# Linux / WSL2の場合
curl -fsSL https://ollama.com/install.sh | sh

# インストール確認
ollama --version

# Llama 3.1 (8B) モデルのダウンロード
ollama pull llama3.1

Ollamaはデフォルトで11434ポートを使ってAPIサーバーとして待機します。これにより、PythonやNode.jsから簡単に推論を呼び出せるようになります。llama3.1(8Bモデル)を選ぶ理由は、VRAM 8GB程度でも高速に動作し、かつ日本語の理解力も実用レベルに達しているためです。

⚠️ 落とし穴: WSL2を利用している場合、デフォルトではGPUを認識しないことがあります。必ず最新のNVIDIAドライバーをWindows側にインストールし、nvidia-smi コマンドがWSL内で動作することを確認してください。ここを飛ばすと、CPU推論になり、レスポンスに数分かかることになります。

Step 2: Pythonライブラリのセットアップ

次に、PythonからOllamaを操作するためのライブラリを導入します。

# 仮想環境の作成
python -m venv venv
source venv/bin/activate  # Windowsは venv\Scripts\activate

# 必要なライブラリのインストール
pip install ollama pandas python-dotenv

ここでは、公式の ollama ライブラリを使用します。これを使うことで、OpenAIのSDKと似た感覚でローカルモデルを叩けるようになります。

# settings.py
import os

# Ollamaのホスト設定(ローカルならデフォルトでOK)
OLLAMA_HOST = "http://localhost:11434"
# 使用するモデル名
MODEL_NAME = "llama3.1"

あえて設定ファイルを分けるのは、将来的にモデルを DeepSeek-V3Gemma 2 に切り替える際、コード本体を書き換えずに済むようにするためです。

Step 3: 動かしてみる

まずは最小限のコードで、GPUが正しく使われているか、レスポンスが返ってくるかを確認します。

import ollama

def test_inference():
    response = ollama.chat(model='llama3.1', messages=[
        {
            'role': 'user',
            'content': 'ローカルLLMを導入する最大のメリットを1行で教えて。',
        },
    ])
    print(response['message']['content'])

if __name__ == "__main__":
    test_inference()

期待される出力

機密データを外部に送信せず、低コストかつプライバシーを維持したまま自由なカスタマイズが可能です。

私のRTX 4090環境では、このレスポンスは0.2秒程度で返ってきます。もし10秒以上かかる場合は、GPUが使われずCPU推論になっている可能性が高いです。その際は、Ollamaのログ(/var/log/ollama.logなど)を確認し、CUDAの初期化に失敗していないかチェックしてください。

Step 4: 実用レベルにする(ドキュメント要約ツール)

ここからが本題です。単なるチャットではなく、実務で使える「大量のテキストファイルを一括で要約するスクリプト」を構築します。

import ollama
import os

class LocalSummarizer:
    def __init__(self, model="llama3.1"):
        self.model = model

    def summarize(self, text):
        prompt = f"""
        以下の文章を、要点を3点に絞って日本語で要約してください。

        文章:
        {text}

        要約(箇条書き):
        """

        try:
            response = ollama.generate(
                model=self.model,
                prompt=prompt,
                options={
                    "num_ctx": 4096,  # コンテキストウィンドウの設定
                    "temperature": 0.2  # 創造性を抑えて正確性を重視
                }
            )
            return response['response']
        except Exception as e:
            return f"Error: {str(e)}"

    def process_files(self, input_dir):
        for filename in os.listdir(input_dir):
            if filename.endswith(".txt"):
                path = os.path.join(input_dir, filename)
                with open(path, 'r', encoding='utf-8') as f:
                    content = f.read()
                    print(f"Processing {filename}...")
                    summary = self.summarize(content)
                    print(f"Summary for {filename}:\n{summary}\n")

if __name__ == "__main__":
    # テキストファイルが入っているディレクトリを指定
    summarizer = LocalSummarizer()
    # 実行前に 'docs' ディレクトリを作成し、適当なテキストを入れておくこと
    if not os.path.exists("docs"):
        os.makedirs("docs")
        with open("docs/sample.txt", "w") as f:
            f.write("ここに長い文章を入力します...")

    summarizer.process_files("docs")

このスクリプトのポイントは options の設定です。num_ctx: 4096 は、モデルが一度に処理できるトークン数(文脈)を指定しています。RTX 3090/4090のようなVRAM 24GBモデルであれば、ここを 819216384 に増やすことで、より長い議事録なども一度に処理できるようになります。

また、temperature: 0.2 に設定しているのは、要約というタスクにおいてモデルの「揺らぎ」を最小限にするためです。実務において、要約のたびに内容が変わってしまうのは使い勝手が悪いですからね。

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

エラー内容原因解決策
connection refusedOllamaサーバーが起動していないollama serve を実行して常駐させる
推論が極端に遅いVRAM不足でCPU/System RAMに溢れているモデルを 8b から 3b に下げるか、量子化率の高いモデル(Q4等)を使う
日本語が文字化けするプロンプトに日本語が含まれていない、またはモデルが未対応Llama 3.1以降、または elyza-llama-3 などの日本語特化モデルを pull する

次のステップ

この記事で、ローカル環境での推論とPython連携の基礎は完成しました。次に取り組むべきは「RAG(検索拡張生成)」の構築です。

今回の要約スクリプトは、モデルの知識と入力したテキストのみを使用していますが、これにベクトルデータベース(ChromaDBやQdrant)を組み合わせることで、社内のPDF数万枚から特定の情報を探し出して回答する「社内専用ChatGPT」が作れます。

また、もし「もっと大きなモデルを動かしたい」という欲求が出てきたら、Redditの投稿にあったように海外へ買い出しに行く……必要はありません。今は秋葉原の中古市場や、ヤフオク等で状態の良いRTX 3090を2枚揃えるのが、最も賢い投資です。2枚刺し(48GB)あれば、70Bクラスの超高性能モデルがサクサク動くようになります。この世界は、物理的なVRAM容量こそが正義なのです。

よくある質問

Q1: RTX 3060 (12GB) でも動きますか?

動きます。Llama 3.1 (8B) の4ビット量子化モデルなら、VRAM消費は5GB程度。12GBあれば、余裕を持って動作し、同時にブラウザを開いていても問題ありません。まずは手持ちのカードで試すのが一番です。

Q2: 処理速度をさらに上げるにはどうすればいい?

バッチ処理(Batch Inference)を検討してください。今回紹介した ollama.generate を非同期(asyncio)で並列実行することで、GPUの稼働率を最大限まで引き上げることが可能です。

Q3: モデルはどう選べばいいですか?

「日本語の自然さ」なら Llama-3-ELYZA-JP-8B、「推論能力の高さ」なら DeepSeek-R1-Distill-Llama-8B が現在のトレンドです。Ollamaなら ollama pull 一つで切り替えられるので、タスクごとに最適なモデルを検証してください。


あわせて読みたい