
1. 多模型接入的乱局为什么统一管理不是可选项我最早接触多模型接入是在两年前当时团队同时用着三家厂商的模型服务一家做通用对话一家做代码补全还有一家专门跑长文本摘要。每个模型都有自己的控制台、自己的密钥体系、自己的计费口径。最崩溃的一次是某个模型的密钥过期了没人收到通知线上客服机器人直接哑火了两个小时排查的时候翻了三个后台才定位到问题。这件事之后我就明白了一个道理当企业接入的大模型超过两个统一管理就不再是优化项而是生存项。所谓统一管理核心要解决的是四件事——统一入口、统一鉴权、统一计费、统一可观测。这四件事听起来简单但每一件背后都有一堆坑。先说统一入口。不同厂商的接口协议差异很大OpenAI 风格、Claude 风格、各家自研的私有协议参数命名、返回结构、流式格式全都不一样。业务方每接一个新模型就要改一次代码改到最后代码里全是 if-else 分支。统一入口要做的就是把这些差异屏蔽掉对外暴露一套标准协议业务方只认这一套。再说统一鉴权。企业内部可能有十几个业务线都在调模型如果每个业务线都拿着厂商的原始密钥去调那密钥管理就是灾难——谁在用、用了多少、该找谁收费全是糊涂账。更严重的是安全风险一个密钥泄露整个企业的额度都可能被刷爆。统一鉴权要做的是业务方只认企业内部的虚拟密钥真实密钥锁在网关里永远不出内网。统一计费是很多团队容易忽略的一环。不同厂商的计费单位不一样有的按 token 算有的按调用次数算有的输入输出价格还不一样。财务月底要账单的时候你得能拿出一张表说清楚A 业务线这个月用了多少 token折算成多少钱。没有统一计费这张表根本做不出来。最后是统一可观测。模型调用和普通接口调用不一样它的延迟波动大、失败原因复杂限流、超时、内容审核拦截、模型本身报错如果没有统一的日志和指标出了问题就是两眼一抹黑。我见过太多团队模型调用失败率飙升了三天才发现因为没人看那个厂商自己的后台。提示如果你的企业目前只接了一个模型可以先不急着上网关但一定要把密钥管理和调用日志这两件事做好等接第二个模型的时候再上统一层迁移成本会低很多。适合读这篇内容的人我大致分三类一是正在做 AI 中台或平台工程的技术负责人二是被多模型接入折磨的一线后端三是想了解企业级 AI 基础设施怎么搭的架构师。不管你是哪一类下面的内容都是我从实际项目里踩出来的不是纸上谈兵。2. 方案选型自研网关、开源方案还是云厂商托管确定要做统一管理之后第一个要回答的问题就是用什么来做。这个问题没有标准答案取决于你的团队规模、预算、合规要求和技术栈。我把常见的三条路线拆开讲每条路线的适用场景和坑都说明白。2.1 三条主流路线的对比先上一张对比表把关键维度列清楚方便你快速判断自己该走哪条路。维度自研网关开源网关方案云厂商托管初期投入高需要 2-3 人月中1-2 周可跑通低配置即可长期维护高要持续迭代中跟随社区低厂商负责定制能力最强想怎么改怎么改中受框架限制弱只能用现成功能数据合规完全自主可控自主可控数据要出内网成本人力成本为主人力服务器按调用量付费适合规模大型企业、有平台团队中型团队、有后端能力小团队、快速验证自研网关这条路我实际做过一次。当时团队有六个人花了大概两个半月做出了第一版能用的东西。核心模块包括协议适配层、鉴权层、路由层、计费层和日志层。好处是完全贴合自己的业务坏处是每一个厂商出新版本、改接口你都得跟着改。如果你的团队没有持续投入的准备自研会变成一个无底洞。开源网关方案是大多数中型团队的最优解。市面上有几款做得比较成熟的项目核心能力都覆盖了协议转换、密钥管理、限流、日志。你只需要部署起来配置好上游厂商的信息业务方就能用。缺点是遇到特殊需求比如自定义的计费规则、特殊的路由策略时要么改源码要么等社区。我一般建议团队先用开源方案跑起来等业务稳定了再考虑要不要自研替换。云厂商托管最省心但有两个硬伤。一是数据合规很多企业的模型调用内容涉及业务敏感信息不允许出内网托管方案直接出局。二是成本托管方案通常按调用量抽成量大之后比自己搭贵不少。所以托管方案更适合做 PoC 或者非核心业务。2.2 选型时最容易忽略的三个点第一个是协议适配的广度。你在选型的时候一定要问清楚这个方案支持哪些厂商的协议支不支持流式支不支持多模态图片、音频输入我见过一个团队选了个只支持文本的方案结果业务方要接视觉模型的时候傻眼了只能推倒重来。第二个是密钥的加密存储方式。厂商的真实密钥是企业的核心资产绝对不能明文存在数据库里。合格的方案应该支持密钥加密存储最好能对接企业的密钥管理服务。这一点在选型的时候一定要验证别等上线了才发现密钥是明文。第三个是限流和熔断的粒度。限流不能只做全局的要能按业务线、按模型、按密钥分别限流。熔断要能识别出是厂商侧的问题还是自己侧的问题厂商侧的问题要能自动降级到备用模型。这两个能力直接决定了你的系统在厂商抖动时能不能扛住。注意选型阶段一定要做压力测试不要只看功能列表。我踩过的坑是某个方案在低并发下一切正常QPS 上到 200 之后连接池直接打满排查了两天才发现是默认配置的问题。2.3 一个务实的落地节奏建议如果你现在从零开始我建议分三步走。第一步先用开源方案搭一个最小可用版本只做协议转换和密钥管理让业务方能统一调用。这一步的目标是能用大概一到两周。第二步加上计费和可观测把每个业务线的用量统计出来这一步的目标是可管大概再花两到三周。第三步根据实际暴露的问题做定制比如加自定义路由、加内容安全过滤、加多级缓存这一步的目标是好用是持续迭代的过程。这个节奏的好处是每一步都有明确的交付物不会陷入憋大招然后迟迟上不了线的困境。我见过太多团队一上来就想做一个完美的平台结果做了半年还没上线业务方早就自己接了一堆野路子了。3. 核心模块拆解鉴权、路由、计费、可观测怎么落地方案定了之后接下来就是具体怎么实现。这一章我把四个核心模块拆开讲每个模块讲清楚设计思路、关键实现和实操中的坑。3.1 统一鉴权虚拟密钥体系怎么设计统一鉴权的核心思路是双层密钥业务方持有的是企业颁发的虚拟密钥也叫 API Key 或 Token网关持有的是厂商的真实密钥。业务方调网关的时候带虚拟密钥网关校验通过后用对应的真实密钥去调厂商。虚拟密钥的设计有几个关键点。第一密钥要能绑定业务线和权限。一个虚拟密钥应该明确属于哪个业务线、能访问哪些模型、有没有额度限制。这样出问题的时候能快速定位到责任方。第二密钥要支持轮换。密钥泄露是迟早的事系统要支持一键吊销和重新生成业务方无感知切换。第三密钥要能设置有效期。临时项目用的密钥设个短期有效期到期自动失效减少长期暴露的风险。密钥的存储我强烈建议用哈希存储就像存用户密码一样。网关校验的时候用同样的哈希算法算一遍比对哈希值。这样即使数据库被拖库攻击者也拿不到原始密钥。真实密钥则用对称加密存储密钥加密密钥放在独立的密钥管理服务里和数据库分离。# 虚拟密钥生成与校验的简化示例 import hashlib import secrets def generate_virtual_key(): # 生成 32 字节随机密钥前缀标识类型 raw secrets.token_urlsafe(32) return fsk-ent-{raw} def hash_key(raw_key: str) - str: # 用 SHA-256 哈希实际生产建议加盐 return hashlib.sha256(raw_key.encode()).hexdigest() def verify_key(raw_key: str, stored_hash: str) - bool: return hash_key(raw_key) stored_hash上面这段代码只是示意实际生产环境还要考虑加盐、密钥版本管理、校验失败的限流防止暴力破解等。我特别要提醒的是校验失败的限流很多团队忘了做这个结果被人拿脚本疯狂试密钥把网关的 CPU 打满。3.2 智能路由怎么让请求落到最合适的模型路由模块要解决的问题是一个请求进来该发给哪个模型。最简单的路由是固定映射业务方指定模型名网关转发到对应的厂商。但实际场景往往更复杂需要动态决策。常见的路由策略有几种。按成本路由同样的任务优先用便宜的模型便宜的不行了再用贵的。按能力路由代码任务走代码模型长文本走长上下文模型多模态走视觉模型。按可用性路由主模型挂了自动切备用模型。按负载路由同一个模型有多个厂商提供时按当前延迟和错误率动态分配。实现上我建议把路由规则做成可配置的而不是硬编码在代码里。规则可以用简单的 DSL 描述比如当模型为 gpt-4 且错误率超过 5% 时切换到 claude-3。这样运营人员不用改代码就能调整策略。# 路由规则配置示例 routes: - name: code-completion match: model: code-* targets: - provider: vendor-a model: code-model-v2 weight: 80 - provider: vendor-b model: code-model-pro weight: 20 fallback: - provider: vendor-c model: general-model路由里最容易踩的坑是降级链路的死循环。A 降级到 BB 又降级回 A请求在里面转圈。所以降级链路一定要是有向无环的配置的时候要校验。另一个坑是降级后的模型能力不匹配比如把长上下文任务降级到一个上下文很短的模型结果请求直接被截断。降级策略要按任务类型分别配置不能一刀切。3.3 统一计费token 统计的准确性怎么保证计费模块的核心是准确统计每个请求消耗的 token。这里有个容易被忽略的点不同厂商对 token 的计算方式不一样。同一个文本A 厂商算 100 个 tokenB 厂商可能算 120 个。所以计费不能自己算要以厂商返回的 usage 字段为准。但厂商返回的 usage 也不是永远可靠。流式响应的情况下很多厂商是在最后一个 chunk 里才返回 usage如果连接中途断了usage 就丢了。这时候需要网关自己估算估算的算法要和厂商的 tokenizer 对齐。我一般建议网关内置主流厂商的 tokenizer流式请求先估算等收到 usage 再修正。计费的另一个难点是多币种和多计费单位。有的厂商按美元计价有的按人民币有的按 token有的按调用次数。网关要维护一张价格表把不同单位统一折算成企业内部的计费单位。价格表要能随时更新因为厂商调价是常事。厂商计费单位输入价格输出价格备注厂商 A每千 token0.01 元0.03 元输入输出分开计厂商 B每千 token0.008 元0.024 元有阶梯折扣厂商 C每次调用0.05 元-不区分输入输出这张表要定期核对我遇到过厂商悄悄调价但没通知的情况月底对账才发现成本涨了 30%。建议每月做一次价格核对把厂商官网的价格和网关里的价格表比对一遍。3.4 可观测日志、指标、追踪一个都不能少可观测这块我把它拆成三层。日志层记录每个请求的详细信息谁调的、调的哪个模型、输入输出是什么、耗时多少、成功还是失败。日志要注意脱敏用户的输入输出可能包含敏感信息不能原样落盘。指标层做聚合统计QPS、延迟分布、错误率、token 消耗量按业务线和模型维度分别统计。追踪层做全链路追踪一个请求从业务方到网关到厂商每一跳的耗时都能看到。日志的存储是个成本问题。全量日志存三个月量大的话存储成本很可观。我的做法是分级存储最近七天的全量日志存在热存储里方便排查七天到三个月的日志只存元数据时间、业务线、模型、耗时、状态不存输入输出三个月以上的归档到冷存储。这样既保证了排查能力又控制了成本。指标告警要设置合理的阈值。错误率告警不能设太低模型调用本身就有一定的失败率设太低会天天误报。我一般建议错误率超过 5% 持续五分钟才告警同时要区分是厂商侧的错误还是自己侧的错误。厂商侧的错误告警给平台团队自己侧的错误告警给业务团队。提示可观测做得好不好一个简单的检验标准是——线上出问题时你能不能在不问任何人的情况下五分钟内定位到是哪个环节的问题。如果做不到说明可观测还有欠缺。4. 实操落地从零搭一个最小可用网关前面讲的是设计思路这一章我带你走一遍实操从环境准备到跑通第一个请求。我用 Python 的 FastAPI 做示例因为它上手快、生态好适合做原型。生产环境你可以用 Go 或者 Java 重写思路是一样的。4.1 环境准备与依赖安装先准备环境。我假设你已经装好了 Python 3.10 以上版本用虚拟环境隔离依赖。python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install fastapi uvicorn httpx pydantic redis这里解释一下每个依赖的作用。fastapi是 Web 框架uvicorn是 ASGI 服务器httpx用来发异步 HTTP 请求调厂商接口pydantic做数据校验redis用来存密钥和做限流。Redis 不是必须的但强烈建议用因为限流和密钥缓存都依赖它。目录结构我建议这样组织gateway/ ├── main.py # 入口 ├── config.py # 配置 ├── auth.py # 鉴权 ├── router.py # 路由 ├── providers/ # 各厂商适配 │ ├── base.py │ ├── vendor_a.py │ └── vendor_b.py ├── billing.py # 计费 └── observability.py # 日志指标这个结构的好处是每个模块职责清晰加新厂商只需要在 providers 下加一个文件不用动核心逻辑。4.2 鉴权中间件的实现鉴权我做成 FastAPI 的中间件每个请求进来先过鉴权。from fastapi import Request, HTTPException from starlette.middleware.base import BaseHTTPMiddleware import hashlib import redis r redis.Redis(hostlocalhost, port6379, decode_responsesTrue) class AuthMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): # 健康检查等路径跳过鉴权 if request.url.path in (/health, /metrics): return await call_next(request) auth_header request.headers.get(Authorization, ) if not auth_header.startswith(Bearer ): raise HTTPException(status_code401, detailmissing token) raw_key auth_header[7:] key_hash hashlib.sha256(raw_key.encode()).hexdigest() # 先查缓存缓存没有再查数据库 key_info r.hgetall(fkey:{key_hash}) if not key_info: raise HTTPException(status_code401, detailinvalid token) # 把业务线信息挂到 request.state 上后续模块用 request.state.business_line key_info[business_line] request.state.allowed_models key_info[allowed_models].split(,) return await call_next(request)这段代码的关键点是缓存优先。每次请求都查数据库的话数据库压力会很大。密钥信息变更不频繁缓存在 Redis 里变更的时候主动失效缓存就行。缓存的有效期我一般设 10 分钟即使失效逻辑出问题最多 10 分钟也能自愈。4.3 协议适配层的实现协议适配层要做的是把厂商的返回格式统一成内部标准格式。我定义一个基类每个厂商实现自己的适配逻辑。from abc import ABC, abstractmethod import httpx class BaseProvider(ABC): def __init__(self, api_key: str, base_url: str): self.api_key api_key self.base_url base_url abstractmethod def build_request(self, messages: list, **kwargs) - dict: 把内部标准请求转成厂商格式 pass abstractmethod def parse_response(self, raw: dict) - dict: 把厂商返回转成内部标准格式 pass async def call(self, messages: list, **kwargs) - dict: payload self.build_request(messages, **kwargs) async with httpx.AsyncClient(timeout60) as client: resp await client.post( f{self.base_url}/chat/completions, jsonpayload, headers{Authorization: fBearer {self.api_key}} ) resp.raise_for_status() return self.parse_response(resp.json())内部标准格式我建议对齐 OpenAI 的格式因为它是事实标准大部分厂商都兼容或者容易转换。这样适配层的工作量最小。如果某个厂商的格式差异特别大就在它的适配类里做转换不影响其他厂商。4.4 限流与熔断的实现限流我用 Redis 的滑动窗口算法按业务线和模型两个维度分别限流。import time def check_rate_limit(business_line: str, model: str, limit: int, window: int 60): 滑动窗口限流limit 是窗口内最大请求数 now time.time() key fratelimit:{business_line}:{model} pipe r.pipeline() pipe.zremrangebyscore(key, 0, now - window) pipe.zadd(key, {str(now): now}) pipe.zcard(key) pipe.expire(key, window) _, _, count, _ pipe.execute() if count limit: raise HTTPException(status_code429, detailrate limit exceeded)熔断我用一个简单的状态机连续失败 N 次后进入熔断状态熔断期间直接返回降级结果过了冷却期进入半开状态放少量请求试探成功了就恢复失败了继续熔断。这个逻辑不复杂但一定要做否则厂商侧挂了会把你的网关也拖垮。4.5 跑通第一个请求把上面的模块组装起来启动服务。uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4然后测试一下curl -X POST http://localhost:8000/v1/chat/completions \ -H Authorization: Bearer sk-ent-your-virtual-key \ -H Content-Type: application/json \ -d { model: general, messages: [{role: user, content: 你好}] }如果返回了正常的响应说明最小可用版本跑通了。接下来就是逐步完善加计费、加日志、加更多厂商适配。我建议每加一个功能就做一次压测确保性能没有明显下降。注意--workers的数量要根据 CPU 核数来定一般是核数的 1-2 倍。设太多反而会因为进程切换导致性能下降。我实测下来4 核机器设 4-8 个 worker 比较合适。5. 踩坑实录那些文档里不会写的问题这一章是我最想写的部分因为前面讲的东西文档里多少能找到但下面这些坑都是真金白银换来的。5.1 流式响应的三个坑流式响应是问题最集中的地方。第一个坑是超时设置。普通请求设 60 秒超时没问题但流式请求可能持续几分钟如果网关的超时设短了请求会被中途掐断。我的做法是流式请求单独设超时一般设 300 秒同时加一个空闲超时如果 30 秒没有新数据就断开。第二个坑是连接复用。流式请求如果每个都新建连接连接数会爆炸。要用连接池但连接池的大小要控制好太大反而会因为连接竞争导致延迟上升。我一般设连接池大小为并发数的 1.5 倍。第三个坑是错误处理。流式响应已经开始返回数据了中途厂商报错这时候 HTTP 状态码已经发出去了没法改。只能在流里发一个错误事件让客户端识别。这个协议要提前和业务方约定好否则业务方不知道怎么处理。5.2 密钥轮换的平滑切换密钥轮换听起来简单做起来容易出问题。我遇到过一次运维直接改了数据库里的密钥结果网关的缓存没失效还在用旧密钥导致一批请求失败。后来我改成双密钥并行新密钥生效后旧密钥保留一段时间网关优先用新密钥失败了自动回退到旧密钥。这样轮换期间业务无感知。密钥轮换还要注意厂商侧的生效时间。有的厂商新密钥不是立即生效的有几分钟的延迟。所以轮换操作要提前做不能等到旧密钥快过期了才做。5.3 计费对账的差异排查月底对账的时候网关统计的用量和厂商账单对不上是常事。差异来源主要有几个。一是重试请求网关重试了一次厂商那边算两次调用但网关可能只记了一次。二是流式中断厂商算了 token但网关没收到 usage。三是时区差异厂商按 UTC 算网关按本地时区算跨天的请求会算到不同的月份。排查差异我一般按这个顺序先看总量差异有多大如果差异在 1% 以内基本是重试和中断导致的可以接受。如果差异超过 5%就要逐笔核对找出具体是哪些请求对不上。我建议网关记录每个请求的厂商侧 request id对账的时候用这个 id 去厂商后台查能快速定位。差异现象可能原因排查方法网关用量小于厂商重试未记录、流式中断查重试日志、查流式请求的 usage网关用量大于厂商请求被厂商拒绝但网关记了核对厂商侧的错误日志跨月差异时区不一致统一用 UTC 时间戳金额差异但 token 一致价格表未更新核对厂商最新价格5.4 厂商限流的应对策略每个厂商都有速率限制有的是按 QPS有的是按 TPM每分钟 token 数。被限流的时候厂商会返回 429 错误。应对策略有几个层次。第一层是本地限流网关自己先限不要等到厂商限了才反应。第二层是重试429 错误要重试但要带退避不能立即重试。第三层是降级重试几次还不行就切到备用模型。重试的退避策略我一般用指数退避加随机抖动比如第一次等 1 秒第二次等 2 秒第三次等 4 秒每次加 0-500 毫秒的随机抖动。抖动很重要防止多个请求同时重试造成惊群。提示厂商的限流阈值不是固定的业务高峰期可能会临时收紧。所以本地限流要留余量我一般设成厂商阈值的 80%留 20% 的缓冲。5.5 内容安全过滤的位置选择内容安全过滤放在哪里是个有争议的问题。放在网关里所有请求都过一遍安全但增加延迟。放在业务侧延迟低但每个业务都要自己实现容易漏。我的建议是网关做基础过滤业务侧做业务相关的过滤。网关过滤明显的违规内容比如明显的敏感词业务侧过滤业务特有的规则。网关过滤要注意不能误伤。我见过一个网关把杀毒软件里的杀字给拦了导致正常的业务请求失败。过滤规则要经过充分测试宁可漏过也不能误伤。另外过滤的日志要保留方便事后审计。6. 规模化之后的架构演进当你的网关从服务几个业务线变成服务几十个业务线从每天几万次调用变成几百万次调用架构就要跟着演进。这一章讲讲规模化之后会遇到的问题和应对思路。6.1 从单机到集群的平滑过渡单机网关最大的问题是单点故障和性能瓶颈。过渡到集群要注意几个点。第一是配置同步路由规则、价格表这些配置要能实时同步到所有节点我一般用配置中心来做。第二是限流的一致性多节点限流如果用本地计数总量会超要用 Redis 做集中计数。第三是会话保持流式请求如果中途切了节点连接会断所以要用一致性哈希把同一个会话固定到同一个节点。集群化之后部署和升级也要考虑。我建议用滚动升级一次升级一个节点升级期间流量打到其他节点。升级前要做健康检查确保新版本能正常处理请求再切流量。6.2 多级缓存的引入模型调用有个特点很多请求是重复的。比如同一个问题被不同用户问了很多次如果每次都调模型既浪费钱又慢。引入缓存能显著降低成本。缓存分几级。第一级是精确匹配缓存输入完全一样才命中用 Redis 存。第二级是语义缓存输入意思相近就命中需要把输入向量化后做相似度匹配。第三级是结果缓存对于确定性的任务比如翻译结果可以直接复用。语义缓存的命中率取决于相似度阈值阈值设高了命中率低设低了会返回不准确的结果。我一般从 0.95 开始试根据实际效果调整。要注意的是缓存要设置合理的过期时间模型更新后旧缓存要失效。6.3 成本优化的几个实操手段规模化之后成本会变得很敏感。除了缓存还有几个手段。模型分级简单任务用便宜的小模型复杂任务才用大模型。我实测下来把简单任务分流到小模型能省 40% 以上的成本。批量合并把多个小请求合并成一个大请求减少调用次数。输出长度控制设置 max_tokens防止模型输出过长。闲时预计算对可预测的请求提前算好结果。成本优化要建立监控每周看一次成本报表找出成本异常的模型和业务线。我见过一个业务线因为代码 bug 导致重复调用一周多花了几万块有监控的话当天就能发现。6.4 多租户隔离的实现当网关服务多个业务线甚至多个子公司时多租户隔离就很重要。隔离分几个层次。逻辑隔离每个租户有独立的密钥、独立的配额、独立的日志。物理隔离核心租户用独立的网关实例避免被其他租户影响。数据隔离租户的数据不能互相看到日志和计费数据要按租户分开存储。隔离的粒度要根据租户的重要性和合规要求来定。核心业务用物理隔离普通业务用逻辑隔离。隔离不是越细越好太细了运维成本高要找到平衡点。7. 一些个人经验和建议写到这里该讲的模块和坑基本都讲完了。最后分享几个我个人的经验不一定对但都是实际项目里验证过的。第一个经验是不要追求一步到位。我见过太多团队想做一个完美的 AI 网关结果做了半年还没上线。正确的做法是先做一个能用的最小版本让业务方先用起来然后在用的过程中迭代。业务方的反馈比你自己拍脑袋想的需求靠谱得多。第二个经验是把可观测放在第一位。功能可以慢慢加但可观测一定要一开始就做好。没有可观测出了问题你连排查的方向都没有。我现在的习惯是任何一个新模块上线前先确保它的日志和指标是完整的。第三个经验是密钥安全再怎么强调都不为过。密钥泄露的后果可能是灾难性的轻则额度被刷爆重则业务数据泄露。密钥的存储、传输、轮换每个环节都要严格把关。我建议定期做密钥安全审计检查有没有明文存储、有没有权限过大的密钥、有没有长期未轮换的密钥。第四个经验是和厂商保持沟通。厂商的接口变更、限流调整、价格变动很多时候不会主动通知。和厂商的技术支持建立联系有问题能第一时间知道。我一般会定期和主要厂商的技术对接人同步一下了解他们的路线图提前做适配准备。第五个经验是留好降级方案。模型服务不是 100% 可靠的厂商侧出故障是常事。网关要能自动降级业务方也要有兜底方案。我一般建议核心业务至少接两个厂商的模型一个主用一个备用主用挂了自动切备用。这个领域变化很快新的模型、新的厂商、新的协议层出不穷。网关的架构要能适应变化核心是把变化隔离在适配层核心逻辑保持稳定。我现在的网关已经迭代了十几个版本核心的鉴权、路由、计费逻辑基本没怎么变变的主要是适配层和路由策略。这种架构的好处是不管外面怎么变我的核心是稳的。