如何为Caveman添加新的Compressor:压缩器注册与开发完全指南
【免费下载链接】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 是一款面向 AI Agent 的 Token 压缩引擎,核心卖点是"用最少的 token 把事办成"——通过压缩器(Compressor)把 JSON、日志、代码等上下文缩减最多 65%。当你想支持一种新内容类型(比如 Markdown 表格、SVG、数据库查询结果),就需要为 Caveman 注册一个新的 Compressor。本文用通俗的方式讲清楚压缩器注册机制、开发步骤、安全等级声明和测试要求,帮助你从零到提交 PR。
一、先搞懂:Caveman 的压缩器注册机制
Caveman 的引擎采用「检测 → 查注册表 → 压缩 → 门禁校验」的流水线。所有 Compressor 都集中在engine/compressors/目录下,由一张**注册表(Registry)**统一路由:
- Compressor 接口:每个压缩器只需实现 3 个方法,见 compressor.go
ContentType():返回它负责的内容类型名(如"json"、"log")SafetyClass():声明自身在 S0–S4 安全阶梯上的等级Compress(input):纯字节变换,成功返回压缩结果,任何解析失败都返回ok=false,引擎会把原始字节原样透传(fail-closed 设计)
- Registry:一张「内容类型 → Compressor」的映射表。
Default()函数一次性注册全部 15 个内置压缩器,你的新压缩器也在这里"上岗"。
type Compressor interface { ContentType() string SafetyClass() safety.Class Compress(input []byte) (out []byte, ok bool) }内置 Compressor 一览
| 内容类型 | 压缩器 | 选择方式 |
|---|---|---|
json | JSON 数组折叠(保留错误项、首尾元素) | 自动检测 |
log | 日志降噪(保留 ERROR/FATAL 行) | 自动检测 |
code | 源码精简(tree-sitter / go-ast 双实现) | 自动检测 |
diff/search-result/text/html/tabular/config/terminal | 对应专用压缩器 | 自动检测 |
toon/a11y/toolschema/repetition等 | 高级变换 | 仅显式指定Options.Type |
几个设计要点值得新手特别注意:
- 纯字节变换:Compressor 不数 token、不存恢复记录、不碰网络——这些由引擎核心负责,所以每个压缩器都是自包含、可独立测试的模块。
- 确定性 + 幂等:相同输入永远得到相同输出,且压缩结果再压缩不会变化。
- 更小的门禁:压缩结果必须比原文小,否则引擎丢弃结果、回退原文。
- 有损可恢复:声明为 S4(有损)的压缩器,原始字节必须先存入 CCR 恢复存储(
engine/ccr/),模型后续可按 handle 取回原文。
二、开发新 Compressor 的 5 个步骤
步骤 1:新建一个压缩器文件
在engine/compressors/下新建文件(如markdown.go),参照 json.go 或 config.go 的写法:定义一个结构体持有可调参数(如保留行数、阈值),并提供NewXxx() Compressor构造函数。以 config 压缩器为例,它用一组正则识别 YAML/TOML/INI,结构体里只有minLines、keepHead、keepTail等几个参数,非常轻量。
步骤 2:声明安全等级
安全等级由压缩方法本身决定,写在 engine/safety/safety.go 的阶梯里:
| 等级 | 含义 | 是否可改模型可见字节 | 是否需要 CCR 恢复 |
|---|---|---|---|
| S0 / S1 | 元数据、缓存提示类 | 否 | 否 |
| S2 / S3 | 结构性 / 行为性变更 | 是 | 否 |
| S4 | 有损压缩(绝大多数压缩器) | 是 | 是,且必须披露丢弃了什么 |
如果你做的压缩会删减模型可见内容(折叠数组、省略行),就老老实实声明 S4。
步骤 3:实现 fail-closed 的 Compress
三条铁律(可对照 compressor.go 顶部注释):
- 有界解析:不要无限制地递归解析,避免内存爆炸;
- 任何疑问都放弃:解析失败、结构不支持、没有把握 → 返回
(nil, false),绝不输出"看起来差不多"的结果; - 省略要留标记:像日志压缩器那样用
... N lines elided (caveman)标记折叠区域,让模型知道内容被省略且可恢复。
步骤 4:在 Default 注册表中注册
打开 compressor.go 的Default()函数,加一行r.Register(NewMarkdown())。这里有个进阶细节:
- 如果自动检测可能误判(比如 Markdown 和纯文本很难区分),学 TOON 和 a11y 的做法——注册但只允许显式指定类型到达,不进自动检测链;
- 如果你的压缩器编译产物永远路由不到,把它加进
manifestExcluded白名单。否则它会进入能力清单,导致RegistrySHA256变化,让所有已发布的 Cave Build 锁在运行期失效——这是注册时最容易踩的坑。
步骤 5:接入内容检测(如需自动选择)
自动检测逻辑在 engine/detect.go,顺序是:严格 JSON → 终端输出 → diff → HTML → 表格 → 代码 → 日志 → 搜索结果 → 配置 → 兜底text。新增检测信号时注意:
- 信号必须是确定性、可证的(参考 ANSI 转义序列作为终端判定依据的做法——"只有终端输出才合法携带它");
- 低置信度内容一律落入
text,交给保守压缩器兜底。
三、Compressor 测试怎么写
参考 log_test.go 的测试套路,一个好压缩器的测试至少覆盖 4 类用例:
| 用例 | 验证点 |
|---|---|
| 核心行为 | 错误/关键行被保留,噪音被折叠,输出出现省略标记 |
| 体积门禁 | 输出严格小于输入 |
| 幂等性 | 压缩结果二次压缩保持不变 |
| 失败回退 | 畸形输入返回ok=false,原样透传 |
测试 fixture 放在engine/compressors/testdata/,边界用例(空输入、恰好阈值长度、超大输入)用真实数据支撑,发布任何性能声明前必须有 fixture 背书(要求见 extending.md)。
四、提交前检查清单 🪨
- ✅ 无歧义的内容类型名 + 已声明的安全等级
- ✅ 有界解析、确定性输出、幂等
- ✅ 非法输入回退原始字节(fail-closed)
- ✅ S4 输出已接入 CCR 恢复存储
- ✅ 明确选择方式:自动检测 or 仅显式指定
- ✅ 覆盖有效/无效/输出变大/边界的 fixture 测试
- ✅ 更新
Default()注册表及 engine.md 中的注册器数量与文档
五、关键文件路径速查
| 路径 | 说明 |
|---|---|
engine/compressors/compressor.go | Compressor 接口、Registry 与 Default 注册表 |
engine/compressors/json.go | JSON 压缩器(省略标记、BM25 相关性选取) |
engine/compressors/config.go | YAML/TOML/INI 压缩器 |
engine/compressors/html.go | HTML 正文提取(纯 Go 可读性启发式) |
engine/detect.go | 内容类型自动检测路由 |
engine/safety/safety.go | S0–S4 安全等级注册表 |
engine/ccr/ | 有损压缩的原始字节恢复存储 |
docs/technical/engine.md | 压缩引擎官方文档(含流水线图) |
docs/technical/extending.md | 扩展指南(新增压缩器要求清单) |
掌握「接口三方法 + 注册表 + 安全等级 + fail-closed 测试」这四件套,你就能像维护者一样为 Caveman 贡献一个稳健的新 Compressor 了。
【免费下载链接】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),仅供参考