如何用投机解码将代码补全延迟降到 <100ms?

解读

面试官问的是“投机解码”在代码补全场景下的端到端延迟优化,目标**<100 ms**(P99)。
在国内真实业务里,这通常意味着:

  1. 模型是百亿/千亿参数的云端大模型,无法全量搬上卡;
  2. 用户侧是 IDE 插件,网络一跳 2040 ms(北京同机房),留给推理本身只有 6080 ms;
  3. 代码补全对首 token 延迟极度敏感,但后续 token 也不能“抖”;
  4. 必须兼顾**中文注释、业务私有框架、国产化 GPU(华为昇腾、寒武纪)**的适配。

因此,候选人需要把“投机解码”当成系统级方案来答,而不是单点算法。

知识点

  1. 投机解码(Speculative Decoding)本质:用小模型(draft model)并行生成 γ 个 token,再由大模型(target model)一次前向做并行验证,通过拒绝采样保证分布等价,实现**“一次前向拿多 token”**。
  2. 延迟公式
    T_total = max(T_draft, T_verify) + T_overhead
    其中 T_verify 是大模型一次前向,通常 4060 ms(FP16,千亿模型,单机 8×A100 NVLink);
    要 <100 ms,必须把 γ 打到 4
    6,且T_verify 不能涨
  3. Draft 模型选型
    • 同词表、同位置编码是硬要求,否则验证阶段 logits 对齐开销爆炸;
    • 国内落地常用深度剪枝 1/10 参数版(如从 175B→16B),用国产 MindSpeedColossal-AI做张量并行,推理延迟 8~12 ms(昇腾 910B 单卡 300W)。
  4. 验证阶段内核优化
    • 验证并行算子需手写 CUDA/Hygon HIP 或昇腾 CANN kernel,把 γ 次采样做成一次 flash-attention 变长矩阵乘
    • 代码词表(32k→64k)权重预重排,把 C++ / Python / Java 高频 token 放在连续块,提升 cache 命中率。
  5. γ 自适应
    • 代码补全场景括号、缩进、分号极易预测,γ=6 时接受率仍 >85%;
    • 中文注释或业务 API 场景接受率骤降,需动态 γ:用 draft 模型 entropy 阈值实时降到 2~3,防止验证回退。
  6. 级联投机
    • 边缘机房再部署 1B 级“迷你 draft”(Qwen-1.8B 剪枝后 800M),γ=2,延迟 3 ms;
    • 形成三级 cascade:800M → 16B → 175B,P99 首包 70 ms,平均接受 token 4.2 个。
  7. LLMOps 配套
    • 拒绝采样日志实时回流,用增量 LoRA 每天微调 draft 模型,保证业务新 API 接受率不掉;
    • 可观测:Prometheus 暴露 spec_accept_rate、draft_latency、verify_latency,告警阈值 85%/15 ms/60 ms
    • 安全:draft 模型与 target 模型同权审,防止“投机投出违禁代码”。

答案

答:要把代码补全端到端延迟压到 100 ms 以内,我会把投机解码做成三级级联系统

  1. 边缘 800M 迷你 draft:首跳机房 3 ms 内生成 2 个 token,接受率 90%;
  2. 机房间 16B draft:NVLink 域内 10 ms 再生成 4 个 token,接受率 85%;
  3. 云端 175B target:一次验证前向 55 ms,平均接受 4.2 个 token。

核心优化点:

  • 验证算子手写融合 kernel,把 γ=6 的变长 attention 做到 55 ms(A100 80G,TP=8);
  • 动态 γ:draft entropy>0.8 时立即缩回 γ=2,防止大模型回退;
  • 词表重排+KV-Cache 预分配,让高频代码 token 连续,验证阶段无额外 memcpy;
  • 每天 LoRA 增量微调 draft,新业务 API 接受率掉 5% 就触发自动训练,30 分钟内热更新;
  • 监控三板斧:spec_accept_rate<85% 告警、draft>15 ms 告警、verify>60 ms 告警,直接回滚。

上线结果:北京 IDE 插件 P99 首 token 延迟 72 ms,平均生成 6.3 个 token,满足 <100 ms 要求。

拓展思考

  1. 如果国产化 GPU(昇腾 910B)算力只有 A100 的 60%,如何把 verify 阶段 55 ms 压回去?
    → 用投机解码 + 4-bit weight-only 量化 + 16K 长窗口 flash-attention 算子,在昇腾上把 verify 降到 50 ms,同时接受率只掉 2%。
  2. 当业务代码出现私有语法(如自研 DSL)时,draft 模型接受率骤降,如何不重新训练大模型?
    → 把 DSL 的 BNF 文法转成约束解码 mask,在 draft 阶段直接屏蔽非法 token,验证阶段保持原分布,零样本即可把接受率从 45% 拉回 80%。
  3. 若未来要支持多文件跨函数补全,上下文 32K token,verify 阶段延迟暴涨,如何继续保证 100 ms?
    → 引入分层投机:先对 4K 窗口内的局部 token 做 γ=6 投机,再对剩余 28K 做 γ=2 的稀疏投机,用双通道验证并行,整体延迟仍压 90 ms。