内容
# 工具列表
**只保留对智能体工具输出的精华部分。永远不会剪切不重要的内容。**
[](https://github.com/firstops-dev/whittle/actions/workflows/ci.yml)
[](https://github.com/firstops-dev/whittle/releases)
[](https://pkg.go.dev/github.com/firstops-dev/whittle)
[](LICENSE)

Whittle 是一个内容感知的压缩器,用于智能体读取的文本工具输出、文件读取、日志、JSON、终端流。长智能体会话中充满了 tokens,但大多数压缩器通过静默地销毁智能体需要的信息来换取压缩比例。
Whittle 坚持一个原则:**结构化压缩是无损的或清晰标记的,代码永远不会达到有损模型,每个异常都打开原始字节。** 报告的减少数量根据实际 tokenizer 计数进行校准 - 而不是字节计数,因为字节计数可能高估节省高达 4 倍。
**它如何连接:** `whittle setup` 安装了一个 Claude Code **PostToolUse hook**,由一个小型、始终在线的本地守护进程支持。您的智能体产生的每个工具输出都会在创建时压缩 - 在您的机器上,在它进入对话之前,脱离模型请求路径,零凭证离开您的盒子。Claude Code 是目前支持的智能体(Cursor、Codex、OpenCode 适配器正在路线图中);同一个守护进程还公开了一个 Go 库、一个 HTTP API 和一个 MCP 检索工具。参见 [为什么使用 whittle](#为什么使用-whittle---在写入时压缩,而不是在读取时压缩) 和 [架构](#架构) 以了解原因和图表。
## 查看

```
$ tail -n 6 build.log | whittle compress -stats
ERROR migrate failed: relation "users" does not exist
... [118 lines omitted]
2026-07-04 INFO worker drained cleanly
ERROR shutdown: connection reset by peer
whittle: action=compressed detected=log strategy=log_compressor tokens=1904->47
```
错误和摘要幸存;118 行 INFO 噪音变成一个诚实的标记。JSON 重塑无损,代码完全通过,终端进度条折叠到其最终帧 - 参见 [基准测试](#基准测试)。
## 安装
```
go install github.com/firstops-dev/whittle/cmd/whittle@latest
whittle setup
```
> `go install` 将二进制文件放在 `~/go/bin` 中,这可能不在您的 `PATH` 上。
> 如果找不到 `whittle`,请添加它:`echo 'export PATH="$HOME/go/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc`。
> (Homebrew 用户可以跳过此步骤 - `brew install firstops-dev/tap/whittle` 会自动将其放在 `PATH` 上。)
这就是全部。`setup`:
- 安装 **Claude Code PostToolUse hook** - 智能体读取的工具输出被 whittle 精简(已知限制:压缩结果大于 ~9.5k 个字符会直接通过;参见 GUARANTEES.md)(Claude Code 是目前支持的智能体;Cursor、Codex 和 OpenCode 适配器正在路线图中);
- 将 ML 散文边车(嵌入二进制文件)转换为 `~/.whittle`,构建其 venv,并自动使用您的 GPU(CUDA > Apple MPS > CPU)- 如果缺少 `python3`,whittle 只运行确定性压缩;
- 注册一个 **launchd 代理**(macOS),以便在登录时启动服务并保持其运行。
在 Linux 上(launchd 仅适用于 macOS),请在 systemd 下运行守护进程:
```
# ~/.config/systemd/user/whittle.service
[Unit]
Description=whittle daemon
[Service]
ExecStart=%h/go/bin/whittle daemon
Restart=always
[Install]
WantedBy=default.target
```
使用 `whittle status`、`whittle stop` 和 `whittle cleanup`(停止服务并删除钩子)进行管理。所有操作都失败打开:如果 whittle 关闭,您的智能体看到原始输出,永远不会出现错误。
## 使用
```
whittle compress output.json # 压缩到 stdout
cat build.log | whittle compress -stats # 统计信息到 stderr
whittle serve -addr :45871 # HTTP: POST /v1/compress
```
作为库:
```go
eng := whittle.New(whittle.Options{})
res := eng.Compress(ctx, toolOutput)
// res.Output, res.Action ("compressed"|"skipped"), res.SkipReason,
// res.Strategy, res.Detected
```
## 每种内容类型的处理方式
| 检测 | 策略 | 保证 |
|---|---|---|
| JSON | 最小化 + 列式重塑(联合模式、类型 CSV、嵌套展平、常量分解) | **无损** - 重建字节精确;行永远不会丢失 |
| 日志 / 构建输出 | 保留错误、警告、堆栈跟踪、摘要 | 有损但 **标记** - `... [N 行省略]`,精确记账 |
| 终端 | ANSI 剥离 + CR-覆盖折叠(进度条 → 最终帧) | 终端实际显示的内容; rune 安全 |
| Markdown 文件读取 | 结构感知:模型压缩散文,**代码块 / 表格 / 列表 / 头部精确通过** | 代码从未到达模型 |
| 源代码 | 不修改 | 路由远离每个有损路径 |
| 散文 | 提取模型(可选)带有保真度保护:实体保护、整个令牌删除、否定保护 | 在任何保护触发器上失败打开 |
每条路径都包裹在 fail-open 保护中:空输出、扩展(字节和令牌诚实)、恐慌恢复。最坏的情况始终是“未压缩”,从未“损坏”。
## ML 散文路径(由 `whittle setup` 安装,可选)
`whittle setup` 自动安装和监督散文边车:Python 源代码包含在二进制文件中,设置构建其 venv,守护进程保持其运行(GPU 自动选择:CUDA > Apple MPS > CPU)。如果缺少 `python3`,设置会告知您,whittle 只运行确定性压缩 - 任何内容都不会损坏。
“可选”意味着确定性策略永远不依赖它。只有当您将 whittle 用作裸库或 `whittle serve` **而没有** 运行设置时,您才会手动连接它(LLMLingua-2 + whittle 的保真度保护 - 参见 [model/](model/)):
```
cd model && python -m venv .venv && .venv/bin/pip install -r requirements.txt
.venv/bin/uvicorn app:app --port 45872
export WHITTLE_MODEL_URL=http://127.0.0.1:45872
```
## 配置
| 环境变量 | 默认值 | 含义 |
|---|---|---|
| `WHITTLE_MODEL_URL` | *(未设置 - 散文关闭)* | 模型边车 URL |
| `WHITTLE_MAX_CHARS` | 262144 | 全局大小上限(跳过分类前) |
| `WHITTLE_PROSE_MAX_CHARS` | 4500 | 散文路径延迟上限 |
## 基准测试
三个层级,按现实程度递增 - 每个数字都可以通过此仓库重新生成(`go run ./bench` 用于确定性行;散文行需要模型边车),基于估计令牌的减少。
### 1. 合成语料库(我们自己的 - 每种内容类别的标题)
[`bench/corpus/`](bench/corpus/) 中的作者固定装置,旨在锻炼每个策略及其保证。完整表格:[`bench/REPORT.md`](bench/REPORT.md)。
| 类别 | 代表性结果 |
|---|---|
| JSON(统一/稀疏/嵌套) | 57% - 无损,字节精确重建 |
| 重复日志 | 97% - 省略标记且精确记账 |
| 终端进度流 | 99% - 最终帧,rune 安全 |
| 代码 / 配置(py,go,yaml) | **0% 按设计 - 跳过,从未触及** |
| 散文 | 30-40% 提取,有保真度保护(需要模型边车;不是确定性 `go run ./bench` 输出的一部分) |
### 2. 并排比较 headroom 的数据
输入冻结来自 [headroom](https://github.com/headroomlabs-ai/headroom) 的[自己的基准测试生成器](https://github.com/headroomlabs-ai/headroom) (Apache-2.0;固定提交,种子 42 - 他们检查没有语料库,因此我们冻结了他们的数字用于计算;`bench/corpus_headroom/`,PROVENANCE.md)。两个工具在相同的字节上运行,默认设置,仅测量,使用相同的 tokenizer。完整表格 + 方法论:[`bench/SIDEBYSIDE.md`](bench/SIDEBYSIDE.md)。
| | headroom-ai 0.30.0 | whittle 0.2.1 |
|---|---|---|
| 总令牌减少(10 个文件,116.5k 令牌) | **41.8%** | 36.5% |
| - 会话 / 智能体转录 JSON(3 个文件) | 2.1% | **5.4%** |
| - 大数据数组(7 个文件) | **48.3%** | 41.6% |
| 减少的保真度 | 包括有损行丢弃(可通过 headroom 的运行时恢复) | **每个文件字节精确无损** |
| 中位数延迟,进程内(相同文件) | 2.93 毫秒 | 2.36 毫秒 |
直接阅读:总而言之,headroom-ai 的默认值比 whittle 多压缩约 5 个百分点 - 通过丢弃 whittle 拒绝丢弃的行来实现。而类别划分显示了每个立场付出的代价:在对话形内容(智能体工具输出实际采用的形状)上,whittle 领先,同时保持无损;在大数据数组上,headroom-ai 的有损采样获得了其优势。延迟接近对等。
### 3. 现实世界:客户服务智能体(两个独立评估)
客户服务智能体是 whittle 的强适应性工作负载 - 他们的工具输出在几乎每个调用中都是结构化 JSON,因此压缩器在 **100% 的工具输出** 上参与,所有无损压缩。两个评估,相互验证:
**广度** - [Salesforce APIGen-MT-5k](https://huggingface.co/datasets/Salesforce/APIGen-MT-5k),5,000 个经过验证的多轮会话:**22% 工具输出减少(o200k)零测量信息丢失**,通过两种方式验证 - 机械无损 **15,846 / 15,846** 个压缩项目,以及一个盲评估小组发现 **0 / 120** 个物质损失在散文路径上(honeypot 验证,Gwet AC2 0.96-1.00)。 [`bench/datasets/salesforce_customer_support/`](bench/datasets/salesforce_customer_support/)
**深度** - Sierra 的 [τ-bench](bench/datasets/tau_bench/) (零售 + 航空),参考轨迹的反事实重放:**22.0% / 23.3% 减少,每个记录字段重建**(所有 16 个航班搜索结果完全恢复)。该评估隔离了 whittle 的实际结构化价值 - 在 **多记录结果** 上,列式重新编码超出了紧凑的 JSON:**+24% 在小型航班搜索中,+45% 在 80 行结果中**,并且优势随着结果大小增长。 [`bench/datasets/tau_bench/`](bench/datasets/tau_bench/)
产品指标是 **令牌 / 上下文减少**:较少的工具输出令牌,从每个后续回合的上下文中删除,整个会话期间累积。美元影响是一个单独的问题,取决于缓存依赖于缓存的发布,双方都使用完整的报告:**在提示缓存下,相同的削减约为 3-5% 会话成本(廉价的缓存读取主导账单),因此令牌节省和美元节省并不相同。
*(两个都使用共享的压缩引擎 `content-aware-router` v0.1.0;whittle 的 `json_crusher` 仅无损。参见每个报告的出处说明。)*
## 为什么使用 whittle - 在写入时压缩,而不是在读取时压缩
上下文压缩器通常与编码智能体集成作为 **请求路径代理**:您的智能体的基本 URL 被重定向到本地服务器,在 *读取时间* 重写对话历史的每个 LLM 调用。该位置强制出现硬问题 - 提示缓存稳定(突变的 history 使缓存前缀无效),每个调用的重新压缩,终止您的 API 流量(密钥,系统提示等),以及一个必须保持运行的驻留运行时,否则您的智能体会随之关闭。它还使得有损压缩成为默认配置,并使用检索循环作为备份:运行时保证存在,因此可以按需提供丢失的内容。
Whittle 采取另一种立场:它是 **PostToolUse 钩子**。每个工具输出在 **创建时** 进行压缩,一旦生成,**在进入对话历史之前**。由此选择产生的一切:
- **节省累积。** 工具输出存在于每个后续回合的上下文中。在写入时删除的令牌从每个后续调用中删除 - 无需每个调用的重复工作,无需缓存手术,因为历史记录从未改变。
- **无需信任扩展。** 钩子一次查看一个工具输出,在本地进行,零凭证。不会终止您的 API 流量。
- **失败是免费的。** 钩子失败打开;如果 whittle 关闭或拒绝,智能体继续使用原始输出。网关故障是智能体故障。
- **损失预算是诚实的。** 读取时间代理可以承受可恢复的有损压缩 - 其驻留运行时按需提供丢失的内容。Whittle 不会在您的请求路径中保留任何运行时;减少的输出带有微小的检索指针,由本地守护进程提供(`whittle_get`),而无损转换根本不携带任何东西 - 无损或标记的构造是构造,恢复是安全网,从不许可。
钩子是 whittle 的默认界面,不是唯一的接口:**库**(`whittle.New`)→ **HTTP 服务**(`whittle serve`)→ **钩子适配器**(今天的 Claude Code PostToolUse;Cursor、Codex、OpenCode 适配器正在路线图中)- 并且相同的库嵌入网关或管道,如果您需要它。立场是重点:压缩发生在输出生成的位置,无论哪个接口将其交付到那里。
## 架构
```
Claude Code ──PostToolUse (HTTP)──▶ whittle daemon (:45871, launchd-kept)
│
├─ router ─▶ json · log · terminal · markdown
│ (确定性,进程内)
└─ 散文 ─▶ 模型边车 (:45872, 可选 GPU)
│
whittle_get(id) ◀──MCP 工具────────┘ 减少的原件,按需可检索
```
一个常驻守护进程,三个接口(钩子 · HTTP · MCP)。压缩发生在输出生成的位置,完全脱离模型请求路径。
## 性能
确定性策略是纯 CPU,单个静态二进制文件,零可分配模型状态(Apple M-series,`go test -bench`):
| 输入 | 大小 | 延迟 |
|---|---|---|
| JSON 数组,200 行,漂亮打印 | ~21 KB | ~1.0 毫秒 |
| 终端进度流 | ~12 KB | ~3.9 毫秒 |
| 构建日志,800 行 | ~56 KB | ~21 毫秒 |
钩子在工具调用完成后运行,因此此成本 **完全脱离 LLM 请求路径** - 模型调用延迟不变。(这些是 whittle 自己的语料库上的绝对路径预算;对于相同输入的工具与工具延迟,请参阅上面的基准测试并排比较以及 `bench/SIDEBYSIDE.md`。)可选的 ML 散文路径由 fail-open 预算限制(默认 1.5 秒),并且永远不会阻塞它。
## 设计原则
1. **打开失败。** 压缩器破坏您的智能体比没有压缩器更糟糕。
2. **从不沉默的损失。** 有损路径标记它们删除的内容并准确记账。
3. **代码是神圣的。** 文件读取、围栏、标识符:字节精确或未触及。
4. **令牌诚实。** 接受门控和报告的节省使用校准的令牌估计(MAE ~8% vs `o200k_base`;使用 `bench/calibrate_tokens.py` 重新生成),不是字节。
5. **对抗性测试。** 上述不变性由重建模糊测试、每语言路由套件和 fail-open 合同测试固定。
## 致谢
Whittle 的日志选择策略、几个内容检测启发式和表格解析器是从 [Headroom](https://github.com/headroomlabs-ai/headroom) (Apache-2.0)改编的 - 改编部分在源代码注释中标记,我们认为他们的压缩工作非常出色。Whittle 的存在是因为我们想要另一个立场:一个写入时 PostToolUse 钩子而不是读取时请求路径代理,具有该立场所需更严格的保真度保证。参见 NOTICE。
## 自行验证
这里的每个声明都可以在克隆中检查 - 这是可验证的。
```
make test # 保证作为可执行测试(参见 GUARANTEES.md)
go run ./bench # 语料库减少 + 保真度,SHA 固定,CI 门控
python bench/calibrate_tokens.py # 复制令牌估计器 MAE(需要 tiktoken)
```
[GUARANTEES.md](GUARANTEES.md) 将每个保真度承诺映射到验证它的测试。
## 已知限制
- **10k 钩子输出上限。** Claude Code 将钩子的替换限制为 10,000 个字符;今天,压缩结果超过 ~9.5k 直接通过。基于检索的块状处理是计划中的修复 ([docs/hook-output-cap.md](docs/hook-output-cap.md))。
- **散文需要边车。** 没有它,散文和 Markdown 文档直接通过;确定性策略不受影响。
- **launchd 仅适用于 macOS。** Linux 在 systemd 下运行守护进程(上面的单元)。
- **散文延迟上限** (默认 4500 个字符)权衡了一个硬上限以获得可预测的路径延迟;提高它与 `WHITTLE_PROSE_MAX_CHARS`。
## 贡献
Whittle 的准则是保证可执行 - 参见 [CONTRIBUTING.md](CONTRIBUTING.md)。最高严重性问题类别是 **保真度**:如果 whittle 曾经改变了输出的含义,那就是一个紧急错误,我们像对待关键问题一样处理(使用保真度问题模板)。好的起点:智能体适配器(Cursor/Codex/OpenCode)、Linux 打包、检测语料库用例。
## 许可证
Apache-2.0.
连接信息
猜你喜欢
暂无推荐服务器