当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > OpenAI Responses API 怎样区分文本增量与工具事件

OpenAI Responses API 怎样区分文本增量与工具事件

来源:17golang原创 2026-10-24 20:07:10 0浏览 收藏

OpenAI Responses API 的流式返回不是“每次收到一段文字”这么简单:文本回答、函数工具参数、文件搜索状态和响应生命周期都通过带有 type 的事件发送。要区分文本增量与工具事件,核心是先按事件类型分流,再用 item_id 和 output_index 维护局部状态。

官方地址:https://platform.openai.com/docs/api-reference/responses-streaming

只把 response.output_text.delta 交给文本渲染器;遇到 response.function_call_arguments.delta 时先缓存字符串,等到对应的 .done 事件再解析和执行工具。不要把所有 delta 拼成一条用户可见文本,也不要在参数尚未完成时调用工具。
  • 文本:response.output_text.delta,可以逐段追加。
  • 工具参数:response.function_call_arguments.delta,必须按调用项单独累积。
  • 工具收束:response.function_call_arguments.done,拿到完整 name 和 arguments。
  • 生命周期:response.created、response.completed、error 等,用来更新会话状态。

先按 type 分流,不要按 delta 字段猜事件

Responses API 在 stream=true 时通过服务器发送事件推送生成过程。事件中都有类型标识,但不同事件携带的字段并不相同:文本增量有 delta 和 content_index,函数参数增量也有 delta,生命周期事件则可能带完整 response 或错误对象。因此,判断依据应是完整的 type 字符串,而不是“看到 delta 就显示”。

事件用途应用侧动作
response.output_text.delta一段新增文本追加到当前文本缓冲区
response.function_call_arguments.delta工具参数的局部字符串按 item_id 追加,暂不解析
response.function_call_arguments.done工具参数已完成检查名称、解析 JSON、进入执行策略
response.completed响应生成结束关闭生成状态,等待工具结果或最终收束
error流中发生错误记录错误并停止继续消费
Responses API 流式事件按 type 分流到文本、工具和生命周期处理器的静态结构说明图
图1:事件路由结构说明图,展示文本、工具和生命周期事件的分流关系;这是原创说明图,不是运行截图。

文本增量可以显示,工具增量只能缓存

response.output_text.delta 的 delta 是面向用户的文本片段,通常可以直接追加到当前回答。工具参数增量看起来也像普通字符串,但它可能只是 JSON 的半截,例如先收到 {"city":",后面才收到城市名和结尾括号;这时既不能把它显示成回答,也不能立即交给 JSON 解析器。

一个响应可能包含多个输出项,所以缓存键不能只用事件类型。至少要按 item_id 区分不同工具调用,必要时再结合 output_index 和工具定义中的调用关联信息。文本渲染器和工具参数缓存也应使用不同的数据结构,避免调试信息混入用户回答。

import json

def consume_event(event, text_parts, tool_buffers):
    # 事件对象来自 SSE 解码层;没有 type 时无法安全决定处理路径。
    event_type = event.get("type")
    if event_type == "response.output_text.delta":
        # 文本增量可以立即显示,但仍按事件顺序追加,避免界面乱序。
        delta = event.get("delta", "")
        text_parts.append(delta)
        return {"kind": "text", "delta": delta}

    if event_type == "response.function_call_arguments.delta":
        # 工具参数可能只是半段 JSON,先按调用项缓存,不能提前执行。
        item_id = event.get("item_id")
        if not item_id:
            raise ValueError("工具增量缺少 item_id")
        tool_buffers.setdefault(item_id, []).append(event.get("delta", ""))
        return {"kind": "tool-buffered", "item_id": item_id}

    if event_type == "response.function_call_arguments.done":
        # done 事件给出完整参数;解析后仍需经过工具白名单和参数校验。
        raw = event.get("arguments", "")
        args = json.loads(raw)
        return {
            "kind": "tool-ready",
            "item_id": event.get("item_id"),
            "name": event.get("name"),
            "arguments": args,
        }

    if event_type in {"response.completed", "error"}:
        # 完成与错误负责收束状态,不应被当成用户可见文本。
        return {"kind": "lifecycle", "type": event_type}

    # 其他事件保留给专门处理器,避免静默吞掉未来新增类型。
    return {"kind": "ignored", "type": event_type}

代码只展示分流策略,没有调用真实 API,也不代表已经在本机执行。生产实现还应处理 SSE 解码、断线、重复事件、取消和请求级超时;其中 JSON 解析失败应进入错误状态,而不是重新拼接到用户文本。

工具参数 done 之后才进入执行层

收到 response.function_call_arguments.done 只说明模型给出了完整的函数名和参数,不等于工具已经执行成功。应用侧还要做名称白名单、参数 schema 校验、权限判断和幂等控制。对不允许的工具或不合规参数,应返回可解释的失败状态,不能把模型输出直接当作执行授权。

如果同时出现文本增量和工具事件,界面可以继续显示已经确定的文本,但工具执行状态应在单独区域呈现。工具执行结果通常需要作为下一轮输入交回 Responses API;不要把本地执行结果伪装成模型刚刚生成的文本。

工具参数完成后经过白名单和参数校验再进入执行层的静态边界说明图
图2:工具执行边界说明图,参数完成、授权校验和执行结果是三个不同状态;这是原创结构图,不是运行证据。

还有一个容易忽略的点:工具参数的局部片段不是可靠的审计对象。审计日志应记录最终解析后的参数摘要、调用项标识和执行结果,而不是把每个 delta 都当成一次调用。跨进程消费时要把调用项状态持久化或交给有序的单一消费者,避免两个消费者同时执行同一个工具。

用生命周期事件收束,而不是看到 done 就宣布成功

response.function_call_arguments.done 只收束“参数生成”这个阶段;响应整体还可能处于进行中,工具本身也可能失败。应用状态建议至少区分 STREAMING、TOOL_READY、TOOL_RUNNING、TOOL_SUCCEEDED、FAILED 和 CANCELLED。response.completed 表示响应生成已完成,不应替代工具业务结果。

排查时先记录 type、sequence_number、item_id 和 output_index,再看文本缓冲、工具缓冲与执行记录是否一一对应。遇到未知事件时保留原始类型并安全忽略,避免新事件导致整个流处理器崩溃;但不要把未知事件当作成功。

为什么工具参数不能边收边执行?因为每个 delta 可能只是 JSON 片段,缺少字段、转义字符或闭合符号时都不能证明参数完整。应该等待对应的 .done 事件,再做解析和策略检查。

只处理 response.output_text.delta 可以吗?如果应用永远不启用工具且不关心生命周期,可以先做最小文本客户端;一旦启用工具、文件搜索或错误恢复,就需要保留未处理事件的记录和明确的状态分支。

官方参考:https://platform.openai.com/docs/api-reference/responses-streaming。事件名称和字段以当前官方参考为准,本文的缓存结构、状态名和 Python 分流代码是独立示例。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
VS Code notebooks 怎样固定 notebook 内核选择VS Code notebooks 怎样固定 notebook 内核选择
上一篇
VS Code notebooks 怎样固定 notebook 内核选择
VS Code port forwarding 怎样限制转发端口的访问范围
下一篇
VS Code port forwarding 怎样限制转发端口的访问范围
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    662次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    682次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    727次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    696次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    528次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码