本地模型 和 api 混用 怎么路由

接入与开发

讲清本地模型和云端 API 混用时怎么设计路由:什么请求走本地、什么走云端、失败怎么退、怎么留痕和验证。

你本地跑了模型,又想接一两个云端 API 兜底或补能力,结果一上手就卡在几个具体问题上:同一份代码怎么判断这次该发去哪、本地超时了要不要自动换云、换过去以后输出格式对不上怎么办、出了问题从哪看日志。这篇不讲协议怎么兼容,只给一套能落地的路由分层、判定条件和排查顺序。

本地跑着模型,又想接一两个云端 API 兜底或补能力,真正卡住人的往往不是协议兼容,而是几个很具体的动作:同一份代码怎么判断这次该发去哪、本地超时了要不要自动换云、换过去之后输出格式对不上怎么办、出问题从哪条日志开始查。这篇只讲路由策略本身,协议对接、模型选型那些不展开。

下面给一套分层的做法,加上每层的判断条件和排查顺序。核心思路是:把「谁该干活」「干活的挑哪个端点」「干砸了怎么办」三件事拆开,别全塞进一段 if-else 里。这样后面调阈值、加端点,只动其中一层就行。

先把路由拆成三层,别一上来就写 if-else

第一层是分流:按任务类型决定候选池。比如隐私数据、需要离线可用的场景、批量低价值任务,优先放进本地候选;对稳定性或能力要求高的任务,进云端候选。这层判定要写成一张显式的表,放在配置或代码里一眼能看到,而不是散落在各个调用点。

任务特征优先候选原因
含敏感或不可外发内容本地数据不出机器
要求断网也能跑本地云端不可达时不能断
批量、单条价值低本地走云端的调用成本不划算
输出要严格结构化看实际情况哪边更容易过 schema 校验就去哪边
长文推理、能力要求高云端本地算力通常撑不住

第二层是选具体端点:候选池里如果有多个,就按可用性、当前排队深度、上次失败记录挑一个。本地通常只有一个服务,这层就退化成一个开关,开或关。第三层是失败后怎么办:超时、报错、返回不合格,分别对应重试、换端点、直接放弃三种动作。这三层分开写,调策略时只动一层。

路由判断该看哪几个输入

判断依据可以归成三类输入:任务属性、实时状态、预算口径。任务属性看三项——是否含敏感内容、是否要求断网可用、输出是否要严格结构化,这三项通常直接决定能不能走本地。实时状态看本地服务是否在跑、上一次调用是否超时、云端是否刚返回过限流;这些状态要缓存一小段时间,不能每次请求都去探活。

预算口径容易被忽略。本地算的是电费和排队时间,云端算的是 token 和额度,两者得换算到同一口径再比较才有意义。具体单价别凭记忆,去站内 /official-api 和 /tools/token-price-calculator 核对当时的数字,再写进你自己的配置表。

  • 任务属性三项:敏感内容、离线要求、结构化输出,任一项命中就倾向本地。
  • 实时状态三项:本地存活、上次是否超时、云端是否限流,缓存几十秒即可。
  • 预算口径:把本地耗时折算成成本,和云端单价放一起比,数据来源以站内页面为准。
  • 不适用情形:如果本地和云端能力差距明显,比如一个只能做分类、一个要做长文推理,就别做动态比较,直接按任务类型写死分工。

降级怎么退,以及退过去之后格式怎么办

本地超时不要立刻判失败。先给一个短超时,超了再重试一次,两次都不过才切云端。这样做是避免本地只是偶尔卡一下,就把请求全推给付费接口。反过来,如果连续几次超时,说明本地这一段时间状态不对,可以临时把分流表里本地的权重降下来,过一阵再恢复。

  1. 第一次调用给本地端点设一个短超时,记录耗时和结果。
  2. 超时后重试同一请求再打一次本地,还是失败才进入降级。
  3. 切云端前统一形状把提示词、系统消息、工具定义收敛到一份中间结构,再由各端点的适配层转出去。不这么做,换一次端点就要改一次业务代码。
  4. 同一套校验结构化输出用同一份 schema 校验,本地过不了云端大概率也过不了。校验失败算这一层失败,别往下传。
  5. 流式与否保持一致本地走流式、云端走非流式,前端拿到的行为会不一致。宁可两边统一,断流排查思路可以先到 /tools/speed-test 量出基线。

留痕与验证:怎么知道路由策略是对的

每次调用至少记四个字段:最终走了哪个端点、中间尝试过哪些端点、各次耗时、失败原因分类。字段够用就行,不用记全量请求体,不然日志体积和排查成本都会失控。失败原因要分类,不能只记一句「报错」,否则后面统计降级触发率时分不清是超时、限流还是格式问题。

按周看一次分布:本地命中率、降级触发率、降级后成功率。降级触发率长期偏高,通常说明本地容量不够或超时阈值设得太紧。另外准备一组固定用例跑回归,覆盖「本地正常」「本地超时切云」「两端都失败」三类路径,每次改完路由逻辑跑一遍,别只靠线上发现问题。

观察指标偏高通常意味着先查哪里
本地命中率低分流表写得太保守分流判定表
降级触发率高超时阈值紧或本地容量不足本地服务负载与超时设置
降级后成功率低云端适配层或校验有问题请求形状与 schema 校验
两端都失败占比上升上游普遍异常云端状态与本地存活探测

端点和模型都会变,价格与能力口径要去 /models 和 /price-watch 对当时的数字,别把某次看到的数值长期写在代码注释里当依据。

下一步把分流表落到配置里,再去 /tools/speed-test 量一次本地和云端各自的基线耗时,路由阈值才有依据。

常见问题

本地模型和云端 API 混用,是不是一定要写一个路由中间层?

不一定。如果只有一两个调用点、任务类型也单一,直接在调用函数里加个判断就够,中间层反而增加排查成本。真正需要中间层的情况是:调用点分散在多处、降级动作不止一种、或者你需要按周统计本地命中率,这时候统一收口才划算。

本地超时了自动切云端,会不会把成本搞失控?

会有这个风险,所以降级要带三个约束:本地重试次数上限、单次请求的降级开关、以及按时间窗口统计的降级比例上限。超过比例就先告警而不是继续切,说明是本地服务本身出了问题,该修本地而不是继续烧云端额度。

两边模型输出格式不一样,怎么保证上层代码不用改?

把业务层拿到的结果固定成一份你自己的结构,由各端点的适配层负责转换,业务代码只认这一份。结构化输出再加一层 schema 校验,校验不过就当这次调用失败处理。要点是转换和校验都放在适配层,不要漏到业务逻辑里。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。