跳到主要内容

AI 流水线中的惰性评估:不到万不得已,不要调用 LLM

· 阅读需 13 分钟
Tian Pan
Software Engineer

大多数 AI 流水线(pipelines)在编写时,都好像每一个请求都值得进行一次完整的 LLM 调用。用户提交一条消息,流水线将其传递给模型,等待响应并返回——每一次都无条件地如此操作。这虽然可行,但既昂贵又缓慢,而且通常是不必要的。

实际上需要完整 LLM 推理的请求比例比大多数工程师预想的要小。关于 token 级别路由的研究表明,1.5B 和 32B 参数模型之间只有约 11% 的 token 存在差异,且只有 4.9% 的 token 是真正的“发散性”的——这意味着如果由较小的模型处理,它们会改变推理路径。生产环境中的语义缓存显示,65% 的传入流量在语义上与流水线已经回答过的内容相似。这些并不是边缘案例。它们占据了流量的大部分,而你却在为处理它们支付全额费用。

解决方法是惰性求值(lazy evaluation):在确认确实需要昂贵模型之前,不要调用它。

函数式编程的类比

惰性求值是函数式编程中一个成熟的概念。像 Haskell 这样的语言使用它来延迟表达式的计算,直到程序的另一部分需要其结果为止。计算过程被包装在一个 thunk(延迟计算单元)中,只有在被强制要求时才会执行。如果结果从未被需要,计算就永远不会运行。

AI 流水线可以应用同样的原理。昂贵的模型调用就是那个 thunk。一个廉价的决策门——分类器、相似性查找或轻量级路由模型——充当强制执行函数。决策门首先运行并询问:这里真的需要 LLM 的结果吗?如果不需要,流水线提前退出。如果需要,则运行 LLM。

这种类比还可以进一步延伸。函数式语言将惰性求值与记忆化(memoization)相结合:一旦 thunk 被强制执行并求值,结果就会被缓存。AI 流水线中的语义缓存正是这样做的——流水线通过语义嵌入记忆化 LLM 的响应,因此未来表达相同意图的请求将完全跳过计算。

主要区别在于时间尺度。函数式惰性求值可以无限期延迟。AI 流水线的惰性求值则在毫秒内做出决策,利用快速模型来预测何时需要慢速模型。

第 1 道门:昂贵模型前的廉价分类器

惰性求值最简单的版本是在流水线入口处进行二元决策:这个请求是否应该到达 LLM?

这种模式在生产环境中表现为基于复杂度的路由。一个轻量级分类器或小模型对传入请求进行评分。复杂度低于阈值的请求由规则、模板或小得多的模型处理。只有真正复杂的请求才会进入大型 LLM。

关于混合路由的研究证明了这种方法的有效性。在一个评估框架中,一个拥有约 5600 万参数的路由器——与 32B 的 LLM 相比微不足道——相比始终调用大型模型实现了 2.76 倍的加速,同时仅将 12.4% 的 token 路由到昂贵模型,并保持了全模型 92% 的性能。另一项研究发现,22% 的查询可以路由到更小的模型,而质量损失不到 1%。

分类器的设计至关重要。区分“小模型能处理”和“需要大模型”的信号不是查询长度或关键词复杂度,而是不确定性。当小模型对输出有信心时,通常是正确的。当它不确定时,token 分布变得分散,熵值升高。训练良好的路由器会检测到这种不确定性并相应地升级。实际实现中通常使用小模型的输出 logits 作为特征:高熵 logit 分布是需要更大模型的信号。

成本状况以一种有益的方式呈现出非对称性。在不需要升级的请求上运行分类器加小模型,比调用大模型要便宜得多。分类器只有在出错时才会变得昂贵——要么是不必要的升级(损失成本节约),要么是该升级时未升级(损失质量)。在实践中,运行这些系统的团队会调整升级阈值,以接受小幅的质量下降来换取大幅的成本降低,通常目标是将 LLM 的激活率控制在 20-50% 之间。

第 2 道门:模型内部的提前退出

惰性求值也可以应用于单次模型调用内部,而不仅仅是在流水线入口处。

大型语言模型通过许多连续的 Transformer 层处理 token。对于简单的 token——语气词、标点符号、高置信度的下一个词——前几层通常已经包含足够的信息来产生正确的输出。剩余的层只会增加计算成本,而不会改变结果。

层跳过(Layer-skipping)技术利用了这一点。在训练过程中,模型学习在中间层产生有效的输出,而不仅仅是在最后一层。在推理时,轻量级预测器在每一层之后决定当前层的输出是否足够,或者是否需要额外的层。简单的 token 提前退出。复杂的 token 则遍历整个网络。

研究中测得的加速效果具有实际意义:在使用推测性提前退出方法(speculative early-exit)的标准基准测试中,速度提升了 2.25–2.43 倍;根据任务类型的不同,使用层丢弃(layer-dropout)训练的速度提升了 1.34–2.16 倍。摘要任务比代码任务受益更多,而代码任务又比需要精确事实回忆的任务受益更多。

实际的意义在于,推理调用的每 token 成本并非固定不变。一批碰巧简单的 token 的成本也低于一批需要深度推理的 token。构建利用这一特性的流水线——通过对请求进行排序和批处理,优先处理简单的 token——可以进一步扩大成本节约。

第 3 关:作为记忆化(Memoization)的语义缓存

语义缓存回答了一个不同的问题:这个请求,或者与其非常接近的请求,是否已经被回答过?

与精确匹配缓存不同,语义缓存存储的是以嵌入向量(embedding vector)为索引的 LLM 响应。传入的请求被嵌入,并通过向量相似度与缓存条目进行比较。如果相似度超过阈值,则直接返回缓存的响应,完全绕过 LLM。

生产环境中的命中率比厂商营销宣传的要保守。在混合流量中,20–45% 的请求会命中语义缓存。分布高度依赖于用例:常见问题解答(FAQ)和客户支持工作负载的命中率可达 40–60%,因为意图模式会重复;开放式对话的命中率则在 10–20% 之间,因为对话是唯一的。一个具有高意图重复性的教育科技(EdTech)平台在学生问答中实现了 45% 的命中率。一个通用的 RAG 系统命中率则接近 20–25%。

即使命中率只有 20–30%,经济效益也极具吸引力。缓存响应的到达时间为个位数毫秒,而典型的 LLM 调用则需要 500ms 到 5s。在每天处理数百万个请求的高流量流水线中,30% 的命中率直接意味着每天减少了数百万次 LLM 调用。根据流量构成,大规模测量的成本降幅在 20% 到 73% 之间。

架构要求是一个运行延迟在亚毫秒级的向量数据库,用于相似度搜索。如果缓存查找耗时超过了 LLM 调用延迟的方差,那么收益就会消失。这意味着缓存需要与推理基础设施部署在一起,而不是通过具有网络往返开销的远程服务。

第 4 关:异步工作的延迟生成

并非每个 AI 流水线都需要实时响应。许多工作流——分类、提取、文档处理、批量扩充(batch enrichment)——可以容忍以分钟而非毫秒计的延迟。将这些视为实时工作负载是一种分类错误,会成倍增加基础设施成本。

延迟生成将请求接收与实际推理分离开来。流水线记录请求,下游消费者在结果就绪时进行轮询或接收结果。这实现了真正的批处理:请求累积成共享前缀上下文(prefix context)的组,单次模型调用处理该批次的成本比单个实时调用低 50% 或更多。

提供商提供批处理 API(Batch API)使这种折扣正式化。关键的架构洞察是,“用户提交了请求”与“模型需要立即运行”并非同一事件。只有交互式的、面向用户的特性才需要亚秒级推理。后台扩充、定期分类、分析流水线和非紧急提取作业可以按批处理计划运行,而不会产生任何用户可见的体验下降。

生产分析一致发现,系统性识别哪些工作负载可以异步执行的组织,在不影响用户体验的情况下,降低了 30–50% 的成本。难点不在于技术实现,而在于评估每个 AI 特性时要遵循的原则:这真的需要实时响应吗?

新鲜度陷阱

当缓存或延迟的答案因为世界已经发生变化而变得错误时,惰性求值就会失败。

有些类别的请求,惰性求值是有害的。实时价格、实时库存、当前天气、突发新闻——任何将新鲜度作为正确性要求的请求,如果从缓存返回,都会得到错误的答案。交易确认——付款收据、预订确认、特定账户状态——绝不能通过缓存满足,因为它们需要与实时记录系统保持一致。依赖于频繁更改的用户状态的高度个性化响应,不能跨用户缓存,甚至不能为同一用户的不同会话缓存。

这种失效模式很隐蔽:流水线返回一个自信、流利的答案,该答案在缓存时是正确的,但现在已经错了。与资深用户可能会质疑的 LLM 幻觉不同,过时的缓存答案看起来很权威,因为它曾经是准确的。

缓解措施有两种方法。基于 TTL 的过期策略按内容类别分配生存时间:价格数据在几分钟内过期,政策文档在几天内过期,定义性内容基本永不过期。事件驱动的失效会在基础数据发生变化时触发缓存清除,这种方法更精确,但需要在数据源进行埋点。实际建议是从保守的 TTL 开始,并根据观察到的命中率和关于过时问题的投诉来延长它们——而不是相反。

另一种失效模式是阈值校准错误。语义缓存使用相似度阈值来决定缓存条目是否足够接近以进行提供。设置得太低,你会有针对语义相邻但含义完全不同的查询返回响应——例如,关于取消政策的问题可能会返回另一个产品的取消政策。设置得太高,命中率就会降至接近零。校准此阈值需要评估生产查询对的精确率和召回率,而不是合成基准测试。

实践中构建延迟评估流水线

一个实用的延迟评估(Lazy Evaluation)流水线会按成本顺序分层排列这些关口:

第一个关口是语义缓存(Semantic Cache)查询。如果请求与最近有效的缓存响应匹配,则立即返回。这只需几毫秒,并能拦截 20–45% 语义冗余的请求。

第二个关口是复杂度路由。对于未命中缓存的请求,由轻量级分类器确定该查询是否需要大模型。低于阈值的请求会被路由到小模型或基于规则的系统。这能拦截另外 20–50% 不需要全量推理能力的流量。

第三个关口是批处理资格判定。对于确实需要大模型的请求,判断它们是否对延迟敏感。后台作业和分析工作负载进入批处理队列。只有真正的交互式、对时间敏感的请求才会进入实时大模型推理。

第四个考虑因素是推理时的提前退出(Early Exit)。对于支持跳层的模型,配置推理引擎以在简单的 Token 序列上启用提前退出。这不需要更改流水线——它是一种服务端配置,能进一步降低到达大模型的请求成本。

如果配置得当,该流水线将显著改变成本和延迟概况。Token 级路由研究显示,端到端速度提升了 2.76 倍。语义缓存完全消除了很大一部分 LLM 调用。批处理为非交互式工作负载削减了一半的单位成本。在大流量系统中,这些叠加效应是巨大的。

开销是真实存在的——维护向量数据库、运行路由分类器、管理批处理队列——但这是基础架构开销,随流量呈亚线性(Sublinearly)增长,而不像 LLM 推理成本那样呈线性增长。

延迟评估不是什么

延迟评估不是在质量上妥协。其目标是识别那些不需要昂贵推理的请求并进行妥当处理,而不是为了省钱而提供低质量的响应。缓存命中的准确率应与新的 LLM 调用一致。小模型的响应应满足其请求类别的质量要求。如果其中任何一个条件不满足,说明关口配置有误。

延迟评估也不是优化提示工程(Prompt Engineering)或模型选择的捷径。如果你全量 LLM 调用的返回质量始终很低,那么将更多流量路由到小模型只会让问题雪上加霜。只有当每个层级的基本质量都达到要求时,延迟评估才有效。

它的本质是承认“请求已到达”和“请求需要昂贵的推理”是两个不同的谓词,而将它们混为一谈是一种代价高昂的假设。函数式编程人员学会在计算表达式之前询问“这个表达式的值真的需要吗?”。AI 工程师也需要将同样的纪律应用于模型调用:只有当廉价方案确实无法处理时,才运行昂贵的计算。

大多数请求都比你想象的要便宜。有趣的工程挑战在于构建能够识别出哪些请求并非如此的流水线。

References:Let's stay in touch and Follow me for more thoughts and updates