GPT-Load 自用使用的探讨
一个高性能、企业级的 AI 接口透明代理服务,专门为需要集成多种 AI 服务的企业和开发者设计。采用 Go 语言开发,具备智能密钥管理、负载均衡和完善的监控功能,专为高并发生产环境而设计
我自己是搭建了这个用来集中管理我的一些ai提供商的配置信息,在使用过程中有些心得和想法,想跟大家分享一下。
一、GPT-Load 的多协议支持
完全保留原生 API 格式,支持 OpenAI、Google Gemini 和 Anthropic Claude 等多种格式。就意味着常见的llm提供商基本上都可以直接接入。我是配置了deepseek、阿里云和openrouter的api密钥,偶尔会接入一下公益站的key,真实使用下来,还是非常方便的。
二、GPT-Load 的多 key 轮询逻辑
在 GPT-Load 中,「多 key 轮询」围绕 分组(Group)+ key 池 的抽象实现:
- 每个 Group 对应一个渠道(如 OpenAI 兼容服务、DeepSeek-OpenAI 入口、Claude/Gemini 渠道等)
- Group 下挂一组 API Key,GPT-Load 在池中轮询使用,同时记录每个 key 的请求次数、失败次数、最后使用时间等
- 智能 key 管理依赖以下动态配置:
max_retries:一次请求最多换几把 key 重试blacklist_threshold:连续失败多少次会被拉黑- 定时后台校验任务:定期验证失效 key 是否恢复可用
整体策略:每条请求从当前「健康」key 池中选取一把;若请求失败且符合重试策略,则换 key 重试;当某 key 失败次数达阈值则临时剔除,后续由后台任务决定何时恢复。
设计目标:负载均衡 + 容灾——在 key 数量多、质量参差不齐、容易被限流/封禁的前提下,确保整体服务尽量可用。
三、大模型提供商的上下文缓存与多账号/多 key 的关系
核心问题
大模型厂商(特别是 DeepSeek)有 prompt cache 命中价 vs 未命中价 的差异计费。网关层多 key 轮询是否会严重降低缓存命中率,从而大幅增加成本?
DeepSeek 缓存机制
- 缓存作用域是账号级,而非 key 级:同一账号下的多把 key 共享同一缓存池;不同账号之间缓存互相不可见
- 缓存命中条件是「前缀完全一致」:请求的前缀 token 序列(系统 + 历史 + 前半段 prompt)必须与已有缓存完全一致才算命中
- 返回字段:
usage中会拆分prompt_cache_hit_tokens与prompt_cache_miss_tokens,分别按不同单价计费
两种场景的影响
场景一:同一账号下的多 key 轮询
对缓存影响不大——缓存作用域是账号而非 key,命中率取决于 prompt 复用情况,与 key 数量无关。
场景二:多用户 BYOK,不同账号的 key 混在同一轮询池
- A 用户的请求走 A 的账号,B 用户走 B 的账号,即使问题内容一模一样,缓存也不共享
- 网关层把各家 key 集中成一个池并随机轮询,从 DeepSeek 视角看,同样的问题在多个账号间分散出现,每个账号偶尔才看到一两次类似前缀,难以形成高命中率
- 经济影响:整体「有效单价」从大量命中的 ¥0.02 推向大量未命中的 ¥1(尤其业务问题高度重复时)
结论:在「多用户、多账号」前提下,跨账号轮询 = 主动打散缓存池,会抬高成本。跨用户之间缓存仍不共享。所以,使用gptload并不能解决高命中率缓存来降低成本的目的。
四、现有网关能否「拯救」缓存命中率?
当前常见的 AI 聚合网关(NewAPI / Sub2API / CPA 等)围绕以下目标设计:
- 多上游聚合
- 多 key 池轮询
- 速率限制与熔断
- 权重策略与优先级
- 自动禁用失效渠道
它们普遍 没有围绕「账号级缓存计费经济学」做设计,也无法突破供应商对缓存作用域的硬性隔离。
若把不同用户的 DeepSeek key 混在同一池中,这些网关的本质行为都是「频繁跨账号轮询」,只会把缓存利用率越摊越碎。
五、GPT-Load 的「普通分组」与「聚合分组」
普通分组(Standard Group)
代表「一类上游渠道 + 一组 key 池」,包含:
channel_type(OpenAI / Gemini / Anthropic 等)- 多个 upstream 地址(同一渠道的不同入口,如多地域/ISP/机房)
- key 池及其轮询、黑名单、失败统计
- Group 级的
model_redirect_rules、头部规则、请求超时等
model_redirect_rules这个模型重定向的配置信息很重要,常规来说是可以不用关心的,但是有些场景是非常有价值的,比如阿里云提供的模型服务,写的模型ID是GLM-5.1,腾讯云提供的模型ID是glm-5.1,这个时候如果你不想频繁修改自己的模型id,就可以使用这个配置项,把用户请求的model_id全部都统一定义成glm-5.1,然后在阿里云的这个分组中,把glm-5.1映射成阿里的GLM-5.1,这样你就可以实现不改代码的情况下,切换不同厂商的模型服务。
聚合分组(Aggregate Group)
自身不存 key,挂多个普通分组为子分组并设置权重:
- 内部使用平滑加权轮询算法按权重分流
- 若某子 Group 当前「无可用 key」则自动跳过
有个问题需要说明一下:如果你挂到聚合分组下的普通分组中,普通分组所提供的模型数量不一致,比如A分组提供了4个模型,B分组提供了2个模型,在使用过程中如果模型id是A中的,但是因为负载均衡的原因使用了B分组作为提供商,就直接报模型不存在了。这个问题有个兜底的解决方案,就是如果你要A分组和B分组计划聚合起来的话,在A和B分组中使用同样数量的模型重定向设置,只不过B分组中原本没有的2个模型要被重定向成自己有的模型,作为兜底。这样使用聚合分组的时候就不会报模型不存在的错误的。
典型用法
- 多 key 池负载均衡:不同部门/各用一个普通 Group,再用聚合 Group
coding-aggregate按权重统一出口 - 多渠道容灾:DeepSeek 官方 + 自建代理 + 兼容服务,权重 90/10/0,出问题随时调整
- 灰度/成本优化:新接入更便宜渠道时初始只给 5% 流量(950/50),验证后逐步提高
六、统一多家 Coding Plan 的模型命名
问题本质
A 家 Coding Plan 提供 3 个模型,B 家提供 5 个模型,模型 id 写法和大小写风格不统一。需要统一管理使用。
关键不是「多 key」,而是 「多厂商模型命名不统一,需要对上游屏蔽差异」。
推荐方案
第一步:在 GPT-Load 中为每个 Coding Plan 建普通分组
coding-a:接 A 家 base_url + A 的 key 池coding-b:接 B 家 base_url + B 的 key 池- 各 Group 内用
model_redirect_rules将统一模型名映射到实际 id:
| 统一名 | coding-a 实际 id | coding-b 实际 id |
|---|---|---|
glm-5.1 | glm-5.1 | GLM-5.1 |
kimi2.5 | Kimi-K2.5 | kimi-k2.5 |
上游业务永远只用 glm-5.1 / kimi2.5 这套逻辑名,底层真实 id 封装在各 Group 的重定向规则中。
第二步:建聚合分组做多 Coding Plan 粘合
coding-aggregate下挂子组:coding-a,weight = 700(70% 流量)coding-b,weight = 300(30% 流量)
- 请求
model: "glm-5.1"→coding-aggregate→ 按权重选 A/B → 对应 Group 的model_redirect_rules改名 → 该 Group 的 key 池轮询调用
整条链路的视角
| 视角 | 看到的 |
|---|---|
| 业务/客户端 | 一套统一的业务模型名(如 glm-5.1)和一个统一入口,底层几家 Coding Plan 完全透明 |
| GPT-Load | 每厂商/计划一个普通 Group 管理真实模型名和 key 池;聚合 Group 管理多家间的流量调度 |
总结:模型名对齐、厂商差异屏蔽、多家 Coding Plan 统一接入、多 key 池轮询、可用性与运维边界——全部集中在 GPT-Load 的 Group / 聚合 Group /
model_redirect_rules中解决。
