mcpField
F
flash

flash

github.com/runpodクラウド・DevOps4714.0k 回インストール2 日前に更新
リポジトリ

flash について

Runpod Flashは、RunpodのGPUおよびCPUワーカー上でPython関数を開発・デプロイするためのスキルです。開発中はリモート実行とホットリロードを使い、完成後にエンドポイントとしてデプロイするコード中心のワークフローを案内します。

主な機能

  1. 01リモートGPUまたはCPUワーカーで関数を実行
  2. 02ホットリロードとワーカーのライブログ
  3. 03関数を安定したエンドポイントとしてデプロイ
  4. 04キューベースとロードバランス型ルートに対応
  5. 05既存エンドポイントへの接続やイメージのデプロイ

活用シーン

  1. 01GPU推論関数の反復開発
  2. 02デバッグ中のワーカーログ確認
  3. 03テスト済み関数のエンドポイント化
  4. 04Pythonから既存エンドポイントを呼び出し

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/runpod/runpod-plugins-official --skill flash

インストール後、Claude Code で/flashを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

evals/
client-external-image.eval.md
connect-existing-endpoint.eval.md
cpu-gpu-pipeline.eval.md
dev-loop-iteration.eval.md
lb-multi-route-api.eval.md
qb-gpu-function.eval.md
volume-cache-model-load.eval.md
evals/fixtures/dev-loop/
main.py
reference/
api.md
patterns.md
setup-and-cli.md

詳細

Runpod Flash

Dockerfile/テンプレートプロジェクトを明示的に求められた場合は、 runpod-build-template を使用してください。ユーザーがコードファーストのワークフローを選択しない限り、その成果物を Flash で置き換えないでください。

コードをローカルで作成し、flash dev で反復します。これはホットリロードとワーカーのログのリアルタイム表示を備え、関数をリモートの Runpod GPU/CPU で実行します。その後、flash deploy でデプロイします。プロビジョニングは Endpoint が処理します。

runpod-flash は独自のペースでリリースされるため、コマンド一覧の確認には flash --help と flash <command> --help が最も信頼できます。このスキルでは、ヘルプ出力にはない基本的な考え方、判断ルール、注意点を説明します。サブコマンドやフラグが利用できないと結論づける前に、pip show runpod-flash でインストール済みのバージョンを確認してください。

複数の手順がある作業では、まず実例を確認してください。 Flash は検証済みのエンドツーエンドの手順で使用されています。03 variant B (whisper endpoint via flash) と 08 (fine-tune → serve) を参照してください。全インデックスは runpod/golden-paths/README.md にあります。デプロイを計画する前に、該当する手順を開いてください。このスキルでは要約にとどめている、手順の順序やコスト削減のためのクリーンアップについて説明されています。

必要に応じて参照してください。このスキルでは基本的な考え方と注意点をインラインで説明し、詳細は reference/ に記載しています。

目的参照先
インストール、認証、flash init、flash コマンドの全一覧reference/setup-and-cli.md
Endpoint(...) のコンストラクターパラメーター、NetworkVolume/PodTemplate/EndpointJob、GPU と CPU の列挙型テーブルreference/api.md
実践的なパターン — モデルの選択、ウォームワーカーでのモデル読み込み、CPU→GPU パイプライン、並列呼び出しreference/patterns.md

クイックスタート:uv tool install runpod-flash → flash login(または export RUNPOD_API_KEY=...)→ flash init my-project → flash dev。詳細は reference/setup-and-cli.md を参照してください。

開発とデプロイ

  • flash dev — 反復開発に使用します。 ローカルサーバーは :8888 で動作しますが、デコレーターを付けた関数はリモートの GPU/CPU ワーカーで実行されます。保存時にホットリロードし、ワーカーのログをターミナルにリアルタイムで表示します。ビルド、アップロード、デプロイを待つ必要はありません。開発中は常にこれを使用してください。
  • flash deploy — デプロイします。 成果物をビルドして、安定したエンドポイントにデプロイします。時間がかかるため(ビルド+アップロード+プロビジョニング)、flash dev でコードが動作することを確認してから実行してください。

flash dev は関数本体のみをワーカーに送信するため、モジュールレベルの名前に対する NameError はすぐに表面化します。一方、flash deploy はモジュール全体をインポートするため、このバグが見えなくなる場合があります(注意点 #1 を参照)。flash dev で開発すれば、まずこの問題を検出できます。

自律型開発ループ

flash dev は長時間実行されるサーバーです。次の3つのルールを守ってください。

  • バックグラウンドで実行する — 完了するまで待たないでください。
  • 出力をログファイルに記録する。
  • HTTP 経由で操作する。

記録したログは、リモートワーカーのライブストリーム(コールドスタート、モデルの読み込み、print、トレースバック)です。デバッグ時はログを確認してください。

flash dev > /tmp/flash-dev.log 2>&1 &                          # background; never run it blocking
for i in $(seq 1 60); do grep -q "flash dev  localhost:" /tmp/flash-dev.log && break; sleep 2; done  # bounded ~2min; if it never appears, check the log for errors
URL=$(grep -o "localhost:[0-9]*" /tmp/flash-dev.log | head -1)               # actual port (8888 bumps if taken)
curl -s "$URL/main/predict" -d '{"data": {...}}'               # dispatches to the remote worker
  • 実際の URL はログから確認する — 8888 が使用中の場合、flash はポート番号を自動的に変更し、ルートテーブルとともに ✓ flash dev localhost:<port> を出力します。
  • ルートはファイルごとに名前空間が分かれています:main.py の /predict は /main/predict で提供されます。
  • ルートの形状が2種類あり、リクエストボディの形式も異なります(不一致の場合は、loc に不足しているフィールド名を示す 422 が返されます)。
    • 負荷分散方式(@api.post("/predict"))→ POST /main/predict。ボディでは引数をトップレベルに置きます。ハンドラー def predict(data: dict) の場合、{"data": {...}} が必要です(オブジェクトをそのまま渡すのではありません)。
    • キュー方式(単独の @Endpoint デコレーター)→ POST /main/runsync(ローカルの開発サーバーが生成するのは /runsync のみです。本番環境では /run も公開されます)。 ボディは input で二重にラップします。ハンドラー def synthesize(data: dict) の場合、{"input": {"data": {...}}} が必要です。外側の input はキューのエンベロープで、内側のキーはハンドラーのパラメーター名です。
  • ハンドラーを編集して保存すると、ホットリロードでボディが再同期されます。再デプロイせずにリクエストを再送信するだけで反映されます。初回呼び出し時のコールドスタートを省略するには --auto-provision を追加してください。完了したら kill %1 を実行します。

エンドポイント:3つのモード

コンストラクターの全パラメーターと GPU/CPU の列挙型テーブルについては、reference/api.md を参照してください。

モード1:独自コード(キュー方式デコレーター)

1つの関数が1つのエンドポイントとなり、それぞれ専用のワーカーを持ちます。

from runpod_flash import Endpoint, GpuGroup

@Endpoint(name="my-worker", gpu=GpuGroup.AMPERE_80, workers=5, dependencies=["torch"])
async def compute(data):
    import torch  # MUST import inside function (cloudpickle)
    return {"sum": torch.tensor(data, device="cuda").sum().item()}

result = await compute([1, 2, 3])
モード2:独自コード(負荷分散ルート)

複数の HTTP ルートで1つのワーカープールを共有します。

from runpod_flash import Endpoint, GpuGroup

api = Endpoint(name="my-api", gpu=GpuGroup.ADA_24, workers=(1, 5), dependencies=["torch"])

@api.post("/predict")
async def predict(data: list[float]):
    import torch
    return {"result": torch.tensor(data, device="cuda").sum().item()}

@api.get("/health")
async def health():
    return {"status": "ok"}
モード3:外部イメージ(クライアント)

ビルド済みの Docker イメージをデプロイし、HTTP 経由で呼び出します。

from runpod_flash import Endpoint, GpuGroup, PodTemplate

server = Endpoint(
    name="my-server",
    image="my-org/my-image:latest",
    gpu=GpuGroup.AMPERE_80,
    workers=1,
    env={"HF_TOKEN": "xxx"},
    template=PodTemplate(containerDiskInGb=100),
)

# LB-style
result = await server.post("/v1/completions", {"prompt": "hello"})
models = await server.get("/v1/models")

# QB-style
job = await server.run({"prompt": "hello"})        # optional: webhook="https://..." for completion callback
await job.wait()
print(job.output)

プロビジョニングせずに、ID を指定して既存のエンドポイントに接続します。

ep = Endpoint(id="abc123")
job = await ep.runsync({"prompt": "hello"})  # runsync wraps this as {"input": {"prompt": "hello"}}
print(job.output)

モードの判定方法

パラメーターモード
name= のみデコレーター(独自コード)
image= を設定クライアント(イメージをデプロイしてから HTTP 呼び出し)
id= を設定クライアント(プロビジョニングせずに既存のものへ接続)

上の表は、パラメーターからモードがどのように選ばれるかを示しています。image= を使うタイミングは次のとおりです。

独自コードではなく image=(カスタムコンテナー)を使う場合

基本的には Python(デコレーター/ルート)で記述してください。dependencies=[...]/system_dependencies=[...] を使って任意のコードを実行でき、Dockerfile も不要です。大規模な HuggingFace モデルもデコレーターモードで実行できます(重みは実行時にストリーミングされます。reference/patterns.md → ML モデルの読み込みを参照してください)。

image= を使うのは、次の場合に限ります。

  • ビルド済みの推論サーバーを使う場合 — vLLM、TensorRT-LLM(image="vllm/vllm-openai:latest"、または runpod/worker-vllm、runpod/worker-comfy)
  • pip ではインストールできないシステムレベルの依存関係がある場合 — 特定の CUDA/cuDNN、OS ライブラリ
  • モデルをイメージに含める場合 — 実行時のダウンロードを完全に省略するため
  • 既存の Runpod Serverless ワーカーを使う場合 — すでに動作するイメージがある場合

トレードオフ:image= モードでは任意の Python を実行できません(すべてのロジックはイメージ側が担います)。また、イメージには Runpod Serverless ハンドラーを実装する必要があります。全項目と例については、次を参照してください。 https://docs.runpod.io/flash/custom-docker-images

注意点

  1. ワーカーに送信されるのは関数本体のみです — 最もよくあるエラーです。インポートと、関数が使用するモジュールレベルの定数やヘルパーは、すべてデコレートされた本体の中に記述してください。flash deploy はモジュール全体をインポートするため、モジュールのグローバル変数は問題なく使えます。一方、flash dev が送信するのは本体だけなので、モジュールレベルの名前を参照すると NameError が発生します。デプロイ環境で動くハンドラーが dev で失敗する場合は、すべてを本体の中に移動してください。
  2. await の付け忘れ — デコレートされた関数とクライアントメソッドには、すべて await が必要です。
  3. 依存関係の指定漏れ — dependencies=[] に記載する必要があります。
  4. gpu と cpu は併用できません — Endpoint ごとにどちらか一方を選んでください。
  5. idle_timeout の単位は秒です — デフォルトは 60 秒であり、分ではありません。
  6. ペイロードの上限は 10MB です — 大きなオブジェクトではなく、URL を渡してください。バイナリ(音声、画像、ファイル)は JSON 内で base64 として返し({"audio_b64": ...})、クライアント側でデコードしてください。さらに大きな出力は NetworkVolume に書き込むか、ストレージにアップロードして URL を返してください。
  7. クライアントとデコレーターの違い — image=/id= はクライアント用です。それ以外はデコレーター用です。
  8. GPU の自動切り替えには workers >= 5 が必要です — GPU タイプのリスト(例:gpu=[GpuGroup.ADA_24, GpuGroup.AMPERE_80])を渡し、workers=5 以上に設定してください。プラットフォームが供給状況に応じて GPU タイプを自動切り替えするのは、最大ワーカー数が 5 以上の場合のみです。
  9. runsync のタイムアウトは 60 秒です — コールドスタートが 60 秒を超える場合があります。初回リクエストには ep.runsync(data, timeout=120) を使うか、代わりに ep.run() と job.wait() を使ってください。
  10. リクエストボディの形式(raw/外部 HTTP 呼び出しの場合のみ) — エンドポイントのタイプに合ったリクエスト形式にしてください。
    • LB ルート(@api.post(...)):ハンドラー引数を最上位に配置して送信します — {"data": {...}}。
    • QB エンドポイント(単独の @Endpoint。.../run または .../runsync 経由で呼び出し):ワーカーは handler(**job_input) を呼び出すため、リクエストの input キーはハンドラーのパラメーター名と一致させる必要があります — def transcribe(input_data: dict) の場合は {"input": {"input_data": {...}}}、def read(input: dict) の場合は {"input": {"input": {...}}} が必要です。名前が一致しないと got an unexpected keyword argument … で失敗します。ハンドラーがペイロードを無視する場合は **kwargs を使ってください。
    • input を空にしないでください。 {"input": {}} を含む QB リクエストは、ワーカー SDK により Job has missing field(s): id or input として拒否されます — 必ずキーを 1 つ以上含めてください。
    • 補足: flash クライアント(ep.runsync(x)、api.post(...))は展開処理を隠蔽するため、この問題が起きるのは raw HTTP/外部呼び出しの場合のみです(不一致時の挙動は、2026-07-10 にワーカーログで確認済みです)。 Autonomous Dev Loop を参照してください。
  11. モデルは呼び出しごとではなく、ワーカーごとに 1 回だけ読み込みます — 実際の推論では、__init__ でワーカーごとに 1 回モデルを読み込むクラス形式の @Endpoint を使ってください(reference/patterns.md → ML モデルの読み込み を参照)。関数形式の場合は、#1 と両立させるため、flash dev と deploy の両方で動作するよう、本体内のモジュールグローバル変数にキャッシュしてください。
    global _MODEL
    try: _MODEL
    except NameError: _MODEL = load_model()   # ワーカーごとに 1 回だけ実行され、以降の呼び出しで再利用されます
    
  12. ネイティブ CUDA ライブラリも dependencies=[] に含めます — たとえば CTranslate2/faster-whisper では、CPU に暗黙でフォールバックしないよう、nvidia-cublas-cu12 と nvidia-cudnn-cu12 が必要です。Python パッケージと一緒に追加してください。
  13. 401 認証エラーが通知されずに発生します — RUNPOD_API_KEY 環境変数が設定されていると、flash login のトークンより優先されるため、無効または期限切れのキーが使われます。この失敗は分かりにくく、プロビジョニングログには GraphQL request failed: 401 と表示されますが、flash dev は通常の準備完了メッセージ(「failed endpoints deploy on-demand」)を表示するため、正常に動作しているように見えます。エンドポイントのプロビジョニングに失敗した場合:
    1. プロビジョニングログに GraphQL request failed: 401 がないか確認します。
    2. 現在のキーを個別に検証します:curl -s -o /dev/null -w '%{http_code}' https://api.runpod.io/v2/serverless -H "Authorization: Bearer $RUNPOD_API_KEY"(200 = 有効、401 = 無効)。
    3. unset RUNPOD_API_KEY を実行して flash login のトークンに切り替えるか、有効なキーを export して修正します。
  14. system_dependencies= はコールドスタートを遅くします — apt パッケージ(例:["ffmpeg", "espeak-ng"])は初回使用前にワーカーにインストールされるため、初回の呼び出しが遅くなります(モデルのダウンロード時間に加えて)。ウォーム状態での呼び出しには影響しません。
  15. デプロイ済みアプリは flash app delete <app> で削除します — デプロイされ、リクエストを処理中のアプリでも、flash undeploy list に「no endpoints」と表示される場合があります。flash app delete(または runpodctl serverless delete <id>)を使えば確実に削除できます。

リソース

コメント