F23|API与流式协议:请求如何变成可执行数据
从具体对象与小例子开始,理解计算过程与适用条件。
本章目录
字符完整、事件完整、工具参数完整是三道关
为什么看到半段JSON时绝对不能执行?
网络像分批送到的纸条,分割点不遵守汉字或JSON边界。接收端先重组字节和字符,再按流协议重组事件,最后解析结构并确认该输出是否表示完整行动。花括号配平不够,因为字符串内部也可能有花括号。
输入与适用条件:真实编码了一个小SSE文本事件,故意把“爱”的三个UTF-8字节拆成两段。示例并不使用厂商特定的事件命名。
1 / 4 · 收到第一段字节
窄屏可左右滑动图形,或点击“放大图形”。文字解释紧随图后。
网络片段可以停在一个汉字的UTF-8编码中间。现在只有“爱”的第一个字节,不能把每个网络片段独立按完整字符串解码。
字节缓冲默认静止。用“下一步”看完解释再继续;播放到最后一步自动停止。键盘聚焦播放器后,可用左右键逐步查看、空格播放/暂停。图中颜色辅助区分,含义同时用文字注明。
为什么需要
让网络分片方式不影响语义与执行次数。
怎样实现
增量解码→组装事件→解析JSON→检查完成状态→按类型分派。
可能的代价与误解
提前执行、重复事件未去重、调用ID错配,都可能把一次动作变成多次副作用。
如何判断是否做对
把同一字节串在每个切分点拆开,解析后的事件都应一致。
API只是程序间约定,不是智能本身
API(应用程序接口)规定一个程序怎样请求另一个程序提供能力。请求给出操作与参数,响应给出结果或错误。调用语言模型的API和调用数据库API都属于这种交互,区别在能力和返回内容。
JSON是一种表示结构化数据的文本格式。花括号表示对象,键后面冒号给值;方括号表示列表;引号里的内容是字符串。例如:
{"name":"read_file","arguments":{"path":"demo.py"},"call_id":"c1"}
这里只是一段数据。反序列化是把这段文本解析成程序对象;序列化是把对象变成可以存储或传输的表示。解析成功不等于动作安全。
Schema在检查什么
Schema(结构约束)可以要求path是字符串且必须提供,禁止某些额外字段。它能发现“path给成数组”之类形状错误,却不证明demo.py存在、当前用户有权读取、或者这真是需要调查的文件。
因此要区分语法合法、结构合法、业务适用、权限允许和执行成功。Structured Outputs主要提高结构符合约定的能力,不是事实保证或权限系统。
为什么网络一次读到的不是一个完整回答
发送方可能分多次发送,网络和客户端也可能以不同片段接收。chunk(传输片段)是这次拿到的一部分字节,不保证对应一个Token、一句中文或一条完整JSON。
例如JSON里有“学习”两个字,UTF-8字节可能恰好在一个汉字中间分开。单独把每个片段直接解成完整字符串可能报错或出现替换字符。需要能够保存未完成字符状态的增量解码。
SSE的事件边界
SSE(Server-Sent Events)是一种服务器向客户端连续发送事件的文本协议。概念上,data:行提供数据,空行结束一条事件。实际标准还有多行字段、换行差异和其他规则。
正确处理通常至少有这些层:网络字节→增量文本→事件边界→事件数据解析→模型输出项重建。这几层边界不能互相替代。
模型的工具参数还可能分成多个delta,即增量片段。收到{"path":"de时显然不能执行;即使暂时拼成合法JSON,也仍需等待对应调用完成信号和宿主校验,而非提前猜最后参数。
call_id为什么比工具名称重要
一次模型输出可能发起两个read_file,分别读取a.py与b.py。结果返回顺序可能相反。用工具名称无法配对,必须使用调用标识call_id或协议规定的输出项身份。
响应完成、单个工具参数完成、某项工具执行完成,又是不同事件。取消请求也未必能撤回已经发生的外部副作用。
一个失败应归到哪层
连接失败是传输问题;JSON破损是解析问题;缺字段是结构问题;路径越界是授权问题;文件不存在是环境或业务问题;文件存在却被模型误解是后续推理问题。
将所有错误变成“工具失败,再试一次”会丢掉重要判断。可修正参数的错误适合反馈模型;权限禁止不应通过偷偷换更强工具绕开;写操作超时需要核验是否已经发生。
接口无状态不等于系统无记忆
无状态模型调用可以由应用显式重传历史;有状态接口可以使用会话或前次响应标识让服务组织状态。两者只是状态放在哪里和如何引用的差别,不自动保证全部历史一直在上下文里。
把“学习.py”拆在一个汉字中间,为什么不能马上解析
输入与条件。一个事件内容是 data: {"path":"学习.py"},后接两个换行。网络可能在“学”的UTF-8字节中间切开。
| 步骤与对象 | 内部动作 | 中间结果 / 新状态 |
|---|---|---|
| 1先收一段字节 | 可能只收到某个汉字的前1或2个字节 | 增量UTF-8解码器保留残余,不制造替代字符。 |
| 2收齐字符 | 后续字节完成“学” | 解码得到部分文本,但JSON和事件可能仍未结束。 |
| 3识别事件边界 | 只有遇到空行才完成此SSE事件 | 不拿一次网络read当一次事件。 |
| 4解析数据 | 从data字段拼出完整JSON | 得到path字符串“学习.py”。 |
| 5等待调用完成 | 即使参数JSON完整,也要核对输出项完成语义 | 执行器仍需检查允许路径,不能只凭文本看起来合法就执行。 |
把过程连起来。字节边界、字符边界、JSON边界、事件边界和工具调用完成边界是不同层次。
边界与反例。配套程序测试LF分隔的教学SSE子集和所有二分字节切点;不是完整浏览器EventSource实现。
课后自检
一段JSON合法,为什么仍不能直接执行删除文件?
查看参考答案收起参考答案
两个同名工具结果乱序,应按什么配对?
查看参考答案收起参考答案
延伸阅读:相关系统问题
09|Agent一次任务的完整循环:谁在思考,谁在执行10|模型输出怎样变成真实工具调用:协议与执行边界
11|工具设计与MCP:从连接到可控执行
12|Codex、Claude Code、Copilot:从公开事实到可诊断运行链
21|可靠执行:重试、幂等、崩溃与状态恢复
机制依据:[TOOLS][STREAM][STRUCTURED][SSE]。本节数值与情景除另注外均为原创教学示例;来源不代替中文讲解。