ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

大模型应用中的智能路由:成本、延迟与质量的动态平衡

大模型应用中的智能路由:成本、延迟与质量的动态平衡 大模型应用做久了你会发现一个特别尴尬的现象明明接入的是同一个顶配模型同一个API网关线上效果却总是忽好忽坏——有些请求被大模型杀鸡用牛刀账单高得吓人有些请求却被小模型草率处理用户一眼看出答案在敷衍。问题往往不在模型本身而在于缺少一层“智能路由”。我先说清楚这里讨论的是大模型应用层的请求调度不是网络层的IP路由。所谓智能路由简单讲就是在大模型前面加一个“调度大脑”让每个请求找到最合适的模型、最合适的上下文深度、最合适的处理链路。这篇文章我会从问题出发讲清楚路由决策的依据、网关层的落地实现、数据校准方式以及我实际踩过的几个坑适合正在做大模型应用集成、本地部署、移动端接入的同学参考。1. 大模型应用的真实困境同一条链路同时杀死成本和体验1.1 全量切大模型账单先撑不住我们团队早期做AI问答助手的时候方案非常简单粗暴所有用户请求统一打到云端一个70B级别的旗舰大模型上。效果确实稳什么问题都能接住技术评审会上没人挑得出毛病。但到了月底一看账单整个人是麻的。对话类应用的平均请求量比我预想的大得多尤其移动端用户经常在短时间内连续追问上下文窗口又长token消耗几乎是翻着倍涨一个月光模型调用费就烧掉了小几万。这个数字看上去还能接受但业务一旦放量单位成本就变得极其敏感。假设一次普通问答平均消耗800个token100万次请求就是8亿token按市场价算大规模商用场景单月成本直逼六位数。而真正需要这种旗舰模型深度推理的请求占比其实不到两成。剩下八成的问题比如“你们的退货政策是什么”“帮我总结一下这段话”“这道题选A还是B”用一个小参数模型完全能接住甚至更快。1.2 全量切小模型质量洼地处处漏风被账单教育之后我们的第一反应是降级全部切到7B级别的开源模型用vLLM在内部GPU服务器上部署成本确实断崖式下跌首token延迟也从900ms降到了200ms左右。但新的问题紧随而来——小模型不是万能的碰到多步推理、复杂代码生成、长文档理解它就开始一本正经地胡说八道。有一次用户问了一个涉及多个条件判断的税务计算问题7B模型给出了一个逻辑上完全自洽但前提全错的答案。用户拿着这个答案去办事回来投诉说我们误导人。那一刻我意识到模型选择不是“选个最好的”或“选个最便宜的”而是要在合适的时候用合适的模型。一刀切的做法本质上是在赌用户的请求复杂度分布赌输了就要付出产品口碑和客诉成本的代价。1.3 智能路由的本质把“调用模型”变成“调度模型”后来我们开始系统性地研究路由方案才发现业界已经有比较成熟的做法——根据请求特征动态分派模型。核心思路就一句话先判断再生成。请求进入系统后路由层先做“体检”识别出任务类型、复杂度、需要的上下文深度、可接受的延迟上限然后决定交给哪个后端模型去处理。我把这种调度拆成三个层面来理解模型路由Model Routing决定请求给7B、14B、70B还是闭源旗舰模型。比如简单问答走7B代码生成走70B涉及多工具调用的复杂任务走旗舰模型。上下文路由Context Routing决定给模型喂多少信息。有些请求只需要最近三条历史消息有些请求却要把整个知识库的检索结果都塞进去。上下文预算分配不合理再强的模型也白搭。链路路由Pipeline Routing决定要不要走重链路。有的请求直接生成答案就够有的请求需要先规划、再检索、再生成甚至要调用外部工具。三层路由合在一起才构成完整的智能路由体系。而整个体系的收益模型其实是一个三角平衡成本、延迟、质量。全量大模型保证了质量但牺牲了成本和延迟全量小模型保证了成本和延迟但牺牲了质量智能路由就是尽可能在这三个维度之间找到动态最优解。2. 路由决策看什么任务类型、上下文预算与端云边界2.1 任务类型是第一个路由键路由决策的第一步永远是识别“用户到底想干什么”。我在工程上习惯先构造一个粗粒度的任务分类器不需要很复杂几个典型类别就够用任务类别典型请求推荐模型档位原因事实问答你们公司地址在哪7B或本地GGUF检索命中后直接抽取低延迟完成内容总结帮我总结这份周报7B~14B对指令跟随要求中等代码生成写一个Python爬虫70B或旗舰模型需要强逻辑与多轮修正能力多步推理分析这个方案的风险点70B或旗舰模型需要链式思维小模型容易断创意写作帮我写一段宣传文案14B~70B对风格控制要求较高闲聊陪伴今天心情不好7B不需要高精度响应快更重要实际工程中这个分类可以通过三选一的方式实现关键词规则、微调的小分类模型、或者让路由模型打分。我建议从第一条开始因为规则的方法最快、最透明、最容易调试。比如请求里出现“怎么实现”“请写一段代码”直接归类为代码生成出现“帮我总结”“概括一下”归类为内容总结。规则覆盖不到的再落到分类模型或打分模型上。2.2 上下文预算决定要不要走“重链路”很多团队做路由只看模型规模忽略了上下文管理这是个很大的误区。同样一个“帮我分析一下”的请求如果只带一条用户消息14B模型就能干得很漂亮如果带了20轮对话加上3份文档内容上下文超过8000 token模型的选择逻辑就完全不同——此时多模态理解、长上下文压缩能力比参数规模更重要。所以我在路由层单独设计了一个“上下文预算评估器”它看三件事当前会话消息长度超过一定阈值说明这是一个深度对话场景要按长上下文模型的标准路由。外部检索内容量如果系统决定注入RAG检索结果路由必须知道这些内容有多长、结构是否复杂避免把3万字的检索内容硬塞给一个上下文窗口只有8K的小模型。回答期望粒度用户问“简单说结论”还是“按一二三四详细拆解”对生成质量的要求完全不同。这个可以通过提示词里直接声明也可以从历史行为里学。决策逻辑可以做成很直白的伪代码def route_with_context(request): task_type classify_task(request.text) context_len estimate_context_tokens(request) if task_type codegen: return ROUTE_LARGE_MODEL if context_len 8000: # 长上下文优先保证窗口充足避免截断 return ROUTE_LONG_CONTEXT_MODEL if task_type in (faq, chat): return ROUTE_SMALL_LOCAL_MODEL # 其他情况走默认的规则路由 return router_model.score(request)这个预算评估器不需要真的是一个大模型一个统计模型加几条阈值规则就够了。关键是让路由决策具备“上下文感知”能力而不是只看消息第一句。2.3 端云边界GGUF本地模型与云端大模型的互补结合本地部署的热潮我觉得智能路由还有一个特别落地的场景——端云协同。移动端APP可以通过llama.cpp等框架加载量化后的GGUF格式小模型比如7B Q4量化版本在手机本地跑推理。好处是零网络延迟、零调用费用、数据不出设备坏处是能力天花板低。我做过一个实际方案Android端先加载一个GGUF小模型处理轻量请求比如天气查询、简单计算、常用知识问答。当本地模型对某个请求计算出的置信度低于阈值时客户端发起请求到云端云端再接上vLLM部署的中型模型或闭源旗舰模型。整套流程在路由层体现为一个“端云分派器”它接收的信息不止是文本本身还包括端侧模型的特征def route_device_or_cloud(request, device_info): if device_info[local_model_loaded]: score device_info[local_confidence] if score 0.85 and not request.requires_reasoning: # 本地直接出结果不涉及网络请求 return ROUTE_LOCAL_GGUF if score 0.6: # 置信度太低立即上云 return ROUTE_CLOUD_VLLM # 中间地带可以放一个异步上云复核 return ROUTE_CLOUD_AFTER_LOCAL_FALLBACK return ROUTE_CLOUD_VLLM这种路由设计有一个隐藏收益把大部分请求从云端卸载之后云端GPU压力骤减那么高峰期的旗舰模型配额可以用来处理真正复杂的请求。移动端用户感知最明显的变化是以前一句“查一下今天天气”要转圈1.5秒现在本地模型200毫秒直接给答案。3. 网关层的智能路由多后端接入、流式转发与降级策略3.1 路由层应该放在调用链的哪个位置很多人觉得路由逻辑写在业务代码里就行每个接口单独判断一下调哪个模型。这种方式在一两个接口时没问题一旦接口数量多起来路由规则会散落得到处都是改一条策略可能要动十几个地方。我的建议是把路由做成一个独立的网关服务放在业务后端和模型后端之间。业务后端不需要关心最终由哪个模型解答它只负责把请求发给网关网关根据预设策略路由到不同的模型服务提供商再把结果流式回传。这样做的好处有三个策略集中管理所有路由规则在一个服务里维护发布时只需重启网关不用改业务代码。后端可灰度切换不同模型服务可以按百分比切流量比如先让10%的请求走新接入的模型观测质量稳定后再放开。故障隔离某个模型服务挂了网关可以自动把流量切到其他后端业务层完全无感知。3.2 路由即服务一份最小可运行的Python路由网关我画一下我们生产环境里网关的最小结构这里展示核心逻辑非完整代码。网关接收请求后用H2章节里说的流程计算路由决策然后调用目标后端的接口。关键点是目标后端的处理必须支持SSE流式输出网关只做透传不要在中间缓冲攒数据。# gateway.py 简化示例 from fastapi import FastAPI, Request from fastapi.responses import StreamingResponse app FastAPI() BACKENDS { local_7b: {url: http://localhost:8001/v1/completions}, cloud_70b: {url: https://llm-api.example.com/v1/completions}, flagship: {url: https://flagship.example.com/v1/chat}, } def decide_backend(req): # ... 结合任务分类、上下文预算、端云信息 ... if req[task] faq: return local_7b if req[context_tokens] 8000: return cloud_70b return flagship app.post(/route) async def route_chat(request: Request): payload await request.json() backend decide_backend(payload) target_url BACKENDS[backend][url] async def sse_stream(): # 这里通过 httpx 或自定义 SSE 客户端向后端发起请求 async for chunk in call_backend_sse(target_url, payload): yield chunk return StreamingResponse(sse_stream(), media_typetext/event-stream)这里有几个工程细节值得展开说。第一路由决策的耗时必须在毫秒级不能为了做判断先调用一次大模型那还不如不做路由。规则和统计模型在这个场景下比“用大模型路由”更实用。第二网关必须记录每个请求的路由决策结果包括分流到哪个模型、决策依据是什么、后端响应时长是多少。这些日志是后续校准策略的唯一数据来源后面第4章还会细讲。3.3 SSE流式转发与AbortController协同的细节智能路由网关一旦介入流式输出的复杂度会上升一个量级。最典型的问题是“用户点击停止生成”时前端会把请求中断此时网关必须同时断开与后端模型服务的连接否则流还会在网关上继续跑白白消耗模型资源计费时长。前端侧如果是浏览器环境一般用AbortController来控制fetch的取消const controller new AbortController(); const response await fetch(/route, { method: POST, body: JSON.stringify({ text: inputText }), signal: controller.signal, }); // 用户点击停止按钮 stopBtn.onclick () controller.abort();网关侧收到客户端的连接中断后要在上下文里传递取消信号主动关闭上游连接。我见过团队把这一步漏掉结果用户每取消一次网关和模型后端之间的连接还会继续把整段内容生成完白烧几万token。所以网关服务里每一个代理出去的请求都要绑定一个asyncio.Task客户端断开时立刻取消这个task再关闭上游连接。具体实现时可以给每个请求加一个影子ID前端在EventSource或fetch里把这个ID传过来网关把它映射到上游请求句柄上。取消时前端发一个/cancel?idxxx请求网关同步取消对应的上游SSE流。Web原生SSE不支持自定义取消这也是为什么很多生产项目自定义SSE协议而不是直接用EventSource的原因之一。3.4 超时熔断与优雅降级接入多个模型后端之后会面临一个很现实的问题不同后端的稳定性完全不一样。开源自部署的7B模型只要GPU没炸延迟相对稳定云端API却可能因为限流或区域网络波动偶尔出现几十秒不返回首token的情况。网关要有三层超时策略而不是统一设一个固定值。客户端等待首token的超时时间应该比网关内部的长否则用户那边已经报错了网关还在傻等上游。我这边常用的配置逻辑如下客户端超时30秒主要兜底用户网络问题。网关到后端首token超时15秒超过则切换备胎后端。单条流式消息的最大空闲时间3秒超过说明流已经断了触发自动重连或降级。降级不是简单换个模型重复请求一遍要考虑累积成本。比如一个请求先派给了本地小模型生成到一半发现质量明显不对网关可以快速中断转投云端大模型重新生成。这种“小模型预检、大模型兜底”的模式在客服场景特别好用本地模型先秒回一个初步答案如果答案置信度低用户会看到一个智能化的提示“正在为您切换高精度引擎”体验上完全说得通。4. 用数据校准路由质量评估、成本核算与A/B验证4.1 立好评估集先有标尺再谈路由路由策略上线之前我最担心的事情是“拍脑袋定阈值”。比如我说“低于0.6置信度就上云”那这个0.6是怎么来的不能拍脑袋。我们的做法是先建立一个小型评估集把历史请求按任务类型、上下文长度分布抽样差不多500条左右每一条都人为标注好“标准答案”。然后让不同的路由策略在这500条数据上跑一遍统计每条请求用了哪个模型、花了多少token、生成结果和标准答案的接近程度如何。这里要注意不同模型对同一请求的答案质量很难自动打分所以早期我们是让三个人分别打取平均分。后期引入了“另一个大模型当裁判”做评估效果也不错但要注意裁判模型的偏好偏差。有了评估集之后路由策略就不是玄学了。比如我们调整“小模型置信度阈值”时可以很快看到一组数据阈值0.7时小模型承担了63%的流量整体质量评分4.2阈值0.9时小模型只承担38%的流量整体质量评分提到4.6。根据业务对质量和成本的不同容忍度选择就变得很清晰。4.2 成本核算模型不看单次调用要看一个月智能路由省钱的核心点在于“高价值请求才走贵模型”。但很多团队算账时错在只看单次调用比如“7B模型一次调用省3分钱”觉得没什么了不起却没有算总量。我提供一个比较简单的估算模型。假设日活1万平均每人每天20次对话请求每条请求的平均输入输出token加起来800那一个月总token消耗大约48亿。用旗舰模型假设百万token价格大概几十到一百元级别一个月就是好几万甚至上十万。如果智能路由能把60%的流量分给自部署的7B模型这部分token基本只花电费和维护费云端只承担剩下40%的旗舰调用月成本可能直接降到原来的三成到五成。但这里有个反向坑本地部署的GPU成本还没算进去。一台能稳定跑7B模型并发的GPU服务器月租加运维摊下来也是一笔钱。所以路由策略不一定只把请求分给自部署模型就“省钱”还要对比云端便宜档位API。路由决策本质是一个收益函数每次转发都要按实时成本做归一化判断简单的伪代码逻辑是def cost_aware_route(req): local_cost_estimate estimate_gpu_cost_per_token() electricity cloud_small_cost cloud_small_price_per_million_tokens cloud_large_cost cloud_large_price_per_million_tokens # 根据模型预计算分数和单次成本 best_value argmin( local_7b: (quality_loss, local_cost_estimate), cloud_small: (quality_loss, cloud_small_cost), cloud_large: (0, cloud_large_cost) )在实际系统里我不会对每次请求都做复杂的成本计算而是每隔几分钟同步一次各后端的单位价格数据路由决策时直接查表。只要保证“决策开销”远小于“省下的成本”这个路由就是划算的。4.3 线上验证方式影子路由与渐进切流评估集验证完不代表策略可以全量上线。因为评估集是离线构造的真实的用户请求分布一定会有出入。我推荐两种线上验证方式胆子小的时候用影子路由胆子大了用渐进切流。影子路由指的是请求真实流量仍然正常发给原来的模型但同时在路由层“模拟”跑一遍新策略计算“如果这个请求按新策略走会分给谁会产生多少成本”。影子路由不改变线上行为只负责记录。连续跑一周后把影子日志和真实日志对比能看出新策略的流量分布、质量变化、成本变化。这套方式的优点是零风险缺点是样本代表性可能不够毕竟真实用户不会受影子路由影响。渐进切流则是把新策略的生效比例从5%、20%、50%、100%逐步上调。每一步都要盯两个核心指标用户满意度比如点赞点踩率、平均对话轮数和业务指标比如转化率、客诉量。切流的每一步都留至少24小时观察期因为很多质量问题要隔天才能从用户反馈中浮现出来。4.4 路由策略本身也要“微调”智能路由上线以后不是一劳永逸的。用户的问题分布会随着产品迭代、季节活动、新功能上线而变化。比如我们上线了一个“法律条文检索”功能后需要走长上下文路由的请求占比明显变多原来在规则里写的8K上下文阈值就显得不合理。这个场景下我对路由策略的调优走的是类似“微调”的节奏只不过微调的对象不是大模型权重而是策略参数和规则库每周拉取路由日志分析各任务类型占比、分流模型占比、平均成本、超时率。对每个超出预期的指标定位到具体路由决策点和特征维度。调整阈值或增加规则先在评估集上回归再灰度发布。如果规则路由已经没法精确表达业务逻辑才考虑用一个小模型来做路由打分。小模型的输入是请求文本加上一些上下文统计特征输出是各候选模型的推荐分。这类模型不需要特别大的参数量7B级别在CPU上也能跑得动甚至可以量化后放在和业务服务同一台机器上。业界的一些开源路由项目比如RouteLLM走的也是类似路线核心思路是训练一个轻量的router模型结合胜率或成本偏好做决策。我们在项目中也参考了这个思路但前期没有直接上模型因为规则在大部分场景已经足够模型路由是用来兜住规则照顾不到的边界情况的。5. 上线之后才会遇到的坑路由误判、流式中断与超时叠加5.1 路由误判比模型答错更隐蔽路由方案落地后最常见的线上问题是“路由误判”。这里不是说模型答错而是请求被分到了一个错误的后端导致模型完全不理解用户意图。举例来说用户问“这段代码为什么报错”分类器把它识别成“报错信息分析”结果路由到了一个专门优化文案创意的模型模型给出的回答完全围绕“如何美化错误提示信息”没有一句对症的。这种误判对体验的破坏力比模型直接答错更隐蔽因为表面看回答是流畅的、有条理的但完全没解决问题。我排查这类问题的方法是给网关加上“路由可解释性”日志——每一次路由决策除了记录最终结果还要记录参与决策的关键特征值比如分类标签、置信度、上下文token数量、命中哪条规则。用户在反馈中心点“答案不满意”时我们可以一键关联到这次请求的路由日志快速判断是分类错了还是模型本身能力不足。没有这层日志排查路由误判只能靠瞎猜。5.2 决策必须抢在第一个token之前完成很多朋友可能没有意识到路由决策一旦晚了哪怕只晚半秒钟就会造成体验上的“风格撕裂”。因为SSE流一旦开始往客户端推数据用户就已经在阅读第一个token了此时路由器如果决定切换后端用户会明显感觉到前半段和后半段的口径、措辞、质量变了。我给网关定了一条铁律路由决策必须在连接建立后200毫秒内做出并且决策完成前不允许向后端发送任何生成请求。如果某类请求确实需要更长时间分析宁可先返回一个“正在分析”的占位提示也不要贸然开流。为了做到这一点任务分类器不能完全依赖规则还要有一个极快的轻量分类模型推理时间控制在10毫秒以内。这类模型不需要很大几百兆参数的量化版本就足够。前端配合上我会建议在SSE协议里加一个元信息事件首个事件专门返回路由决策结果类似{event: routing, data: {backend: cloud_70b, reason: task_typecodegen, confidence0.93}}前端拿到这个事件后可以选择展示一个“正在匹配高精度引擎”的过渡状态。既解决了决策延迟的感知问题也让用户对系统能力更有信心。5.3 超时时间不要叠加要分层多跳链路里超时配置是重灾区。一个请求从客户端到网关到模型后端每一跳都有超时时间如果每一跳都是20秒那整体最坏情况不是20秒而是可能叠加成60秒——客户端已经把请求放弃了网关上层的连接还悬着底层模型还在生成最后生成结果发回一个没人接收的socket。我们的处理原则是“内层超时要小于外层超时”。客户端有一个总超时网关内部每一跳的超时都比总超时小。以一个30秒的客户端总超时为例网关到后端的首token超时设15秒后端收到请求后如果15秒没返回网关立刻熔断切到备胎备胎请求的超时再减5秒。这样最坏情况下用户等待不超过30秒并且每一次等待都有意义。5.4 缓存与路由的冲突不能只缓存“答案”做了路由之后一定会有同学想顺手做个结果缓存这是好事但很快会发现一个问题如果路由策略本身在变缓存命中旧模型的答案可能会把错误答案重新发出去。比如路由策略更新后某个请求从前一天开始就走70B旗舰模型了可因为命中缓存用户拿到的还是三天前7B模型生成的低质量答案。解决思路是给缓存键加几个路由相关的维度任务类型、路由策略版本、上下文摘要哈希。只要路由策略版本变化缓存命中率会暂时下降但能保证不会把旧策略的答案错发给新策略的用户。另外缓存分层也要做简单高频请求可以长期缓存涉及复杂推理的请求干脆不缓存因为这类答案对时效性和上下文敏感度极高。5.5 别忘了“人肉路由”给用户留一个人工通道最后一个坑不在技术层面而在产品层面。智能路由再聪明也总有判断不了边界情况的时候。尤其是客服、法律咨询、医疗建议这些高价值场景用户如果连续两次对AI答案表达了不满继续在模型间来回路由已经没有意义。这时候路由应该把请求直接升级到人工座席而不是再做第三轮模型打分。我们最后在路由链路上加了一个“人工接管”出口如果模型置信度连续低或者用户连续点踩两次网关直接给该会话打上“需要人工”标签通知后台客服系统接入。后来复盘发现这个设计本身也在反向优化我们的路由——人工座席的聊天记录比普通用户反馈更有价值它们是最贴近用户真实意图的训练数据来源后续用来校准路由模型和评估集提升非常明显。6. 我的落地顺序与最终心得如果让我给一套可复制的落地路径我会按下面的顺序推进先完善观测。在现有架构里记录下每个请求由哪个模型处理、耗时、成本、用户反馈。没有这些数据所有优化都是空谈。启用简单规则路由。按任务类型关键词、上下文长度、用户端类型等最容易获取的特征先做出第一个路由版本。哪怕只有三条规则也比全量一个模型好。建立离线评估集。花一周时间人工标注几百条请求给路由版本做回归测试找到规则里的明显问题。接入数据校准。把成本数据、质量评分、超时率拉通调整阈值和分类逻辑。加上模型路由。只在规则不够用的边界引入轻量router模型做打分同时把它当做一个可替换的组件随时可以回退到规则版。沉淀人工反馈闭环。让每次用户点踩、每次人工座席接管都变成下一次路由决策改进的养料。我个人实际做下来最深的体会是智能路由不是一个一次性开发完成的系统它是一种持续演进的产品能力。模型在更新、用户在变、成本在波动路由策略必须像对待一个独立产品版本一样来管理和迭代。最后多说一句如果你打算在自己的项目里做这件事不要一开始追求“用模型来做路由”先把规则和数据跑通收益就已经超过你的预期了。
返回列表