大模型API错误码不统一怎么办?不同上游报错格式差异与聚合层归一机制怎么处理?

上游各家错误码格式不统一时,靠聚合层做响应翻译与归一,把不同厂商的报错映射成统一结构(错误类型、原始码、可重试标记),调用方只按归一后的类型分支处理即可,不必为每家大模型单独写解析逻辑。

大模型 API 错误码不统一时,正确做法是在聚合层做一次响应翻译与归一,把各上游互不相同的报错结构映射成统一的错误对象,调用方只按归一后的错误类型分支处理,而不是为每个上游厂商单独写解析逻辑。这个方案适用于通过 API 中转站或多模型路由接入两家以上上游的情况;如果只接一家上游、或应用本身已经强绑定某厂商 SDK,归一层带来的收益有限,甚至可能因为多包一层而增加排障环节。 上游错误码之所以不统一,根子在每个厂商都按自己的业务模型定义错误枚举。OpenAI 风格接口通常返回 HTTP 状态码加 JSON 体里的 error.type、error.code、error.message,常见 type 有 invalid_request_error、rate_limit_error、authentication_error 等;国内厂商有的沿用类似结构,有的则用业务码加子码,例如把欠费、模型未开通、内容安全拦截各给一个独立数字码,HTTP 状态还可能统一返回 200 或 400,真实原因藏在响应体里。 排查的第一步不是看错误码数字,而是先分清错误发生在哪一层。请求可能失败在四个位置:客户端参数拼装、聚合层的鉴权与路由、上游服务本身、以及网络链路。客户端错误通常是 400 或 422 这类语义,特征是同一份参数偶尔成功偶尔失败;聚合层错误多与 Key 无效、余额不足、模型名不在路由表内有关,特征是所有上游同时不可用;上游错误会带厂商自己的报错文案;网络类错误则表现为连接超时、读取超时或流式中断。 归一机制的核心是维护一张错误映射表,按“上游标识 + 原始状态码 + 原始错误码”三元组映射到统一错误类型。统一类型建议收敛到十类以内,例如参数错误、鉴权失败、额度不足、限流、模型不可用、内容安全拦截、上游超时、上游内部错误、路由无匹配、未知错误。映射表要允许同一厂商的不同原始码合并,也要允许同一原始码在不同接口路径下映射到不同类型,否则一次性批量调用和流式调用会在同一码上得到互相矛盾的处置结论。 归一后的错误对象至少应包含四个字段,才能支撑稳定的客户端重试策略。字段一是统一类型,决定客户端走哪条分支;字段二是原始错误码与原始错误信息,保留给日志和人工排障;字段三是可重试标记,区分瞬时故障与永久失败;字段四是建议动作,例如稍后重试、换模型重试、检查 Key、停止重试。少了原始信息,排障时会变成对着一句“服务异常”猜;少了可重试标记,客户端很容易把永久性的参数错误反复重试。 限流是最容易在归一时被误判的一类错误,因为它同时具有可重试和不可立即重试两重属性。上游返回 429 时,有的厂商在响应头里给 Retry-After,有的只在 body 里给重置时间,有的干脆不给。聚合层若统一映射为“限流”,同时把 Retry-After 缺失的情况补一个带抖动的默认退避区间,客户端就不必各自实现一套退避逻辑。要注意的是,并发限制和配额限制在部分上游是两种不同错误,归一时若合并成一种,客户端就无法区分“降低并发能解决”和“等额度刷新才能解决”。 鉴权与额度类错误需要单独归一,不能和限流混在一起。Key 失效、Key 被禁用、账户欠费、模型未开通,这几种情况重试都不会成功,但如果被归为“限流”或“上游错误”,客户端可能会持续重试并在日志里刷出大量噪音。稳妥做法是把它们统一归到“鉴权失败”和“额度不足”两类,并把“是否需要更换 Key”“是否需要充值”“是否需要申请模型权限”写进建议动作字段,让调用方能直接把告警指向对应负责人。 模型名称与路由相关的错误,归一时要特别处理。同一模型在不同上游可能叫不同名字,也可能某上游临时下线。调用方传入的模型名如果不在路由表内,聚合层可以立刻返回“路由无匹配”,不必打给上游;如果上游返回模型不存在或模型已下线,则应归一为“模型不可用”,并附上替代模型建议。这样做的价值在于,客户端不必知道上游模型的命名差异,只处理“可用”与“不可用”两种状态。 流式响应的错误处理比非流式更麻烦,因为响应头可能已经发出,错误只能在数据流里体现。常见形态是连接建立后先返回几个正常分片,中途插入一个错误事件,然后连接关闭。归一层需要在流式解析中识别这类中途错误,把它转成统一错误事件推给客户端,同时标记这一次请求的已输出内容是否可用。如果不做这一步,客户端会把半截回答当完整结果入库,事后很难判断这条记录到底是成功还是失败。 排查时建议按固定顺序走一遍,能大幅缩短定位时间。先看聚合层返回的统一错误类型,确定问题层级;再取原始错误码与原始信息,去对应上游的文档核对;然后看请求是否命中了缓存、是否触发了内容安全、是否在重试队列里被反复投递;最后检查同一 Key 在多上游下的表现差异,判断是 Key 级问题还是上游级问题。把这几步固化成排障清单,比每次临场猜要稳定得多。 日志字段的设计直接决定归一机制是否可用。建议每条失败记录至少落统一类型、原始状态码、原始错误码、上游标识、模型名、请求耗时、是否流式、重试次数、追踪 ID 九个字段,其中追踪 ID 要能贯穿聚合层与上游请求。很多排障困难的根因不是错误码看不懂,而是日志里只留了一句错误文案,既没有上游标识也没有原始码,无法判断到底是谁返回的、返回了什么。 归一机制也有边界,不是所有错误都适合强行统一。内容安全拦截涉及合规判断,不同上游的拦截粒度和标准并不一致,归一时应保留上游原始判定结果,不能简单压成一类“内容违规”,否则无法向业务方解释为何同一段文本在 A 上游被拦、在 B 上游通过。同理,涉及计费扣减的错误,原始信息要完整保留,避免对账时出现无法追溯的差额。 对通过 API 中转接入多个模型的团队来说,归一层的价值随接入上游数量上升而放大。接一家上游时,直接按该厂商文档处理错误码最省事;接三家以上时,客户端的错误分支会迅速膨胀,归一层的维护成本反而低于在每个业务模块里重复实现映射。选择中转服务时可以重点问三件事:统一错误类型是否公开文档、原始错误码是否透传、限流与可重试标记是否区分,这三点决定了排障效率。按量计费的接入方式下,建议先用小额测试 Key 把各类错误各触发一遍,记录归一结果,再决定是否把它作为主链路。 最后要强调的是,错误码归一不改变上游的真实行为,只改变调用方看到的信息形态。它解决的问题是“同一类故障在不同上游有不同表达”,不解决上游本身的不稳定。因此归一层应配合超时、退避、降级和熔断一起使用,并在文档里明确哪些错误会自动重试、哪些必须由调用方处理。把这条边界写清楚,接入方就不会把归一后的统一错误类型误当成上游能力的等价承诺。