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
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for hellohazime/qwen3-1p7b-pokellm-lora_50k_ev0p05

Finetuned
Qwen/Qwen3-1.7B
Adapter
(243)
this model