跳到主要内容

AI 原生 API 设计:当后端开始概率性思维,REST 为何失效

· 阅读需 12 分钟
Tian Pan
Software Engineer

大多数后端工程师能够背诵 REST 契约:客户端发送请求,服务器处理请求,服务器返回状态码和响应体。200 表示成功,4xx 表示客户端出了问题,5xx 表示服务器出了故障。响应是确定性的,超时是可预测的,幂等键保证了安全重试。

而 LLM 后端违背了上述所有假设。一个返回 200 OK 的请求,可能意味着模型对整个响应产生了幻觉。一次成功的请求可能需要十二分钟,而不是十二毫秒。两次参数完全相同的请求会返回不同的结果。如果服务器在推理过程中超时,你根本不知道模型究竟是否已完成。

把 LLM 硬塞进传统 REST API 的团队,最终往往面对一堆补丁:超时杀死了正在运行的 Agent 任务,客户端把带幻觉的 200 当成成功,重试逻辑因为幂等键没有针对概率性操作设计而三次扣了用户的信用卡。本文将梳理这些不匹配最致命的地方,以及真正在生产环境中能站得住脚的接口模式。

同步请求-响应模型是为速度而生的

REST 是为快速、无状态操作而设计的。数据库查询在毫秒内完成,文件上传最多几秒。HTTP 默认 30 秒的超时对于确定性工作负载来说绰绰有余。

LLM 推理从两个维度都不符合这一模型。首先,即使是简单的文本生成,按传统标准来看也很慢——以每秒 30 个 token 的速度生成 500 个 token 的响应需要 16 秒。其次,链式调用工具的 Agent 任务可能持续数分钟乃至数小时。一个需要搜索资料、编写代码、运行测试并对失败进行迭代的 Agent,可能需要 20 分钟的实际运行时间。

当客户端的 HTTP 超时在 30 秒触发时,它不知道任务究竟是被中止了,还是仍在服务器端运行。连接断开了,但模型还在继续。客户端重试,现在同一个 Agent 任务的两个实例在同时运行,可能同时向同一个数据库写入、调用同样的外部 API,并发送重复的邮件。

解决方案是异步任务模式,各大 LLM API 提供商已独立收敛到了这种模式:初始请求立即返回 202 Accepted 和一个任务 ID,客户端随后轮询状态端点或建立流式连接获取更新,任务无论客户端是否在线都会运行至完成。这种解耦是传统 REST API 与面向长时运行 AI 工作负载的 API 之间最重要的结构性差异。

状态码无法捕获语义失败

HTTP 状态码传递的是基础设施结果,而非语义结果。服务器返回 200 OK 意味着请求在传输层面处理成功,与内容是否正确无关。

对于确定性后端,这个区别无关紧要——API 返回用户数据,数据要么存在(200),要么不存在(404)。但 LLM 后端可能返回语法正确、却在语义上存在问题的响应,而 HTTP 对此没有任何表达能力。

以下所有失败模式都会返回 200 OK

  • 幻觉:模型虚构了 API 参数、方法名或并不存在的事实。JSON 解析正常,Schema 验证通过,但数据完全是捏造的。
  • 拒绝回答:模型拒绝作答,返回"我无法帮助处理这个问题"之类的礼貌提示,而不是应用程序期望的结构化输出。
  • Schema 漂移:模型返回了合法的 JSON,但使用了下划线命名而你的 Schema 期望驼峰命名,或者省略了它认为不重要的必填字段。
  • 截断:模型在响应中途耗尽了 token,你得到的是截断点之前的合法 JSON,然后是乱码或突然结束。

只检查 HTTP 状态码的客户端会错过所有这些问题。其下游影响是:应用程序将幻觉响应当作真相,尝试解析被截断的 JSON,并在字段缺失时崩溃——而这一切都不会在 API 错误统计中体现,因为每个请求都返回了 200。

解决这个问题的模式是:在 HTTP 状态码之外返回一个结构化错误信封。响应体携带一个语义状态字段,而不是仅依赖状态码:

{
"status": "partial_success",
"result": { ... },
"errors": [
{
"type": "schema_violation",
"message": "Field 'unit_price' missing from line_items[2]",
"severity": "warning",
"recovery_suggested": true
}
]
}

HTTP 200 表示请求已处理,响应体中的 status 字段告诉你输出是否可用。这种模式让客户端能做出细粒度的决策:对轻微漂移记录警告,对 Schema 违规进行重试,对幻觉信号上报给人工处理。它也让你的 API 对自己能真正保证什么保持诚实:基础设施层面的交付,而非语义正确性。

流式传输不是可选项——但协议选择至关重要

对于文本生成,流式传输决定了应用程序是感觉流畅还是看起来卡住了。用户可以在 200 毫秒内开始阅读,而不是等待 16 秒拿到完整响应。对于长时 Agent 任务,流式状态更新是让用户了解进展的唯一方式,无需反复轮询。

业界已收敛到两种协议,各自适用于不同场景。

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates