关于 flash
Runpod Flash 是用于在 Runpod GPU 和 CPU Worker 上开发、部署 Python 函数的技能,采用代码优先流程:开发时远程执行并热重载,完成后部署为端点。
主要功能
- 01在远程 GPU 或 CPU Worker 上运行函数
- 02热重载与实时 Worker 日志
- 03将函数部署为稳定端点
- 04支持队列式和负载均衡路由
- 05连接现有端点或部署镜像
适用场景
- 01迭代开发 GPU 推理函数
- 02调试时查看 Worker 日志
- 03将测试通过的函数部署为端点
- 04通过 Python 调用现有端点
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ runpod/ runpod-plugins-official --skill flash安装后在 Claude Code 中输入/flash确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/client-external-image.eval.mdconnect-existing-endpoint.eval.mdcpu-gpu-pipeline.eval.mddev-loop-iteration.eval.mdlb-multi-route-api.eval.mdqb-gpu-function.eval.mdvolume-cache-model-load.eval.mdevals/fixtures/dev-loop/main.pyreference/api.mdpatterns.mdsetup-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 是一个长期运行的服务。请遵循三条规则:
- 在后台运行——不要等待它结束。
- 将输出写入日志文件。
- 通过 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提供服务。 - 两种路由形式,对应两种请求体形式(不匹配时会返回
422,并在loc中指出缺少的字段):- 负载均衡(
@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。
Endpoint:三种模式
完整的构造函数参数以及 GPU/CPU 枚举表,请参阅 reference/api.md。
模式 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 路由共享一个工作进程池。
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 → Loading ML models)。只有在以下情况需要时,才使用 image=:
- 预构建的推理服务——vLLM、TensorRT-LLM(
image="vllm/vllm-openai:latest",或runpod/worker-vllm、runpod/worker-comfy) - 无法通过 pip 安装的系统级依赖——特定版本的 CUDA/cuDNN、操作系统库
- 预先打包在镜像中的模型——完全跳过运行时下载
- 现有的 Runpod Serverless 工作进程——你已经有可用的镜像
权衡:image= 模式无法运行任意 Python 代码(所有逻辑都由镜像负责),且镜像必须实现 Runpod Serverless 处理程序。完整列表和示例:
https://docs.runpod.io/flash/custom-docker-images
注意事项
- 只有函数体会被发送到 worker——这是最常见的错误。将导入语句以及函数所用的任何模块级常量/辅助函数都放到装饰后的函数体内。
flash deploy会导入整个模块,因此模块全局变量碰巧能正常使用;flash dev只会发送函数体,因此模块级名称会引发NameError。部署后能正常运行的处理函数,在 dev 模式下可能会出错——将所有内容移到函数内部即可修复。 - 忘记使用 await——所有装饰后的函数和客户端方法都需要使用
await。 - 缺少依赖项——必须在
dependencies=[]中列出。 - gpu 和 cpu 互斥——每个 Endpoint 只能选一个。
- idle_timeout 的单位是秒——默认值为 60s,不是分钟。
- 负载上限为 10MB——传递 URL,而不是大型对象。将二进制数据(音频/图片/文件)以 base64 形式放在 JSON 中返回(
{"audio_b64": ...}),并在客户端解码;对于更大的输出,将其写入 NetworkVolume 或上传到存储空间,然后返回 URL。 - 客户端与装饰器的区别——
image=/id=属于客户端参数;否则属于装饰器参数。 - 自动切换 GPU 要求 workers >= 5——传入 GPU 类型列表(例如
gpu=[GpuGroup.ADA_24, GpuGroup.AMPERE_80]),并将workers=5或更高。只有当最大 worker 数至少为 5 时,平台才会根据供应情况自动切换 GPU 类型。 runsync超时时间为 60s——冷启动可能超过 60s。首次请求请使用ep.runsync(data, timeout=120),或改用ep.run()+job.wait()。- 请求体结构(仅适用于原始/外部 HTTP 调用方)——请求结构必须与 Endpoint 类型匹配:
- LB 路由(
@api.post(...)):在顶层发送处理函数参数——{"data": {...}}。 - QB Endpoint(裸
@Endpoint,通过.../run或.../runsync调用):worker 会调用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。 QB 请求中的{"input": {}}会被 worker SDK 拒绝,并报错Job has missing field(s): id or input——始终至少包含一个键。 - 背景: flash 客户端(
ep.runsync(x)、api.post(...))会隐藏参数展开过程,因此只有原始 HTTP/外部调用方会遇到此问题(已通过 2026-07-10 的 worker 日志验证不匹配行为)。请参阅 Autonomous Dev Loop。
- LB 路由(
- 每个 worker 加载一次模型(而非每次调用都加载)——对于实际推理,请使用类形式的
@Endpoint,并在其__init__中加载模型,使每个 worker 只加载一次(参见 reference/patterns.md → Loading ML models)。使用函数形式时,需兼顾第 #1 条:在函数体内将模型缓存到模块全局变量中,确保它在flash dev和deploy模式下都能正常工作:global _MODEL try: _MODEL except NameError: _MODEL = load_model() # 每个 worker 只运行一次,后续调用会复用 - 原生 CUDA 库也要放进
dependencies=[]——例如,CTranslate2/faster-whisper 需要nvidia-cublas-cu12+nvidia-cudnn-cu12,否则会静默退回 CPU。请将它们与 Python 包一并添加。 - 401 身份验证失败不会明确提示——设置了
RUNPOD_API_KEY环境变量时,它会覆盖flash login令牌,因此无效或过期的密钥会优先生效。该失败不会明确提示:配置日志会显示GraphQL request failed: 401,但flash dev仍会打印正常的就绪信息(“failed endpoints deploy on-demand”),因此看起来一切正常。Endpoint 无法配置时:- 检查配置日志中是否有
GraphQL request failed: 401。 - 独立验证当前密钥:
curl -s -o /dev/null -w '%{http_code}' https://api.runpod.io/v2/serverless -H "Authorization: Bearer $RUNPOD_API_KEY"(200 = 正常,401 = 无效)。 - 修复方式:运行
unset RUNPOD_API_KEY,以回退到flash login令牌;或运行export设置有效密钥。
- 检查配置日志中是否有
system_dependencies=会延长冷启动时间——apt 软件包(例如["ffmpeg", "espeak-ng"])会在首次使用前安装到 worker 上,因此首次调用会更慢(还要加上任何模型下载所需的时间);热调用不受影响。- 使用
flash app delete <app>拆除已部署的应用——对于已部署且正在提供服务的应用,flash undeploy list可能会显示“no endpoints”;flash app delete(或runpodctl serverless delete <id>)能可靠地将其删除。
资源
- 设置与 CLI:reference/setup-and-cli.md · API 与计算枚举:reference/api.md · 模式:reference/patterns.md
- Flash 源码:https://github.com/runpod/flash
- 可运行示例:https://github.com/runpod/flash-examples — 克隆并改造最接近的示例
- 软件包(PyPI):https://pypi.org/project/runpod-flash/
- 文档:https://docs.runpod.io/flash/overview
- 自定义 Docker 镜像(何时使用及如何使用):https://docs.runpod.io/flash/custom-docker-images
- 存储/网络卷:https://docs.runpod.io/flash/configuration/storage