OpenAI 后台响应被取消后客户端怎么保存最终状态
我在接入后台响应时最容易踩的坑,是把“用户发起了取消”当成“本地任务已经取消”。真正可靠的做法是保存 OpenAI 返回的 response_id,把 response.cancelled 作为独立终态事件写入任务表,并用条件更新保证重复 webhook 和迟到事件不会把终态改回运行中。
官方地址:https://developers.openai.com/api/docs/guides/background
结论:本地任务至少要区分 queued、running、completed、failed、cancelled 和 incomplete;收到取消事件后只允许幂等地落为 cancelled,后续事件不能覆盖已经确认的终态。
先把取消当成一种独立终态
后台模式会异步创建响应,客户端可以轮询响应对象,也可以接收 webhook。官方文档把 queued、in_progress 和离开这两个状态后的最终状态区分开;只有设置了 background=true 的响应才支持取消。webhook 事件中,response.cancelled 表示后台响应已经被取消,它不应该和普通失败共用一个模糊的 error 状态。
我会在本地任务表中保存外部响应和业务状态的双重信息:response_id 用于关联 OpenAI 对象,status 用于驱动客户端展示,version 或更新时间用于挡住旧事件。下面这张图只表达状态关系,是静态说明图,不是实际运行结果。

任务表不要只存一个布尔值
如果只有 is_done,取消、失败和正常完成都会变成同一种结果,客户端无法决定是否重试,也无法向用户解释任务为什么停止。最小表结构可以这样设计:
CREATE TABLE ai_tasks (
id BIGINT PRIMARY KEY,
response_id VARCHAR(128) NOT NULL UNIQUE,
status VARCHAR(24) NOT NULL,
version INT NOT NULL DEFAULT 0,
last_event_id VARCHAR(128),
updated_at TIMESTAMP NOT NULL
);
-- response_id 建唯一约束,防止同一个后台响应被重复创建成本地任务。
-- status 保存业务终态,last_event_id 用于记录最近一次已处理的事件。
UPDATE ai_tasks
SET status = 'cancelled', version = version + 1,
last_event_id = :event_id, updated_at = CURRENT_TIMESTAMP
WHERE response_id = :response_id
AND status IN ('queued', 'running');
关键不是字段多,而是更新条件。只有 queued 或 running 允许转成 cancelled;如果同一个事件被投递两次,第二次更新不到行即可视为幂等成功。如果 completed 已经先落库,迟到的 cancelled 不应覆盖它;如果业务明确规定取消优先级,也应该把这条优先级写进状态机,而不是靠最后到达的网络包决定。
Webhook 接收层要验签并快速返回
OpenAI 的 webhook 指南建议在服务端验证签名,且验签应使用尚未解析的原始请求体。接收函数只做验签、记录事件和投递内部任务,然后尽快返回 2xx;耗时的数据库联动或通知放到后台 worker。官方文档还说明,失败响应会触发重试,webhook-id 可以作为去重键。
下面的 Python 示例展示处理思路,具体 SDK 版本以项目实际依赖为准。代码没有把密钥写入文件,unwrap 处理的是原始字节,事件业务处理则交给一个幂等函数。
import os
from openai import OpenAI, InvalidWebhookSignatureError
client = OpenAI(webhook_secret=os.environ["OPENAI_WEBHOOK_SECRET"])
def receive_webhook(raw_body: bytes, headers: dict) -> int:
# 先用原始请求体验签,不能先 json.loads 再把重排后的内容拿去验证。
try:
event = client.webhooks.unwrap(raw_body, headers)
except InvalidWebhookSignatureError:
# 签名不可信时直接拒绝,不把事件写入任务队列。
return 400
event_key = headers.get("webhook-id")
# 先按 event_key 去重,再把业务更新交给可重试的 worker。
if not event_key or already_seen(event_key):
return 200
save_event_once(event_key, event.type, event.data.id)
enqueue_state_update(event_key, event.type, event.data.id)
# 快速确认收到,避免非必要的 webhook 重试。
return 200
def apply_state_update(event_key: str, event_type: str, response_id: str) -> None:
# 只有未结束任务允许被取消、完成或失败事件推进。
target = {
"response.cancelled": "cancelled",
"response.completed": "completed",
"response.failed": "failed",
"response.incomplete": "incomplete",
}.get(event_type)
if target is not None:
conditional_update(response_id, target, event_key)
这里的 already_seen 和 save_event_once 应该共享唯一约束,不能只放在进程内存里;服务重启或多副本部署后,内存集合会失效。事件类型不在映射表时可以记录并返回成功,避免未知事件阻塞整个投递链,同时保留告警供后续补充。

把恢复和清理策略也写进状态模型
取消不是异常重试的同义词。客户端收到 cancelled 后,可以把任务展示为“已取消”,允许用户新建一次任务;failed 才适合根据错误类型决定自动重试;incomplete 则应单独保留原因,避免把不完整结果误当成成功。查询详情时仍可带上 response_id,方便把本地记录和远端对象对应起来。
清理时也不要马上删除所有行。至少保留事件去重键、最终状态和更新时间一段时间,让重试到达时仍能得到幂等结果;超过保留期再归档或删除事件明细。对外返回状态时只暴露业务需要的字段,不要把 webhook 签名、内部队列名或密钥相关信息放进客户端响应。
常见问题
收到 response.cancelled 后还要继续轮询吗?
通常不必把取消当成继续等待的中间态。保存为 cancelled 后结束本地任务;如果需要补充审计信息,再异步读取或记录,不要让用户界面一直显示处理中。
重复 webhook 会不会把 version 加很多次?
用 webhook-id 唯一约束做事件级去重,再用状态条件做任务级幂等。重复事件第一次更新成功,后续请求应直接返回成功但不重复推进业务状态。
为什么不能只在前端点击取消时改状态?
前端可能断网、刷新或重复点击,真正的远端状态仍由 API 和 webhook 传递。服务端收到 response.cancelled 后再落库,才能让多个客户端看到同一个最终状态。
我现在会把这类任务拆成两层:外部用 response_id 追踪 OpenAI 响应,内部用带条件的状态机追踪业务任务。这样取消、失败、完成和不完整结果各自有明确含义,网络重试也不会把已经确定的 cancelled 改回处理中。
Haystack Pipeline 组件连接类型不匹配怎么办
- 上一篇
- Haystack Pipeline 组件连接类型不匹配怎么办
- 下一篇
- Hydra 怎么在命令行切换配置组并允许缺省配置
-
- 科技周边 · 人工智能 | 17分钟前 | Pipeline ·
- Haystack Pipeline 组件连接类型不匹配怎么办
- 383浏览 收藏
-
- 科技周边 · 人工智能 | 17分钟前 | 人工智能 · openai · Webhook · WebHook OpenAI Responses API background response response.completed
- OpenAI 后台响应怎么用 webhook 接收完成事件
- 499浏览 收藏
-
- 科技周边 · 人工智能 | 21分钟前 |
- Gradio 并发请求怎么设置 concurrency_limit
- 305浏览 收藏
-
- 科技周边 · 人工智能 | 23分钟前 |
- OpenAI webhook 事件失败后怎么区分完成取消和失败状态
- 356浏览 收藏
-
- 科技周边 · 人工智能 | 26分钟前 | 人工智能 · A2A Agent Card Agent Card capabilities supportedInterfaces
- A2A Agent Card 怎么声明代理能力和服务地址
- 165浏览 收藏
-
- 科技周边 · 人工智能 | 11小时前 | Hugging Face Datasets rename_columns 列名冲突
- Hugging Face Datasets 批量重命名列遇到重名怎样处理
- 468浏览 收藏
-
- 科技周边 · 人工智能 | 15小时前 | python · 人工智能 · Hugging Face Transformers tokenizer max_length truncation 句子对分词 only_second
- Transformers 对句子对分词时怎样只截断第二段
- 471浏览 收藏
-
- 科技周边 · 人工智能 | 16小时前 | Transformers 标签对齐 word_ids 词级标注 token分类
- Transformers 怎样用 word_ids 对齐词级标注
- 378浏览 收藏
-
- 科技周边 · 人工智能 | 16小时前 |
- Transformers 怎样取得特殊 token 的位置掩码
- 367浏览 收藏
-
- 科技周边 · 人工智能 | 17小时前 | Hugging Face 向量检索 FAISS Datasets 索引保存
- Hugging Face Datasets 怎样单独保存与载入 FAISS 索引
- 403浏览 收藏
-
- 科技周边 · 人工智能 | 18小时前 | Hugging Face Datasets batch_size to_dict batched 数据集导出
- Hugging Face Datasets 怎样分批导出字典而不一次读取全量
- 241浏览 收藏
-
- 科技周边 · 人工智能 | 21小时前 | 数据分片 Hugging Face Datasets shard
- Hugging Face Datasets 分片时连续划分和交错划分有什么区别
- 123浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 976次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 982次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 1098次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 1068次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 906次使用
-
- 量化模型本地推理的显存估算方法
- 2026-10-17 501浏览
-
- 本地大模型反复输出同一句话怎么调整生成参数
- 2026-09-06 501浏览
-
- Python 调用大模型时如何用结构化输出校验 JSON:从解析失败到可重试
- 2026-08-29 501浏览
-
- AI写作工具免费版安装教程(含豆包Clawdbot)
- 2026-05-30 501浏览
-
- WPS AI能自动生成PPT吗?输入主题一键制作演示文稿
- 2026-05-27 501浏览

