WSL×RTX3090でローカルLLMを動かす:vLLM + Qwen2.5-14B-AWQ構築記録
はじめに
最近は RTX 5090 も定価で市場に出回ってきて、だいぶ物欲を刺激されました。とはいえ、手元の RTX 3090(24GB) もまだ十分に戦えるはず。まずは 今ある戦力を使い倒す 方針で、WSL2(Ubuntu 24.04)上に vLLM + Qwen2.5‑14B‑Instruct‑AWQ を立て、OpenAI互換APIとして動かすところまでやってみた記録です。
気になったのは、CUDA 13.0 ドライバのまま vLLM を導入すると依存解決で PyTorch が自動的に CUDA 12.8 系(2.8.0+cu128)へ切り替わること。結論から言うと、この「自動ダウングレード」を受け入れても 安定稼働しました(実測は後述)。最終的には /v1/chat/completions で日本語応答まで通せています。
TL;DR
- Windows 11 + WSL2 (Ubuntu 24.04) + RTX3090 で vLLM を立ち上げ、OpenAI互換API を即利用できる。
-
CUDA 13.0 ドライバのまま
pip install vllmすると、依存解決で PyTorch 2.8.0 + cu128 に自動ダウングレードされるが、そのまま安定稼働(実測あり)。 - Qwen2.5-14B-Instruct-AWQ を /v1/chat/completions で日本語応答。curl と OpenAI SDK のサンプル付き。
図で把握
💡 ポイント
- CUDAドライバはWindows側。WSL はドライバを透過利用しつつ、ユーザー空間の CUDA ランタイムは cu128(12.8系)として落ち着く構成。
- vLLM が OpenAI互換API を起動するため、外部アプリからそのまま叩ける。
検証環境
| 項目 | 内容 |
|---|---|
| ホスト | Windows 11 Pro |
| 仮想環境 | WSL2 + Ubuntu 24.04 (noble) |
| GPU | NVIDIA RTX 3090 (24GB VRAM) |
| ドライバ | 581.29(CUDA 13.0 対応) |
| CUDA | 13.0(Driver 由来) |
| Python | 3.12.3 |
| PyTorch | 2.8.0 + cu128(自動ダウングレード) |
| vLLM | 0.11.0 |
| モデル | Qwen/Qwen2.5-14B-Instruct-AWQ |
まず動かす(クイックスタート)
3分でAPI応答まで。細かい背景は後半へ。
1) venv 準備
sudo apt update && sudo apt install -y python3-full python3-venv build-essential
cd /mnt/c/Users/xxxxx/work
mkdir vllm && cd vllm
python3 -m venv .venv
source .venv/bin/activate
pip install -U pip wheel
2) PyTorch(CUDA13対応版)を一旦導入
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu130
初期確認:
python - <<'PY'
import torch
print("PyTorch:", torch.__version__)
print("CUDA available:", torch.cuda.is_available())
if torch.cuda.is_available():
print("Device:", torch.cuda.get_device_name(0))
PY
# => PyTorch: 2.9.0+cu130 / RTX3090 が見えればOK
3) vLLM を入れる(※ここで自動的に cu128 へ)
pip install vllm
⚙️ 依存解決により torch==2.8.0+cu128 へ自動置換されます。以後は cu128 前提で進みます。
再確認(2.8.0+cu128 になっていれば想定どおり):
python - <<'PY'
import torch
print("PyTorch:", torch.__version__)
print("CUDA:", torch.version.cuda)
print("CUDA available:", torch.cuda.is_available())
if torch.cuda.is_available():
print("Device:", torch.cuda.get_device_name(0))
PY
4) AWQ 対応
pip install autoawq
5) Hugging Face ログイン
pip install huggingface_hub
hf auth login # 新コマンド。旧: huggingface-cli login(廃止予定)
6) モデル起動(vLLM API サーバ)
vllm serve Qwen/Qwen2.5-14B-Instruct-AWQ \
--quantization awq \
--max-model-len 8192 \
--gpu-memory-utilization 0.92 \
--port 8000 --host 0.0.0.0
起動ログ例:
INFO ... Starting vLLM API server 0 on http://0.0.0.0:8000
Route: /v1/chat/completions
Route: /v1/models
7) 動作確認(curl)
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model":"Qwen/Qwen2.5-14B-Instruct-AWQ",
"messages":[
{"role":"system","content":"日本語で簡潔・正確に答えてください。"},
{"role":"user","content":"自己紹介を一段落で。"}
],
"temperature":0.3,
"max_tokens":400
}'
🎉 OpenAI互換API として JSON 応答が返れば成功。
背景と設計の肝
-
なぜ「CUDA13 ドライバ × cu128(12.8)ランタイム」で動くのか?
NVIDIA ドライバは後方互換を持ち、ユーザー空間の CUDA ランタイムが 12.8 系でも、13.0 ドライバ上で正常に実行できます。vLLM は検証済みの PyTorch + CUDA 組み合わせへ依存を合わせ込み、動作安定性を優先します。 -
WSL での CUDA
WSL 側は Windows の GPU ドライバを透過利用します。nvidia-smiは WSL 側でも確認でき、VRAM 使用量やプロセスを観測可能です。
API 呼び出しをもう一歩(ストリーミング & SDK)
Streaming(SSE)
curl -N http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model":"Qwen/Qwen2.5-14B-Instruct-AWQ",
"messages":[{"role":"user","content":"要約してください。"}],
"stream": true
}'
OpenAI SDK(Python)
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="dummy")
resp = client.chat.completions.create(
model="Qwen/Qwen2.5-14B-Instruct-AWQ",
messages=[
{"role": "system", "content": "日本語で簡潔に。"},
{"role": "user", "content": "このAPIの構成を一言で。"}
],
temperature=0.3,
max_tokens=300,
)
print(resp.choices[0].message.content)
🔒 セキュリティ:
--host 0.0.0.0はLANへ公開します。個人環境ではFWで閉じるか、リバースプロキシ+Basic認証などで保護してください。
実測(ログからの概況)
| 指標 | 値 |
|---|---|
| 初期起動時間 | 約 90 秒 |
| VRAM使用量 | 約 9.5 GiB |
| 生成速度 | 約 4〜5 tokens/s |
| 並列処理 | 約 7 リクエスト(8Kトークン換算) |
ログ抜粋:
Available KV cache memory: 11.26 GiB
GPU KV cache size: 61,472 tokens
Maximum concurrency for 8,192 tokens per request: 7.50x
✅ 14B + AWQ 構成なら 3090 24GB で 実用レンジ。
用途により--max-model-lenと--gpu-memory-utilizationのトレードオフを調整。
トラブルと対処集(現場対応メモ)
❌ fatal error: Python.h: No such file or directory
原因:Python 開発ヘッダ未導入
対処:
sudo apt install -y python3-dev python3.12-dev build-essential zlib1g-dev libexpat1-dev
# 既存ビルドキャッシュのリセット
rm -rf ~/.cache/vllm/torch_compile_cache ~/.cache/torch/inductor ~/.cache/torch_extensions
⚠️ LoRA 読み込み失敗
ValueError: Loading lora personaA failed: No adapter found for /models/lora/personaA
原因:adapter_config.json 不在(PEFT 形式でない)
回避:LoRA を使わないなら --enable-lora を外す。使うなら PEFT 形式に揃え、adapter_config.json を配置。
WSL 特有のTips
- デフォルトで
pin_memory=Falseになりわずかに遅くなる場合あり(体感差は小)。 - FlashInfer 未導入時は PyTorch ネイティブへフォールバック。導入は上級者向け(ビルドや互換で詰まりがち)。
- パスは
/mnt/c/...のWindowsディスク直下を使うと安定(権限・I/O 周りで無用なハマりを回避)。
まとめ(判断材料の要約)
| ポイント | 内容 |
|---|---|
| ✅ CUDA13ドライバでもOK | vLLM導入で cu128 へ自動調整されるが 安定稼働 |
| ✅ OpenAI互換APIが即利用可能 |
/v1/chat/completions で疎通確認済み |
| ⚙️ Pythonヘッダは必須 | Inductor のビルド失敗を防止 |
| 🧩 LoRAはPEFT形式が安全 |
adapter_config.json を確認 |
| 🚀 RTX3090でも快適 | 14B + AWQ で 4〜5 tok/s 目安 |
付録:そのまま再現するワンライナー
sudo apt update && sudo apt install -y python3-full python3-venv build-essential
cd /mnt/c/Users/xxxxx/work && mkdir vllm && cd vllm
python3 -m venv .venv && source .venv/bin/activate
pip install -U pip wheel
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu130
pip install vllm autoawq huggingface_hub
sudo apt install -y python3-dev python3.12-dev build-essential zlib1g-dev libexpat1-dev
vllm serve Qwen/Qwen2.5-14B-Instruct-AWQ --quantization awq --max-model-len 8192 --gpu-memory-utilization 0.92 --port 8000 --host 0.0.0.0
おわりに
vLLM は ローカルGPUを即API化できる実戦的フレームワーク。
Windows + WSL2 + RTX3090 でも、CUDA13 ドライバ × cu128 ランタイムの“ねじれ”をそのまま受け入れて運用できました。
「まずは 動く」→「必要に応じて 最適化」の順で、手元の 3090 を価値ある生成系 APIへ育てていきましょう。
Discussion