延迟预算拆分
端到端响应时间由若干环节串起来:查询改写、向量化、向量检索、重排、生成,任何一环都可能成为瓶颈。有效的做法是先定 p95 目标,再把目标拆成各环节的预算,上线后按环节埋点核对实际占用。经验上生成与重排占大头,向量检索往往只占几毫秒到几十毫秒,所以在索引参数上反复微调常常收益有限;真正见效的通常是缓存、并行化与流式输出。
基本信息
| 指标口径 | p95 与 p99,平均值会掩盖长尾 |
|---|---|
| 预算拆分 | 改写、向量化、检索、重排、生成各自设上限 |
| 常见瓶颈 | 生成与重排 |
| 见效手段 | 缓存、并行调用、流式输出、控制候选数 |
| 观测方式 | 每环节埋点并写入 trace |
典型使用场景
- 体验优化立项:先埋点找到真实瓶颈,再决定优化谁
- 容量规划:按 p95 目标反推单实例 QPS 与机器数量
- SLA 评估:对外承诺响应时间前先量清各环节的最坏耗时
- 降级设计:生成耗时超阈值时切换到短回答或先给检索结果
- 版本对比:模型换代后按环节比对新旧延迟构成
环节埋点示例
环节埋点示例
import time
t0 = time.perf_counter()
rewritten = rewrite(question)
t1 = time.perf_counter()
hits = retriever.search(rewritten)
t2 = time.perf_counter()
top = rerank(rewritten, hits)
t3 = time.perf_counter()
answer = generate(rewritten, top)
t4 = time.perf_counter()
log_latency(trace_id, {'rewrite': t1 - t0, 'retrieve': t2 - t1,
'rerank': t3 - t2, 'generate': t4 - t3})环节与量级参考
| 环节 | 量级参考 | 优化手段 |
|---|---|---|
| 查询改写 | 数百毫秒 | 与小模型合并调用,简单问题跳过 |
| Embedding | 几十至百毫秒 | 本地模型、批量化、结果缓存 |
| 向量检索 | 几至几十毫秒 | HNSW 参数、过滤下推、量化 |
| 重排 | 百毫秒级 | 小模型、控制候选条数 |
| 生成 | 秒级 | 流式输出、模型档位、输出上限 |
流式输出能显著改善体感:首字时间缩短后,用户对总耗时的容忍度明显提高,这往往比在索引层挤出几十毫秒更划算。