Qwen3-1.7B PokéLLM LoRA (Gen9 OU / JSON Action Selector)
Summary:
Qwen/Qwen3-1.7B を LoRA で事後学習し、ポケモン Showdown の Gen9 OU 対戦における 単手意思決定(行動選択)を行う軽量アダプタです。
本モデルは、与えられた候補集合に対して 厳密 JSON で {"action":"index::<k>"} を返すことを目的に最適化されています。
(index::<k> は、あなたのエージェントが提示する候補リストの 0-based インデックス)
Model Details
- Base model:
Qwen/Qwen3-1.7B - Adapter type: LoRA (PEFT)
- Task: Pokémon Showdown Gen9 OU の 1 手意思決定(行動選択)
- I/O 仕様:
入力: 観測(軽量テキスト or 構造化を文字列化)+候補CANDIDATES(内部で index にマッピング)
出力: 厳密 JSON 一個{ "action": "index::<k>" } - Intended framework: 🤗 Transformers + PEFT(PyTorch)
- License: Base モデルに準拠(Qwen/Qwen3-1.7B のライセンスをご確認ください)
- Author : 波浪 創(hellohazime)
What this model is / isn’t
- ✅ すること: 候補(技 / 交代など)から 1 つを選ぶ。
- ⚠️ しないこと: 一般的な雑談・長文生成・マルチターン方策学習・ダメージ計算の厳密再現。
Uses
Direct Use
- 対戦中の観測テキストと、候補キー(内部で
indexに変換したもの)を提示し、1 手を選択させる。 - 出力は 必ず 1 行 1 JSON。解析側は
actionを読み取り、あなたのindex_map[k]に解決して実行してください。
Downstream Use
- poke-env / Pokémon Showdown クライアントと組み合わせれば、ローカル対戦エージェントとして利用できます。
- 学習済みプロンプト・スキーマに依存します。異なるスキーマで使う場合は再学習を推奨。
Out-of-Scope
- 一般領域の対話、長文化・推論タスク、Gen9 OU 以外のフォーマットへの強い汎化は想定していません。
How to Get Started
Load with PEFT (Transformers)
from transformers import AutoTokenizer, AutoModelForCausalLM
from peft import PeftModel
BASE = "Qwen/Qwen3-1.7B"
ADAPTER = "hellohazime/qwen3-1p7b-pokellm-lora_50k_ep0p05"
tok = AutoTokenizer.from_pretrained(BASE, trust_remote_code=True)
if tok.pad_token_id is None and tok.eos_token_id is not None:
tok.pad_token = tok.eos_token
base = AutoModelForCausalLM.from_pretrained(BASE, trust_remote_code=True, device_map="auto")
model = PeftModel.from_pretrained(base, ADAPTER)
# --- 推論の例(厳密JSONを狙うプロンプト) ---
obs = "turn | 3\nyour_active | Gholdengo\nopp_active | Great Tusk\nmoves | Make It Rain, Shadow Ball, Trick, Focus Blast"
# 例: allowed は内部で index に並べ替えた候補(move群→switch群)に対応
allowed = ["index::0","index::1","index::2","index::3"] # 例
prompt = (
"You are a Gen9 OU single-battle agent.\n"
"Return exactly one JSON object on a single line.\n"
'Schema: {"action": "index::<k>"} No markdown, no extra text.\n'
f"ALLOWED: {' | '.join(allowed)}\n\n"
f"{obs}\n\n"
"Action:"
)
inputs = tok(prompt, return_tensors="pt").to(model.device)
out_ids = model.generate(
**inputs,
max_new_tokens=48,
do_sample=False, # 温度0相当
eos_token_id=tok.eos_token_id,
pad_token_id=tok.eos_token_id
)
print(tok.decode(out_ids[0], skip_special_tokens=True))
Note: MLX ランタイムで LoRA を直接ロードするには別途変換が必要です(標準の PEFT/Torch では上記のように動作します)。
Training Details
Training Data
出典:
jakegrigsby/metamon-parsed-replays(Showdown リプレイの構造化アーカイブ)フィルタ: Gen9 OU / Elo ≥ 1500 を中心に抽出・整形
生成された SFT データは以下のindex スキーマ(簡略):
system: 「厳密 JSON で 1 手のみ返す」等の指示user:{ "state": {...}, "CANDIDATES": ["index::0", ...] }assistant:{ "action": "index::<k>" }
Preprocessing
- 候補(move / switch)を アルファベット順に整列し、
index::<k>に対応付け。 - 観測は軽量テキスト(ターン/自他アクティブ/使用可能技の見出し名 etc.)に要約。
- 長さ上限(cutoff): 1024 tokens 目安。
Training Procedure (LoRA / SFT)
- PEFT LoRA:
r=8, alpha=16, dropout=0.05, bias="none"target_modules:q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj - Optimizer: AdamW(
transformers.TrainingArguments(optim="adamw_torch")) - LR: 2e-4 近辺(スモーク→本学習でスケール)
- Batch size: 端末依存(例:
per_device_train_batch_size=8,gradient_accumulation_steps=1) - Max steps: 12500
- Evaluation:
eval_ratio ≈ 5%,eval_steps=500前後EarlyStoppingCallback(patience=3, metric=eval_loss) - Precision: fp32(Mac/MPS で安定運用)
実行スクリプトは TRL
SFTTrainerを用いた標準的な SFT(packing 無効、formatting_funcで chat template を適用)構成です。
Evaluation
Protocol
- 環境: ローカル Pokémon Showdown (:8080),
poke-env経由 - 形式:
gen9ou(同一チーム同士で LLM vs Random の簡易ベースライン) - 強制スキーマ: 厳密 JSON 一個(
{"action": "index::<k>"})
Result
normal
Baseline vs Random (Gen9 Random Battle, N=10)
| Model | Adapter | Win% | Fallback% | Avg Lat(ms) |
|---|---|---|---|---|
| Qwen/Qwen3-1.7B | — | 50.0 | 31.74 | 450.3 |
datasize 50k
uv run python eval_vs_ou.py \
--n_battles 10 \
--backend hf \
--model Qwen/Qwen3-1.7B \
--adapter outputs/qwen3-1p7b_lora_50k_ev0p05 \
--format gen9ou \
--schema index \
--team1 teams/ou_team.txt \
--team2 teams/ou_team.txt
| Model | Win% | Fallback% | Avg Lat(ms) | p95(ms) | Decis. | Battles |
|---|---|---|---|---|---|---|
| Qwen/Qwen3-1.7B + outputs/qwen3-1p7b_lora_50k_ev0p05 | 70.00 | 0.00 | 1646.1 | 1731.6 | 363 | 10 |
- 補足: 対戦相手は poke-env の
RandomPlayer。本 LoRA の “index スキーマ厳守” と最小限観測だけで、安定した JSON 出力を確認。 - さらなる妥当性評価(他フォーマット、強い相手、別チーム、長期戦)や人手検証は今後の課題です。
Bias, Risks, and Limitations
- 単手方策であり、長期的なプランニングやリソース管理は学習していません。
- index スキーマ依存のため、プロンプト逸脱や候補整列順の不一致で性能が大きく劣化します。
- データは公開リプレイ由来で、プレイヤースキルやメタに偏りがあり得ます。
- ダメージ計算・乱数・特性相互作用は簡略観測のみで与えており、完全再現ではありません。
Recommendations
- 生成の健全性チェック(JSON 解析、候補外出力のフォールバック)を必ず実装してください。
- 実運用では 評価対戦の拡充(様々な構築・相手・ルール)を推奨します。
Technical Specifications
Architecture
- Qwen3-1.7B(Causal LM)+ LoRA(PEFT)
Software
- Transformers / TRL / PEFT / PyTorch(MPS)
- Tokenizer は base に付属の chat template を使用(無い場合は簡易フォールバック)
How to Cite / Credit
- Base: Qwen/Qwen3-1.7B
- Data inspiration: metamon-parsed-replays(Showdown 由来の公開リプレイ構造化)
Model Card Authors
- 波浪 創(hellohazime) *
Framework versions
- PEFT 0.17.1(動作確認)
- Transformers / TRL は 2025 時点の安定版で確認(詳細は
training_args.binを参照)
- Downloads last month
- 29