caveman cacheengine:独立运行的 Provider 原生 Prompt Cache 规划器与 Wire 引擎深度解析
【免费下载链接】caveman🪨 why use many token when few token do trick — Claude Code skill that cuts 65% of tokens by talking like caveman项目地址: https://gitcode.com/GitHub_Trending/caveman1/caveman
本文围绕 caveman 仓库中的cacheengine模块展开,讲解它如何在不依赖网关、网络、数据库或控制面的前提下,为一组"有序稳定前缀"计算正收益的缓存断点,并针对 Anthropic、OpenAI、Bedrock、Gemini 等 provider 生成原生 wire 变换。读完本文,你将理解其能力驱动(capability-driven)的规划模型、盈亏平衡经济学计算、pass-through 安全边界,以及如何通过Profile+Driver两个扩展点接入新的 provider。
一、模块定位:独立、纯本地的缓存元数据引擎
cacheengine是一个独立的 prompt-cache 规划器与 provider 原生 wire 引擎,导入路径为:
github.com/JuliusBrussee/caveman/cacheengine它的职责边界非常明确(见 cacheengine/doc.go):只规划并应用 provider 原生的 prompt 缓存元数据,不存储或回放模型响应,也不管理自托管 KV 缓存内存。它接受 wire bytes 并返回 wire bytes,不做任何 provider 调用,因此 proxy、SDK、sidecar 或本地进程都可以直接内嵌。
从源码结构看,核心生产路径只复用 6 个非标准库包:Caveman JSON splice、cache guard、catalog/cost 与 YAML 相关包(cacheengine/native.go 中可见对jsonsplice与cacheguard的依赖)。Parity 测试(cacheengine/wire_parity_test.go)将 Anthropic 与 Bedrock 行为锁定到既有网关变换,但生产代码不导入网关运行时。
许可说明
源码采用 Business Source License 1.1(BSL-1.1),属于 source-available,在 Change Date 之前不算 OSI 开源。第一方自托管生产使用被允许;第三方托管、托管服务或嵌入式服务使用需要商业许可。详见 cacheengine/LICENSE 与 LICENSING.md。
二、通用规划器:认识能力,而非 provider 名称
Engine.Plan是纯规划入口:它不编辑任何 wire bytes,只返回一份Plan。设计核心是Profile结构体(cacheengine/types.go)——一段与 provider 名称解耦的能力数据:
| 字段 | 含义 |
|---|---|
Mode | explicit/affinity/implicit/unsupported四种 provider 缓存控制语义 |
Attribution | 一次命中证明什么:causal(可归因引擎)、affinity(仅亲和)、organic(自然发生)、none |
MinPrefixTokens | provider 最小可缓存前缀 token 数 |
MaxBreakpoints | 允许的断点数上限 |
WriteMultiplier/ReadMultiplier | 以输入费率单位为基准的写入/读取缓存倍率 |
EconomicsKnown | 经济学参数是否可信 |
TTL/Rolling/RoutingKey/MaxRPMPerKey | TTL、滚动边界、路由键与每键 RPM 上限 |
规划调用示例
来自 cacheengine/README.md 的完整示例:
engine := cacheengine.New(cacheengine.Config{}) plan, err := engine.Plan(cacheengine.PlanRequest{ Scope: "org/project", Epoch: "conversation-42", ExpectedCalls: 8, Profile: cacheengine.Profile{ ID: "provider-cache-v1", Mode: cacheengine.ModeExplicit, MinPrefixTokens: 1024, MaxBreakpoints: 4, EconomicsKnown: true, WriteMultiplier: 1.25, ReadMultiplier: 0.10, RoutingKey: true, }, Segments: []cacheengine.Segment{ {Name: "tools", Content: toolBytes, Tokens: 1800, Stable: true, Cacheable: true}, {Name: "live", Content: userBytes, Stable: false}, }, })两个关键语义(README 与types.go注释一致强调):
ExpectedCalls指"在 provider 缓存条目保持热身的 TTL 窗口内、预期共享该前缀的调用次数",不要灌入跨越缓存过期缝隙的终身总调用数。Segment.ExpectedCalls为零时继承PlanRequest.ExpectedCalls;PlanRequest.ExpectedCalls为零时按保守的"一次写入/一次读取"处理(实现见 cacheengine/engine.go,零值被规整为 2)。- 经济学使用输入费率单位(input-rate units),绝不猜测美元。1 个单位 = 1 个按全价输入费率计费的 token,调用方只能用有据可依的 provider 目录数据自行定价。
盈亏平衡与断点选择
规划器在 engine.go 的breakpointCandidates中逐段累积前缀,对每个候选边界计算净收益:
net = prefix_tokens × (calls − WriteMultiplier − (calls−1)×ReadMultiplier)以 Anthropic 类 1.25/0.10 的倍率为例,calls=2时 net = tokens × (2 − 1.25 − 0.10) > 0,即两次调用即回本;breakEvenCalls则通过 2..10000 的线性搜索给出正收益的最小调用数。候选还需满足MinPrefixTokens门槛(不满足记below_minimum),且"更长前缀不能拥有更高预期复用次数"(违反即报错)。当候选数超过MaxBreakpoints时,limitBreakpoints按ExpectedNetInputRateUnits降序保留前 N 个,再恢复原始顺序(engine.go)。
路由键与负载分片
对RoutingKey: true的 profile(如 OpenAI),keyShard依据ExpectedRequestsPerMinute与MaxRPMPerKey(默认 15)计算分片数:count = 1 + (rpm−1)/maxRPM,上限为Config.MaxKeyShards(默认 64,显式值 1..1,000,000)。分片号由PartitionKey(缺省回退到Epoch)的 SHA-256 取模得到;routingKey最终是scope\0profileID\0prefixSHA\0shard的 SHA-256 前 16 字节 hex。从源码结构看,这些键是**租户不透明(tenant-opaque)**的——不含任何业务身份信息,只用于 provider 侧的缓存亲和路由。
前缀安全:drift 与 volatile 检测
规划前,引擎把稳定段按 8 字节长度帧(name 长度 + content 长度,大端序,见appendFrame)拼装成 epoch 字节,交给两个安全检查:
- volatile 检测:
cacheguard.DetectVolatile识别"标称 stable 但内容实际波动"的段;命中则返回volatile_prefix并附volatile_stable_slot警告。引擎内部还有一个 8192 容量 LRU 的prefixSafetyCache缓存"已确认安全"的前缀摘要,避免重复扫描。 - 前缀漂移(drift)检测:
cacheguard.Inspect以sha256(scope\0epoch\0profileID)为 epoch key 追踪历史前缀摘要;若同一 epoch 内前缀摘要发生变化,返回prefix_drift直接 pass-through。StartEpoch则允许调用方显式冻结新前缀(要求前缀不含 volatile 内容),返回new_epoch决策。
三、Optimize:一条不改字节的调用链
Engine.Optimize是面向 wire 的主入口(cacheengine/native.go),README 中的用法:
result, err := engine.Optimize(ctx, cacheengine.NativeRequest{ Scope: "org/project", Epoch: "conversation-42", Provider: "openai", Model: "gpt-5.6", Endpoint: "/v1/responses", Body: requestBody, PrefixTokens: providerCount, ExpectedCalls: 8, RuntimeMode: "optimize", AuthMode: "payg", }) upstreamBody := result.Body // original bytes on every unsafe/unsupported path它不做任何 provider 调用,且在任何不安全/不支持路径上都原样返回拷贝后的原始字节。NativeRequest的关键字段:PrefixTokens应来自 provider 计数(为零时变换仍可进行,但阈值/经济学资格未知);StableSegments供自定义 provider 绕过内建信封提取;Profile仅对注册了自定义Driver的 provider 生效,内建编译器拒绝逐请求的能力覆盖(reason: profile_mismatch)。
内建稳定前缀的提取规则
nativeStablePrefix(native.go)按 provider 从请求体中抽取稳定字段并加帧:
| Provider | 稳定字段 | 序列字段 |
|---|---|---|
| anthropic | tools、system | messages(仅 system/developer 前导项) |
| openai | tools、instructions | responses端点为input,否则messages |
| bedrock | toolConfig、system | messages |
| gemini | systemInstruction、tools | contents |
model字段也会加入前缀帧,因为换模型即换缓存语义。
必须 pass-through 的完整条件清单
以下任一情况发生,Optimize保留原始字节并给出显式reason(NativeResult.Reason,取值来自 types.go):
- 畸形或歧义 JSON(包括重复键,由
inspectUniqueJSONValue的 token 级扫描强制,深度上限 512); - 不支持的内置模型/端点(内建端点白名单:anthropic
/v1/messages;openai/v1/chat/completions、/v1/responses;bedrockconverse/converse-stream/invoke/invoke-with-response-stream;geminigenerateContent); - 请求元数据模型与 body 中
model字段不匹配(profile_mismatch); - 请求体已含调用方自管的缓存字段(
caller_managed,如cache_control、prompt_cache_key等,cacheMarkerAt按 provider 识别标记路径); - record 模式(
record_mode)、非 PAYG 认证模式(non_payg); - volatile 稳定段(
volatile_prefix)、前缀漂移(prefix_drift)、低于 provider 最小前缀(below_minimum)、无预期复用(no_expected_reuse)、负经济学(negative_economics)。
此外,配置层还有一道资源上限:provider 原生 body 上限与加帧稳定前缀上限默认各自 64 MiB,通过Config.MaxRequestBytes与Config.MaxStablePrefixBytes配置,显式值必须在 1 字节到 1 GiB 之间;两者都在拷贝或拼接之前拒绝超限(stablePrefix在 engine.go 中按帧逐段检查)。请求标识、段名、profile ID 与路由元数据都有长度上限并拒绝控制字符;自定义 driver 输出不得超过配置的 body 上限。
四、Provider 原生桥接:各家的"落地编译"策略
README 给出了一张内置策略表,下面结合源码逐一印证:
| 表面 | 行为 | 归因上限 |
|---|---|---|
| Anthropic | 复用既有稳定 tool/system 断点;追加顶层滚动自动缓存 | 因果 provider 观测;独立美元保持为零 |
| OpenAI GPT-5.6 家族 | 范围化 affinity key + 1 个稳定断点与最近 3 个显式断点;body 无安全可标记块时回退为纯 affinity | 因果 provider 观测;仓库验证账本扩展尚未构建 |
| 早期 OpenAI | 在 provider 自动缓存之上使用范围化 affinity key | 仅 affinity |
| Bedrock Anthropic Claude | 复用目录门控的稳定点,追加滚动消息检查点 | 因果 provider 观测;独立美元保持为零 |
| Gemini | 观测 provider 隐式管理的缓存,不改写 body | 自然发生,绝不归因于引擎 |
| 未知 | 精确 pass-through | 不可用 |
Anthropic / Bedrock:稳定点 + 滚动点
applyAnthropic(native.go)先由applyAnthropicStable落一个稳定的 tool/system 断点(optimizer idanthropic-cache-breakpoints),再用jsonsplice.AppendObjectFields在顶层追加cache_control: {"type":"ephemeral"}作为滚动点(optimizer idcave-cache-anthropic-rolling-v1)——追加前检查字段是否已存在,已存在则不动。Bedrock 类似:稳定点(bedrock-cache-points)+appendBedrockRolling按端点区分——converse系列往最后一条消息content追加{"cachePoint":{"type":"default"}};invoke系列则把字符串 content 包装成带cache_control的 block 或在最后 block 上追加cache_control。
内置 profile 的兼容条件是硬编码的(builtinProfileCompatible,native.go):Anthropic/Bedrock 要求ModeExplicit+TTL 5min+MaxBreakpoints 4+Rolling+ 指定 OptimizerID;OpenAI explicit 要求TTL 30min且RoutingKey;Gemini 要求ModeImplicit+AttributionOrganic。能力数据本身由 profiles.go 从 provider 目录(catalog 包的prompt_cache/prompt_cache_key/explicit_cache能力位)解析,并叠加模型级最小前缀(如 Anthropic haiku-4-5/opus-4-5/4-6 为 4096,fable-5/mythos-5 为 512,其余默认 1024;Bedrock opus-4-5/4-6、sonnet-4-5、haiku-4-5 为 4096,claude-3-5-haiku 为 2048)。缓存写/读倍率优先取自目录价格(CacheWritePerMillion / InputPerMillion),无价时回退 1.25/0.10,OpenAI 无写价时回退 1.0。
OpenAI:affinity key 与 GPT-5.6 显式断点
applyOpenAI(cacheengine/openai.go)先插prompt_cache_key(routingKey),再视显式模式决定是否插prompt_cache_options: {"mode":"explicit"}。核心在markOpenAIBreakpoints:
- 扫描
messages(chat)或input(responses)序列中可标记项:chat 端支持text/image_url/input_audio/file/refusalblock,responses 端支持input_text/input_image/input_file,且 role 限定(responses 端不含tool); - 选出"1 个稳定锚点 + 最近 3 个可缓存块",按索引降序逐一写入
prompt_cache_breakpoint: {"mode":"explicit"}——降序保证每次插入不破坏后续目标的原始 span 有效性; - 若 body 找不到任何安全可标记块,则整体回退为纯 affinity(结果
reason: affinity_fallback,Attribution被降级为affinity,见 native.go)。
源码注释点明了滚动语义的意图:GPT-5.6 显式模式不向"未标记前缀"回退——保留 N 请求写入的滚动标记,使 N+1 请求能读到 N 写下的前缀,同时至多新增一个滚动写入。而"哪些模型走 explicit"被刻意收窄:openAIExplicitModel只认gpt-5.6及gpt-5.6-前缀,因为旧模型会拒绝显式缓存字段。
Gemini:只观测,不改写
Gemini 的 profile 是ModeImplicit+AttributionOrganic+EconomicsKnown: false。Plan对 implicit 模式直接把所有净收益清零、EconomicsBasis置为provider_managed_unattributed,决策为observe_only(engine.go)——引擎不插入任何字段,只承认 provider 自己管理的缓存是"自然发生"的,永不归因于引擎。
五、观测与记账:绝不"铸造"已验证美元
README 强调:两条观测路径都不铸造已验证节省(verified savings),VerifiedSavingsUSD恒为零;更强的美元声明只属于受管网关账本。
Observe(result, usage):接受归一化的 provider 用量,区分hit/write/miss/unavailable四种状态;仅当result.Applied且 profile 为AttributionCausal时才置AttributedToEngine(types.go)。ObserveRawCacheUsage/NormalizeRawCacheUsage(cacheengine/raw_usage.go):直接映射各家官方原始计数器,覆盖 OpenAIinput_tokens_details/prompt_tokens_details下的cached_tokens与cache_write_tokens(旧版共享归一器可能不暴露该字段)、Anthropic 的cache_read_input_tokens/cache_creation_input_tokens(并校验cache_creation.ephemeral_5m/1h明细之和)、Bedrock 的cacheReadInputTokens/cacheWriteInputTokens、Gemini 的cachedContentTokenCount。重复键、负数/小数、OpenAI 双形状歧义(input_tokens_details与prompt_tokens_details同时出现)一律 fail closed。ExtractProviderUsage:从完整非流式响应中提取用量对象并绑定 provider 计数的总输入 token 分母;Anthropic/Bedrock 的总量按 provider 契约等于未缓存 + 缓存读 + 缓存写之和,任何不一致都拒绝。
六、接入新 Provider:Profile + Driver,规划器不变
README 的扩展契约:提供能力 profile 加一个Driver,规划器保持不动。内建 profile 必须显式绑定Provider;Driver 收到选中的断点,且当安全编译不可能时必须返回原始字节且不携带任何 optimizer ID。
engine := cacheengine.New(cacheengine.Config{ ResolveProfile: func(r cacheengine.NativeRequest) (cacheengine.Profile, bool) { return acmeProfile, r.Provider == "acme" }, Drivers: map[string]cacheengine.Driver{ "acme": acmeWireDriver, }, })约束细节:Driver 的 key 是归一化(trim + 小写)的 provider 名,归一化后必须唯一,否则NewChecked直接报错;自定义请求需提供StableSegments(缺失时返回no_stable_prefix);ResolveProfile与Driver回调可能并发执行,必须自行保证并发安全。Engine构造后并发安全(New/NewChecked见 engine.go),生产构造器应使用NewChecked;遗留New也把配置错误存起来,使所有操作 fail closed。DriverFunc适配器让函数式 driver 实现接口。
七、验证体系:97% 门禁与诚实数字
README 的 Proof 部分给出零 provider 调用的本地验证命令(注意其假设仓库源码位于public目录下的布局,当前仓库中对应路径为cacheengine/):
go test -race ./cacheengine/... go vet ./cacheengine/... go test -run '^$' -bench BenchmarkOptimizeOpenAIExplicit -benchmem ./cacheengine go run ./cacheengine/cmd/cache-experiment go run ./cacheengine/cmd/cachebench go run ./cacheengine/cmd/cache-replay -helpcache-experiment的 fixture token 计数与盈亏平衡输出是模型化证据,不是活缓存命中证据。
cachebench:可复现的 97% 门禁
cacheengine/cachebench/README.md 回答了核心问题:cacheengine 能否在一个工具型 agent 上维持 ≥97% 缓存命中,同时不隐藏冷启动、压缩、语义变更、非法用量或不支持的 provider 行为?
- 默认运行(
go run ./cacheengine/cmd/cachebench,零 flag):每 provider 128 请求,覆盖 4 家 provider;负载含 8192 声明稳定 system/tool token、增长的用户/assistant 工具调用/工具结果历史、每 64 轮一次计划内压缩(压缩开启新 epoch,其冷写入留在分母内)。预期输出为CACHEBENCH agent-cache evaluation: PASS,四家 provider 请求命中 99.22%、token 命中 97.79%(gemini 归因为 0.00%,因其命中永远是 organic)。 - 指标契约:
request_hit_rate = 有 cache_read_tokens>0 的请求 / 全部合格请求;token_hit_rate = Σcache_read_tokens / Σ合格前缀 token。两者都计入冷启动、TTL 过期、压缩与前缀失效;inelig(低于 provider 最小值)不算 miss 也不算无效样本;未知 provider、畸形 body、静默漂移、不安全变换、缺失 usage 则记 invalid 并使门禁失败。 - 公开语料:导入 CC-BY-4.0 的 LMCache Agentic Traces(SWE-bench/GAIA/WildClaw agent 请求历史),固定源码 hash 并限制留存内存。README 明确记录当前公开语料结果是保守模拟且未通过严格 97% 门禁(完整训练集:24,880 请求,96.89% 请求命中 / 95.76% 估算 token 命中,门禁 FAIL;单 shard 跨 provider 回放:四家请求命中 97.01%~97.63%,token 命中均 <97%),机器可读结果见 results/lmcache-agentic-traces-2026-08-10.json。内置能力行为已于 2026-08-10 对照各 provider 官方缓存文档校验(Anthropic、OpenAI、Gemini、AWS Bedrock)。
cache-replay:不削弱证据的外部 runner 胶水
cache-replay(cacheengine/cmd/cache-replay)提供精确 v3 trace 重建、opt-in 认证调用、无自动重试、provider 计数用量、外部任务打分、私有留存产物与 exact-population 观测 v3。全部 trace 的优化与模型可见等价性在第一次调用之前完成;有界并发 worker 使用绝对 trace 计时,调度漂移超限即失败。调用方声明的优化后 wire 输入上限加 provider 原生最大输出字段构成 preflight 计费 token 上限——provider 计数基准仍是调用方自证,上限不保证实际 token 或美元封顶。合成/会话本地计时与估算 token 预算在 live 默认下直接失败。详见 cacheengine/cachebench/REPLAY_PROTOCOL.md。
八、产品边界:与响应缓存、KV 缓存的区分
README 用一张表划清边界,避免概念混淆:
| 类别 | 代表 | 差异 |
|---|---|---|
| Provider prompt 前缀规划器 | cacheengine | 纯元数据请求变换;provider 仍运行模型并上报缓存计数器 |
| 精确/语义响应缓存 | Helicone、Portkey、GPTCache 等网关产品 | 回放存储的输出;语义模式引入答案等价风险 |
| 自托管 KV 缓存 | vLLM APC、LMCache | 控制推理内存;需要服务基础设施 |
README 同时明确:目前不存在任何"市场上最优"的声明——那需要同一人群的活 provider 计数器、任务质量验证、延迟与竞品对比,当前公开语料产物仍是保守模拟。"永远缓存"作为字面保证不可能成立:provider 最小值、TTL、并发、容量、精确前缀变更、不支持的模型与自然缓存都仍可能 miss。引擎的职责是最大化合格稳定前缀,并在无法行动时返回显式原因;调用方的缓存字段永远优先。
小结
cacheengine的价值主张可以概括为三点:其一,规划器与 provider 解耦——能力数据(Profile)驱动断点选择与经济学判定,wire 差异被隔离在Driver/内建编译器之后;其二,全程 fail closed——从重复 JSON 键、前缀漂移、volatile 段到超限字节,任何不确定都退回原始字节并给出机器可读 reason;其三,证据分层严格——模拟、provider 观测、可归因、已验证美元是四个不同强度,模块只承诺到它有能力证明的层面。对需要在 proxy、SDK 或 sidecar 中嵌入原生 prompt 缓存优化的工程,它的Optimize单入口 + 零外部依赖的特性使其可以直接内嵌使用。
【免费下载链接】caveman🪨 why use many token when few token do trick — Claude Code skill that cuts 65% of tokens by talking like caveman项目地址: https://gitcode.com/GitHub_Trending/caveman1/caveman
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考