大模型API调用
一次用户请求通常包含八个阶段:
1.业务请求进入:校验用户身份、租户、套餐、功能权限、请求大小。
2.上下文组装:System Prompt用户输入、历史消息、RAG证据、工具schema、输出格式约束。
3.Token预算预估:估算输入Token,预算输出Token,决定是否裁剪历史、压缩上下文或换小模型。
4.模型网关路由:选择模型、供应商、区域、超时参数、重试策略、限流桶。
5.供应商API调用:同步返回或流式返回,可能经过SSE、WebSocket或普通HTTP响应体。
6.响应解析:处理delta、finish reason、tool call、usage、拒答、结构化JSON、异常中断。
7.状态回写:保存完整回答、增量片段、Token用量、调用成本、失败原因和业务状态。
8.观测与告警:记录traceId、providerRequestId、TTFT、总耗时、重试次数、429次数、解析失败率。
名词解释:
delta:流式返回中的“增量内容”。模型不是一次性返回完整文本,而是一小段一小段吐出,每段就是delta。
finish reason:模型停止生成的原因。常见值:stop正常结束、length达到长度限制、tool_calls需要调用工具、content_filter被安全策略截断。
tool call:模型请求调用外部工具/函数。
usage:本次调用的用量统计,包括输入token、输出token、总token,用于计费和监控。
traceld:链路追踪ID,用来把一次请求在多个服务之间的日志串起来,方便排查问题。
providerRequestId:模型供应商侧生成的请求ID。
429次数:收到HTTP [429 Too Many Requests]的次数,表示请求过频、超过限流或额度限制。
同步返回与流式返回的对比
| 对比项 | 同步返回 | 流式返回 |
| 首字延迟 | 高,需要等完整结果 | 低,收到第一个片段即可展示 |
| 端到端总耗时 | 取决于完整生成时间 | 通常仍取决于完整生成时间 |
| 前端体验 | 像提交表单后等待结果 | 像聊天软件逐字出现 |
| 后端实现 | 简单,拿到完整字符串再处理 | 复杂,需要处理增量事件、取消、断流 |
| 结构化解析 | 简单,完整JSON一次解析 | 需要缓存完整内容,或使用增量解析器 |
| 适合场景 | 短文本、后台任务、严格事务 | 聊天、写作、报告生成、长回答 |
| 不适合场景 | 用户强交互的长回答 | 强事务、必须一次性校验完整结果的链路 |
流式输出常见的承载方式
| 方式 | 核心特点 | 适合场景 | 边界 |
| SSE(Server-Sent Events,服务器发送事件) | 浏览器原生EventSource,服务端到客户端单向推送,格式是text/event-stream(SSE的标准MIME类型) | 文本聊天、模型增量输出(Streaming)、状态通知 | 单向通信;复杂双向控制需要额外HTTP请求 |
| WebSocket(一种建立在TCP之上的长连接协议) | 双向长连接,客户端和服务端都能随时发消息 | 实时语音、多人协作、需要频繁取消或插话 | 连接管理更复杂,网关、鉴权、心跳(ping、pong)都要自己管好 |
| HTTP chunked(HTTP分块传输编码) | HTTP/1.1的分块传输机制,响应体分块发送 | 后端到后端流式代理、低层传输 | 它不是传输机制,不是应用事件协议;HTTP/2之后有自己的流式机制 |
HTTPChunked属于底层传输机制;SSE属于应用层协议,通常基于HTTP+Chunked实现;WebSocket属于独立协议,建立之后不再是普通HTTP。
SSE的优势是简单,SSE是服务端到客户端的单向数据流。WebSocket适合更实时、更复杂的交互。HTTPchunked更底层,很多服务端框架在没有Content-Length的情况下会用分块响应,它能实现“边写边发”,但不会定义事件类型、重连语义、消息边界,业务层仍然要自己设计协议。
补充:
delta字段的来源是:模型在流式生成时,每次只返回“新增的那一点内容”。
TCP是一种网络传输协议,全程Transmission Control Protocol,即传输控制协议。它负责在两台机器之间建立一条可靠连接:客户端 ⇄ 服务器。TCP核心特点:面向连接(三次握手)、可靠传输、有序传输、流式传输。
Content-Length:提前告诉客户端“总共要发多少字节”,适合一次性响应。
Transfer-Encoding: chunked:提前不知道总长度,边生成边发送。
SSE:建立在 HTTP 之上的事件流格式,通常借助 Chunked 实现实时推送。
ChatGPT 的流式输出本质上就是:Chunked + SSE + delta。
SSE 协议的事件边界
SSE不是按TCP包、HTTP Chunk来划分消息的,而是按空行(\n\n)来划分一个完整事件。因为 TCP/HTTP 流只是连续字节,事件边界用来告诉客户端“一条消息到这里结束,下一条消息从这里开始”。SSE 的事件边界是空行 \n\n,正文换行必须转义成 \\n 或拆成多行 data:,不能直接裸换行。
流式异常的四类场景
1.用户取消
用户关闭页面、点击停止生成、切换会话,都应该触发取消。后端也要同时取消:到供应商API的请求/正在解析的响应流/后续TTS、工具调用、落库任务/还没提交的增量缓存。
2.超时
·连接超时:连不上供应商
·TTFT超时:连接上了,但迟迟没有第一个事件
·总时长超时:一直有输出,但超过业务可接收时间
TTFT超时通常指向模型排队、上下文过长或供应商抖动;总时长超时可能只是用户让模型写太长。
3.断流
断流就是本应持续传输的数据流,在完成之前意外中断了。常见原因:网络问题、网关超时、服务崩溃、429限流、客户端主动取消。发现断流后,先确认不是正常结束,再记录 traceId 等上下文,尝试自动重试或续传,同时统计和排查根因。
4.重连
重连后是否能从断点续传,取决于你的服务端是否保存了事件序号、增量片段和供应商调用状态。多数情况下,供应商侧流已经断掉,无法真正从 Token 级别续上。
更稳妥的做法:服务端为每个流式响应生成messageId和递增sequence;已发送片段写入短期缓存;前端重连时先补发已缓存片段;如果供应商流已结束或已失效,提示用户重新生成,而不是假装无缝续写。
大模型API的重试有两个特殊点:
1.请求贵:失败请求也可能消耗配额,甚至已经消耗了部分token
2.输出非确定:即使prompt一样,第二次返回也可能和第一次不同
错误类型对照表
| 类型 | 示例 | 是否建议重试 | 处理方式 |
| 网络瞬断 | 连接重置、DNS抖动、读超时 | 可以 | 指数退避+抖动,限制最大次数 |
| 供应商5xx | 500、502、503、504 | 可以 | 短暂重试,超过阈值切换模型或降级 |
| 供应商过载 | Anthropic 529、类似 overloaded 错误 | 可以 | 慢重试,必要时熔断该供应商 |
| 429限流 | RPM、TPM、RPD、并发限制超出 | 谨慎 | 优先看Retry-After和限流头,排队或降级 |
| 流式中断 | 未收到正常结束事件 | 视场景 | 用户可见任务不自动重试,后台任务可幂等重试 |
| 400参数错误 | Schema不合法、字段缺失、上下文超限 | 不建议 | 修请求,不要重试同一payload |
| 401/403鉴权错误 | API Key无效、权限不足 | 不建议 | 告警并停用对应key |
| 安全拒答 | 内容策略拒绝 | 不建议 | 进入业务拒答流程 |
| 解析失败 | JSON不完整、字段类型错误 | 可有限重试 | 带失败原因二次修复,最多1-2次 |
注:
DNS(Domain Name System,域名解析系统)负责把域名转换成IP地址。
DNS抖动就是解析偶尔失败/解析变慢/返回不同节点。
连接重置:TCP连接已经建立,但被一方强制断开。可能原因:服务端重启、负载均衡切换、网络设备中断。
读超时:请求已经发出去,但在规定时间内没有收到响应。
指数退避:重试时等待时间逐渐增加。
HTTP 5xx 表示:服务端出错,不是你的请求有问题。
500 Internal Server Error:服务器内部异常。
502 Bad Gateway:网关错误。
503 Service Unavailable:服务不可用。
504 Gateway Timeout:网关超时。
降级:主模型不可用时切换备用方案。
供应商过载:服务还能工作,但负载太高。
熔断:发现某个供应商连续失败,暂时停止请求它。
429限流:请求太频繁,被限制。
RPM(Requests Per Minute):每分钟请求数。
TPM(Tokens Per Minute):每分钟Token数。
RPD(Requests Per Day):每天请求数限制。
并发限制:同时执行的请求数限制。
400参数错误:请求格式有问题。
Payload:请求体(Request Body)。
抖动(Jitter)的核心是不要让所有请求在同一时间点一起重试。
生产里加两条硬约束:最大重试次数、总体截止时间
幂等 Key 是客户端给一次“业务操作”生成的唯一 ID。去重机制就是服务端保存“已经处理过的 Key”。
常见限流策略对比
| 策略 | 适合场景 | 优点 | 缺点 |
| 固定窗口 | 简单后台任务、管理接口 | 实现简单,容易统计 | 窗口边界容易突刺 |
| 滑动窗口 | 用户级请求限制 | 边界更平滑 | 实现和存储成本更高 |
| 令牌桶 | 模型调用、token预算 | 支持一定突发,工程上常用 | 参数需要调优 |
| 漏桶 | 严格平滑出流量 | 输出稳定,适合保护供应商 | 突发体验差 |
| 并发信号量 | 流式生成、长任务 | 能限制同时占用连接 | 不控制单个请求token成本 |
| 优先级队列 | 多租户、多套餐 | 能保护高优先级请求 | 需要处理饥饿和超时 |
用户级:滑动窗口+日token上限
租户级:令牌桶+月度预算
模型级:令牌桶+并发信号量
供应商级:全局令牌桶+熔断器
流式请求:并发信号量+总时长限制
HTTP429表示请求过多。后端处理429时,建议:
1.读取Retry-After或供应商rate limit header:有明确恢复时间就尊重它
2.标记限流维度:是请求数打满,还是token打满,还是日配额耗尽
3.短请求可排队:例如后台摘要任务可以进延迟队列。
4.用户交互请求少重试:用户等不起时,直接提示稍后再试或切换轻量模型。
5.供应商连续 429 时熔断:不要让所有请求继续撞墙。
| 方式 | 约束强度 | 工程价值 | 风险 |
| 普通自然语言 | 几乎没有 | 适合展示型回答 | 不适合程序解析 |
| Prompt 要求 JSON | 弱 | 简单、跨模型 | 容易混入解释文本或缺字段 |
| JSON Mode | 中 | 通常能保证语法是 JSON | 不一定符合业务字段 Schema |
| JSON Schema | 强 | 明确字段、类型、必填、枚举 | 不同供应商支持子集不同 |
| Structured Outputs | 更强 | 供应商在解码或 SDK 层增强约束 | 受模型、SDK、Schema 子集限制 |
| Function Calling / Tool Use | 面向动作 | 适合让模型选择工具和参数 | 不是最终自然语言答案的万能替代 |
结构化输出失败后兜底:
1.本地校验:用JSON Schema、Jackson、BeanValidation校验字段和类型
2.轻量修复:只让模型修复格式,不重新生成业务内容
3.降级Scheam:复杂对象拆成多个小对象,或先分类再抽取字段
4.人工或规则兜底:高价值订单、金融、医疗、法务场景不要完全依赖自动修复
面试高频问题
1.模型API调用的完整链路是什么
一次调用从业务请求进入开始,先做用户、租户、权限和参数校验;然后组装System Prompt、用户输入、历史消息、RAG证据、工具定义和输出Schema;接着估算Token预算,经过网关模型做路由、限流、超时、重试和供应商选择;供应商返回同步结果或流式事件后,后端解析增量、校验结构化输出、落库状态和usage;最后把TTFT、总耗时、错误码、重试次数、Token成本写入观测系统。
2.Streaming为什么能改善体验
Streaming 让模型边生成边返回,用户可以更早看到第一个 Token,因此降低 TTFT。它不保证总生成时间变短,也不天然减少 Token 成本。后端需要额外处理取消、超时、断流、重连、半成品 JSON 和增量落库。
3.SSE和WebSocket怎么选
如果只是服务端向浏览器推模型文本,SSE 更简单,天然适合单向增量输出;落地时别忘了 text/event-stream 对换行与事件边界敏感,以及反向代理缓冲会把「流式」攒成「批量」。如果客户端也要频繁向服务端发数据,例如语音流、实时控制、多人协作、插话打断,WebSocket 更适合。HTTP chunked 更偏底层传输机制,业务层仍要自己定义消息边界和事件类型。
4.哪些大模型API错误可以重试
网络瞬断、连接重置、部分5xx、504、供应商过载通常可以有限重试;429 要结合 Retry-After、限流头、排队和降级处理;400 参数错误、401/403 鉴权错误、内容安全拒答通常不能重试。结构化解析失败可以做 1-2 次格式修复,但不要无限重试。
5.为什么大模型调用必须做幂等
因为重试、用户重复点击、网关超时都会让同一个业务请求被执行多次。没有幂等 Key,就可能重复落库、重复扣费、重复发通知。正确做法是用业务消息 ID 生成幂等 Key,把多次模型调用 attempt 挂在同一条业务消息下,只允许一个 attempt 成为最终结果。
6.限流为什么不能只按QPS(Queries Per Second,每秒请求数)
因为大模型 API 的成本和压力主要由 Token 决定。一个 500 Token 请求和一个 80K Token 请求都是 1 次请求,但资源消耗差异很大。生产限流要同时看 RPM、TPM、并发数、上下文大小、最大输出和租户预算。
7.JSON Mode 和Structured Outputs区别
JSON Mode 更关注“输出是合法 JSON”,但不一定符合你的业务 Schema。Structured Outputs 或 JSON Schema 约束更强,可以要求字段、类型、必填项、枚举等结构。Function Calling 或 Tool Use 更适合让模型产出工具调用参数。不同供应商支持的 Schema 子集不同,落地前要查官方文档并写兼容层
8.流式结构化返回怎么处理
不要一边收到 delta 一边直接 JSON.parse() 完整对象。更稳的做法是:增量阶段只展示文本或记录片段,等收到正常结束事件后拼成完整内容,再做 Schema 校验。若供应商支持结构化流式事件或 SDK accumulator,可以使用官方累积器;否则自己维护 buffer、sequence 和结束状态。
9.模型网关是稳定性入口。路由、限流、重试、幂等、观测全在这里收口。没有网关的团队,每个业务模块各自处理 API Key 和重试逻辑,短期省事,长期一定出事故。
结构化返回是数据契约。JSON Schema、Structured Outputs、Tool Use 解决的是"让下游系统能稳定消费模型输出",而不是"让输出看起来像 JSON"。
没有观测就没有稳定性。TTFT、usage、attempt、providerRequestId、parse failure rate——线上排查时少任何一个字段,都会让你多花几倍时间定位问题。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)