基础篇

F23|API与流式协议:请求如何变成可执行数据

基础篇约 3 千字1 组分步图解

从具体对象与小例子开始,理解计算过程与适用条件。

本章目录
动态图解 · F23

字符完整、事件完整、工具参数完整是三道关

为什么看到半段JSON时绝对不能执行?

网络像分批送到的纸条,分割点不遵守汉字或JSON边界。接收端先重组字节和字符,再按流协议重组事件,最后解析结构并确认该输出是否表示完整行动。花括号配平不够,因为字符串内部也可能有花括号。

UTF-8把字符表示成字节序列的编码。
SSE以事件形式持续传送文本数据的一种协议。
Schema描述字段和类型约束的结构规范,不保证字段事实正确。

输入与适用条件:真实编码了一个小SSE文本事件,故意把“爱”的三个UTF-8字节拆成两段。示例并不使用厂商特定的事件命名。

1 / 4 · 收到第一段字节

第1步,共4步

窄屏可左右滑动图形,或点击“放大图形”。文字解释紧随图后。

字符完整、事件完整、工具参数完整是三道关:收到第一段字节接收端缓冲状态字节缓冲已经接收64 61 74 61 3a 20 7b 22 74 65 78 74 22 3a 22 e7接下来/解释未收到其余字节

网络片段可以停在一个汉字的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破损是解析问题;缺字段是结构问题;路径越界是授权问题;文件不存在是环境或业务问题;文件存在却被模型误解是后续推理问题。

将所有错误变成“工具失败,再试一次”会丢掉重要判断。可修正参数的错误适合反馈模型;权限禁止不应通过偷偷换更强工具绕开;写操作超时需要核验是否已经发生。

接口无状态不等于系统无记忆

无状态模型调用可以由应用显式重传历史;有状态接口可以使用会话或前次响应标识让服务组织状态。两者只是状态放在哪里和如何引用的差别,不自动保证全部历史一直在上下文里。

运行示例 · F23

把“学习.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实现。

依据与适用范围:[SSE] [TOOLS]。示例输入和场景由本书明确设定。

课后自检

自检 1

一段JSON合法,为什么仍不能直接执行删除文件?

查看参考答案收起参考答案
合法只说明格式可解析。还要核对结构、目标、授权、用户意图及高风险动作的确认。
自检 2

两个同名工具结果乱序,应按什么配对?

查看参考答案收起参考答案
按协议提供的调用标识或输出项身份,不按工具名称,也不按到达顺序猜。

机制依据:[TOOLS][STREAM][STRUCTURED][SSE]。本节数值与情景除另注外均为原创教学示例;来源不代替中文讲解。

记录保存在本机浏览器。

输入关键词即可检索。

↑ ↓ 选择 Enter 打开Esc 关闭 · 仅本地搜索

阅读设置

阅读设置仅保存在本机浏览器,不上传任何数据。