Skip to main content
Ace Data Cloud 上的服务在响应模式上分两类: 本文重点讲后两类:异步任务的 TaskHandle 轮询 和 chat 流式响应 的细节、陷阱和跨语言差异。

一、TaskHandle —— 异步任务的统一抽象

三种 SDK 都把异步任务封装成 TaskHandle,提供同样的 4 个方法:

创建任务的两种调用方式

每个异步资源(images.generate / video.generate / audio.generate)都有 wait 参数:
  • wait=False(默认):立即返回 TaskHandle,业务代码自己决定何时轮询。
  • wait=True:SDK 内部直接调 handle.wait(),函数返回完成后的响应。仅当你确定目标 API 一定会返回 status: succeeded 字段时再用——少数 provider 没遵守这个约定,会让 wait 一直转到 max_wait 才抛 TimeoutError。

单位差异(⚠️ 必看)

poll_interval 和 max_wait 的单位在三种语言里不一样,跨语言迁移时是常见踩坑点:
把 TS 的 { pollInterval: 3000 } 当成秒翻成 Python poll_interval=3000,会让 SDK 等 50 分钟才轮询第二次。

示例:Python 显式轮询 Midjourney

整段代码做的是:
  1. images.generate(..., wait=False) 把 prompt 提交给 Midjourney API,立即拿到 handle,不阻塞。
  2. handle.wait(poll_interval=3.0, max_wait=180.0) 内部每 3 秒 POST 一次 /midjourney/tasks,直到 status 变成 succeeded 或 failed,或总耗时超过 180 秒抛 TimeoutError。
  3. 完成后 result["response"]["data"] 通常包含 4 张图(Midjourney 默认 2x2 grid)。

示例:TypeScript 显式轮询

同步生成 vs 异步任务的取舍

如果你的 provider 本身就是同步出图(NanoBanana / Flux / Seedream),不要传 wait:
判断方法很简单:如果目标 API 文档里没有 task_id + /tasks 这一对,就是同步生成;同步生成的响应里 data 字段已经包含最终结果。

TaskHandle 内部协议

TaskHandle.get() 调用的是:
响应统一结构:
SDK 同时兼容没有外层 response 包裹的旧版响应——直接读取顶层 status,所以新旧版响应切换不影响业务代码。

二、SSE 流式响应(chat.completions)

chat.completions.create(stream=True) 是目前 SDK 里唯一的流式接口(音频 / 视频流尚未支持)。三种语言的迭代风格各自原生:

TypeScript

真实运行结果:

Python

真实运行结果:

Go

真实运行结果:

流式 chunk 的结构

每一帧 chunk 都是一个 OpenAI 兼容的 chat.completion.chunk:
  • 第一个 chunk 通常带 delta.role: "assistant" 但 content 为空。
  • 中间的 chunk 每个带 delta.content,可以直接拼接。
  • 最后一个 chunk delta 为空、finish_reason 是 stop / length / content_filter。

中途取消

提前取消已经计费的 token —— 取消时刻之前生成的 token 还是会按实际消耗扣费。

三、超时和重试

三种 SDK 共享同一套重试策略: 要禁用重试:构造客户端时传 max_retries=0 / maxRetries: 0 / WithMaxRetries(0)。 异步任务(TaskHandle)的轮询本身不受 max_retries 影响——它的循环是业务级的而不是 HTTP 级的,靠 max_wait 控制总时长。

四、常见陷阱

  1. 同步 provider 不要传 wait:NanoBanana / Flux / Seedream 都是同步生成,强行 wait=True 会让 SDK 去轮询一个根本不会更新的 tasks 接口。
  2. TaskHandle 单位差异:Python 是秒、TS 是毫秒,跨语言移植时一定换算。
  3. wait=True 仍可能 TimeoutError:响应必须满足 status in ('succeeded','failed') 才会退出循环;如果 provider 用了别的字段名,需要业务代码自己 handle.get() 解析。
  4. 流式取消:取消前生成的 token 已经计费。
  5. 同一 process 内复用 client:SDK 自带连接池,频繁 new AceDataCloud() / AceDataCloud() 会让 TLS 握手成为瓶颈。

了解更多