> For the complete documentation index, see [llms.txt](https://tinyhumans.gitbook.io/openhuman/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tinyhumans.gitbook.io/openhuman/zh/gong-neng/token-compression.md).

# 智能 Token 压缩

TokenJuice——一个多阶段压缩路由器，在冗长的工具输出进入 LLM 上下文之前就将其压缩。

LLM 令牌很昂贵，而冗长的工具输出正是它们大量“消耗殆尽”的地方。一个 `git status` 在繁忙的仓库中，一个 `cargo build` 日志、一个 600 条消息的电子邮件线程、一个 `docker ps -a` 针对真实集群。每一项都可能几乎没有信息增益却把上下文窗口撑大。

OpenHuman 随附 **TokenJuice**，这是一个直接接入智能体工具执行路径的压缩路由器。在任何工具结果到达模型之前，TokenJuice 会对其分类，将其路由到专用压缩器，必要时把完整原文卸载到可恢复缓存中，并记录它节省了多少 token（以及多少钱）。

它最初是 [vincentkoc/tokenjuice](https://github.com/vincentkoc/tokenjuice)的移植版本。那层 JSON 规则叠加仍然作为日志/命令压缩器存在于此，但后来已发展为一个多阶段、感知内容的管道。

***

## 管道，逐步说明

所有通过策略感知的 TokenJuice 工具输出适配器流转的数据块，都会通过随附的 TinyJuice 路由器（`vendor/tinyjuice/src/compress.rs`):

```
原始工具结果
        │
        ▼
1. 大小门控          路由器启用了吗？输入 ≥ min_bytes_to_compress（2 KB）吗？
        │  是
        ▼
2. 检测类型        Json · Diff · Html · Search · Code · Log · PlainText
        │
        ▼
3. 选择压缩器      每种类型一个专用压缩器（+ 每种类型的开关）
        │
        ▼
4. 压缩             运行它；如果它拒绝压缩或使输出变大，则回退 / 透传
        │
        ▼
5. CCR 资格         有损 AND ≥ ccr_min_tokens（≈500）？→ 将原文卸载到缓存
        │
        ▼
6. 追加标记         ⟦tj:<hash>⟧ 尾注，以便智能体可以取回完整原文
        │
        ▼
7. 记录节省         按模型和按压缩器记录节省的 token 与成本
        │
        ▼
   紧凑文本 → LLM 上下文
```

1. **大小门控。** 如果路由器被禁用，或者输入低于 `min_bytes_to_compress` （默认 **2048 字节**），则会原样透传。太小的输出不值得压缩。
2. **内容检测** (`detect/kind.rs`）。该数据块会被分类为七种 `ContentKind`之一。优先级：显式提示 → MIME/扩展名标签 → 每工具的先验（例如 `grep` → Search， `git_operations` → Diff， `run_tests` → Log）→ 低成本结构启发式（JSON → Diff → HTML → Search → Code → Log → PlainText）。热路径上不使用正则表达式。
3. **压缩器选择。** 每种类型都会路由到专用压缩器，并遵守按类型开关（`search_enabled`, `code_enabled`, `html_enabled`, `ml_compression_enabled`).
4. **压缩。** 压缩器开始运行。如果它拒绝压缩，或者其输出不比输入更小，TokenJuice 会回退到通用压缩器或直接透传原始内容。它绝不会让内容变大。
5. **CCR 卸载。** 对于 **有损** 压缩，只要原文足够大（`ccr_min_tokens`，默认约 500 个 token），完整原文就会存入 **Compress-Cache-Retrieve** 存储中，因此不会永久丢失。
6. **恢复标记。** 会附加一个带有规范标记的尾注 `⟦tj:<hash>⟧` ，告诉智能体它看到的是部分视图，以及如何获取其余内容。
7. **节省统计。** 节省的 token 和估算节省的成本都会被记录，并按模型和压缩器归因。

***

## 这些压缩器

每种内容类型都有一个专门构建的压缩器（`vendor/tinyjuice/src/compressors/`):

| 压缩器              | 类型        | 作用                                                                                                              |
| ---------------- | --------- | --------------------------------------------------------------------------------------------------------------- |
| **SmartCrusher** | JSON      | 将对象数组重新渲染为紧凑表格；超过约 40 行后保留开头 + 结尾 + 错误行 + 数值异常值。                                                                |
| **Code**         | Code      | 保留签名和导入，将深层函数体折叠为 `{ … N 行 … }` （可用时使用 tree-sitter，否则使用花括号深度启发式）。保留 `TODO`/`FIXME`/`error`/`panic`/`unsafe` 标记。 |
| **Log**          | Log       | 对于 **命令输出**，委托给下面的 JSON 规则引擎。对于其他日志，则保留错误 / 警告 / 堆栈跟踪 / 摘要，并丢弃噪音。                                               |
| **Search**       | Search    | 按文件分组 grep/ripgrep `path:line:body` 命中，按查询词密度排序，保留每个文件的最佳匹配，并汇总 `[+N more]`.                                    |
| **Diff**         | Diff      | 保留改动行和 hunk 头，将长时间未变化的区段折叠为一个锚点；lockfile 的块会缩减为一行的 `+A/-B` 摘要。                                                  |
| **Html**         | HTML      | 去除标记，将其转换为可读文本，并在合理的块边界处换行并解码实体（轻量分配，无 DOM）。                                                                    |
| **MlText**       | PlainText | 可选启用的 ML 重要性压缩（见下）。                                                                                             |
| **通用**           | 回退        | 用于没有匹配到特定规则的命令输出的首尾摘要器；对结构化数据块会拒绝压缩，以便保留原样。                                                                     |

多字节文本（CJK、emoji、组合标记）全程按字素逐个处理，绝不会在字符中间切开。

***

## ML 压缩（可选启用）

除确定性压缩器之外，TokenJuice 还可以将纯文本路由到一个 **ModernBERT** token 重要性模型，由其对低信息量片段打分并丢弃。TinyJuice 压缩器暴露了可选的 ML 插槽，而 OpenHuman 在 `crates/openhuman-core/src/inference/tokenjuice/ml/`.

* **中将其桥接到 Kompress。** 默认关闭。 `使用` 在 `[tokenjuice]`.
* **本地运行** 作为 `kompress` 共享 Python 运行时 sidecar 的后端。没有任何数据会离开你的机器。
* **可调：** `ml_model_id` （默认 `answerdotai/ModernBERT-base`), `ml_target_ratio` （默认 `0.5`), `ml_max_input_chars` （默认 `200000`), `ml_device` (`cpu`/`auto`), `ml_sidecar_idle_timeout_secs`.
* **平滑降级：** 如果 sidecar 不可用，或者输入超过字符上限，它会降级到原生压缩器，而不会让智能体循环失败。

***

## 不会丢失任何内容：CCR 缓存与检索

有损压缩通常意味着丢弃数据。TokenJuice 则会 **卸载** 完整原文到 **Compress-Cache-Retrieve（CCR）** 存储，并留下一个线索（`vendor/tinyjuice/src/cache/`).

* **内存层** （始终启用）：一个按 SHA-256 哈希键控的进程全局存储，受条目数（`max_cache_entries`，默认 256）和总字节数（`max_cache_bytes`，默认 64 MiB）限制，采用 FIFO 淘汰。
* **磁盘层** （可选）： `<workspace>/.tokenjuice/ccr/`，通过 `ccr_disk_enabled`启用，可在内存淘汰后保留。可通过 `ccr_ttl_secs`.
* **设置可选 TTL。** 标记： `压缩后的输出会以如下尾注结尾：[compacted tool output — PARTIAL view; full original available via tokenjuice_retrieve with token "…"]` ，其中携带 `⟦tj:<hash>⟧` token。
* **检索工具：** 智能体使用只读的 **`tokenjuice_retrieve`** 工具并带上该 token（可选字节/行 `范围`）来取回完整原文或其切片。这个 token 是无法猜测的 SHA-256 摘要。

因此，智能体默认拿到廉价的压缩视图，只有在真正需要时才会透明地“放大”查看完整文本。

***

## 节省跟踪

每次压缩都会通过 OpenHuman 节省回调进行计量（`crates/openhuman-core/src/inference/tokenjuice/savings.rs`）。TokenJuice 报告事件和 token 差值；OpenHuman 会按配置的默认模型输入定价进行计算，汇总 `总计`, `按模型`，以及 `按压缩器`，并将统计数据持久化到 `<workspace>/state/tokenjuice_savings.json`.

可通过 RPC 用 `openhuman.tokenjuice_savings_stats`读取；用 `openhuman.tokenjuice_savings_reset`.

***

## 清除。

原始的三层 JSON 规则叠加仍然驱动着 Log/命令压缩器。规则按顺序合并，后面的层覆盖前面的层：

| 层      | 路径                            | 用途                                             |
| ------ | ----------------------------- | ---------------------------------------------- |
| **内置** | 随二进制发布                        | 约 96 条随附规则，覆盖 git、npm、cargo、docker、kubectl、ls… |
| **用户** | `~/.config/tokenjuice/rules/` | 个人覆盖，适用于所有地方                                   |
| **项目** | `.tokenjuice/rules/`          | 仓库特定覆盖，已提交并与团队共享                               |

每条规则都会命名一个命令/工具模式和一个缩减策略（跳过/保留过滤器、如 strip-ANSI 和 dedupe 之类的转换、首尾摘要、命名计数器、预置消息）。规则是 JSON。新增一条即可生效，无需重新编译。

***

## 配置、RPC 与工具

所有内容都位于 `[tokenjuice]` config 块下（`crates/openhuman-core/src/config/schema/tokenjuice.rs`），且可热更新。

* **总开关：** `router_enabled` （默认 `true`).
* **阈值：** `min_bytes_to_compress`, `ccr_min_tokens`.
* **CCR：** `ccr_enabled`, `ccr_disk_enabled`, `max_cache_entries`, `max_cache_bytes`, `ccr_ttl_secs`.
* **按类型：** `search_enabled`, `code_enabled`, `html_enabled`，以及 `ml_*` 键。
* **RPC** (`openhuman.tokenjuice_*`): `detect`, `compress` （对管道进行试运行）， `settings_get` / `settings_update` （在线部分补丁）， `cache_stats`, `retrieve`, `savings_stats`, `savings_reset`.
* **智能体工具：** `tokenjuice_retrieve` （只读）恢复已卸载的原文。
* **调试：** 启动核心时使用 `RUST_LOG=openhuman_core::inference::tokenjuice=debug` 以观察检测、匹配，以及每个数据块被裁剪了多少。

***

## 这为何重要

智能体的生死取决于其上下文预算。一段工作会话可能会扩展成几十次工具调用：grep、构建、测试运行、 `git` 输出，以及智能体拉取下来的大量 [web-fetch / scrape](/openhuman/zh/gong-neng/native-tools/web-scraper.md) 结果。TokenJuice 位于该工具执行路径上，并在每个结果进入上下文之前将其压缩，因此智能体可以扫过嘈杂的仓库或很长的网页，而不会让每一步都把窗口撑大。节省会在整个会话中累积，并以真实美元计量（见 [计费、成本与用量](/openhuman/zh/gong-neng/billing-and-usage.md)).

> **范围说明。** TokenJuice 运行在智能体的 **工具结果**上，而不是后台的 [自动抓取](/openhuman/zh/gong-neng/obsidian-wiki/auto-fetch.md) 摄取管道上。构建 [Memory Tree](/openhuman/zh/gong-neng/obsidian-wiki/memory-tree.md) 的 20 分钟同步使用的是自己的规范化和分块方式，目前不会将负载通过 TokenJuice 路由。

***

## 另见

* [可用工具](/openhuman/zh/gong-neng/native-tools.md)：大多数沉重的工具输出都会流经 TokenJuice。
* [Memory Tree](/openhuman/zh/gong-neng/obsidian-wiki/memory-tree.md)：压缩输出的下游消费者。
* [计费、成本与用量](/openhuman/zh/gong-neng/billing-and-usage.md)：令牌节省如何转化为真实金钱的地方。
