优化的最高境界不是换更强的模型,而是让该做的事情不需要模型来做。

延迟账单:477ms 到底花在哪了?

全量 LLM function calling:每次把所有 tool schema(5 个工具 × ~150 字描述)传给 Qwen,LLM 读完所有描述再抉择。我们用 qwen-turbo 实测了 500 次(50 条 query × 10 repeats):p50=477ms、p95=672ms、p99=1200ms。延迟分解:input token 编码(~730 tokens) + LLM 推理 + output token 解码(~24 tokens)≈ 477ms p50。

为什么准确率 92% 还不够? 因为按意图拆开,query-order 只有 80%——"我的订单到哪了"被系统性地误判为 check-shipping("到哪了"→语义上天然偏向物流)。一个错误的路由不只是延迟,是后续整个对话链路的崩塌——用户会收到错误的查询结果,然后反复纠错。qwen-max 可能更准,但会更慢(参数量翻倍),且同样存在"语义相近"的混淆问题。92% 准确率值不值 477ms?答案是不值——因为后面我们会看到,P0+P1 已经在 25ms 内达到了更高的命中率。

每天 1 万次请求,仅意图识别就花掉约 1.33 小时(477ms × 10000),年成本约 ¥2,400(qwen-turbo)。

注意:这个 477ms 只是"意图识别→工具选择"这道工序的延迟。后面 RAG 流水线中 LLM 生成最终答案的延迟是 ~9.1s(qwen3.6-plus 最新实测),完全不同量级。这里优化的对象仅限意图识别——别搞混了。

目标是 50ms,但不想换模型、不想加 GPU、不想降准确率。


分层拦截的设计逻辑

核心思路:大部分请求在到达 LLM 之前就应该完成意图识别。不是"每一步都快",而是"只让必要的步骤发生"。

P0 规则过滤 ~5ms
用户输入包含明确关键词。"我想退掉昨天买的洗衣机"→ 关键词"退"直接识别为退款意图,映射到 request-return 工具。关键设计:关键词不是人工维护的,从 Skill YAML 的 trigger_keywords 字段自动抽取 + TF-IDF Top-3。关键词覆盖 53%,但触发后准确率仅 81%——53 条命中里 10 条判错。有效解决率 43%。剩下(如"我的东西到哪了"这种不含明确关键词的)不能指望关键词。

P1 FAISS 语义重排 ~20ms
当关键词失效时,用语义来补。整句 BGE-small-zh-v1.5 embedding + HNSW 索引,但三个工程细节让精度大幅提升:

  • 指令前缀(instruction-aware encoding):零延迟增加,精度提升 5-10%
  • 意图描述内建反向锚点:在退款意图描述末尾写"区分:纯物流咨询请走 shipping 通道",互为对比的描述在向量空间中相互推开
  • 意图词加权:关键词匹配结果 ×1.5 给语义匹配注入方向偏好

指令前缀怎么用? BGE-small-zh-v1.5 官方明确给出了指令:为这个句子生成表示以用于检索相关文章:。标准用法:文档入库时不加前缀,查询时前缀——模型训练时就是这样对齐的。如果查询不加前缀,或者文档误加了前缀,向量空间错位,召回会烂掉。我们的实际选择:考虑到全链路有多个 embedding 消费方(P1 意图匹配 + RAG 文档检索 + 语义缓存),统一不加指令前缀,牺牲约 5-10% 精度换零运维心智负担。

结果:P0+P1 Top-2 命中率达到 85%,Top-1 达到 75%。P1 把 P0 未覆盖的 57% 中的绝大多数兜了回来——从 43% 到 85%,增量贡献 +42%。仅剩 15% 的极端歧义 case 需要 P2 介入。

P2 本地小模型确认 ~157ms
从 P1 Top-3 意图候选里最终确认一个。不在云端跑——p99 延迟抖动(500ms+)不可接受。

本地模型明确说明:P2 意图确认运行 Qwen2.5-1.5B-Instruct,部署在 RTX 4070,p50 推理延迟 94ms(benchmark 实测),显存占用 2.88GB。为什么选 1.5B 而非 1.7B 或 3B?Qwen2.5-1.5B 在简化后的二选一确认任务上达到 92% Top-1 / 94ms p50——精度-速度-显存的甜点。完整 4 模型 × 2 设备全量对比见第六篇

所有 benchmark 均在 **RTX 4070 GPU(8GB 显存)**实测完成。2.88GB 显存门槛意味着任何主流独显都能跑。关键不是 GPU 算力——是 P0+P1 已经把 5-10 个意图筛选为 Top-2 候选,P2 只做二选一确认,问题复杂度降了一个数量级。

P2 之后的工具选择:一张映射表 ~0ms
意图一旦确认,工具选择就是 O(1) 查表。不需要 LLM,不需要 embedding。这是工具选择只需二层(P0+P1)的根本原因——它依赖的是意图识别的输出,不是独立的复杂决策。

P2 交叉校验逻辑:当 P2 的 Top-1 与 P1 的 Top-1 不一致时,同时纳入 Top-2,给后续执行器 agent 更多选择空间。

最终:P0+P1+P2 → ~99% 意图识别命中率(P1 Top-2 85% + P2 对剩余 15% 的兜底确认)。p50 延迟仅 ~25ms——85% 的请求在 P0 或 P1 阶段即命中,无需走到 P2(P0+P1 本身约 25ms,P2 的 ~157ms 仅在 p85+ 尾部触发,不影响 p50 统计量);p95 约 ~182ms(含 P2 完整路径)。


为什么是 P0→P1→P2 这个顺序?

设计逻辑:零成本先跑(P0,解决 43%)→ 语义补缺(P1,Top-2 到 85%)→ LLM 兜底(P2,仅 15% 触发,仅做候选确认)。这才是真正的"经济性设计"。


总延迟对比

方案 p50 p95 p99 年成本*
纯 LLM function calling (qwen-turbo) 477ms 672ms 1200ms ~¥2,400
纯 LLM function calling (qwen-max 估) ~700ms ~900ms ~1500ms ~¥21,000
P0+P1+P2(本项目,共享 GPU) ~25ms ~182ms ~312ms ~¥2,500

*按 qwen-turbo 实测 token 消耗 ~730 input + ~24 output 计算(500 次请求的平均值)。P0+P1+P2 方案中 P2 本地环节运行 Qwen2.5-1.5B-Instruct on GPU,详见下文 benchmark 数据。qwen-max 行标注为"估"——未实测。完整成本拆解见第十一篇。


意图识别 P0→P1→P2 三级流水线 + 工具选择一层映射

P2 本地小模型确认 ~157ms

P1 FAISS 语义匹配 ~20ms

P0 规则过滤 ~5ms

命中

未命中 57%
'我的东西到哪了'

命中

剩余 15% 模糊

用户输入
'我想退掉昨天买的洗衣机'

关键词匹配
trigger_keywords
来自 Skill YAML

✅ 命中 43%
意图=退款

BGE-small Embedding
+ HNSW 检索
+ 意图词加权 ×1.5

✅ 累计命中 85%
Top-2 意图候选

Qwen2.5-1.5B-Instruct
RTX 4070
交叉校验 P1 Top-1
不一致时纳入 Top-2

✅ 累计命中 ~99%

意图→工具映射 ~0ms
退款 → request-return

路由到执行器

三方案延迟对比

意图识别延迟对比 (p50 / p95) 纯 LLM function calling P0 + P2 P0 + P1 + P2 (本项目) 1000 900 800 700 600 500 400 300 200 100 0 延迟 (ms)

这套方法论不止适用于意图识别:RAG 流水线审计

在进入 RAG 优化之前,用同一套"砍 LLM"的眼光审视一下 RAG 流水线。RAG 的延迟里,有多少是检索造成的,有多少是不必要的 LLM 调用?

我们把 4-Step RAG 流水线逐步骤审计了一遍:

步骤 是否需要 LLM? 审计结论
Step 1 问题改写 大部分 query 不需要改写,可用 Embedding 替代
Step 2 安全检查 部分 本地小模型优先,云端仅兜底
Step 3 检索+精排 零 LLM,纯工程手段(具体优化见第三篇)
Step 4 答案生成 唯一无法替代的 LLM 调用

RAG 流水线的延迟大头不是检索,而是那些可以砍掉的 LLM 调用。 真正不可替代的只有 Step 4 的答案生成(~9.1s),而 Step 1 的问题改写每一次都在调云端 LLM——对于"洗衣机有什么功能"这种完全不需要改写的问题,纯属浪费。

审计告诉我们哪些步骤不需要 LLM;下一篇我们聚焦唯一需要 LLM 的那一步——它的输入质量如何确保。也就是 Step 3 检索优化:混合检索、图增强、以及藏在它们背后的一堆工程细节。

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐