LLM 网关与模型路由
典型题:公司内部多个业务都要调用大模型,如何设计一个统一的 LLM Gateway,支持模型路由、限流、日志、成本统计和降级?
面试官真正想看什么
把网关想成机场调度:便宜的小模型处理“改一句话”,复杂推理才转给大模型;遇到供应商限流时要切备用航线,但不能把不同模型的 JSON 能力和安全边界假设成一样。
- 你是否知道大模型调用不能散落在各个服务里。
- 你能否设计统一接入层,解决路由、限流、观测、成本和安全。
- 你是否理解模型路由不是简单随机分配,而是按任务和风险选择。
先问清楚
Q1:设计 LLM 网关前先问什么?
参考答案
我会先问:
- 有多少业务接入,QPS 和峰值是多少。
- 接哪些模型:商业 API、自部署模型、embedding、rerank。
- 是否需要多租户、部门预算、用户级限流。
- 是否涉及敏感数据和合规要求。
- 是否需要缓存、降级和灰度发布。
- 是否要统一 trace、成本统计和 eval。
这些决定网关是简单代理,还是企业级模型平台入口。
最小架构
核心设计
Q2:LLM Gateway 的核心模块有哪些?
参考答案
我会拆成:
| 模块 | 作用 |
|---|---|
| 认证与权限 | 判断调用方是谁,能用哪些模型和工具 |
| 模型路由 | 按任务类型、成本、延迟选择模型 |
| 限流与预算 | 控制用户、部门、应用的用量 |
| 缓存 | prompt 前缀、检索结果、热门问答 |
| 日志与 trace | 记录请求、模型、usage、latency、cost |
| 安全处理 | 脱敏、注入检测、危险输出检查 |
| 降级与重试 | 模型不可用时切换或返回降级结果 |
Q3:模型路由怎么设计?
参考答案
可以按几类策略组合:
- 任务类型:分类/抽取用小模型,复杂推理用大模型。
- 风险等级:高风险任务用更强模型和更严格 guardrails。
- 成本预算:低价值任务走低成本模型。
- 延迟要求:实时交互优先低延迟模型。
- 可用性:某模型失败时切换备用模型。
路由结果要记录下来,否则后面无法分析为什么某个请求花了很多钱或答错了。
Q4:限流和预算怎么做?
参考答案
可以分多层:
- 应用级 QPS。
- 用户级 QPS。
- 部门级月度预算。
- 单任务最大 token。
- 单任务最大成本。
- 单任务最大轮数。
超过预算时可以降级小模型、拒绝请求、排队或转人工。不要让某个 Agent 死循环把预算打穿。
Q5:网关里缓存什么?
参考答案
可以缓存:
- 稳定 prompt 前缀。
- 工具定义。
- 热门问题答案。
- 检索结果。
- embedding 结果。
但涉及用户隐私、权限和动态状态的数据要谨慎缓存。缓存必须带租户、权限和版本隔离。
Q6:如何记录成本?
参考答案
网关记录每次请求的:
- model。
- input_tokens。
- cached_tokens。
- cache_write_tokens。
- output_tokens。
- latency。
- retry 次数。
- cost。
- tenant / app / user。
成本不能只看模型调用,还要加 embedding、rerank、搜索和工具成本。
Q7:如何做模型降级?
参考答案
降级策略包括:
- 大模型不可用时切小模型。
- 复杂功能不可用时返回简化答案。
- 检索服务失败时提示稍后重试。
- 高风险任务失败时转人工。
降级不能悄悄降低安全要求。比如退款审批不能因为大模型不可用就让小模型直接判断。
Q8:如何做安全和脱敏?
参考答案
网关可以统一做:
- 输入敏感信息识别。
- 日志脱敏。
- 模型供应商权限控制。
- 输出安全检查。
- prompt injection 风险标记。
但业务权限仍应在业务系统和工具层做,网关不是唯一安全边界。
评估与指标
Q9:LLM 网关上线后看什么指标?
参考答案
- QPS。
- 成功率。
- 平均延迟和 P95 延迟。
- 平均成本和 P95 成本。
- 缓存命中率。
- 模型错误率。
- 降级率。
- 各业务成本占比。
- 安全拦截率。
Q10:这个系统最难的点是什么?
参考答案
最难的是在多业务、多模型、多租户之间平衡成本、质量、延迟和安全。网关不能只是转发层,必须能观测、能限流、能路由、能回放。
30 秒收口
我会把 LLM Gateway 设计成统一模型入口,负责认证、模型路由、限流预算、缓存、trace、成本统计和降级。
业务方不直接散落调用模型,而是通过网关统一治理,便于成本控制和问题复盘。本题常见扣分点
- 只说“封装一个 API”。
- 不讲预算和限流。
- 不记录 cached tokens 和输出 tokens。
- 不考虑多租户权限。
- 降级策略没有安全边界。
深挖追问:把网关讲成可治理的生产入口
Q11:Token 缓存到底是什么,网关如何计算一次请求的真实成本?
参考答案
Token 是模型实际处理的文本、图片等输入被编码后的单位。对文本模型,一次调用至少要区分输入 token 和输出 token;有些模型还支持提示词缓存:当多个请求共享一段足够长、完全一致且位置稳定的输入前缀时,供应商可以复用此前计算过的中间状态,命中的这部分计为 cached_input_tokens,价格通常低于普通输入 token。部分供应商还会区分写入缓存的 token 和读取缓存的 token,计价规则必须以具体模型的当期价格表为准。
因此网关不能只用“请求次数 × 单价”估算。一次请求的成本应按模型和价格版本计算:
cost = uncached_input_tokens * input_unit_price
+ cached_input_tokens * cached_input_unit_price
+ cache_write_tokens * cache_write_unit_price
+ output_tokens * output_unit_price
+ reasoning_tokens * reasoning_unit_price(若供应商单独计费)
+ tool_cost + retrieval_cost日志里既保留供应商原始 usage,也落一份内部归一化 usage:prompt_tokens、cached_tokens、completion_tokens、reasoning_tokens、price_version、currency。价格版本非常重要,不能用今天的单价回算三个月前的账单。最终把模型费用与 embedding、rerank、搜索、OCR、代码执行等外部工具费用放进同一个 request ledger,才能得到应用、租户和任务的真实成本。
替代方案何时使用
没有供应商 usage 明细时,可以在网关用对应 tokenizer 做预估,但账单结算要以供应商返回值为准,并标记 estimated=true;自部署模型没有按 token 付费,也仍应记录 token 和 GPU 秒数,用于容量归因和内部成本分摊。
常见扣分点
- 把 token 缓存误说成业务层 Redis 缓存,它们解决的问题不同。
- 只记录总 token,无法解释为什么成本变化。
- 不保存模型和价格版本,成本报表无法审计。
Q12:怎样提高提示词缓存命中率,同时不破坏正确性和隐私隔离?
参考答案
提示词缓存通常依赖“前缀完全相同且顺序一致”,所以网关需要把稳定内容放在前面,把易变内容放在后面。稳定内容包括系统提示词、工具 schema、固定格式规范和长的公开知识前缀;易变内容包括用户问题、当前时间、用户身份、动态检索片段和临时 trace。Agent 的工具定义应做版本化并保持顺序稳定,不要每次按随机顺序序列化 JSON;同类请求尽量复用统一模板,避免在前缀里插入 request id、时间戳或无关调试信息。
业务层缓存与提示词缓存要分层:前者可缓存“权限过滤后、知识库版本固定的问答结果或检索结果”,直接省掉一次调用;后者仍会调用模型,但降低重复前缀的计算成本。两者的 cache key 至少含 tenant、用户或权限范围、模型/提示词版本、知识库版本、工具版本和语言,绝不能因为两个用户提了相同问题就跨权限返回内容或共享敏感前缀。
我会观测三项指标:可缓存前缀占输入比例、缓存命中 token 比例、命中后实际成本与延迟下降。命中率低先检查模板漂移、工具 schema 频繁变化和动态信息位置,而不是盲目延长提示词。缓存只是优化,不能让已撤销权限的内容继续可见;知识库或策略版本变化时必须让相关业务缓存失效。
替代方案何时使用
强个性化、短上下文的请求不必为缓存强行重排;若供应商不提供 prompt caching,则可用前缀摘要、工具 schema 压缩、检索裁剪和结果缓存来降低 token。
常见扣分点
- 为了命中缓存,把动态用户信息放在稳定前缀里,造成隐私串租。
- 只说“把 prompt 放 Redis”,没有说明模型侧缓存机制。
- 频繁修改系统提示词和工具 schema,却期待命中率稳定。
Q13:路由决策的数据流和接口契约怎么设计?
参考答案
业务方不应把“模型名称”和供应商参数散落在代码里,而是提交一个逻辑请求,例如:
{
"capability": "chat.reasoning",
"quality_tier": "standard",
"max_latency_ms": 8000,
"max_cost_micros": 200000,
"tenant_id": "t_123",
"policy_tags": ["internal"],
"messages": ["..."],
"idempotency_key": "..."
}网关先完成认证、输入大小校验、内容分级和预算预留,再把请求交给路由器。路由器查询能力目录:每个候选模型都记录支持的模态、上下文长度、地区、可用性、单位成本、历史质量、P95 延迟、数据驻留和安全等级。它先过滤掉不满足硬约束的模型,例如数据不能出境、任务需要 JSON schema、剩余预算不足、模型不支持图片;再按质量、延迟、预估成本和当前健康度打分。决策结果连同 route_id、候选模型、过滤原因和策略版本写入 trace。
调用完成后,usage 回写预算账本,若实际费用高于预留则补扣,低于预留则释放差额。失败和降级也要写事件:不能只记录最终用了哪个模型,否则无法分析路由是否把低质量模型选得过多。
替代方案何时使用
早期可以采用静态映射,如“分类走小模型、复杂问答走大模型”;请求量和历史数据足够后,再引入基于离线 eval、延迟和预算的动态评分,避免一开始用黑盒 bandit 难以解释。
常见扣分点
- 只按模型名路由,没有能力、数据驻留和输出格式等硬约束。
- 实际扣费在调用前就完成,失败也不返还预算。
- 路由不可解释,出了质量事故无法复盘。
Q14:如何给 Agent 设置预算,防止多轮工具调用耗尽资金?
参考答案
预算要从“账户月额度”落到“这一次任务还能做什么”。我会同时维护租户、应用、用户、任务和步骤五个层级的配额。请求进入网关时先用输入长度、max output、模型价格和预计工具次数做成本预估并 reserve;Agent 每次模型调用、检索或外部工具调用都消耗任务预算。剩余额度不足以支持当前模型时,路由器可以选更便宜的模型、压缩上下文、限制输出或停止并返回“预算不足、当前已完成哪些步骤”。
预算策略要和风险绑定。例如客服总结可以从强模型降级为小模型;财务审批、法律结论或会触发外部动作的 Agent,在预算不足时只能转人工或拒绝,不能静默降低模型质量。还要给循环设置硬限制:最大模型轮数、最大工具调用数、最大累计输出 token、最大重试次数和最长 wall-clock 时间。阈值应可配置并出现在 trace 中。
对并发请求采用原子预留而非事后汇总,避免十个并发任务同时看到“余额还够”而一起超支。日/月预算接近阈值时可逐级采取告警、限速、降级和拒绝;用完后有清晰的管理员申请或下周期恢复流程。
替代方案何时使用
只有单一内部应用时可以先做应用级日限额;一旦有多租户、可配置 Agent 或付费归属,必须增加任务级预留与归因,否则成本争议无法处理。
常见扣分点
- 只有“每月 10 万元上限”,没有单任务保护。
- 超预算后继续重试或无限切模型。
- 把质量敏感任务也一律降级到小模型。
Q15:限流、排队和背压分别解决什么问题?
参考答案
限流是准入控制:限制某租户、用户、API key 或模型的请求和 token 消耗,避免单个调用方压垮全局。排队是把已经接受但暂时无法执行的异步任务持久化,并按优先级调度。背压是当下游模型、工具或账本处理不过来时,让上游减速、拒绝或返回稍后重试,防止队列无限堆积。
我会按 token 而非仅按请求数做限流,因为一个 100k token 请求和一个短分类请求的资源消耗差异巨大。实时聊天通常使用令牌桶配合短队列,超过等候阈值返回明确的 429 和 retry-after;长任务进入持久队列,按租户配额、优先级和预计成本调度。网关还要根据模型供应商的 RPM、TPM、并发和地域限制维护本地配额,避免所有业务各自碰到 429 后同步重试。
当 P95 延迟、错误率或队列等待时间上升时,路由器可以减少对异常模型的流量,优先处理高优先级请求,并拒绝低优先级批任务。这个过程必须和预算、灰度策略联动,不能把排队当成“服务已成功”。
替代方案何时使用
强实时、用户可交互的场景更适合快速失败加流式反馈;离线评测、文档批量处理可以排队并安排在供应商低峰或批处理窗口。
常见扣分点
- 只做 API 网关 QPS 限制,不考虑 TPM 和模型侧配额。
- 所有 429 同时重试,引发重试风暴。
- 长任务占满实时通道,导致聊天延迟失控。
Q16:模型失败时的 fallback 链路怎样兼顾质量与一致性?
参考答案
fallback 不是“主模型失败就随便换一个”。路由目录要先定义可替代集合:输出格式、数据处理地域、上下文长度、工具调用能力、安全级别和质量下限必须兼容。同步聊天可以采用短超时后 hedge 到同等级备用模型,但要控制并发副本,避免双倍计费;异步任务通常先重试同一模型,再切备用模型,以避免因模型差异造成风格或结构漂移。
切换模型后,网关将 fallback_reason、新旧模型、输出差异和实际成本写入 trace。对于需要严格 JSON 或工具调用的任务,先做 schema 校验;备用模型不支持该能力时应返回受控错误或降为人工处理。对于高风险结论,fallback 后可以只产草稿并要求复核;对于外部动作,任何模型降级都不能绕过权限与确认。
还需区分失败类型:网络超时、供应商 5xx、限流通常可重试;输入违规、上下文超长、schema 不满足属于确定性错误,应立即给调用方可操作的错误信息;工具已经执行但响应丢失时必须查状态,而非再次执行。
替代方案何时使用
有严格一致性要求的批量生成可以锁定单模型版本,宁可排队或稍后重试,也不即时切换;探索性问答可以更积极地使用多供应商 fallback,提高可用性。
常见扣分点
- 只按 HTTP 状态码切换,不检查能力和合规兼容性。
- 切模型后不记录,导致质量波动无从解释。
- 对非幂等工具调用直接重试。
Q17:网关如何做多租户权限和数据安全?
参考答案
认证回答“你是谁”,授权回答“你能用什么”。网关从可信身份令牌得到 tenant、应用、用户、角色和数据分级,不接受业务方在 body 里随意声称自己是高权限租户。策略引擎基于这些属性决定可调用的模型、最大上下文、是否允许外发、是否能启用日志正文、可用工具和预算上限;密钥由服务端托管,业务方拿不到供应商主密钥。
数据流中至少要有三道边界:输入进入日志前按规则脱敏或只存哈希/摘要;发给供应商前检查数据驻留、保留策略和合同约束;缓存、trace、对象存储都以 tenant 和访问策略隔离。管理员调试 trace 也必须经过审计和按需解密,不能因为“内部排障”就能看全量用户对话。对含个人信息、源代码、财务数据的请求,用户可以配置禁止用于供应商训练、缩短保留期或强制走自部署模型。
模型网关只能做横向治理,业务工具仍要二次鉴权。例如网关允许某个客服 Agent 调用 CRM,并不表示 Agent 可以读取所有客户;工具服务必须根据当前用户和任务 scope 再检查一次。
替代方案何时使用
个人本地工具可以简化为单账户密钥和本地日志;企业平台必须采用租户隔离、服务身份、审计和最小权限,不能把“内网”当作安全策略。
常见扣分点
- 只做 API key,没有用户、租户和工具权限传递。
- 日志存全量 prompt 和附件,泄露面比模型本身还大。
- 指望网关替业务系统完成所有数据授权。
Q18:怎样评估和灰度一条新的路由策略?
参考答案
路由策略上线前,先用带标注的离线任务集重放:按能力、语言、上下文长度、风险等级和租户规模分层,比较新旧策略的任务成功率、格式合规率、人工偏好、P95 延迟、单任务成本和降级率。仅看平均成本没有意义,因为便宜模型可能把高价值任务答坏;仅看平均质量也不够,因为可能把实时体验拖慢。
在线采用 shadow 和 canary。Shadow 模式让新路由接收镜像请求但不返回给用户,仅记录预测路由和结果;确认无明显退化后,按低风险应用、少量租户或请求 hash 分桶放 1% 流量。仪表盘既看系统指标,也看业务指标,例如客服一次解决率、人工转接率、结构化抽取准确率。超过阈值自动熔断到旧策略,保留 trace 供分析。
路由策略、模型目录和价格表分别版本化。一次实验只改一两个变量,否则发现成本或质量变化也无法归因。模型供应商价格变更时,先在影子环境验证成本估算,再更新预算阈值,避免把旧价格当作稳定事实。
替代方案何时使用
在流量极低且任务高风险的场景,线上 A/B 样本难以收集,可以以专家审批和离线回放为主;流量足够的低风险场景则可以逐步探索自适应路由,但仍要设质量护栏。
常见扣分点
- 把新策略直接全量切换。
- 只比较模型 benchmark,不比较真实业务任务和账单。
- 灰度没有回滚阈值和版本号。
把答案讲完整:从统一 API 到生产闭环
Q19:统一 API 应该长什么样?为什么不直接暴露供应商协议?
参考答案
我会对业务暴露面向能力的统一协议,而不是把某个供应商的字段原样透传。一个最小的同步请求可以是:
{
"capability": "chat.reasoning",
"messages": [
{"role": "system", "content": "..."},
{"role": "user", "content": "..."}
],
"constraints": {
"quality_tier": "standard",
"max_latency_ms": 8000,
"max_cost_micros": 200000,
"data_region": "cn"
},
"response_format": {"type": "json_schema", "schema": {"...": "..."}},
"stream": true,
"metadata": {"app_id": "crm-assistant"},
"idempotency_key": "task-20260902-001"
}响应统一为 request_id、route_id、model_alias、output、usage、finish_reason、degraded 和 error。流式响应使用 SSE 或 gRPC stream,事件类型至少包括 message.delta、tool_call.delta、usage、error 和 done。业务代码只依赖能力、质量档位和约束,不依赖真实供应商模型名;网关可以在后台替换供应商、调整价格或回滚路由策略。
统一协议不能假装所有模型完全等价。网关应保留 provider_extensions,但把它作为显式、受策略控制的扩展;不支持的参数要在路由前返回 unsupported_capability,不能静默丢弃 json_schema、工具调用或安全参数。协议还要定义最大输入、最大输出、取消语义、错误码、重试建议和 usage 的口径,避免每个业务自行猜测。
工程取舍
- 抽象层太薄,只统一 URL,供应商差异仍会泄漏;抽象层太厚,又会把最小公分母压得过低。优先统一稳定的业务语义,供应商特性通过版本化扩展承载。
- 同步接口适合交互请求;超过几十秒或需要大量工具调用的任务应返回
202 + task_id,由异步 API 查询状态或订阅事件,避免连接和网关线程长期占用。
常见扣分点
- 把供应商的
model字段直接暴露给所有业务,迁移成本和权限治理都会扩散。 - 只定义成功响应,不定义流式中断、取消、部分结果和错误恢复。
Q20:模型路由除了静态规则,还能怎样做?如何避免评分函数变成拍脑袋?
参考答案
我会把路由拆成“硬约束过滤 + 软目标评分 + 健康检查”三步。先过滤能力不匹配、上下文不足、禁止出境、不支持结构化输出、超过租户预算或已熔断的候选;再对剩余候选评分;最后检查该供应商当前的并发、RPM、TPM 和区域配额。
常见策略可以按成熟度逐步引入:
| 策略 | 适用场景 | 风险 |
|---|---|---|
| 规则路由 | 初期、强约束、高风险任务 | 覆盖不了复杂流量,维护规则顺序 |
| 能力路由 | 按文本/图片/工具/JSON 等能力选择 | 能力声明可能不等于真实质量 |
| 评分路由 | 质量、延迟、成本、健康度综合优化 | 权重不当会牺牲业务质量 |
| 成本路由 | 大量低风险、预算敏感任务 | 便宜模型可能增加重试和人工成本 |
| 负载路由 | 多副本、自部署或多供应商并发 | 只看 CPU 不代表模型真实可用 |
| 自适应路由 | 有充分 eval 和在线反馈的场景 | 可解释性、冷启动和反馈偏差较难 |
一个可解释的评分例子是:
score(model) = 0.45 * quality_norm
+ 0.25 * latency_norm
+ 0.20 * cost_saving_norm
+ 0.10 * health_norm其中分数只在满足硬约束后计算,所有输入先按历史分位数归一化,避免成本的绝对数值压过质量。权重来自离线任务集和业务目标,不是凭感觉写死;策略发布时带 policy_version,并能回放同一请求得出同一决策。对高风险任务可以把 quality_norm >= 0.9 设为硬门槛,而不是让成本权重把它抵消。
常见扣分点
- 用一个总分掩盖硬约束,导致不支持 JSON 或不符合数据地域的模型被选中。
- 只看下游机器 CPU;LLM 更应看排队时延、首 token 时延、TPM、并发槽位和供应商错误率。
Q21:规则路由、评分路由和负载路由发生冲突时,决策顺序是什么?
参考答案
优先级应稳定且可解释:
- 安全与合规硬约束:数据驻留、内容等级、供应商合同、租户允许列表。
- 能力硬约束:模态、上下文长度、工具调用、JSON Schema、最大输出。
- 业务约束:质量下限、最大延迟、单任务预算、是否允许降级。
- 健康与容量:熔断状态、并发、TPM/RPM、预计排队时间。
- 软评分:质量、延迟、成本、区域和历史成功率。
- 稳定性处理:同等条件下按一致性 hash 或加权随机,避免流量在多个模型间抖动。
这样“负载高”不能覆盖“该模型不允许处理财务数据”,“便宜”也不能覆盖“任务要求严格结构化输出”。路由器应返回候选模型列表和每一步过滤原因,例如 rejected: region_not_allowed、rejected: schema_unsupported、selected: score=0.84,方便面试时解释,也方便线上排查。
对于负载路由,我会使用短 TTL 的健康快照而不是每个请求都同步查询所有供应商。快照过期时采用保守策略:保留静态可用模型,但降低并发或快速失败;不能因为监控系统故障就放开全部流量。路由策略本身应无状态,目录和健康数据通过配置中心或缓存分发,保证多实例决策口径一致。
Q22:token 到底怎么算?输入、输出、缓存 token 与计费 token 有什么区别?
参考答案
Token 是特定 tokenizer 对输入内容切分后的计量单位,同一段文本在不同模型上可能不是同一个 token 数。输入 token 通常包括 system、历史消息、工具 schema、图片或多模态占位信息;输出 token 是模型生成的可见答案,推理模型还可能有供应商单独返回的 reasoning token。max_tokens 或类似参数是上限,不是实际消耗。
网关应归一化保存这些字段,但保留供应商原始 usage:
input_tokens # 普通输入 token
cached_input_tokens # 被供应商 prompt cache 命中的输入 token
cache_write_tokens # 首次写入供应商缓存的 token,是否收费依供应商而定
output_tokens # 可见输出 token
reasoning_tokens # 若供应商单独提供
estimated # usage 缺失时是否为网关估算缓存 token 不是“少传了文本”,而是供应商复用了前缀计算;请求仍可能包含完整输入。业务层结果缓存则可能直接不调用模型,二者不能混为一谈。图片、音频等多模态输入也不能简单用字符数代替 token,应使用供应商规定的图像分辨率、音频时长或 token 计算方式。
常见扣分点
- 把字符数除以四当成精确 token 数;这最多是粗略预估。
- 只统计输出,忽略长历史、工具 schema 和检索上下文造成的输入成本。
- 把
max_tokens当成实际账单消耗。
Q23:请给出单次任务成本公式,并现场算一个例子。
参考答案
我会先声明价格口径和货币,再计算,避免不同供应商的单价被混在一起:
model_cost = uncached_input_tokens * input_price / 1,000,000
+ cached_input_tokens * cached_input_price / 1,000,000
+ cache_write_tokens * cache_write_price / 1,000,000
+ output_tokens * output_price / 1,000,000
task_cost = sum(model_cost for every model call)
+ embedding_cost + rerank_cost + search_cost
+ tool_cost + compute_cost + storage_cost假设某模型普通输入为 $2/M tokens,缓存读取为 $0.2/M,首次缓存写入为 $2.5/M,输出为 $8/M。一次任务输入共 8,000 token,其中稳定前缀 6,000 token 首次写入缓存,另有 2,000 token 普通输入,输出 1,200 token,则首次调用模型成本是:
2,000 * 2 / 1,000,000
+ 6,000 * 2.5 / 1,000,000
+ 1,200 * 8 / 1,000,000
= $0.0286下一次命中这 6,000 个缓存 token,假设不再收写入费,则:
2,000 * 2 / 1,000,000
+ 6,000 * 0.2 / 1,000,000
+ 1,200 * 8 / 1,000,000
= $0.0148单次模型调用的输入相关成本下降约 73%,总成本下降约 48%。生产系统必须按 provider + model_version + price_version + effective_at 查价。若同一 Agent 调用了三次模型,必须逐次计费后求和,不能只用最后一次响应的 usage。
Q24:prompt cache 的命中条件、TTL 和失效机制怎样设计?
参考答案
供应商 prompt cache 通常要求前缀在 token 级别完全一致,且达到供应商规定的最小长度;模型、版本、请求序列和部分参数也可能必须一致。不同供应商对缓存粒度、最小前缀、自动缓存或显式 cache key、TTL 和计费方式不同,所以网关要把它当成供应商能力,而不是自己的强一致存储。
前缀建议按以下顺序组织:稳定的 system prompt、固定格式规则、版本化工具 schema、长期不变的公开知识;后面再放租户策略摘要、权限过滤后的检索内容、历史对话、当前时间、用户问题和 request id。动态内容放后面既提高命中率,也避免把用户身份和临时权限写进跨请求共享前缀。JSON、工具列表和枚举值必须确定性序列化并固定排序。
TTL 有两层:供应商缓存由供应商控制,网关只能记录预计 TTL;业务结果缓存由网关控制,可按知识库版本、策略版本和权限版本主动失效。权限撤销、知识库删除、系统提示词发布、工具 schema 变化、供应商模型切换都应让相关业务 cache key 失效。不能把 cache key 只做成 hash(question)。
我会同时监控:请求命中率、命中 token / 输入 token、可缓存前缀比例、缓存带来的美元节省、首 token 延迟、未命中原因和跨租户拒绝数。命中率高但成本没降,可能是缓存 token 价格没有正确入账;成本降了但质量变差,可能是前缀版本或权限上下文没有纳入 key。缓存不能作为正确性前提,供应商不支持或缓存失效时请求仍应正常执行。
Q25:超时、重试、幂等和熔断如何组合?
参考答案
先设置端到端 deadline,再给 DNS、连接、首 token、读取流和总耗时分配子超时。流式接口尤其要区分“连接建立超时”和“两个 token 之间长时间没有数据”;不能因为连接还没断就无限占用资源。超时响应中返回 request_id 和可重试建议,不泄漏供应商内部异常。
只有临时性错误才重试,例如连接失败、供应商 429、部分 5xx;输入过大、参数非法、内容策略拒绝、schema 永远不支持属于确定性错误。重试使用指数退避加随机抖动,并受总 deadline、最大次数和租户预算限制;供应商已给 Retry-After 时优先遵守。网关应做每供应商、模型和租户的重试预算,避免故障时重试流量超过原流量。
幂等键用于防止客户端超时后重复创建同一任务。网关可以把 tenant_id + idempotency_key 映射到任务状态和最终响应,重复请求返回同一结果或明确 in_progress。对纯模型生成,重复调用通常只增加成本;对“生成后扣款、发邮件、改订单”的 Agent,幂等必须贯穿工具调用,工具侧还要用业务幂等键查询执行状态。模型请求超时但供应商可能已经生成完成时,不能仅凭网络超时再次触发非幂等动作。
熔断器按供应商/模型/区域维度统计连续失败率、超时率和排队时延,打开后只保留探测流量,经过半开成功窗口再恢复。熔断和限流不同:限流是主动保护容量,熔断是隔离已异常下游;两者都要有恢复和告警。
Q26:流式响应怎么做,怎样处理断流、取消和 usage?
参考答案
网关收到上游模型的流后,不应等完整答案才转发。它可以先发 request.accepted,然后转发增量文本、工具调用增量和最终 usage;每个事件带序号,客户端以 request_id + sequence 去重。客户端断开时,网关取消上游请求并释放并发槽位;如果供应商不支持取消,至少停止向客户端转发并标记成本可能继续产生。
流式中断分三类:已经有可用文本但连接断开,可以返回“部分结果 + 可重试状态”;首 token 前失败,可以选择备用模型;已经输出了部分 JSON 或工具参数后切模型,不能把两家模型的片段拼接成一个答案,应重新生成并明确标记重试。对普通文本可以在前端展示部分答案,对结构化输出则应等到完整 JSON 通过校验后才提交业务动作。
usage 有时只在最终事件返回,有时只能在非流式查询中获得。网关要在 done 或供应商 usage API 到达后补写账本;在账单完成前把成本标为 provisional,不能把“未知”当成零成本。首 token 延迟、token 间隔、总时长、客户端断开率和上游取消成功率都应单独统计。
Q27:结构化输出和工具调用在多供应商之间如何统一?
参考答案
我会把结构化输出分成三层:供应商原生 JSON Schema 约束、网关侧增量/完整 JSON 解析、业务侧语义校验。原生支持的模型优先使用 schema;不支持的模型只能使用严格提示词加完整 JSON 校验,失败后有限次修复或切换到兼容模型,不能把正则替代真正的 schema 约束。
工具调用的统一对象至少包含 tool_name、版本化参数 schema、调用 id、参数、权限 scope 和确认要求。网关可以校验参数类型和大小,但工具服务必须再次鉴权、校验业务状态和幂等键。工具结果回传模型前要限制长度、标记不可信外部内容,并避免把秘密凭证放入上下文。
供应商差异要通过 adapter 隔离:消息角色、工具字段、停止原因、usage 字段、并发限制和错误码在 adapter 内转换为内部协议。不要在业务层写 if provider == ...。兼容性矩阵要能回答“这个模型是否支持图片、并行工具、严格 schema、流式 tool call、取消和 prompt cache”,路由器据此过滤。
Q28:多租户配额、预算账本和审计怎样保证准确?
参考答案
配额至少分为并发、请求数、输入/输出 TPM、日/月金额和单任务金额。令牌桶适合 QPS/TPM 限流,信号量适合并发槽位,预算账本负责金额。请求进入时根据输入 token、最大输出和候选模型价格做原子预留;完成后按供应商真实 usage 结算,多退少补。预留记录要有状态机:reserved -> settled,异常则进入 reconcile,不能靠定时脚本无条件加回余额。
账本写入至少包含租户、应用、用户、任务、步骤、模型、供应商、价格版本、原始 usage、归一化 usage、预估金额、最终金额、货币、状态和 trace id。月度报表从不可变 ledger 聚合,而不是从普通日志重新推算。供应商账单到达后按账期对账,发现 usage 差异要有差异队列和人工处理入口。
审计记录谁在何时以什么身份改变了模型白名单、价格、路由权重、预算和脱敏策略,也记录谁读取了敏感 trace。日志分级存储:指标保留聚合数据,debug trace 默认只存摘要或哈希,经过授权才短时解密原文。审计日志应追加写、限制删除,并给出保留期和访问告警。
Q29:密钥管理、隐私和日志脱敏具体怎样落地?
参考答案
供应商密钥放 KMS 或 Secret Manager,网关运行身份按供应商和区域读取最小权限的短期凭证;不写入代码、镜像、前端、普通配置或请求日志。密钥轮换采用双 key 窗口:先生成并验证新 key,再切换流量,确认旧 key 无使用后撤销。每个租户若有自己的供应商账户,密钥引用与租户绑定,业务服务只能拿到内部凭证,不能读取原始 secret。
脱敏应分输入、供应商出站、日志和缓存四个位置。可按字段或实体类型遮蔽手机号、身份证、密钥、Cookie、源码凭证和财务数据;需要回溯时保存带权限控制的 tokenized value,而不是明文。日志中默认记录长度、hash、模板版本和错误类别;若为了质量调试暂存原文,要设短 TTL、加密、访问审批和自动删除。隐私策略还要决定哪些数据允许发送到外部供应商、是否允许供应商留存或训练、数据存在哪个区域。
脱敏不能破坏业务正确性。例如金额抽取需要保留数值关系,实体识别可能需要稳定替身;因此脱敏策略要经过离线质量评测,并在 trace 中记录策略版本。模型发现的 prompt injection 只能作为风险信号,不能替代业务权限检查。
Q30:如果让你负责上线后的故障演练与可观测性,你会怎么设计?
参考答案
我会先定义 SLO,再把一次调用拆成可追踪的 span:鉴权、策略评估、token 预估、预算预留、缓存查找、路由决策、上游排队、首 token、流式传输、工具调用、usage 结算和最终响应。所有日志、指标和账本共享 trace_id、request_id、tenant_id、route_id,但 tenant 和用户字段要做访问控制。
核心指标不只看平均成功率,还包括首 token P50/P95、完整响应 P95、token 间隔、上游各错误类型、429、重试放大倍数、熔断状态、fallback 率、队列等待、并发槽位、TPM 利用率、结构化校验失败率、工具重复执行率、缓存命中 token、每租户成本和预算预留差异。告警按租户、模型、供应商、地域和能力切分,避免一个大租户掩盖其他用户的失败。
故障演练要覆盖:单供应商全 5xx、429 配额耗尽、延迟变成平时十倍、流式中途断开、价格表错误、账本不可写、缓存污染、密钥过期、区域不可用和工具执行后响应丢失。每项演练预先写清注入方式、预期告警、自动动作、人工决策、恢复步骤和数据核对。比如账本不可写时,财务敏感任务可以暂停准入或进入待结算队列,不能为了可用性无成本放行;供应商故障时只切到经过能力和合规检查的备用模型。
演练后要核对三件事:用户是否收到正确的状态、是否发生重复外部动作、成本账本是否最终与供应商账单对齐。这样可观测性才不只是大盘,而是能支持定位、止损和复盘。
连环追问:面试官继续加约束时怎么答
追问 1:如果 QPS 突然翻十倍,你先做什么?
先保护系统:按租户和能力启用 token/并发限流,暂停低优先级批任务,限制重试预算,观察队列和上游 TPM。再依据健康快照把流量分散到合规的备用模型或自部署副本;实时请求快速失败并返回 Retry-After,长任务进入有界队列。最后检查是否是某个 Agent 循环导致 token 爆炸,而不是只扩容网关。
追问 2:为什么不所有请求都用最强模型?
因为质量、延迟和成本不是同一个目标。先用能力和风险把任务分层,用离线 eval 找到达到质量下限的最便宜模型;对低风险分类、抽取、改写走小模型,复杂推理或高价值任务才走强模型。路由后持续观测业务成功率,而不是凭模型排行榜决定。
追问 3:prompt cache 命中率 80%,账单却没降,怎么看?
先确认 80% 是请求命中还是 token 命中,检查 cached token 的单价是否正确入账,是否同时产生 cache write 费,是否因为输出 token、重试或工具成本上升抵消了节省。再核对供应商 usage 和内部账本,确认没有把估算值当真实值。若账单无误,说明命中前缀占比可能很小,应该看“缓存节省金额 / 总任务成本”,不能只看命中率。
追问 4:客户端超时后重试,模型其实已经生成了答案,怎么办?
使用 tenant_id + idempotency_key 查询任务状态;若响应已落库,直接返回同一结果。若状态未知,先向供应商或内部执行记录查询,不能立即重复外部工具动作。纯文本生成可以在明确安全的情况下重新生成,但要把重复成本记到原任务,并向调用方返回最终一致的状态。
追问 5:备用模型不支持严格 JSON,怎么降级?
不能把它当作等价 fallback。若业务需要机器消费,就只选择支持 schema 的备用模型;否则返回受控错误、排队等待或转人工。若业务允许草稿,可以返回标记为 draft 的文本,但不得自动触发下游动作,且保留 schema 校验失败原因。
追问 6:网关是否应该保存完整 prompt 和答案?
默认不应该。生产上按租户策略、数据分级和用途分层保存:指标和 usage 长期保留,trace 保存摘要,原文仅在授权调试时短期加密保存。必须能解释成本和故障,但这不等于拥有永久读取所有对话的权限。业务需要回放时可使用经过脱敏、采样和访问审计的数据集。
追问 7:模型质量怎么进入路由,而不是只看延迟和价格?
建立按能力分层的真实任务集,记录格式合规、事实性、工具成功率、人工偏好和业务结果。离线得到模型质量先验,线上通过抽样评测、用户反馈和人工复核更新;质量低于硬阈值直接剔除,高于阈值后再与成本、延迟、健康度做软评分。反馈有延迟和偏差,所以策略更新要版本化、限幅并支持回滚。
追问 8:网关和业务服务的边界在哪里?
网关负责通用治理:身份、模型能力、路由、限流、供应商适配、usage、成本、通用安全和可观测性。业务服务负责业务语义、领域权限、工具实际授权、结果落库和最终动作确认。网关可以阻止明显违规请求,但不能知道“这个客户是否有退款资格”;这种判断必须回到业务系统。
5 分钟系统设计作答模板
我先确认规模、SLO、数据地域、能力类型和多租户预算。
接口上提供面向 capability 的统一 API,隐藏供应商模型名,统一流式、错误、usage 和幂等语义。
请求进入后依次做认证授权、输入校验、预算预留和硬约束过滤,再按质量、延迟、成本、健康度评分选模型。
供应商通过 adapter 隔离差异;调用链配置 deadline、指数退避、重试预算、熔断和兼容的 fallback。
成本按输入、输出、cached token、reasoning token 和所有工具调用逐项结算,价格版本化并写不可变账本。
稳定 prompt 前缀放前、动态内容放后,业务结果缓存和供应商 prompt cache 分开,按租户和版本隔离并监控 token 命中收益。
流式响应支持序号、取消和部分结果;结构化输出必须校验,备用模型不兼容时不自动触发外部动作。
最后用 trace、usage、成本、质量和业务 SLO 做观测,用 shadow/canary 灰度,通过供应商故障、429、账本故障和重复工具调用演练验证恢复。新增内容对应的工程取舍
- 统一抽象 vs. 供应商特性:稳定语义进入公共协议,差异留在 adapter 和受控扩展中。
- 成本 vs. 质量:硬质量门槛优先,门槛之上才优化价格;高风险任务不以降级换取可用率。
- 可用性 vs. 一致性:普通问答可 fallback,结构化和外部动作要先保证能力兼容与幂等。
- 可观测性 vs. 隐私:长期保存聚合指标和账本,原文按需、短期、加密、审计。
- 实时性 vs. 资源利用率:实时请求快速失败或短队列,批任务异步排队,避免互相争抢容量。
至此,本题的重点不是“能调用多少模型”,而是能否把每次调用变成可解释、可计费、可恢复、可审计的生产请求。