拿到一个中转站的 Key,多数人是先复制一段示例代码跑通,然后就直接塞进项目了。跑得通不等于配得对——模型名写的是别名的全称、超时用默认的无限等待、重试对非幂等请求照重不误,这些坑平时不报错,等到账单出来或者半夜开始刷失败日志才发现。这篇给一份按顺序过一遍就能落地的接入清单,每项都给一个默认可用的做法,并说明哪些设置会推高成本,以及什么情况下这套默认值不适用。
拿到一个中转站的 Key,多数人的流程是:复制一段示例代码、跑通、直接塞进项目,然后就不管了。跑得通和配得对是两回事——模型名写成了别名的全称、超时沿用客户端默认的无限等待、重试对非幂等请求照重不误,这些坑平时不报错,等账单出来或者半夜开始刷失败日志才发现。
下面这份清单按接入顺序排,每一项都给一个默认就能用的做法,并标出哪些设置会悄悄推高成本。适合已经有 Key、准备接进真实项目的人逐项对;如果你还在挑要不要用某个站,那是另一件事,先去 /sites 看可信度再回来接。
密钥与入口:先把身份和地址钉死
- 密钥只走环境变量或密钥管理服务,不写进代码仓库、不贴进聊天工具、不打进前端包;本机开发用 .env 并加进 .gitignore,团队走统一分发,换站或有人离职时能一次轮换。
- Base URL 只写到版本段为止,末尾不要手写 /chat/completions,绝大多数客户端自己会拼路径;先在命令行用一条最小请求确认连通,再往配置里填。
- 模型名按当前可用写法填,不要凭记忆拼全称或加日期后缀;清单和口径到 /models 与 /official-api 核对,中转站实际能调哪些以它的模型列表页为准。
- 一个项目固定一套密钥一套入口,多套并存时出问题分不清是哪层引起的;要分环境就开发/预发/线上各一套,别在同一环境混用。
连通性和鉴权经常被混成一件事。区分口径很简单:401 是身份问题(Key 错了或没带上),403 多半是权限或余额,超时和连接拒绝才是网络层。分不清状态码含义时,可以到 /ai-dict/category/basics 把名词对一遍再排查。
超时与重试:默认值大多不能用
| 设置项 | 默认就该用的做法 | 什么情况下要改 |
|---|---|---|
| 连接超时 | 设一个短值,几秒内连不上就换路 | 跨区域线路差,适当放宽但别超过读取超时 |
| 读取超时 | 按最长一次生成来定,不设无限 | 流式请求按「多久没新片段」算,不是整段时长 |
| 整体超时 | 给一个上限兜底,到点就放弃 | 批处理任务可放宽,交互式要收紧 |
| 重试次数 | 个位数,带指数退避和随机抖动 | 非幂等请求不重试,直接失败上报 |
| 降级开关 | 重试耗尽后切备用模型或备用站 | 只读查询可激进,写操作要谨慎 |
流式请求最容易踩的坑,是把读取超时理解成「整段生成要多久」。实际它不是这个意思——它衡量的是两个数据片段之间的间隔。设错的结果就是:一条慢请求挂在那里,占着并发、照常计费,而你的客户端还以为在正常工作。
- 先量延迟基线用 /tools/speed-test 跑一遍你自己线路到目标站点的延迟,拿到数字再设超时,而不是凭感觉填一个。
- 分开设三类超时连接、读取、整体各一个值,写进配置而不是散在代码里;改的时候一处改全生效。
- 给重试加条件只重试超时、限流、临时 5xx;401、403、参数错误直接抛出,别浪费重试次数。
- 验证降级路径手动把主模型名改错一次,看是否真的切到备用并且日志里能看出来,别等到真出事才发现没生效。
日志与用量:让每一次调用都能复盘
日志不是越多越好。接入阶段最少记这几项就够了:时间戳、用的哪套密钥和哪个入口、请求的模型名、是否流式、耗时、成功或失败、返回的用量字段。不要记完整的 prompt 和回复——既占存储,也多一份泄露面,真需要排查再临时开。
- 用量按「请求数」和「token 数」两个维度分别累计,这两者不是一回事,混一起会算错账;口径到 /ai-dict/category/basics 的 Token 条目对齐。
- 设日预算或小时预算告警,并按调用来源分组,用量尖峰才能定位到具体功能、具体人、具体某次循环。
- 日志里同时记「期望模型」和「实际返回模型」,两者不一致就报警,这是抓偷偷降级或偷偷换档最省力的办法。
- 注意客户端的隐形消耗:自动补全、会话摘要、后台索引都可能在你不知情时多发调用,按来源分组就是为了抓这类。
哪些默认设置会悄悄推高账单
账单变贵通常不是单价问题,而是调用方式问题。下面几种情况在接入阶段最常见,而且它们全都不报错,只是安静地多花钱。判断自己有没有中招,看日志里的分布比看总额更有用。
| 现象 | 为什么会推高成本 | 接入阶段怎么防 |
|---|---|---|
| 流式请求挂住不动 | 占并发、照常计费,还可能卡住连接池 | 首字节超时单独设,超时就断开 |
| 并发设得比套餐高 | 触发限流后不断重试,失败请求也有成本 | 并发上限写进配置,重试前先看限流响应 |
| 整份文档每次原样重发 | 调用次数没变,token 翻倍 | 日志里记每次发了多少,先能看见 |
| 失败写请求被反复提交 | 成组重复调用,账单里出现重复条目 | 每个逻辑请求带客户端生成的请求 ID,便于聚合去重 |
| 实际模型和期望不一致 | 悄悄回退到更贵档位,无人察觉 | 期望与实际都记,不一致就告警 |
这些优化里,裁剪上下文、做缓存命中属于另一个话题,本文不展开。接入阶段的目标很简单:先让「每次发了多少、用了哪个模型、重试了几次」这三件事在日志里看得见。看不见的东西,你没法优化,也没法跟人交代。
异常兜底与上线前自查
兜底不要写成一团 if-else 到处散落。按严重度分三档就够清晰:可恢复的(超时、限流、临时 5xx)走重试和降级;不可恢复的(401、403、参数错误、余额不足)直接失败加告警,不重试;未知错误保留原始响应体,方便后面比对。
- 给上层留一个「降级后还能用」的最小能力,比如切到更小更快的模型先返回结果,同时打标说明这是降级输出,避免用户按正常质量解读。
- 降级输出要在界面上或返回结构里有痕迹,否则事后没人分得清哪些结果是降级的。
- 预算告警要真的能收到——很多人配了告警却没验证过通道,等于没配,上线前手动触发一次确认。
- 一次性脚本、临时压测、纯本地试验可以跳过预算告警和降级设计;但只要是有人用、会跑一整天的服务,这几项就别省。
- 过一遍七项检查表密钥是否在环境变量里、Base URL 是否只到版本段、模型名是否与当前可用列表一致、超时三项是否都设了、重试是否限幂等和次数、日志是否覆盖用量与来源、预算告警是否真的能收到。
- 核对当时的数据价格口径和模型清单会变,逐项检查前先到 /official-api 与 /models 核对当时的写法,别用记忆里的版本。
- 记录在线状态以后排查问题和比价都指着它,尤其是你同时用多个站的时候,出问题才知道从哪问起。
常见问题
接入中转站需要改很多代码吗?
通常不用。绝大多数中转站提供的是 OpenAI 或 Anthropic 兼容格式,你原来调官方的那套客户端只要改 Base URL 和密钥,模型名换成对方支持的写法即可。真正的改动量在超时、重试、日志这几块,这部分不管接谁都得自己写一遍。
为什么我的请求总是超时,但用网页或别的客户端却正常?
多半是超时参数的问题:读取超时设得太短,长回答还没生成完就断了;或者流式请求里按整段生成时长来设限。先到 /tools/speed-test 量一下你自己这条线路的首字节和整体延迟,再按分位数来定超时,不要照抄别人的常量。
怎么知道账单是被哪部分调用推高的?
按调用来源(哪个功能、哪个用户、哪次循环)和模型名分组统计 token 用量与请求数,同时记录「期望模型」和「实际返回模型」。中转站目录和当时的价格口径可以到 /sites/all 与 /price-watch 对照,先定位来源再谈优化,否则只能看到总数在涨。