首页
/ Caveman Engine 深度解析:可恢复的本地上下文压缩引擎,15 个压缩器、S0–S4 安全阶梯与 CCR 恢复存储

Caveman Engine 深度解析:可恢复的本地上下文压缩引擎,15 个压缩器、S0–S4 安全阶梯与 CCR 恢复存储

2026-09-04 19:13:41作者:鲍丁臣Ursa

Caveman Engine 是 caveman 项目中的核心压缩引擎,负责在 AI Agent 的每次模型调用前,把对话历史与工具结果中的大日志、JSON、表格、代码清单、diff 和终端输出压缩成更小的上下文,并保证压缩可精确恢复。本文基于 engine/README.md 及其配套源码,完整讲解其四调用核心 API、fail-closed 字节安全契约、内容寻址的 CCR 恢复存储、caveman-engine CLI 的每条子命令与限制参数,帮助你在现有 Agent 中接入该引擎,或将其作为库与 CLI 直接嵌入自己的工具链。

引擎要解决的问题

Agent 在单个任务中会反复把对话历史和工具结果重新发给模型。大日志、JSON、表格、代码清单、diff 和终端输出往往被同一任务重复读取多次,这些内容构成了上下文中可压缩的"噪音"。Caveman Engine 的思路是:检测内容形态 → 路由到匹配压缩器 → 在发出有损结果之前先把原始字节存到本地 → 把更小的上下文和恢复句柄交给 Agent

由于压缩改变的是模型实际看到的内容,Engine 的设计前提是"任何压缩都必须可恢复":

  • 输入无法解析时,原样透传,不声明任何节省;
  • 恢复存储不可用时,有损压缩器拒绝运行;
  • 压缩结果在 token 计数下不比原文更小时,同样原样透传。

Engine 完全本地运行,不需要 Caveman 账号。所有 token 减少量是本地 o200k_base 分词器给出的估计值,结果中标注 inferred 基线——它们是本地估计,不是供应商账单,也不是经过验证的节省金额。

快速开始:在现有 Agent 中使用

终端用户安装薄 CLI 后,通过本地运行时启动受支持的 Agent:

npm i -g @caveman-ai/cli
caveman claude

Claude Code、Codex、Gemini、Aider、Hermes、OpenClaw 和 opencode 均已有注册 profile。具体行为取决于 Agent 协议和可用的恢复路径;当安全的压缩路径不可用时,运行时要么收窄变换范围,要么带显式警告直接启动。

工作流程与核心 API

README 中给出的核心流水线如下:

agent context
    ↓
detect content type
    ↓
matching compressor
    ↓
store original locally before lossy replacement
    ↓
smaller context + recovery handle

CompressRetrieveDetectStats 构成稳定核心 API,被 proxy、CLI、SDK、MCP server 和 WASM 构建共同使用。在 engine/engine.go 中可以确认这一契约:

// Engine is the compression core. Construct it with New.
type Engine struct {
    registry *compressors.Registry
    counter  tokens.Counter
    store    *ccr.Store
}

构造函数 New(store, counter) 有一个关键的 fail-closed 语义(见 engine.go#L36-L41):store 可以为 nil,此时引擎仍然能检测并做透传,但永远不会运行有损压缩器——因为"没有恢复路径的有损结果"违反了可逆性契约。

除四调用 API 外,源码中还有一个补充接口 Simulate:它与 Compress 走完全相同的 detect → route → compress → count 流水线,但不写入任何 CCR 记录、不发起网络调用,纯干跑报告一次真实压缩将会达到的 token 缩减。它的唯一刻意差异是:对没有 store 支撑的有损压缩器,Compress 会 fail-closed 透传,而 Simulate 仍然报告"将会发生的缩减"并以 Recoverable=false 标记,提示调用方必须先配置 CCR 才能真的发出该变换。

15 个默认压缩器

默认注册表包含 15 个压缩器,在 compressors/compressor.goDefault() 中逐一注册:

# 内容类型 说明
1 json 结构化 JSON 压缩
2 log 日志行压缩
3 code 代码清单压缩,构建时选择:启用 cgo 用 tree-sitter,否则用纯 Go go/ast 实现
4 diff diff 压缩
5 search-result 搜索结果(文件:行号)压缩
6 text 保守的通用文本压缩
7 html HTML 文档/片段
8 tabular 表格数据
9 config 配置文件
10 tool-schema 工具 schema
11 tool-schema-annotations 工具 schema 注解
12 toon JSON 到 TOON 的无损往返编码
13 a11y(accessibility tree) 无障碍树
14 repetition 重复内容去重
15 terminal 终端输出

其中 tool-schema、tool-schema-annotations、TOON、a11y、repetition 五类永远不会被自动检测命中,只能通过强制 Options.Type 到达。每个压缩器都是纯字节变换:不数 token、不写恢复、不联网——这些职责由引擎核心在压缩器外围承担。这也是"新增压缩器只需一个文件加其测试"的原因。

压缩器接口定义同样在 compressor.go

type Compressor interface {
    ContentType() string
    SafetyClass() safety.Class
    Compress(input []byte) (out []byte, ok bool)
}

Compress 在任何解析问题下返回 ok=false,调用方必须原样转发原始字节。可选的 QueryAwareCompressor 能力允许压缩器在设置查询时(确定性 BM25,无 embedding)把保留内容偏向查询相关项;空查询行为与历史行为完全一致。

record 模式与失败方向

Mode 只有两个取值,定义在 result.go

const (
    ModeRecord   Mode = "record"   // 永远透传,默认
    ModeCompress Mode = "compress"
)

record 模式绝不变换字节,输出与输入逐字节一致,也不写恢复存储。Mode.normalized() 的实现显示:空值或任何未知模式都回落到 record——未知枚举值 fail-closed。同理,evals 中未知 grader 返回 passed: false

安全阶梯:S0–S4 分类

每个压缩器声明自己所在的安全等级,该等级内生于压缩方法本身,而非用户选项。等级注册表在 safety/safety.go 中,它回答两个"诚实问题":该类是否改变模型可见字节?是否必须先存可恢复记录(CCR)才允许运行?

等级 语义 ByteSafe RequiresCCR Reversible
S0 字节安全行为(元数据、记账) true false true
S1 供应商原生提示(缓存、路由) true false true
S2 需要 SDK 配合的结构变换 false false true
S3 行为变换(路由、推理),云端经 eval 门控 false false false
S4 有损结构压缩:改变模型可见字节,必须可逆(CCR),并披露丢弃了什么 false true false

只有 S4 强制 RequiresCCR:没有恢复存储,S4 压缩器根本不允许运行。Lookup 对未知等级返回 false,调用方一律按"不可安全运行"处理。

Compress 的 fail-closed 契约

engine.go#L68-L140 中的 Compress 是引擎的心脏,其透传条件完整覆盖了 README 的承诺:

  1. record 模式 → 直接透传;
  2. 注册表中没有匹配的内容类型压缩器 → 透传;
  3. 安全等级未知 → 透传;
  4. S4 压缩器但没有本地 store(且调用方未声明 ExternalRecovery)→ 透传;
  5. 压缩器报告解析问题(ok=false)→ 透传;
  6. 压缩后 token 数不小于原文,或字节逐字节相同 → 透传,不声明任何节省
  7. 有损结果的 CCR 写入失败 → 所有结果字段保持透传值,调用方永远不会拿到"没有持久句柄的变换字节"。

结果结构体 Result 的 JSON 字段如下(result.go#L47-L69):

{
  "content_type": "json",
  "tokens_before": 1200,
  "tokens_after": 780,
  "token_count_basis": "o200k_base",
  "ratio": 0.35,
  "basis": "inferred",
  "recovery_handle": "ccr_...",
  "method": "json",
  "lossless_to_model": true
}

PassedThrough() 通过 recovery_handle == "" && method == "" && ratio == 0 判定本次调用是否原样透传,供上层(如 CLI 的边界检查)使用。

CCR:内容寻址的恢复存储

CCR(Caveman Context Recovery)包负责保存每次有损压缩的原始字节,engine/ccr/store.go 头部注释说明了其不变式:retrieve(handle) 必须逐字节返回原文,引擎压缩的内容绝不被销毁

关键设计(ccr/store.go):

func Handle(original []byte) string {
    sum := sha256.Sum256(original)
    return "ccr_" + hex.EncodeToString(sum[:16])
}

句柄是原文的 SHA-256 前 16 字节的十六进制,前缀 ccr_。内容寻址使引擎天然幂等:同一载荷压缩两次得到同一句柄,只存储一次。

存储实现按平台分裂:宿主平台用本地 SQLite 库(ccr/store_sqlite.go),js/wasm 构建用纯 Go 内存 map(ccr/store_wasm.go,因为 modernc.org/sqlite 不支持 js/wasm 构建)。两者暴露相同类型与方法,引擎对差异无感知。CLI 默认在 ~/.caveman/ccr.db 打开该存储,路径解析在 cmd/caveman-engine/main.go#L741-L746

  • CAVEMAN_CCR_DB 可覆盖数据库路径;
  • CAVEMAN_HOME 可覆盖 ~/.caveman 目录。

另外,CCR store 还持有第二个 ID 空间:原生运行时工具输出掩码铸造的 typed OBJECT id(显示为 ccr://<id>)。因此 Retrieve 在 blob 表未命中时会先回落到 object 表再报错(engine.go#L247-L266)——解析不了句柄会诱发反复重试取回,恢复路径必须解析运行时能发出的所有引用。

512 MiB 存储预算与 CAVEMAN_CCR_MAX_BYTES

持久 CCR 存储默认保留至多 512 MiB 载荷。在启动前设置 CAVEMAN_CCR_MAX_BYTES 为正整数字节数可更改上限,环境变量解析见 store_sqlite.go#L129-L132,非法值直接报错拒绝启动。达到上限后的行为同样 fail-closed:

  • 新的有损变换回落为原始字节透传,CLI 报告 cave_ccr_budget_exceeded(存储不可用则为 cave_ccr_unavailable);
  • 已存在的句柄永不被逐出,保持可恢复

Engine CLI:caveman-engine

caveman-engine 是独立压缩引擎二进制,CLI 与其他工具通过 shell 调用它。完整子命令集:

caveman-engine compress < input
caveman-engine detect < input
caveman-engine retrieve <handle>
caveman-engine stats
caveman-engine registry
caveman-engine toon encode|decode
caveman-engine pixel render|simulate
caveman-engine evals run [--fixtures DIR]

结合 main.go 的源码,各命令的实际行为如下:

compress

compress 从 stdin 读取载荷,输出压缩后的字节到 stdout,JSON 报告写 stderr(保证 stdout 是干净的载荷字节)。支持 --type <content-type> 强制内容类型,--type auto 等价于自动检测:

caveman-engine compress --type json < payload.json

当 CCR 写入失败时,CLI 边界层 emitCompressResult 会做一致性校验:只要输出不是原始字节、或结果不满足透传条件,就直接 fatal,而不是猜测着继续——这是对引擎字节安全契约在进程边界上的最后一道守卫。

detect

detect 打印 stdin 载荷的检测到的内容类型,不需要打开恢复存储。检测算法在 detect.go 中是确定性的、fail-open 的:不确定一律归为 text(路由到保守压缩器)。严格顺序为:strict-JSON → terminal → diff → HTML → tabular → code → log → search-result → config → text。其中有几个值得注意的判断:

  • terminal 放在 diff/code/log 之前,因为裸 ANSI/CSI 转义序列是决定性信号(只有终端输出会内嵌它),低置信时还要求 3 个以上裸回车(排除普通 CRLF);
  • #!/ 开头、关键词 ≥ 3 且带结构信号(花括号、缩进块等)判为代码;被日志行主导的载荷即使含代码关键词也路由到 log 压缩器;
  • HTML 检测会先排除携带 JSX/TSX 代码结构的载荷,避免把源码里的标记字符串当文档抽成垃圾文本。
caveman-engine detect < some.log      # 输出 log

retrieve

retrieve <handle> 打印该 CCR 句柄对应的原始字节;带第二个参数(查询)时走与 MCP caveman_retrieve 工具相同的 BM25 路径,只返回最相关的章节:

caveman-engine retrieve ccr_8f3a...            # 字节精确原文
caveman-engine retrieve ccr_8f3a... "timeout" # 与 timeout 最相关的段落

stats / registry

stats 从恢复存储聚合压缩记账,输出含 totalsby_content_typestorage_bytesmax_storage_bytesstorage_full 的 JSON;registry 输出 transform-capability manifest JSON——一份稳定的能力 ABI 清单,列出每个变换的 ID、安全等级、确定性标志、恢复方式与 conformance 摘要(见 compressor.go#L152-L200)。

toon encode|decode

无状态、不走 CCR 的 JSON⇄TOON 转换器:让 Agent 发出紧凑的 TOON 形式(下游再恢复 JSON),或读取大 JSON 的 TOON 渲染,而无需在自己的上下文里写入/读出冗长 JSON。编码 fail-closed:不是合法 JSON 或形状超出已证明可往返的子集时返回错误而非有损近似,调用方保留原 JSON。

pixel render|simulate

pixel render 把文本文件渲染为 <file>.pxN.png 分页 PNG 加 JSONL 指标,默认 reflow 换行,支持 --cols N--multicol N--density conservative|balanced|max--dense--no-reflowpixel simulate 嗅探请求 JSON 格式(input → OpenAI Responses,contents → Gemini,messages → Anthropic Messages),无网络地输出像素变换的 TransformInfo JSON,--model 可覆盖或补全模型字段。

evals run

evals run [--fixtures DIR] 运行内嵌或调用方提供的评估夹具,全部通过才返回 0,任何 fixture/grader 失败均以非零退出(fail-closed)。调用方提供的夹具目录被约束在 DIR 内,路径穿越与逃逸符号链接 fail-closed。

64 MiB stdin 上限

所有读取 stdin 的命令强制 64 MiB 输入上限(maxStdinBytes = 64 << 20main.go#L40),超限失败并报 cave_input_too_large

if int64(len(input)) > maxBytes {
    return nil, fmt.Errorf("cave_input_too_large: stdin exceeds %d bytes", maxBytes)
}

许可与构建

Engine 源码以 BSL 1.1 发布:它是 source-available,在 Change Date 2030-06-21 之前不属于 OSI 定义的开源软件;第一方自托管生产使用是被允许的。Agent SDK、薄 CLI、contracts、evals 与其他采纳面为 MIT。

在本仓库内构建与测试:

make product-build PRODUCT=engine
make product-test PRODUCT=engine

注册表 ID 为 engine

小结

Caveman Engine 的工程价值在于把"压缩上下文"从一个有损黑盒变成了一个可审计、可恢复、处处 fail-closed 的确定性管线:15 个内容感知压缩器由注册表路由,S0–S4 安全等级把"是否允许改变模型可见字节"变成静态事实,内容寻址的 CCR 存储保证任何有损结果都能逐字节取回原文,512 MiB 预算与 64 MiB 输入上限让本地资源消耗有界可预测。所有 token 数字以 inferred 基线诚实标注,透传时不声明任何节省——这套契约使得 proxy、CLI、SDK、MCP server 与 WASM 构建可以共享同一个四调用 API,而不必各自重新实现安全性。

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

项目优选

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