model-migrate-flagos について
上流の vLLM モデルを FL プラグインへ移行するためのスキルです。ソースの適応、互換性パッチ、登録、検証、ベンチマーク、エンドツーエンド確認を順に進めます。
主な機能
- 01モデル名とパスの解析
- 02上流および HuggingFace ソースの調査
- 03互換性パッチの適用
- 04インポート、API、登録の検証
- 05ベンチマークとエンドツーエンドテスト
活用シーン
- 01FL プラグインへの上流モデル追加
- 02上流更新後の移行再実行
- 03適応やサービングエラーの調査
- 04上流とのエンドツーエンド動作確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ flagos-ai/ skills --skill model-migrate-flagosインストール後、Claude Code で/model-migrate-flagosを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSE.txtREADME_zh.mdREADME.mdreferences/compatibility-patches.mdoperational-rules.mdprocedure.mdscripts/benchmark.she2e_config.template.jsone2e_eval.pye2e_remote_serve.she2e_test_prompts.jsonrequest.shserve.shvalidate_migration.py詳細
FL Plugin — モデル移行スキル
使用方法
/model-migrate-flagos <model_name> [upstream_folder] [plugin_folder]
| 引数 | 必須 | デフォルト |
|---|---|---|
model_name | はい | — |
upstream_folder | いいえ | /tmp/vllm-upstream-ref |
plugin_folder | いいえ | 現在の作業ディレクトリ |
実行
ステップ 1:引数を解析し、パスを検証する
ユーザー入力から以下を抽出します。
{{model_name}}= 最初の引数(必須、snake_case){{upstream_folder}}= 2 番目の引数、または/tmp/vllm-upstream-ref{{plugin_folder}}= 3 番目の引数、または現在の作業ディレクトリ
{{upstream_folder}} が存在しない場合は、クローンするかどうかをユーザーに尋ねます。{{plugin_folder}} が存在しない場合は、エラーを返します。
→ ユーザーに伝える:解析したモデル名とパスを確認します。
ステップ 2:参照資料を読み込み、プレースホルダーを解決する
以下のファイルを読み込みます(この SKILL.md からの相対パス)。
references/procedure.md— 移行手順のステップごとの説明references/compatibility-patches.md— 0.13.0 パッチカタログreferences/operational-rules.md— コミュニケーション、TaskList、bash のルール、回復性
手順では、scripts/ 内の実行可能スクリプトを参照します。
scripts/validate_migration.py— 自動コードレビュー(ステップ 6)scripts/benchmark.sh— ベンチマーク検証(ステップ 9)scripts/serve.sh— モデルをローカルでサーブ(ステップ 10.1、E2E でも使用)scripts/request.sh— テストリクエスト(ステップ 10.2)scripts/e2e_eval.py— E2E 正確性検証(ステップ 11)scripts/e2e_test_prompts.json— E2E 用テストプロンプト(テキスト 5 件 + マルチモーダル 5 件)scripts/e2e_config.template.json— E2E 設定テンプレート(e2e_config.jsonにコピーして記入)scripts/e2e_remote_serve.sh— SSH 経由でリモートマシン上の GT サーバーを管理
次に、上流ソースと HuggingFace を調査して、すべてのプレースホルダーを解決します。
| プレースホルダー | 導出方法 |
|---|---|
{{model_name}} | 引数から直接取得 |
{{model_name_lower}} | model_name を小文字に変換(通常は同一です。例:qwen3_5)— ファイルパスで使用 |
{{MODEL_DISPLAY_NAME}} | 上流コードまたは HF モデルカードから取得 |
{{ModelClassName}} | 上流のモデルクラスから取得(PascalCase) |
{{model_type}} | HF の config.json にある model_type フィールドから取得 |
{{ConfigClassName}} | 上流から取得するか、model_type から導出 |
{{skill_root}} | このスキルのフォルダー(この SKILL.md を含むディレクトリ)の絶対パス |
モデルによって命名規則は異なります。推測せず、必ず実際のソースで確認してください。
→ ユーザーに伝える:解決した値をすべて提示します。不明点がある場合は AskUserQuestion を使用します。
ステップ 3:手順を実行する
プレースホルダーを解決したら、procedure.md の全ステップを順番に実行します。コピー後にパッチを適用するステップでは、compatibility-patches.md のパッチを適用します。全体を通して operational-rules.md に従います。
→ ユーザーに伝える:開始前に番号付きの計画を提示します。各ステップの区切りで進捗を報告します。
スクリプトのリファレンス
| スクリプト | ステップ | 説明 |
|---|---|---|
validate_migration.py | 6 | インポート/API/登録の自動チェック |
benchmark.sh | 9 | ダミーの重みを使用した vllm bench throughput |
serve.sh | 10, 11 | ローカル vLLM サーバーを起動(ポート 8122、VLLM_FL_PREFER_ENABLED=false) |
request.sh | 10 | 簡易スモークテスト用リクエスト |
e2e_eval.py | 11 | 上流の GT サーバーとのトークン単位の比較 |
e2e_test_prompts.json | 11 | テキスト 5 件 + マルチモーダル 5 件のテストプロンプト |
e2e_config.template.json | 11 | 設定テンプレート(GT マシン、ローカルポート、評価パラメーター) |
e2e_remote_serve.sh | 11 | SSH ベースの GT サーバーのライフサイクル管理(起動/停止/状態/ログ) |
例
例 1:一般的な新規モデル
User says: "/model-migrate-flagos kimi_k25"
Actions:
1. Parse → model_name=kimi_k25, defaults for upstream/plugin paths
2. Clone upstream, find vllm/model_executor/models/kimi_k25.py
3. Discover it wraps DeepseekV2 → follow kimi_k25 (wrapper) pattern
4. Copy file, apply P1+P2 patches, create config bridge
5. Register, validate, test, benchmark, serve+request
6. E2E verification against upstream GT
Result: kimi_k25 fully working in plugin, all 11 steps passed
例 2:上流の更新後に再実行
User says: "migrate qwen3_5 again, upstream updated"
Actions:
1. Idempotent re-run — overwrite existing files with fresh upstream copy
2. Re-apply patches, re-validate, re-test
3. Re-run E2E to confirm no regression
Result: qwen3_5 updated to match latest upstream, no regressions
トラブルシューティング
一般原則:ランタイムエラーが発生した場合は、まず vLLM の上流コードを、プラグインへの適応内容とインストール済みの 0.13.0 環境の両方と比較してください。差分を確認するのが根本原因を特定する最短の方法です。プロトコルの詳細については、operational-rules.md § Debugging Priority: Upstream-First を参照してください。
| 問題 | 典型的な原因 | 対処方法 |
|---|---|---|
コピー後のパッチ適用で ImportError が発生する | P1 の修正(相対インポートから絶対インポートへの変更)が不足している | すべての from .xxx が from vllm.* または from vllm_fl.* に変換されていることを確認します |
AttributeError: module 'vllm' has no attribute X | 0.13.0 に API が存在しない | compatibility-patches.md の P3 を確認し、スタブを追加するか削除します |
| vLLM が設定を認識しない | model_type の不一致、または設定ブリッジが不足している | _CONFIG_REGISTRY[model_type] が HF config.json と完全に一致していることを確認します |
| 登録が反映されない | クラス名またはインポートパスの誤り | __init__.py にある既存の登録と比較します |
ベンチマークで設定フィールドの KeyError が発生する | 設定ブリッジにフィールドが不足している | 上流の設定クラスとブリッジを比較し、不足しているフィールドをデフォルト値付きで追加します |
| ベンチマーク/Serve が OOM または「insufficient memory」で失敗する | 他のプロセスが GPU を使用している | GPU プロセスを終了します:nvidia-smi --query-compute-apps=pid --format=csv,noheader | xargs -r kill -9 を実行してから再試行してください。これらの手順を省略しないでください。 |
| モデルの出力が文字化けする/意味不明なテキストになる | サブ次元が異なる統合射影に ColumnParallelLinear を使用している(TP シャーディングの不一致) | __init__ をオーバーライドし、MergedColumnParallelLinear(output_sizes=[...]) を使用します。compatibility-patches.md の P8 を参照してください |
AssertionError: Duplicate op name | 子クラスが親クラスとは異なるモジュールパスからカスタム op をインポートしている | 親モジュールと同じインポートパスを使用します(例:vllm_fl.models.fla_ops ではなく vllm_fl.ops.fla)。P11 を参照してください |
CUDA グラフのウォームアップ中に fused_recurrent_* で AttributeError が発生する | nn.Module.__init__(self) を使用した __init__ のオーバーライドで、継承した _forward_core が使用する属性が設定されていない | カスタム op を特に含め、親クラスの __init__ が作成する属性をすべて作成します。P12 を参照してください |
| E2E:ローカルサーバーに接続できない | serve.sh のポートが e2e_config.json のローカルポートと一致していない | 両方で同じポート(デフォルトは 8122)を使用していることを確認します |
| E2E:GT サーバーに接続できない | GT マシンが停止している、または Docker/conda 環境が正しくない | e2e_remote_serve.sh status を確認するか、手動で SSH 接続します |
| E2E:初期トークンで乖離する(最初の 5 トークン) | 重みの読み込みバグ、TP シャーディングのエラー | load_weights、stacked_params_mapping、MergedColumnParallelLinear を確認します |
| E2E:後半でわずかに乖離する(トークン #15 以降) | op の実装の違いによる数値ノイズ | 通常は許容範囲です。レポートに記載します |
VLLM_FL_PREFER_ENABLED=false で resolve_op が失敗する | op がディスパッチに登録されておらず、フォールバックもない | op のインポートコードに flag_gems への try/except フォールバックを追加します |