
使用 LMCache CacheBlend 进行 Multi-Doc QA 基准测试完整指南与原理剖析【免费下载链接】LMCacheLMCache: Supercharge Your LLM with the Fastest KV Cache Layer项目地址: https://gitcode.com/GitHub_Trending/lm/LMCache本指南围绕 LMCache 仓库中的benchmarks/multi_doc_qa基准测试套件展开系统讲解如何在多文档问答Multi-Doc QA场景下通过 CacheBlend 技术实现非前缀位置的 KV Cache 复用从而显著降低首 token 延迟TTFT。读完本文你将掌握该基准测试的两轮请求设计原理、三种基线纯 vLLM、vLLM 原生 LMCache、vLLM LMCache blending的完整启动方式、全部命令行参数含义以及 blending 在源码层面的实现机制。一、基准测试定位为什么要做 Multi-Doc QA传统的 KV Cache 复用依赖前缀匹配——只有当两个请求的开头 token 完全相同时才能复用缓存。但在多文档问答这类真实场景中用户请求通常是把若干文档按不同顺序拼接进 prompt每个请求的前缀各不相同前缀缓存几乎完全失效。LMCache 的CacheBlend技术正是为了解决这一问题它允许 KV Cache 在非前缀位置被复用通过重算拼接处及关键位置的一小部分 token把多个文档各自独立的预计算 KV Cache 组合起来使用。benchmarks/multi_doc_qa就是用于量化验证这一收益的基准测试套件其核心目标与 blending 设计文档 中描述的机制一一对应。二、基准测试设计两轮请求机制根据 benchmarks/multi_doc_qa/README.md 的 Overview该基准包含两个请求轮次Warmup 轮预热轮把每个文档作为单独 prompt 发送。这一轮的作用是让 LMCache 把每个文档的 KV Cache 分别计算并缓存下来按分隔符切分成独立块。Query 轮查询轮为每个请求随机采样若干文档将它们与系统提示词、查询提示词拼接后作为一个长 prompt 发送。由于各文档的 KV 已在 warmup 轮缓存启用 blending 后可以按任意顺序复用它们。两轮均通过 OpenAI 兼容接口AsyncOpenAI 客户端发送请求warmup 轮的每个文档都使用相同的系统提示词You are a helpful assistant.和查询提示词Whats up? how are you recently?从而保证缓存内容在 query 轮可以被稳定命中。三、配置文件解读基准目录下提供了两个 LMCache 配置文件均以LMCACHE_CONFIG_FILE环境变量方式加载1. vanilla LMCache 配置lmcache.yamlmax_local_cpu_size: 60仅设置了一个配置项CPU 本地缓存上限为 60 GB对应环境变量LMCACHE_MAX_LOCAL_CPU_SIZE默认 5.0 GB。文档总数 100、每文档 3000 token 时总 prompt 量约 30 万 token60 GB 足以容纳全部文档的 KV Cache避免查询轮因缓存被逐出而失效。此配置下 LMCache 只提供前缀缓存复用能力。2. blending 配置lmcache_blend.yamlmax_local_cpu_size: 60 enable_blending: True blend_special_str: # # use_layerwise: TrueYAML 配置项环境变量含义默认值enable_blendingLMCACHE_ENABLE_BLENDING是否启用 blendingfalseblend_special_strLMCACHE_BLEND_SPECIAL_STR文档块之间的分隔字符串LMCache 据此切分与识别各文档 KV 块 # # use_layerwiseLMCACHE_USE_LAYERWISE是否启用逐层layerwise流水线。启用 blending 时必须开启falsemax_local_cpu_size的完整配置含义可参见 配置参考文档其中还有两个与 blending 强相关的进阶参数YAML 配置项环境变量含义默认值blend_recompute_ratiosLMCACHE_BLEND_RECOMPUTE_RATIOS需要重算的 token 比例0.15blend_check_layersLMCACHE_BLEND_CHECK_LAYERS在哪一层决定哪些 token 需要重算1四、Step 1启动 Serving Engine三种基线基准通过对比三条命令的结果来体现 blending 的收益模型以mistralai/Mistral-7B-Instruct-v0.2为例可按需替换为其他 vLLM 支持的模型。基线 1纯 vLLM无 KV Cache 复用vllm serve mistralai/Mistral-7B-Instruct-v0.2 --gpu-memory-utilization 0.8 --port 8000没有任何缓存层query 轮的每个长 prompt 都必须完整重新计算。基线 2vLLM vanilla LMCache仅前缀缓存LMCACHE_CONFIG_FILElmcache.yaml vllm serve mistralai/Mistral-7B-Instruct-v0.2 --gpu-memory-utilization 0.8 --port 8000 --kv-transfer-config {kv_connector:LMCacheConnectorV1, kv_role:kv_both}--kv-transfer-config指定通过LMCacheConnectorV1连接器接入 LMCachekv_role: kv_both表示该实例同时承担 KV 的存储与读取角色。由于 query 轮中文档顺序随机前缀缓存命中率趋近于零理论上这一基线的收益很小。基线 3vLLM LMCache with blendingLMCACHE_CONFIG_FILElmcache_blend.yaml vllm serve mistralai/Mistral-7B-Instruct-v0.2 --gpu-memory-utilization 0.8 --port 8000 --no-enable-prefix-caching --kv-transfer-config {kv_connector:LMCacheConnectorV1, kv_role:kv_both}与基线 2 相比增加了--no-enable-prefix-caching开关。这是为了保证对比公平vLLM 自带的前缀缓存会干扰实验关闭后所有前缀级命中都只能来自 LMCache 的 blending 机制从而让测量结果真实反映 blending 的贡献。五、Step 2发送请求并理解全部参数启动服务后运行python multi_doc_qa.py --num-total-documents 100 --document-length 3000 --output-len 1 --num-requests 100 --num-docs-per-request 5 --model mistralai/Mistral-7B-Instruct-v0.2 --port 8000 --max-inflight-requests 1multi_doc_qa.py 基于 vLLM 官方benchmark_long_document_qa_throughput.py改编而来完整的命令行参数及默认值如下表参数默认值说明--num-total-documents100生成多少个文档用于采样--document-length3000每个文档的 token 长度约等于一篇不含图的系统论文体量--output-len10每个 prompt 生成的最大 token 数--num-requests100发送的请求总数--num-docs-per-request5每个请求拼接的文档数量--sampling-strategyrandom文档采样策略当前仅支持 random--random-seed0随机种子保证实验可复现--blend-special-str # # 文档间的分隔字符串必须与 LMCache 配置中的blend_special_str一致--port8000查询 vLLM 服务的端口--modelmeta-llama/Llama-3.1-8B-Instruct模型名--max-inflight-requests20最大并发在途请求数README 示例中设为 1即串行发送--sleep-time-after-warmup0.0warmup 轮结束后、query 轮开始前的休眠秒数--output无stdout所有响应写入的文件名--expected-ttft-gain无期望的最小 TTFT 加速比warmup/query低于则脚本以错误退出--expected-latency-gain无期望的最小整体延迟加速比每 prompt 耗时比低于则脚本以错误退出需要特别指出脚本用AutoTokenizer.from_pretrained(args.model)在本地完成 tokenization把sys_prompt 分隔符 文档 分隔符 查询提示词拼成 token 序列后再发给服务端请求体为{prompt: prompt_ids}形式的 token id 列表。这是 blending 正确工作的前提详见下文第六节。六、Blending 原理纵深从配置到源码6.1 为什么必须预分词从 blending 设计文档 可以看到直接 tokenize 一个拼接后的长字符串与把各段文本分别 tokenize 再拼接结果产生的 token 可能完全不同。因此必须先在本地用tokenizer.encode(...)分别处理系统提示词、每个文档、查询提示词再用分隔符 token 连接。multi_doc_qa.py 中的generate_warmup_prompt_ids和generate_prompt_ids正是这一逻辑的实现两者都先编码blend_special_ids tokenizer.encode(blend_special_str)[offset:]再按sys_prompt_ids blend_special_ids doc_ids ... blend_special_ids query_prompt_ids的次序组装。offset1用于去掉编码后可能引入的前导空格 token保证与缓存时一致。6.2 分隔符与块级缓存LMCache 依据blend_special_str识别 prompt 中的文档边界把各文档的 KV Cache 切分成独立块分别存储文档正文是唯一的与拼接顺序无关。这样 query 轮无论文档以何种顺序出现都能从缓存中按块取出复用。6.3 层内重算机制源码级为什么 blend 配置要求use_layerwise: True因为 blending 需要在模型推理逐层进行的过程中把缓存 KV 与当前实际输入做比对并对差异显著的位置做重算——这要求 KV 存取与模型执行逐层交错正是 layerwise 流水线的职责。核心实现在 lmcache/v1/compute/blend/blender.py 的process_qkv方法中。当layer_id落在blend_check_layers默认第 1 层指定的层时算法执行以下步骤从 GPU 连接器取出该层缓存的 KVself.gpu_connector.get_kv(layer_id)计算当前层新计算出的 K 与缓存 K 的逐位置平方差diff_k sum((k - old_k)^2, dim1)按blend_recompute_ratios默认 0.15取差值最大的topk_num int(total_len * ratio)个位置至少 1 个即当前输入与缓存差异最大的 token只对这些位置的 Q/K/V 和 residual 进行重算并通过attn_metadata.update_from_top_indices(top_indices)更新注意力掩码其余位置直接沿用缓存的 KVold_k[imp_indices] k从而实现只重算少量 token的拼接复用。blend_check_layers、blend_recompute_ratios等参数正是在LMCBlendCommonMetadata中从配置文件解析后传入的见 blender.py 构造函数。源码中的 TODO 注释support threshold-based blending、support different ratios for different layers表明当前实现采用的是固定比例的 top-k 选择策略。七、结果指标与自动化校验脚本结束时会输出以下指标Warmup 轮平均 TTFT秒、总耗时、prompt 数Query 轮平均 TTFT秒、总耗时、prompt 数若指定--expected-ttft-gain实际 TTFT 加速比 warmup 平均 TTFT / query 平均 TTFT若指定--expected-latency-gain实际每 prompt 延迟加速比warmup 每 prompt 耗时 / query 每 prompt 耗时。两个expected参数的作用是把基准测试变成可断言的自动化检查例如传--expected-ttft-gain 4.3表示期望 blending 带来至少 4.3 倍的 TTFT 提升若实测低于该值脚本会打印错误并以非零码退出sys.exit非常适合接入 CI 流水线。TTFT 在process_single_prompt中通过记录首个非空响应 chunk 到达时间 - 请求发送时间测得。注意warmup 轮因为要逐文档计算并写缓存总耗时通常显著高于 query 轮query 轮若 blending 生效每个请求只需处理文档边界处约 15% 的 tokenTTFT 将大幅下降。本文不预设任何具体加速比数值实际收益取决于硬件、模型与文档长度请以本机实测为准。八、进阶工具shuffle_doc_qa.py 的错位排列测试目录下还提供了 shuffle_doc_qa.py用于更严格地验证顺序无关的缓存复用能力。该脚本会为 n 个文档生成 n−1 个错位排列derangement请求每个排列保证任意文档都不出现在与基线恒等排列相同的序位上perm[i] ! i。如果 blending 实现正确这些完全打乱顺序的请求依然应能命中缓存。其特点包括--num-documents必填、--document-length必填、--output-len必填、--port默认取环境变量SERVICE_PORT或 10001、--random-seed文档构造方式与multi_doc_qa.py完全一致str(i) .join([hi] * document_length)n ≤ 8 时枚举全部错位排列并随机挑选n 较大时用洗牌-拒绝法随机采样保证pick_derangements的可行性检查不足时抛出错误请求采用 chat 消息格式system 若干对 (user 标签, user 文档正文) 汇总请求流式输出并逐请求打印 TTFT。该脚本尤其适合验证同一个文档出现在不同位置都能被复用是 blending 正确性测试的补充手段。九、运行注意事项参数一致性multi_doc_qa.py的--blend-special-str必须与 lmcache_blend.yaml 中的blend_special_str保持完全一致默认均为 # # 否则 LMCache 无法按分隔符正确切分文档块。层间依赖enable_blending: True时必须同时开启use_layerwise: True且 vLLM 端需使用支持 layerwise 的执行路径。关闭前缀缓存对比 blending 收益时务必保留--no-enable-prefix-caching否则 vLLM 自带前缀缓存会污染测量结果。内存规划warmup 轮会把全部文档的 KV Cache 写入 CPU 内存max_local_cpu_size需根据文档总数与单文档长度估算示例配置为 60 GB。模型选择README 示例使用mistralai/Mistral-7B-Instruct-v0.2脚本默认模型为meta-llama/Llama-3.1-8B-Instruct两者都需保证 vLLM 服务端与本机 tokenizer 加载的是同一模型。环境要求脚本依赖openai与transformers库可通过 requirements/bench.txt 等依赖清单安装服务端需按 vLLM 集成文档 正确安装 LMCache 连接器。十、总结benchmarks/multi_doc_qa用一套简洁的两轮请求设计把多文档随机拼接导致前缀缓存失效这一真实痛点量化成可对比的 TTFT 指标warmup 轮负责建立文档级 KV Cachequery 轮验证随机顺序下的复用效果。配合lmcache_blend.yaml中的enable_blending、blend_special_str、use_layerwise三项配置以及 blender.py 中第 1 层按 K 差异 top-k 挑选重算 token的核心算法你可以在自己的模型与硬件上完整复现并验证 CacheBlend 在非前缀场景下的缓存复用能力。【免费下载链接】LMCacheLMCache: Supercharge Your LLM with the Fastest KV Cache Layer项目地址: https://gitcode.com/GitHub_Trending/lm/LMCache创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考