异步图像生成 API 允许您提交生成请求,立即获得任务标识符,并在稍后检索生成的图像,而不是一直保持 HTTP 连接。本教程涵盖了任务生命周期、何时使用轮询与 Webhook,以及如何设计重试机制,以确保缓慢或失败的任务不会破坏您的产品体验。
关键要点
- 图像生成是基于任务(Job)而非请求-响应模式的,因为生成延迟(几秒到几十秒)使得保持同步连接变得不可靠。
- 轮询构建和调试更简单;Webhook 可以降低延迟和请求量,但需要公共端点、签名验证以及对重复交付的幂等处理。
- 重试逻辑需要区分提交失败、任务卡死和 Webhook 漏发;每种情况都需要不同的恢复路径。
- 具体的端点名称、字段名称和 Webhook 有效载荷格式因提供商及 TokenLab 自身的 API 表面而异。在发布前,请务必在 docs.tokenlab.sh 上确认当前的具体细节。
为什么图像生成 API 是异步的
文本补全 API 通常可以在同一连接上返回响应,因为 Token 生成速度足够快,可以进行流式传输。图像生成模型(无论是基于扩散模型还是自回归模型)通常需要更长时间,并且根据分辨率、模型选择和队列深度,延迟波动较大。保持同步 HTTP 请求几十秒是非常脆弱的:客户端超时、负载均衡器空闲限制以及移动网络中断,都会增加丢失已付费生成的完整结果的风险。
跨图像生成提供商使用的标准模式是任务模型:您提交请求并收到一个任务标识符和初始状态(通常类似于 queued 或 processing)。然后,您可以轮询状态端点,或者在任务达到终止状态时接收 Webhook 通知,并在单独的调用中获取最终的图像 URL 或二进制数据。
TokenLab 通过单一 API 表面提供对多种图像模型的访问,包括 Nano Banana 2, Nano Banana Pro, 和 Nano Banana 2 Lite 系列、GPT Image 2、Reve 2.0 和 MAI-Image-2.5。请参阅图像模型目录获取当前列表,并参阅异步图像生成任务指南了解 TokenLab 特定的任务端点行为。以下通用模式适用于您调用的任何底层模型,但具体的字段名称和状态值记录在 docs.tokenlab.sh 中,应在那里进行验证,而不是根据本文进行假设。
任务生命周期:提交、轮询、检索
从概念层面来看,异步图像任务有三个阶段:
- 提交:POST 提示词和参数,接收任务 ID 和初始状态。
- 检查状态:使用任务 ID 轮询 GET 端点,或等待 Webhook 事件。
- 检索输出:一旦状态变为终止(成功或失败),获取图像 URL 或错误详情。
以下是 Python 中的一个轮询模式示例。请将端点路径和字段名称视为占位符;在使用前请在 API 文档中确认当前的 TokenLab 任务端点格式。
import time
import requests
API_BASE = "https://api.tokenlab.sh/v1" # 在 docs.tokenlab.sh 中验证当前基础 URL
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def submit_image_job(prompt, model="nano-banana-2"):
resp = requests.post(
f"{API_BASE}/images/jobs",
headers=HEADERS,
json={"prompt": prompt, "model": model, "idempotency_key": generate_key()},
)
resp.raise_for_status()
return resp.json()["job_id"]
def poll_job(job_id, max_wait_seconds=120, interval=2, backoff=1.5):
waited = 0
while waited < max_wait_seconds:
resp = requests.get(f"{API_BASE}/images/jobs/{job_id}", headers=HEADERS)
resp.raise_for_status()
data = resp.json()
if data["status"] in ("succeeded", "failed"):
return data
time.sleep(interval)
waited += interval
interval = min(interval * backoff, 15)
raise TimeoutError(f"Job {job_id} did not complete within {max_wait_seconds}s")
job_id = submit_image_job("a studio product shot on white background")
result = poll_job(job_id)
if result["status"] == "succeeded":
image_url = result["output"]["url"]
else:
print("job failed:", result.get("error"))
提交调用中的 idempotency_key 很重要:如果任务创建后但在您的客户端收到任务 ID 之前发生网络错误,使用相同的 key 重试提交调用应该返回现有任务,而不是创建重复的生成任务。请确认 TokenLab 的任务端点在当前文档中是否以及如何支持幂等键,因为这是跨提供商的常见但非通用的模式。
轮询 vs. Webhook:权衡
两种方法都是有效的;正确的选择取决于您的流量模式和基础设施。
轮询更易于实现和本地测试,不需要公共端点,适用于低流量或批处理工作负载,其中几秒钟的额外延迟无关紧要。其缺点是延迟下限等于您的轮询间隔,如果对长时间运行的任务轮询过于频繁,会导致不必要的请求量。
Webhook 在任务状态改变时向您的服务器推送通知,这降低了延迟并减少了浪费的状态检查调用。代价是运营成本:您需要一个可公开访问的 HTTPS 端点、用于确认有效载荷确实来自提供商的签名验证,以及对重复或乱序交付的处理。
OpenAI 的 Webhook 事件参考文档记录了异步操作的通用模式:您的端点接收带有类型和对象标识符的事件,推荐的做法是将 Webhook 有效载荷视为通过 API 获取资源当前状态的通知,而不是将 Webhook 正文视为最终事实来源。无论您集成的是哪个图像提供商,这种“先推送后拉取”的模式都值得采用,因为它可以在 Webhook 有效载荷被截断、延迟或多次交付时保护您。
安全实现 Webhook
如果您选择 Webhook 来处理图像任务完成,以下做法可以减少静默失败的几率:
- 验证签名:在处理每个传入的 Webhook 请求之前验证签名。拒绝任何不匹配的请求,并将拒绝记录与正常流量分开,以便快速发现配置错误的密钥。
- 快速响应,稍后处理:验证后立即以 200 状态响应 Webhook,然后将实际工作(获取图像、写入存储、通知用户)交给后台任务或队列。如果提供商没有及时收到 2xx 响应,通常会重试 Webhook 交付,如果您的处理程序缓慢且同步,这可能导致重复处理。
- 按任务 ID 去重:存储已处理的任务 ID(或事件的哈希值),以便重试的交付不会重新生成通知或重复写入文件。
- 重新获取资源:使用 Webhook 有效载荷中的任务 ID 重新获取资源,而不是盲目信任嵌入的输出 URL,这符合上述“先推送后拉取”的模式。
一个最小化的处理程序草图:
from flask import Flask, request, abort
app = Flask(__name__)
processed_job_ids = set() # 在生产环境中使用真实的存储
@app.route("/webhooks/image-jobs", methods=["POST"])
def handle_webhook():
if not verify_signature(request):
abort(401)
event = request.get_json()
job_id = event.get("job_id") or event.get("data", {}).get("id")
if job_id in processed_job_ids:
return "", 200 # 已处理,确认并跳过
enqueue_background_task("fetch_and_store_image", job_id)
processed_job_ids.add(job_id)
return "", 200
请根据当前的提供商文档以及 docs.tokenlab.sh 中描述的 TokenLab 自身 Webhook 支持,验证用于图像任务完成的确切 Webhook 事件名称、有效载荷结构和签名头,因为这些细节是特定于提供商的,并且可能会发生变化。
重试设计:三类失败
异步图像任务以三种不同的方式失败,每种方式都需要单独处理:
- 提交失败:创建任务的 POST 请求返回 4xx 或 5xx。对于 5xx 和网络错误,请使用指数退避和抖动进行重试,并重复使用相同的幂等键,以免创建重复任务。对于 4xx 错误(错误的提示词、无效模型、配额超限),不更改请求的重试只会再次失败;应将错误呈现给调用者。
- 任务卡死:任务在预期生成时间过后仍处于非终止状态。为每个模型设置最大等待阈值(生成时间因模型和分辨率而异),并将超过该阈值的任务视为失败,即使提供商尚未正式将其标记为失败。请单独记录这些任务,因为卡死任务率的上升通常预示着提供商端的事故。
- Webhook 漏发:您的端点宕机或交付被丢弃,导致没有任何事件到达。这就是为什么即使在 Webhook 优先的设计中也值得保留轮询回退的原因:定期扫描检查任何超过几分钟仍未达到终止状态的任务,可以捕获那些 Webhook 静默失败的任务。
决策清单
在决定如何为图像生成功能配置任务完成机制时,请使用此清单。
| 场景 | 推荐方法 | 原因 |
|---|---|---|
| 低流量、内部工具或批处理脚本 | 轮询 | 构建最简单;无需公共端点 |
| 延迟敏感的用户侧功能 | Webhook,配合轮询回退扫描 | 延迟更低;回退可捕获漏发的交付 |
| 高任务量(每天数千次) | Webhook | 避免过多的状态检查请求量 |
| 无法暴露公共 HTTPS 端点 | 轮询 | Webhook 需要可访问的接收器 |
| 需要严格的重复预防 | 提交时使用幂等键,接收时按任务 ID 去重 | 防止重试提交和重复的 Webhook 交付 |
| 单一流水线中使用多个图像模型 | 在您自己的层中规范化任务状态和错误处理 | 底层提供商(参见图像模型比较)不共享相同的状态分类法 |
局限性
本文描述了异步图像任务 API 的通用模式,并不断言 TokenLab 或任何特定底层模型提供商的确切端点路径、字段名称、超时值或 Webhook 事件名称(上述引用的除外)。任务状态词汇表、Retry-After 头和 Webhook 签名方案在不同提供商之间存在差异,并可能随时间变化;请将本文中的代码视为说明性的,而非可直接复制的生产代码,并在发布前在 docs.tokenlab.sh 上确认当前的请求和响应格式。本文不涵盖任何特定模型的定价、速率限制或吞吐量保证。
常见问题解答
我应该总是使用 Webhook 而不是轮询吗? 不。Webhook 以更高的运营成本降低了延迟和请求量。对于低流量或内部用例,轮询通常是更简单且同样可靠的选择。许多生产系统将 Webhook 作为主要路径,并以定期轮询扫描作为回退。
如何避免重试时产生重复的图像生成? 在任务提交请求中使用幂等键,以便网络故障后的重试 POST 请求返回现有任务,而不是创建一个新任务。在依赖此功能之前,请确认您的提供商的任务创建端点是否支持它。
如果任务完成时我的 Webhook 端点宕机了怎么办? 行为取决于提供商;有些会重试交付一段时间,有些则不保证重新交付。无论提供商的重试策略如何,对超过几分钟仍未达到终止状态的任务进行定期轮询扫描是一种实用的保障措施。
如果您正在构建图像生成功能,并希望在一个 API 中比较跨多个模型的基于任务的访问方式,请查看图像模型目录和异步图像生成任务指南,然后访问 Get Started 查看 TokenLab 的 API 文档,以确认您构建所需的当前端点和 Webhook 细节。
来源
价格观测于 2026-07-14
- OpenAI webhook events观测于 2026-07-14
- TokenLab API documentation观测于 2026-07-14
- TokenLab model directory观测于 2026-07-14



