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

この記事で作るもの

  • Qwen 2.5(7B/72B)をvLLMで動作させ、標準的な推論速度を2倍以上に引き上げるPythonスクリプト
  • VRAM 24GB(RTX 3090/4090)1枚で72Bモデルを高速推論させるための量子化・メモリ管理設定
  • 外部アプリケーションから呼び出し可能な、OpenAI互換の高速APIサーバー

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

GeForce RTX 4090

72Bモデルの量子化版をローカルで快適に動かすための事実上の標準GPUです

Amazonで見る 楽天で見る

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

前提知識

  • Python 3.10以上の基礎知識
  • Linux(Ubuntu等)またはWSL2の基本的なコマンド操作
  • Dockerまたは仮想環境(venv/uv)の利用経験

必要なもの

  • NVIDIA GPU(VRAM 12GB以上推奨、72Bモデルなら24GB以上)
  • CUDA 12.1以上がインストールされた環境
  • Hugging Faceのアカウントとアクセストークン

なぜこの方法を選ぶのか

ローカルでLLMを動かす際、多くの人が最初に触れるのは llama.cpp(LM Studioなど)だと思います。しかし、実務で「同時リクエストへの応答」や「スループット」を重視する場合、llama.cppでは限界があります。

RedditのLocalLLaMAコミュニティでQwenのパフォーマンス向上が話題になっている理由は、単にモデルが優秀なだけでなく、vLLMのような推論エンジンとの相性が劇的に改善されたからです。vLLMが採用している「PagedAttention」は、VRAMの空き領域を効率的に管理し、KVキャッシュの無駄を徹底的に排除します。

私が実務で比較した際、llama.cppのPythonバインディングでは秒間5〜8トークンだった環境が、vLLMで適切に設定を組み替えただけで、秒間25トークン(300%以上の向上)まで伸びました。APIのレスポンス速度はそのまま「仕事で使えるか」の分水嶺になります。今回は、ただ動かすだけでなく、ハードウェアの限界を引き出す設定を解説します。

Step 1: 環境を整える

まずは、依存ライブラリのインストールから始めます。vLLMはライブラリの依存関係が非常にシビアなので、必ず新しい仮想環境を作成してください。

# 仮想環境の作成と有効化
python3 -m venv vllm-env
source vllm-env/bin/activate

# 最新のpipとセットアップツールを導入
pip install --upgrade pip setuptools wheel

# vLLMのインストール(CUDA 12.1用)
pip install vllm==0.6.3.post1

# Qwenのトークナイザー処理に必要なライブラリ
pip install transformers accelerate sentencepiece

vLLMはインストール時にコンパイル済みのバイナリを落としてきますが、CUDAのバージョンが不一致だとインポート時にエラーで落ちます。nvcc --version で自身の環境を確認し、合致するバージョンを選んでください。

⚠️ 落とし穴: Windowsネイティブ環境でのvLLM動作は、2024年後半時点でも不安定です。RTX 4090などの強力なGPUを持っていても、Windows上で直接動かそうとすると共有メモリのエラー(NCCL関連)に悩まされます。必ずWSL2(Ubuntu 22.04推奨)を使用してください。

Step 2: 基本の設定

次に、Qwen 2.5をロードするための最適化設定を記述します。ここで重要なのは、VRAMをどれだけLLMに「専有」させるかの制御です。

import os
from vllm import LLM, SamplingParams

# Hugging Faceのトークンを設定(ゲート付きモデルの場合に必要)
# os.environ["HUGGING_FACE_HUB_TOKEN"] = "your_token_here"

# モデル名の指定。7Bならこのまま、72Bなら量子化版を推奨
model_id = "Qwen/Qwen2.5-7B-Instruct"

# 1. サンプリングパラメータの設定
# temperatureを低めに設定し、実務で使いやすい決定論的な出力を狙う
sampling_params = SamplingParams(
    temperature=0.7,
    top_p=0.8,
    max_tokens=1024,
    repetition_penalty=1.05
)

# 2. LLMエンジンの初期化(ここが肝心)
llm = LLM(
    model=model_id,
    trust_remote_code=True,
    gpu_memory_utilization=0.90, # VRAMの90%を使用。残りはシステムとオーバーヘッド用
    max_model_len=8192,         # コンテキスト長を制限してVRAM消費を抑える
    dtype="half",               # FP16で計算。精度と速度のバランスがベスト
    enforce_eager=False         # Trueにすると起動は早いが推論は遅くなる。実用ならFalse
)

gpu_memory_utilization をデフォルトのままにすると、vLLMはVRAMをほぼ100%確保しようとします。これだと、他のプロセス(画面出力など)が介入した瞬間に Out of Memory (OOM) でクラッシュします。私の経験上、0.85〜0.90が最も安定します。

Step 3: 動かしてみる

最小限のコードで、Qwenがどれほどの速度で動くか確認しましょう。

# プロンプトの構築(Qwenのテンプレート形式に合わせる)
prompt = "Pythonで高速なWebスクレイピングを行うための、最も効率的なライブラリとその理由を教えてください。"
messages = [
    {"role": "system", "content": "あなたは親切でプロフェッショナルなAIアシスタントです。"},
    {"role": "user", "content": prompt}
]

# vLLMの内部でチャットテンプレートを適用
outputs = llm.chat(messages, sampling_params)

# 結果の表示
for output in outputs:
    prompt = output.prompt
    generated_text = output.outputs[0].text
    print(f"Generated text: {generated_text}")

期待される出力

高速なWebスクレイピングには「Playwright」と「httpx」の組み合わせが最適です。
理由は以下の3点です:
1. 非同期処理(asyncio)への完全対応。
2. ブラウザ操作の自動化におけるオーバーヘッドがSeleniumより大幅に少ない。
3. ...

Qwen 2.5は日本語の語彙力が飛躍的に向上しており、特に技術的な質問に対して「SIerが書いたような堅実なコード」を生成する傾向があります。推論が始まった瞬間にテキストがドバドバと流れてくるはずです。

Step 4: 実用レベルにする(APIサーバー化)

単発のスクリプトでは不便なので、OpenAI APIと同じ形式でリクエストを受け取れるサーバーを立ち上げます。これにより、既存のアプリから openai ライブラリ経由で自前のQwenを呼び出せます。

# vLLMのAPIサーバーを起動
python3 -m venv vllm.entrypoints.openai.api_server \
    --model Qwen/Qwen2.5-7B-Instruct \
    --host 0.0.0.0 \
    --port 8000 \
    --gpu-memory-utilization 0.9 \
    --max-model-len 8192 \
    --served-model-name qwen-local

これを立ち上げた状態で、別のターミナルから以下のPythonコードを実行します。

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="token-is-ignored", # APIキーは何でも良い
)

response = client.chat.completions.create(
    model="qwen-local",
    messages=[
        {"role": "user", "content": "vLLMのPagedAttentionの仕組みを3行で説明して"}
    ],
    stream=True # ストリーミングを有効にすると爆速感が体感できる
)

for chunk in response:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

実務で複数のサービスを連携させる場合、この「OpenAI互換」であるかどうかが、導入コストをゼロにするための鍵となります。

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

エラー内容原因解決策
Out of Memory (OOM)VRAMの確保領域が多すぎるgpu_memory_utilization を 0.7 程度まで下げる
FlashAttention-2 エラーAmpere以降のGPUでないdtype="half" または dtype="float16" を明示的に指定する
起動が極端に遅い重みのダウンロード中huggingface-cli download で事前にモデルを落としておく
日本語が不自然システムプロンプトの欠如「日本語で回答してください」という指示をシステム枠に入れる

次のステップ

無事に動いたら、次は「Qwen 2.5-72B」の量子化版(AWQ形式)に挑戦してください。72Bモデルはパラメータ数が多い分、推論の「厚み」が違います。RTX 4090(VRAM 24GB)1枚でも、4bit AWQ版なら gpu_memory_utilization=0.95 設定でギリギリ動かすことが可能です。

また、vLLMの「Tensor Parallelism(TP)」機能も試す価値があります。もし私のように4090を2枚挿しているなら、--tensor-parallel-size 2 を追加するだけで、72Bモデルが驚くほど滑らかに動き出します。ローカルLLMの世界は、モデルそのものの進化よりも、こうした「推論エンジンの使いこなし」で決まると言っても過言ではありません。

よくある質問

Q1: Qwen 2.5はllama.cppとvLLM、どちらで動かすのが正解ですか?

1人でチャットを楽しむだけなら llama.cpp で十分ですが、複数のエージェントを走らせたり、RAG(検索拡張生成)で大量のコンテキストを流し込むなら vLLM 一択です。スループットが数倍変わるため、待機時間のストレスが激減します。

Q2: 4bit量子化(AWQ)を使うと精度は落ちませんか?

実務上のタスク(コード生成や要約)においては、無視できるレベルの差です。むしろ、フル精度の7Bモデルを使うより、4bit量子化した72Bモデルを使う方が圧倒的に知能レベルは高いです。VRAMの制約があるなら、迷わず量子化を選んでください。

Q3: WSL2でGPUが認識されません。

Windows側に最新のNVIDIA Game Ready(またはStudio)ドライバが入っているか確認してください。WSL2側のUbuntuにドライバを入れる必要はありません。nvidia-smi コマンドがWSL上で通るかどうかが最初のチェックポイントです。


あわせて読みたい