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

この記事で作るもの

  • Qwen-2.5シリーズ(噂の27Bを含む)をローカルPCで動かし、フォルダ内の全ドキュメントを自動解析・構造化するPythonスクリプトを作ります。
  • 前提知識:Pythonの基本的な文法(pipインストールや関数の実行)がわかること。
  • 必要なもの:NVIDIA製GPU(VRAM 12GB以上推奨)またはApple Silicon搭載Mac(メモリ24GB以上推奨)、Ollama。

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

RTX 4060 Ti 16GB

VRAM 16GB搭載で、27Bクラスのモデルを予算を抑えて動かすための最低ライン

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

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

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

ローカルLLMを「仕事で使う」なら、スペック妥協は厳禁です。 今回注目されている27B(270億パラメータ)クラスのモデルを快適に動かすには、4ビット量子化版で約16GBから18GBのVRAMを消費します。 RTX 3060(12GB)だと、推論はできますがシステム全体のメモリを圧迫し、レスポンスが1秒間に2〜3トークンまで落ちて実用的ではありません。

理想はRTX 3090や4090の24GBモデルです。 これならQwen-2.5-32B(現行の近いサイズ)を動かしても5GB以上の余裕があり、長文のコンテキストを読み込ませてもクラッシュしません。 Mac派なら、最低でもM2/M3の「32GBメモリ」以上のモデルを選んでください。 WindowsでGPUを新調できない場合は、WSL2(Windows Subsystem for Linux)のセットアップが必須になります。

API料金は一切かかりません。 電気代を除けば、どれだけ回してもタダなのがローカルLLMの最大のメリットです。

なぜこの方法を選ぶのか

クラウドAPI(GPT-4oやClaude 3.5 Sonnet)は確かに優秀ですが、社外秘の設計書や個人情報を含むソースコードを投げるのはリスクが伴います。 「プライバシーのためにローカルで動かす」というのは大前提として、私がQwenの27Bクラスを推す理由は「Gemma 2 27B」への対抗馬として、日本語の処理能力とプログラミング能力のバランスが非常に高いからです。

7Bだと知能が足りず、70Bだと一般的なPCでは重すぎる。 この「27B〜32B」というサイズは、コンシューマー向けハイエンドGPU1枚で「賢さ」と「速度」を両立できるスイートスポットなのです。 今回は、環境構築が最も簡単で、かつAPIサーバーとしても機能する「Ollama」をベースに解説します。

Step 1: 環境を整える

まずは、LLMを実行するためのエンジンであるOllamaをインストールします。

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

# Windowsの場合は公式サイト(ollama.com)からインストーラーをダウンロードして実行

次に、モデルをダウンロードします。現時点では27Bの正式リリース前(あるいは噂の段階)のため、ほぼ同等のリソースを消費する「Qwen2.5:32b」を使用して環境を構築します。27Bがリリースされた際は、モデル名を変更するだけでそのまま動きます。

# モデルのプル(約19GBのダウンロードが発生します)
ollama pull qwen2.5:32b

このコマンドは、モデルファイルをローカルに保存し、GPUメモリへのロード準備を整えるものです。 32BモデルをQ4_K_M(標準的な4ビット量子化)で扱うため、精度を維持しつつメモリ消費を抑えています。

⚠️ 落とし穴: Windowsで「GPUが認識されない」というトラブルが多発します。 タスクマネージャーの「パフォーマンス」タブで、専用GPUメモリが使用されているか確認してください。 もしCPU(Shared Memory)が使われている場合は、NVIDIAの最新ドライバーを入れ直し、Ollamaを再起動する必要があります。

Step 2: 基本の設定

PythonからOllamaを操作するためのライブラリをインストールし、スクリプトの土台を作ります。

pip install ollama

次に、実務で使える「ドキュメント解析用」の設定コードを書きます。

import os
import ollama

# モデル名の定義(27Bがリリースされたらここを書き換える)
MODEL_NAME = "qwen2.5:32b"

def check_model_availability(model_name):
    """モデルがローカルに存在するか確認する"""
    models = ollama.list()
    for m in models['models']:
        if m['name'].startswith(model_name):
            return True
    return False

if not check_model_availability(MODEL_NAME):
    print(f"警告: {MODEL_NAME} が見つかりません。'ollama pull {MODEL_NAME}' を実行してください。")
else:
    print(f"使用モデル: {MODEL_NAME} - 準備完了")

なぜこの構成にするのかというと、ローカルLLMはモデル名が少しでも違うとエラーになるからです。 ollama.list() で動的に確認を入れることで、スクリプト実行時の「モデルがない」という初歩的なミスを防ぎます。

Step 3: 動かしてみる

まずは最小限のコードで、Qwenのレスポンス速度と日本語の質を確認します。

def simple_chat(prompt):
    response = ollama.chat(model=MODEL_NAME, messages=[
        {
            'role': 'user',
            'content': prompt,
        },
    ])
    return response['message']['content']

result = simple_chat("ローカルLLMを業務で導入する際、最も注意すべきセキュリティ上の懸念を3点挙げてください。")
print(result)

期待される出力

1. モデルファイルの出所(サプライチェーン攻撃のリスク)
2. 実行環境におけるメモリ内データの残留
3. ローカルAPIサーバーへの不正アクセス

(※Qwen-2.5は非常に論理的な回答を返します。レスポンスが返るまで3〜5秒程度なら、正常にGPUが動いています)

結果の読み方: 回答が「一文字ずつ」表示されず、数秒待ってドバッと出る場合は、ストリーミング設定が無効になっています。 実務レベルでは「待たされている感」を減らすためにストリーミングが必須です。

Step 4: 実用レベルにする

ここからが本番です。 「指定したフォルダにある複数のテキストファイルを読み込み、その内容を技術的な視点で要約・比較する」スクリプトを作ります。 これができれば、大量のログ解析や仕様書の比較が自動化できます。

import glob

def analyze_documents(folder_path):
    # フォルダ内のtxtファイルを全取得
    files = glob.glob(os.path.join(folder_path, "*.txt"))

    if not files:
        print("解析対象のファイルが見つかりません。")
        return

    combined_content = ""
    for file_path in files:
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
            combined_content += f"--- ファイル名: {os.path.basename(file_path)} ---\n{content}\n\n"

    # Qwenへの指示(システムプロンプトで役割を固定)
    system_prompt = "あなたは熟練のSIerエンジニアです。複数のドキュメントの内容を比較し、矛盾点や重要な変更点を箇条書きで抽出してください。"

    user_prompt = f"以下のドキュメント群を解析してください:\n\n{combined_content}"

    # ストリーミング再生でレスポンスを表示
    stream = ollama.chat(
        model=MODEL_NAME,
        messages=[
            {'role': 'system', 'content': system_prompt},
            {'role': 'user', 'content': user_prompt},
        ],
        stream=True,
    )

    print("--- 解析結果 ---")
    for chunk in stream:
        print(chunk['message']['content'], end='', flush=True)

# 実行例('docs'フォルダにテキストファイルを入れておく)
# analyze_documents("./docs")

このコードでは stream=True を採用しています。 27B/32Bクラスのモデルは、長文を投げると推論に時間がかかります。 ストリーミングにしないと「プログラムがフリーズした」ように見えるため、UX(ユーザー体験)の観点からこの書き方が「仕事で使える」基準です。

また、システムプロンプトに「熟練のSIerエンジニア」という役割を与えたのは、Qwenがコンテキスト(文脈)を非常に重視するモデルだからです。 単に「要約して」と言うよりも、出力の専門性が劇的に向上します。

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

エラー内容原因解決策
Error: model not foundモデル名がOllamaに登録されたものと完全一致していないollama list で正確な名前を確認して修正する
OutOfMemoryErrorVRAM(ビデオメモリ)が不足している他のアプリ(ブラウザ等)を閉じるか、より小さいモデル(14B等)に変更する
回答が英語になるシステムプロンプトで言語指定をしていないmessages の先頭に「日本語で回答してください」と明記する

次のステップ

この記事の内容をマスターしたら、次は「RAG(検索拡張生成)」に挑戦してください。 今回はファイルをまるごとプロンプトに投げましたが、27Bクラスのモデルでも、数万行のソースコードを一度に読み込むことはできません。

具体的には、

  1. ChromaDBFAISS といったベクトルデータベースを導入する。
  2. ドキュメントを断片化(チャンク分割)してデータベースに保存。
  3. 質問に関連する部分だけを抽出してQwenに投げる。 という流れを組むことで、PCのメモリ制限を超えた「巨大なナレッジベース」をローカルに構築できるようになります。 Qwen-2.5シリーズはコンテキストウィンドウが128kと非常に広いため、RAGとの相性は抜群です。

よくある質問

Q1: 27Bモデルが出たら、今の32Bモデルから乗り換える価値はありますか?

あります。もし27BがGemma 2のように「27Bというサイズに特化したアーキテクチャ」で設計されているなら、32Bよりも計算効率が良く、VRAM 16GBのGPU(RTX 4080等)でより高速に動作する可能性が高いからです。

Q2: 4ビット量子化(Q4)だと精度が落ちませんか?

実務上の差はわずかです。16ビット(FP16)で動かそうとすれば50GB以上のVRAMが必要になり、H100などのプロ向けGPUが必要になります。個人開発や社内ツールレベルなら、Q4_K_M量子化が「賢さと速度」のベストバランスです。

Q3: Python以外の言語でも操作できますか?

可能です。Ollamaはデフォルトでポート11434でREST APIを受け付けています。JavaScriptなら ollama-js がありますし、最悪 curl でリクエストを投げるだけでも推論を実行できるため、既存のウェブシステムへの組み込みも容易です。


あわせて読みたい