flash
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRunpod Flash
Runpod Flash
Write code locally, iterate with — it runs your functions on remote Runpod GPUs/CPUs with hot-reload and live worker logs — then to ship. handles provisioning.
flash devflash deployEndpointLoad on demand — this skill keeps the mental model + gotchas inline; details live in :
reference/| Need | Read |
|---|---|
Install, auth, | reference/setup-and-cli.md |
| reference/api.md |
| Worked patterns — choosing a model, warm-worker model loading, CPU→GPU pipeline, parallel calls | reference/patterns.md |
Quick start: → (or ) → → . Details in reference/setup-and-cli.md.
uv tool install runpod-flashflash loginexport RUNPOD_API_KEY=...flash init my-projectflash dev本地编写代码,通过进行迭代——它会在远程Runpod GPU/CPU上运行你的函数,并支持热重载和实时工作日志——随后使用完成部署。负责资源调度。
flash devflash deployEndpoint按需查阅——本工具将核心概念与常见陷阱整合在文档内;详细内容请查看目录:
reference/| 需求 | 查阅文档 |
|---|---|
安装、认证、 | reference/setup-and-cli.md |
| reference/api.md |
| 实践模式——模型选择、预热工作进程模型加载、CPU→GPU流水线、并行调用 | reference/patterns.md |
快速开始: → (或)→ → 。详细步骤请查看reference/setup-and-cli.md。
uv tool install runpod-flashflash loginexport RUNPOD_API_KEY=...flash init my-projectflash devDev vs Deploy
开发(Dev)与部署(Deploy)对比
- — iterate. Local server at
flash dev, but your decorated functions execute on remote GPU/CPU workers. Hot-reloads on save and streams the worker's logs live to the terminal. No build/upload/deploy wait — use this the whole time you develop.:8888 - — ship. Builds an artifact and deploys a stable endpoint. Slow (build + upload + provision); only do this once the code works under
flash deploy.flash dev
flash devNameErrorflash deployflash dev- — 迭代开发。本地服务器运行在
flash dev端口,但你标记的函数会在远程GPU/CPU工作进程上执行。保存代码时自动热重载,并将工作进程的日志实时流式传输到终端。无需等待构建/上传/部署——开发全程均可使用该命令。:8888 - — 发布上线。构建工件并部署稳定的端点。速度较慢(需构建+上传+资源调度);仅当代码在
flash deploy环境下运行正常后再执行此命令。flash dev
flash devNameErrorflash deployflash devAutonomous Dev Loop
自主开发循环
flash dev- Run it in the background — don't block on it.
- Capture its output to a log file.
- Drive it over HTTP.
The captured log is the remote worker's live stream (cold start, model load, s,
tracebacks) — read it to debug.
printbash
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- Read the real URL from the log — flash auto-bumps the port if 8888 is in use, and
prints plus the route table.
✓ flash dev localhost:<port> - Routes are namespaced by file: 's
main.pyis served at/predict./main/predict - Two route shapes, two body shapes (mismatch → naming the missing field in
422):loc- Load-balanced () →
@api.post("/predict"), body is the arg at top level: a handlerPOST /main/predictwantsdef predict(data: dict)(not the bare object).{"data": {...}} - Queue-based (bare decorator) →
@Endpoint(the local dev server only generatesPOST /main/runsync; production also exposes/runsync), body is double-wrapped in/run: a handlerinputwantsdef synthesize(data: dict). The outer{"input": {"data": {...}}}is the queue envelope; the inner key is the handler's param name.input
- Load-balanced (
- Edit a handler and save — hot-reload re-syncs the body; just re-send the request, no
redeploy. Add to skip the first-call cold start.
--auto-provisionwhen done.kill %1
flash dev- 在后台运行——不要阻塞终端。
- 将输出捕获到日志文件。
- 通过HTTP调用。
捕获的日志包含远程工作进程的实时流(冷启动、模型加载、输出、回溯信息)——可通过阅读日志进行调试。
printbash
flash dev > /tmp/flash-dev.log 2>&1 & # 后台运行;切勿阻塞式运行
for i in $(seq 1 60); do grep -q "flash dev localhost:" /tmp/flash-dev.log && break; sleep 2; done # 最多等待约2分钟;若始终未出现该信息,请检查日志中的错误
URL=$(grep -o "localhost:[0-9]*" /tmp/flash-dev.log | head -1) # 实际端口(若8888被占用会自动切换)
curl -s "$URL/main/predict" -d '{"data": {...}}' # 调度到远程工作进程- 从日志中读取真实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: Three Modes
Endpoint:三种模式
Full constructor params and the GPU/CPU enum tables are in reference/api.md.
完整的构造函数参数及GPU/CPU枚举表请查看reference/api.md。
Mode 1: Your Code (Queue-Based Decorator)
模式1:自定义代码(队列式装饰器)
One function = one endpoint with its own workers.
python
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])一个函数对应一个独立工作进程的端点。
python
from runpod_flash import Endpoint, GpuGroup
@Endpoint(name="my-worker", gpu=GpuGroup.AMPERE_80, workers=5, dependencies=["torch"])
async def compute(data):
import torch # 必须在函数内部导入(cloudpickle要求)
return {"sum": torch.tensor(data, device="cuda").sum().item()}
result = await compute([1, 2, 3])Mode 2: Your Code (Load-Balanced Routes)
模式2:自定义代码(负载均衡路由)
Multiple HTTP routes share one pool of workers.
python
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"}多个HTTP路由共享一个工作进程池。
python
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"}Mode 3: External Image (Client)
模式3:外部镜像(客户端)
Deploy a pre-built Docker image and call it via HTTP.
python
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),
)部署预构建的Docker镜像并通过HTTP调用。
python
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")
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)
Connect to an existing endpoint by ID (no provisioning):
```python
ep = Endpoint(id="abc123")
job = await ep.runsync({"prompt": "hello"}) # runsync wraps this as {"input": {"prompt": "hello"}}
print(job.output)job = await server.run({"prompt": "hello"}) # 可选:设置webhook="https://..."接收完成回调
await job.wait()
print(job.output)
通过ID连接到已存在的端点(无需调度资源):
```python
ep = Endpoint(id="abc123")
job = await ep.runsync({"prompt": "hello"}) # runsync会自动包装为{"input": {"prompt": "hello"}}
print(job.output)How Mode Is Determined
模式判定规则
| Parameters | Mode |
|---|---|
| Decorator (your code) |
| Client (deploys image, then HTTP calls) |
| Client (connects to existing, no provisioning) |
The table above is how the mode is picked from params. When to reach for :
image=| 参数 | 模式 |
|---|---|
仅设置 | 装饰器模式(自定义代码) |
设置 | 客户端模式(部署镜像后通过HTTP调用) |
设置 | 客户端模式(连接到已存在的端点,无需调度资源) |
上表说明了如何通过参数选择模式。以下是何时选择的场景:
image=When to use image=
(custom container) vs your own code
image=何时使用image=
(自定义容器)而非自定义代码
image=Default to writing Python (decorator / routes) — it runs arbitrary code with
/ and needs no Dockerfile. Even large
HuggingFace models stay in decorator mode (weights stream at runtime — see
reference/patterns.md → Loading ML models).
Reach for only when you need:
dependencies=[...]system_dependencies=[...]image=- a pre-built inference server — vLLM, TensorRT-LLM (, or
image="vllm/vllm-openai:latest",runpod/worker-vllm)runpod/worker-comfy - system-level deps not pip-installable — a specific CUDA/cuDNN, OS libraries
- models baked into the image — to skip the runtime download entirely
- an existing Runpod Serverless worker — you already have a working image
Trade-off: mode can't run arbitrary Python (the image owns all logic) and the
image must implement a Runpod Serverless handler. Full list + examples:
https://docs.runpod.io/flash/custom-docker-images
image=默认优先编写Python代码(装饰器/路由模式)——该模式支持通过/运行任意代码,无需Dockerfile。即使是大型HuggingFace模型也可使用装饰器模式(运行时流式下载权重——参见reference/patterns.md → 加载ML模型)。仅在以下场景下使用:
dependencies=[...]system_dependencies=[...]image=- 预构建的推理服务器——vLLM、TensorRT-LLM(例如,或
image="vllm/vllm-openai:latest"、runpod/worker-vllm)runpod/worker-comfy - 无法通过pip安装的系统级依赖——特定版本的CUDA/cuDNN、操作系统库
- 内置模型的镜像——跳过运行时下载步骤
- 已有的Runpod无服务器工作进程——你已经有一个可正常运行的镜像
权衡:模式无法运行任意Python代码(所有逻辑由镜像控制),且镜像必须实现Runpod无服务器处理函数。完整列表及示例:https://docs.runpod.io/flash/custom-docker-images
image=Gotchas
常见陷阱
- Only the function body ships to the worker -- most common error. Put imports and any module-level constants/helpers the function uses inside the decorated body. imports the whole module so module globals happen to work;
flash deployships just the body, so a module-level name raisesflash dev. A handler that works deployed can break under dev — fix it by moving everything inside.NameError - Forgetting await -- all decorated functions and client methods need .
await - Missing dependencies -- must list in .
dependencies=[] - gpu/cpu are exclusive -- pick one per Endpoint.
- idle_timeout is seconds -- default 60s, not minutes.
- 10MB payload limit -- pass URLs, not large objects. Return binary (audio/images/files) as base64 in the JSON () and decode client-side; for larger outputs write to a NetworkVolume or upload to storage and return a URL.
{"audio_b64": ...} - Client vs decorator -- /
image== client. Otherwise = decorator.id= - Auto GPU switching requires workers >= 5 -- pass a list of GPU types (e.g. ) and set
gpu=[GpuGroup.ADA_24, GpuGroup.AMPERE_80]or higher. The platform only auto-switches GPU types based on supply when max workers is at least 5.workers=5 - timeout is 60s -- cold starts can exceed 60s. Use
runsyncfor first requests or useep.runsync(data, timeout=120)+ep.run()instead.job.wait() - Request body shape (raw/external HTTP callers only) -- match the request shape to the endpoint type:
- LB routes (): send the handler arg at the top level —
@api.post(...).{"data": {...}} - QB endpoints (bare , hit via
@Endpointor.../run): the worker calls.../runsync, so the request'shandler(**job_input)keys must match the handler's parameter names —inputwantsdef transcribe(input_data: dict), and{"input": {"input_data": {...}}}wantsdef read(input: dict). A mismatch fails with{"input": {"input": {...}}}. Usegot an unexpected keyword argument …if the handler ignores the payload.**kwargs - Never send an empty . A QB request with
inputis rejected by the worker SDK as{"input": {}}— always include at least one key.Job has missing field(s): id or input - Context: the flash client (,
ep.runsync(x)) hides the spreading, so this only bites raw HTTP/external callers (mismatch behavior verified 2026-07-10 via worker logs). See Autonomous Dev Loop.api.post(...)
- LB routes (
- Load a model once per worker (not per call) -- for real inference use a class whose
@Endpointloads the model once per worker (see reference/patterns.md → Loading ML models). In function-form, reconcile with #1 by caching in a module global inside the body so it works under both__init__andflash dev:deploypythonglobal _MODEL try: _MODEL except NameError: _MODEL = load_model() # runs once per worker, reused across calls - Native CUDA libs go in too -- e.g. CTranslate2/faster-whisper needs
dependencies=[]+nvidia-cublas-cu12or it silently falls back to CPU. Add them alongside the Python package.nvidia-cudnn-cu12 - Silent 401 auth failure -- a set env var overrides the
RUNPOD_API_KEYtoken, so a bad/expired key wins. The failure is quiet: provisioning logsflash login, butGraphQL request failed: 401still prints its normal ready line ("failed endpoints deploy on-demand"), so it looks healthy. When endpoints fail to provision:flash dev- Check the provisioning log for .
GraphQL request failed: 401 - Verify the current key independently: (200 = good, 401 = bad).
curl -s -o /dev/null -w '%{http_code}' https://rest.runpod.io/v1/endpoints -H "Authorization: Bearer $RUNPOD_API_KEY" - Fix it: to fall back to the
unset RUNPOD_API_KEYtoken, orflash logina valid key.export
- Check the provisioning log for
- adds to cold start -- apt packages (e.g.
system_dependencies=) install on the worker before first use, so the initial call is slower (on top of any model download); warm calls are unaffected.["ffmpeg", "espeak-ng"] - Teardown a deployed app with --
flash app delete <app>may show "no endpoints" for an app that is deployed and serving;flash undeploy list(orflash app delete) reliably removes it.runpodctl serverless delete <id>
- 仅函数体被发送到工作进程——最常见的错误。将导入语句及函数使用的所有模块级常量/辅助代码放在装饰器内部的函数体中。会导入整个模块,因此模块全局变量可能正常工作;但
flash deploy仅发送函数体,因此模块级名称会触发flash dev。在部署环境下正常运行的处理函数可能在开发环境中出错——解决方法是将所有相关代码移到函数体内部。NameError - 忘记使用await——所有装饰器修饰的函数及客户端方法都需要使用。
await - 缺失依赖——必须在中列出所有依赖。
dependencies=[] - GPU/CPU互斥——每个Endpoint只能选择其中一种。
- idle_timeout单位为秒——默认60秒,而非分钟。
- 请求体大小限制为10MB——传递URL而非大型对象。返回二进制数据(音频/图片/文件)时需在JSON中以base64格式编码(例如),并在客户端解码;对于更大的输出,可写入NetworkVolume或上传到存储服务后返回URL。
{"audio_b64": ...} - 客户端模式与装饰器模式区分——设置/
image=即为客户端模式,否则为装饰器模式。id= - 自动切换GPU需要workers≥5——传入GPU类型列表(例如)并设置
gpu=[GpuGroup.ADA_24, GpuGroup.AMPERE_80]或更高。仅当最大工作进程数至少为5时,平台才会根据供应情况自动切换GPU类型。workers=5 - 超时时间为60秒——冷启动可能超过60秒。首次请求时使用
runsync,或改用ep.runsync(data, timeout=120)+ep.run()。job.wait() - 请求体格式(仅原生/外部HTTP调用者适用)——请求体格式需与端点类型匹配:
- 负载均衡路由():将处理函数的参数放在顶层——
@api.post(...)。{"data": {...}} - 队列式端点(仅使用,通过
@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会被工作进程SDK拒绝,提示{"input": {}}——始终至少包含一个键。Job has missing field(s): id or input - 说明:flash客户端(、
ep.runsync(x))会自动处理参数展开,因此仅原生HTTP/外部调用者会遇到此问题(不匹配行为已在2026-07-10通过工作进程日志验证)。请查看自主开发循环部分。api.post(...)
- 负载均衡路由(
- 每个工作进程仅加载一次模型(而非每次调用)——实际推理时,请使用类形式的,其
@Endpoint方法会在每个工作进程启动时加载一次模型(参见reference/patterns.md → 加载ML模型)。若使用函数形式,需结合陷阱#1,在函数体内部将模型缓存到模块全局变量中,以确保在__init__和flash dev环境下均能正常工作:deploypythonglobal _MODEL try: _MODEL except NameError: _MODEL = load_model() # 每个工作进程仅运行一次,跨调用复用 - 原生CUDA库也需添加到——例如CTranslate2/faster-whisper需要
dependencies=[]+nvidia-cublas-cu12,否则会自动回退到CPU运行。请将它们与Python包一起添加到依赖列表中。nvidia-cudnn-cu12 - 静默的401认证失败——设置的环境变量会覆盖
RUNPOD_API_KEY生成的令牌,因此无效/过期的密钥会导致认证失败。失败是静默的:资源调度日志会显示flash login,但GraphQL request failed: 401仍会打印正常的就绪信息("failed endpoints deploy on-demand"),因此看起来服务正常。当端点无法调度资源时:flash dev- 检查资源调度日志中是否存在。
GraphQL request failed: 401 - 独立验证当前密钥:(返回200表示正常,401表示无效)。
curl -s -o /dev/null -w '%{http_code}' https://rest.runpod.io/v1/endpoints -H "Authorization: Bearer $RUNPOD_API_KEY" - 修复方法:执行以使用
unset RUNPOD_API_KEY生成的令牌,或flash login一个有效的密钥。export
- 检查资源调度日志中是否存在
- 会增加冷启动时间——apt包(例如
system_dependencies=)会在工作进程首次使用前安装,因此首次调用会更慢(叠加模型下载时间);预热后的调用不受影响。["ffmpeg", "espeak-ng"] - 使用删除已部署的应用——
flash app delete <app>可能显示某个已部署并提供服务的应用"无端点";使用flash undeploy list(或flash app delete)可可靠地删除应用。runpodctl serverless delete <id>
Resources
资源
- Setup & CLI: reference/setup-and-cli.md · API & compute enums: reference/api.md · Patterns: reference/patterns.md
- Flash source: https://github.com/runpod/flash
- Runnable examples: https://github.com/runpod/flash-examples — clone and adapt the closest one
- Package (PyPI): https://pypi.org/project/runpod-flash/
- Docs: https://docs.runpod.io/flash/overview
- Custom Docker images (when + how): https://docs.runpod.io/flash/custom-docker-images
- Storage / network volumes: https://docs.runpod.io/flash/configuration/storage
- 安装与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