首页
/ caveman cachebench:面向 Agent 提示词缓存引擎的命中率基准测试与实时回放体系

caveman cachebench:面向 Agent 提示词缓存引擎的命中率基准测试与实时回放体系

2026-09-05 13:28:32作者:范垣楠Rhoda

本文围绕 cachebench 展开,讲解 caveman 项目如何用一个确定性基准回答“cacheengine 能否在持续增长的工具调用 Agent 上维持至少 97% 的缓存命中”,覆盖黄金路径模拟基准、指标契约、公开 Agent 语料回放、真实 Provider 实时重放(cache-replay)与失败演练。读完你将掌握一套“零网络模拟 + 付费实测分层、证据严格隔离”的缓存命中率评测方法,以及可直接复制运行的命令、参数与源码级验证依据。

解决的核心问题:一个严格的问题陈述

cachebench 回答单一问题:能否在持续增长的工具使用型 Agent 上维持 ≥97% 缓存命中,同时不掩盖冷启动、压缩(compaction)、语义变更、无效样本或不支持的 Provider 行为?

从源码结构看,整个包通过 schema 常量把证据类型硬编码隔离(types.go):

  • 模拟证据基准:benchmark_simulated / benchmark_public_corpus_simulated
  • 观测证据基准:provider_observed
  • 质量基准:model_visible_request_equivalence(模型可见请求等价)或 external_task_verifier(外部任务验证器);
  • trace 与 observation 均有版本化 schema(caveman.cachebench.trace.v3caveman.cachebench.observation.v3),模拟与观测证据永不混合。

报告结构 Report 强制携带 publishable: falseevidence_limitations 字段——基准结果自始就声明自己不是生产证据或已验证的节省证明。

黄金路径:零参数模拟基准

运行方式

原文档给出的命令面向 public 模块布局书写;当前仓库布局中 go.mod 位于仓库根目录,因此在仓库根目录直接执行即可:

go run ./cacheengine/cmd/cachebench

零参数运行会对 Anthropic、OpenAI、Bedrock、Gemini 四个 Provider 各跑 128 个请求。工作负载携带 8,192 个声明的稳定 system/tool 前缀 token、持续增长的用户消息、assistant 工具调用与工具结果历史,并每 64 轮计划一次压缩(compaction)。压缩开启新 epoch,其冷写入仍计入分母——这正是“不掩盖冷启动”的体现。

内置默认场景与 Provider 配置定义在 types.go 中,可直接对照:

// DefaultScenario 返回 128 轮 Agent 工作负载
Scenario{
    Name: "tool-using-agent-128-turn", Turns: 128, CompactionEvery: 64,
    StaticTokens: 8_192, UserTokens: 64, AssistantTokens: 96,
    ToolResultTokens: 256, SummaryTokens: 512,
    Step: 3 * time.Second, AssumedTTL: 5 * time.Minute,
}

四条内置 Provider 泳道(模型与端点均以仓库当前内容为准):

Provider 模型 端点
anthropic claude-sonnet-4-6 /v1/messages
openai gpt-5.6 /v1/chat/completions
bedrock global.anthropic.claude-sonnet-4-6(us-east-1) converse
gemini gemini-2.5-pro generateContent

预期读值

CACHEBENCH agent-cache evaluation: PASS
Evidence: benchmark_simulated | publishable: false | quality: model_visible_request_equivalence
Target: request hits >= 97.00%, eligible-token hits >= 97.00%, >= 100 eligible requests/provider

provider   mode       rolling  eligible  inelig  req-hit  token-hit  attributed  cold  invalid  safety  gate
anthropic  explicit   true          128       0   99.22%     97.79%      97.79%     1        0       0  PASS
openai     explicit   true          128       0   99.22%     97.79%      97.79%     1        0       0  PASS
bedrock    explicit   true          128       0   99.22%     97.79%      97.79%     1        0       0  PASS
gemini     implicit   true          128       0   99.22%     97.79%       0.00%     1        0       0  PASS

这证明的是本地机制,对象是确定性的 Provider 缓存模拟:零 Provider 调用,且永远不构成生产或已验证节省的证据。注意 128 个请求中恰好 1 个冷写入(epoch 首请求),127/128 = 99.22% 的请求命中率;Gemini 的 attributed 为 0.00%,因为其隐式缓存命中是“自然(organic)”的,见下文归因说明。

完整 CLI 参数

main.go 中定义了全部标志,按功能分组如下:

工作负载形状(模拟模式)

参数 默认值 说明
-providers all 逗号分隔:anthropic,openai,bedrock,gemini,all
-turns 128 每个 Provider 的 Agent 请求数
-compaction-every 64 每 N 轮开启新缓存 epoch;0 禁用
-step 3s Agent 请求之间的时间间隔
-assumed-ttl 5m Provider profile 无显式 TTL 时的模拟 TTL
-static-tokens 8192 声明的稳定 system/tool 前缀 token 数
-user-tokens 64 每用户轮声明 token
-assistant-tokens 96 每 assistant 工具调用声明 token
-tool-result-tokens 256 每工具结果声明 token
-summary-tokens 512 每次压缩摘要的声明 token

门槛与输出

参数 默认值 说明
-target 0.97 要求的请求与合格 token 命中率(比例值)
-min-requests 100 每 Provider 最少合格请求数
-format text text 或 json
-include-requests false JSON 中是否包含逐请求行

模式切换(互斥,由 main.go 强制)

参数 说明
-observations 提供 Provider 观测 JSONL,从模拟切换到观测回放(必须搭配 -trace-in,且不能与 -corpus 同用)
-trace-in 观测模式必需的请求 trace JSONL
-trace-out 将生成的 Provider 原生请求 trace 写为 JSONL(供 cache-replay 使用)
-corpus LMCache Agent 语料文件,- 表示 stdin
-corpus-format lmcache-jsonl 或 hf-rows
-corpus-name / -corpus-license / -corpus-revision 记录进报告的语料名称、许可、不可变 revision
-corpus-max-rows / -corpus-max-sessions 行数/会话数 fail-closed 上限(默认 100,000 / 10,000)
-corpus-max-bytes 保留语料字节上限,默认 1 GiB(1<<30)

指标契约:冷写入必须留在分母里

主门槛(primary gates)显式包含冷写入(cold writes):

request_hit_rate = requests with cache_read_tokens > 0
                   / all cache-eligible requests

token_hit_rate   = sum(cache_read_tokens)
                   / sum(cache-eligible prompt-prefix tokens)

两者都必须 ≥ 目标值,每个 Provider 都必须满足最小样本数,质量通过率必须等于 100%,模型可见等价失败必须为零,无效样本必须为零。速率从不排除计划内冷启动、TTL 过期、压缩或前缀失效——这与 simulate.go 的 finalizeProvider 逐项对应:任一条件未满足即追加 blocking_reasons,全部清零才 gate_passed。聚合层 aggregateProviders 还会把最小样本数乘以 Provider 数量再校验 overall。

三个容易被误读的概念:

  • opportunity_*_capture_rate(机会捕获率)是诊断量,永不替代门槛。它用“同一证据支持分区内此前已见过的、完全可复用前缀”除以实际读取,忽略 TTL。作用是把引擎/Provider 的实现能力与冷启动、全新后缀 token 区分开,同时保持原始 97% 目标不变。
  • inelig(不合格)不是 miss 也不是无效:短于 Provider 最小前缀的请求只报告为不合格样本;而未知 Provider、畸形请求体、静默稳定前缀漂移、不安全变换或缺失 usage 仍是无效样本,直接令门槛失败。
  • attributed_token_hit_rate 独立统计:Gemini 的隐式命中保持“自然”归因——它改善缓存表现,但永不变成引擎因果(engine-causal)证据。

模拟缓存模型的内部实现

理解读值为何如此,需要看模拟器的三个核心机制(simulate.go):

  1. 前缀段与最长公共前缀:每个请求的前缀建模为 PrefixSegment(ID + token 数)数组,命中读取量取同一分组内与当前请求的最长公共前缀,且要求达到 MinPrefixTokens 才算读取。cold_write 判定为 read == 0;已有分组但读取为零记为 invalidated(前缀失效)。
  2. TTL 过期与分区隔离:缓存前缀带 expiresAt = request.At + TTL(profile 无 TTL 时回落到场景 AssumedTTL)。simulatedStateKey 用 provider/model/scope 加 partition key 构造状态键,注释明确写道“公开语料通常只提供 per-session 间隔而无全局时间线,绝不推断不相干会话在 Provider TTL 内重叠”——这是语料回放不跨会话计复用的源码级依据。
  3. 机会状态双轨:模拟器维护两组前缀状态——一组带 TTL 过期(真实命中),一组不过期(opportunity 机会集),从而同一遍遍历同时产出严格命中率与诊断性捕获率。

此外,OpenAI 显式模式下的查找前缀边界由 simulatedLookupPrefix 决定:解析请求体,定位含 prompt_cache_breakpoint 的消息(Responses 端点用 input 序列而非 messages),无断点且引擎走亲和回退(affinity fallback)时退化为最后一条 user/tool 消息。这保证了模拟读取量与引擎真实注入断点的位置一致。

公开 Agent 语料:LMCache Agentic Traces 回放

LMCache Agentic Traces 数据集记录了 SWE-bench、GAIA 与 WildClaw 的 Agent 请求历史,许可 CC-BY-4.0。获取脚本固定不可变 revision 并逐分片校验 SHA-256(脚本内五个 parquet 分片的字节数与摘要均硬编码),已有文件先验大小再验摘要,失败即退出:

sh cacheengine/cachebench/scripts/fetch_lmcache_agentic_traces.sh /tmp/lmcache-agentic-traces
python3 -m pip install pyarrow

五个分片按顺序流式转换为 JSONL,再作为一个连续语料整体回放。完整归一化输入约 2.43 GB,因此命令显式上调默认 1 GiB 的保留输入护栏:

cachebench_data_dir=/tmp/lmcache-agentic-traces
for cachebench_shard in "$cachebench_data_dir"/*.parquet; do
  python3 cacheengine/cachebench/scripts/lmcache_parquet_to_jsonl.py "$cachebench_shard"
done | GOMEMLIMIT=12GiB go run ./cacheengine/cmd/cachebench \
  -corpus - \
  -corpus-name lmcache-agentic-traces/full-train \
  -corpus-license CC-BY-4.0 \
  -corpus-revision hf:6e043b9e89865df3aec19fd5679286b683bfd70e \
  -corpus-max-bytes 3221225472 \
  -providers openai \
  -target .97 \
  -format json

转换脚本 用 pyarrow 按批(默认 32 行,上限 4096)流式输出 JSONL,支持 --expected-sha256 在输出前校验分片摘要,BrokenPipeError 视为正常结束(配合管道使用)。

解码护栏(fail closed)

语料解码对源字节、保留字节、行数、会话数、行大小、消息数与消息大小都设上限(CorpusLimits):默认每请求最多 4,096 条消息、单行 64 MiB、单消息 16 MiB、源/保留字节各 1 GiB;而 normalizedCorpusLimits 对一切显式配置设置了硬顶——任何一项超过 16 GiB 或行数/会话数超过 1,000,000 直接报错,显式上限过高同样 fail closed

数据集只暴露归一化消息、模型标签、输出长度和 per-session 间隔——不含完整原始 Provider 信封或工具 schema。

机器可读的固定结果

仓库内置 固定结果文件(2026-08-10 测量):

  • 24,880 个请求、767 个会话(来源 swebench 665 / gaia 94 / wildclaw 8);
  • 24,706 个 OpenAI 缓存合格请求、174 个低于 Provider 下限;
  • 请求命中率 96.89%,估计 token 命中率 95.76%;零无效样本、零模型可见等价失败;
  • 两个指标上严格门槛均为 FAIL。原因在数据本身:语料无全局时间线,基准隔离会话、不记任何跨会话复用;每会话一次冷 epoch 在其它任何损失之前就把请求命中率封顶在 96.92%((24,880−767)/24,880)——没有单独测量的跨会话复用,97% 对该总体不可达。
  • 引擎捕获了 100% 的会话内可复用机会:23,938 个请求、665,558,422 个估计 token。机会捕获是诊断量,不会把失败的原始门槛变成通过。结果仍是使用 o200k 估计的确定性模拟,不是 Provider 计数器,更不是可发布的节省证据。

跨 Provider 分片回放:固定分片 train-00000-of-00005 上每个内置适配器各跑 4,976 个请求(固定结果中的 shard 区块):

Provider 请求命中率 估计 token 命中率 机会捕获(请求/token)
Anthropic 97.01% 95.69% 99.36% / 99.23%
OpenAI 97.63% 96.43% 100% / 100%
Bedrock 97.01% 95.69% 99.36% / 99.23%
Gemini 97.01% 95.69% 99.36% / 99.23%

所有严格门槛均因 token 率失败;零无效样本、零等价失败。OpenAI 捕获 100% 可复用请求/token 机会;其余三家因 5 分钟 TTL 假设使 31 个本可复用请求过期而分别停在 99.36%/99.23%。OpenAI 受益于保证的 30 分钟 GPT-5.6 保留期;直连 Anthropic 与选定 Bedrock profile 使用保证的 5 分钟保留期;Gemini 的取值是带 5 分钟回退的自然模拟,永不作为引擎因果归因。

给语料命令附加 -trace-out /tmp/lmcache-openai-trace.jsonl 可将同一批 Provider 原生请求以 trace v3 导出。由于公开语料的时间戳仍是会话局部、token 数仍是 o200k 估计,实时运行器默认拒绝它们;显式降级标志只是在预检中保留这些限制,并不制造任何“有据可依”的证据。语料模拟与实时证据始终是两份独立报告。

真实 Provider 回放:cache-replay

生成可回放的请求体

go run ./cacheengine/cmd/cachebench \
  -providers openai \
  -trace-out /tmp/cachebench-openai.jsonl

生成的 trace v3 记录(TraceRecord)绑定原始请求体与全部优化器输入:请求 ID、Provider、模型、region、端点、scope、epoch、分区键;预期 RPM 与 TTL 内预期调用数;运行/鉴权模式;原始体与 SHA-256;用于规划的声明可缓存前缀 token;优化后 wire 总输入上限、Provider 原生最大输出 token 与调用方 token 计数基准;时间戳与时序基准。

零网络预检

cache-replay 执行精确的优化器重建、认证 Provider 调用、保留响应捕获、外部任务验证和有界绝对时间并发调度,且整条 trace 在第一次实时调用前必须全部通过优化与模型可见等价。先从零网络预检开始:

go run ./cacheengine/cmd/cache-replay \
  -trace /tmp/cachebench-openai.jsonl \
  -max-requests 128 \
  -max-declared-billed-tokens 5000000 \
  -allow-ungrounded-timing \
  -allow-estimated-token-budget

有据可依(grounded)的生产 trace 会省略降级标志。预检打印声明总输入、声明最大输出、declared_billed_token_ceilingtiming_groundedinput_budget_claimed_provider_countedmax_concurrency;标志从不改写证据基准。

实时执行

实时模式额外要求 -execute -accept-live-cost -output <新私有目录> -verifier-command <path>REPLAY_PROTOCOL.md 给出了完整证据管线:

trace.v3
  -> 精确 NativeRequest 重建
  -> cacheengine 仅元数据优化
  -> 模型可见等价检查
  -> 认证 Provider 请求
  -> 保留完整响应 + Provider usage 提取
  -> 外部任务验证器
  -> observation.v3 + replay-evidence.v1
  -> 精确总体 97% 报告

关键执行约束:

  • 请求开始之后绝不重试:连接失败可能是歧义的(Provider 可能已处理并已计费),自动重试会导致双重计费并破坏缓存时序。
  • 绝对时间调度:排程使用首个 trace 时间戳的绝对偏移,Provider 延迟不叠加到历史 start-to-start 间隔上;-max-concurrency 约束 1..1024(默认 1)个活跃回放生命周期,每个 worker 在发送前立即测量漂移,漂移超过 -max-schedule-drift 时发出 schedule_drift不发送该请求。并发容量不足会使证据失败,而不是静默拉伸排程。
  • 预算校验:预检把所有请求的声明总输入加精确最大输出求和为 declared_billed_token_ceiling,超过运营上限即拒绝;Provider 响应总输入/输出超过请求声明即在该请求后失败运行。完整 usage 提取要求 Provider 原生输入与输出计数器——缺失、歧义、小数、负数或溢出全部 fail closed。
  • CLI 硬上限:trace 输入 512 MiB、合计配置的响应/验证器缓冲 1 GiB、付费 trace 总体 100,000 请求、Provider 请求受可配置 -provider-timeout(默认 2 分钟)约束;trace、输出与验证器路径必须为绝对路径。库层 trace 解码默认每 JSONL 记录 96 MiB、100,000 条记录、64 MiB 请求体;观测解码默认每记录 8 MiB、100,000 条记录,ReadTraceJSONLWithLimits / ReadObservationJSONLWithLimits 允许嵌入方收紧边界。

内置 HTTP 传输支持四家 Provider(凭据均走环境变量,重定向一律拒绝,默认客户端忽略环境代理、要求 TLS 1.2+、限制响应大小、绝不把凭据写入证据或错误信息):

Provider 凭据环境变量 端点
OpenAI OPENAI_API_KEY Chat Completions 或 Responses
Anthropic ANTHROPIC_API_KEY Messages
Gemini GEMINI_API_KEY generateContent
Bedrock AWS_BEARER_TOKEN_BEDROCK,或 access key + secret + 可选 session token Converse;使用 IAM 时走 SigV4

observation v3 与评估

运行器发出 observation v3 记录(结构见 ObservationRecord):

{"schema":"caveman.cachebench.observation.v3","request_id":"request-001","request_body_sha256":"<sha256-from-trace>","provider_evidence_sha256":"<sha256-of-retained-provider-response>","provider":"openai","epoch":"agent-epoch-1","eligible_input_tokens":10000,"cache_eligible":true,"applied":true,"engine_decision":"apply","engine_reason":"applied","profile_id":"openai-gpt-5.6-explicit-v1","attribution":"causal","optimizer_ids":["openai-prompt-cache-key","cave-cache-openai-explicit-v1"],"quality_passed":true,"quality_verifier":"swebench-harness@pinned-revision","quality_evidence_sha256":"<sha256-of-retained-grader-artifact>","usage":{"input_tokens_details":{"cached_tokens":9900,"cache_write_tokens":100}}}

评估 Provider 计数器:

go run ./cacheengine/cmd/cachebench \
  -observations /tmp/cachebench-observations.jsonl \
  -trace-in /tmp/cachebench-openai.jsonl

嵌入代码仍可用 NewObservationRecord 构造记录:它绑定真实 NativeResult 归因与优化器 ID,以及保留的 Provider 响应、验证器身份与质量工件的 SHA-256。观测评估器拒绝重复 ID/JSON 键、未知字段、畸形/负计数器、超过合格输入的计数器、无精确优化器证据的因果标签、任何失败的任务验证与低于要求数量的样本。回放层的失败也使用稳定失败码(validReplayFailureCode):schedule_driftmodel_visible_mismatchengine_not_cacheableclock_regressiontransport_errorprovider_response_invalidprovider_http_statusprovider_usage_invalidprovider_input_budget_exceededprovider_output_budget_exceededquality_verifier_errorquality_provenance_missing

保留输出目录必须不存在;命令以 0700 创建,文件原子写入、同步、0600,逐请求文件名以 SHA-256 派生、绝不暴露请求 ID(布局见 REPLAY_PROTOCOL.mdmanifest.jsonreport.jsonreplay-summary.jsonevidence.jsonlobservations.jsonl 与四个逐请求子目录)。被中断/失败的目录本身仍是证据,且永不续入同一总体——墙上时间与 Provider 缓存状态都已改变。

Provider 观测层面的通过仍不证明被省略的尾部流量、流量普遍性、Provider 账单支出或已验证节省——那些属于受管账本工作,因此 publishable 恒为 false。

失败演练与退出码

失败演练验证门槛确实会拒绝坏场景。让所有 Anthropic 请求都超出 5 分钟 TTL(默认间隔 3 秒改为 6 分钟):

go run ./cacheengine/cmd/cachebench \
  -providers anthropic \
  -turns 128 \
  -step 6m \
  -target 0.97

预期 FAIL。程序退出码语义固定(见 main.go 的出口逻辑):门槛失败退出 1;无效输入/配置退出 2;仅当每个选中的 Provider 都通过门槛时退出 0

证据边界小结

cachebench 的设计可以浓缩为四条边界:

  1. 模拟证明机制:黄金路径与语料回放都是确定性 Provider 缓存模拟,零网络调用,永远不是生产或节省证据(benchmark_simulated / benchmark_public_corpus_simulated)。
  2. 观测证明总体:实时回放用 Provider 原生计数器评估,但只证明所供应的精确总体,不证明流量普遍性与账单节省(provider_observedpublishable: false)。
  3. 门槛从不放水:冷启动、TTL 过期、压缩、前缀失效全部留在分母;低于下限的请求是 inelig 而非 miss;无效样本与等价失败一票否决。
  4. 诊断与门槛分离opportunity_* 捕获率解释“引擎实现得有多好”,97% 原始门槛回答“这个数字对用户成立吗”——两者不可互相替代。

自定义 Provider 的接入路径同样明确:构造 Trace 值并调用 EvaluateTrace,与内置场景共用同一套缓存与安全门槛;cacheengine 中同一套 Profile/Driver 仍是缓存语义的唯一来源。

相关文件索引:cacheengine/cachebench/README.mdcacheengine/cachebench/REPLAY_PROTOCOL.mdcacheengine/cachebench/types.gocacheengine/cachebench/simulate.gocacheengine/cachebench/corpus.gocacheengine/cachebench/replay.gocacheengine/cmd/cachebench/main.gocacheengine/cmd/cache-replay/main.gocacheengine/cachebench/scripts/fetch_lmcache_agentic_traces.shcacheengine/cachebench/results/lmcache-agentic-traces-2026-08-10.json

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.79 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
988
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384