この記事では、後者の二つに重点を置きます:非同期タスクの TaskHandle ポーリング と チャットのストリーミングレスポンス の詳細、罠、及び言語間の違い。
一、TaskHandle —— 非同期タスクの統一抽象
三つの SDK は非同期タスクをTaskHandle にカプセル化し、同じ 4 つのメソッドを提供します:
タスク作成の二つの呼び出し方法
各非同期リソース(images.generate / video.generate / audio.generate)には wait パラメータがあります:
wait=False(デフォルト):即座にTaskHandleを返し、ビジネスコードがいつポーリングするかを決定します。wait=True:SDK 内部で直接handle.wait()を呼び出し、関数は完了後のレスポンスを返します。ターゲット API が必ずstatus: succeededフィールドを返すことが確実な場合のみ使用してください——少数のプロバイダーはこの約束を守っておらず、waitがmax_waitまで回り続け、TimeoutErrorをスローします。
単位の違い(⚠️ 必見)
poll_interval と max_wait の単位は三つの言語で異なります。言語間の移行時に一般的な落とし穴です:
TS の{ pollInterval: 3000 }を秒として Pythonpoll_interval=3000に変換すると、SDK は 50 分間待機してから二回目のポーリングを行います。
例:Python 明示的ポーリング Midjourney
images.generate(..., wait=False)がpromptを Midjourney API に送信し、即座にhandleを取得し、ブロックしません。handle.wait(poll_interval=3.0, max_wait=180.0)が内部で 3 秒ごとに/midjourney/tasksに POST し、statusがsucceededまたはfailedに変わるまで、または合計時間が 180 秒を超えるとTimeoutErrorをスローします。- 完了後、
result["response"]["data"]には通常 4 枚の画像が含まれます(Midjourney のデフォルトは 2x2 グリッド)。
例:TypeScript 明示的ポーリング
同期生成 vs 非同期タスクの選択
もしあなたのプロバイダーが元々同期的に画像を生成するものであれば(NanoBanana / Flux / Seedream)、wait を渡さないでください:
task_id + /tasksのペアがない**場合、それは同期生成です;同期生成のレスポンスには data フィールドに最終結果が既に含まれています。
TaskHandle 内部プロトコル
TaskHandle.get() の呼び出しは次の通りです:
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 控制总时长。
四、常见陷阱
- 同步 provider 不要传
wait:NanoBanana / Flux / Seedream 都是同步生成,强行wait=True会让 SDK 去轮询一个根本不会更新的tasks接口。 - TaskHandle 单位差异:Python 是秒、TS 是毫秒,跨语言移植时一定换算。
wait=True仍可能TimeoutError:响应必须满足status in ('succeeded','failed')才会退出循环;如果 provider 用了别的字段名,需要业务代码自己handle.get()解析。- 流式取消:取消前生成的 token 已经计费。
- 同一 process 内复用 client:SDK 自带连接池,频繁
new AceDataCloud()/AceDataCloud()会让 TLS 握手成为瓶颈。

