关于 distil
distil 是用于测量和管理 LLM Agent 上下文的 Rust 库与工具集,可分析会话记录的令牌成本,并提供缓存对齐、预算和压缩等层。
主要功能
- 01分析会话记录中的令牌用量
- 02分别测量各上下文层的效果
- 03调整内容顺序以保留可缓存前缀
- 04应用上下文预算与压缩层
- 05可选安装 MCP 服务
适用场景
- 01分析 Agent 会话的令牌分布
- 02比较本地会话记录上的上下文策略
- 03在设定预算前检查上下文成本
MCP 相关
可选的 `mcp` 功能提供 `distil-mcp` MCP 服务。README 还说明了如何为 Claude Code 注册该服务。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
claude mcp add distil -- npx -y @munhq/distil
无需账户、API 密钥,也无需任何配置。此软件包只是一个轻量封装程序,会为你的平台获取二进制文件,并根据已发布的校验和进行验证;对于没有 Node 的用户,仍可使用 install.sh 和预编译的二进制文件。
缓存写入只占你令牌用量的 2%,却占账单的 28%
这不是说法,而是实测结果:对 13,814 个真实 Agent 会话、410,742 轮助手对话进行了重新运行,日期为 2026-08-29。其中的每个独立令牌都被计费了 550 次,因为每个请求都会重新发送完整历史记录。
这意味着,显而易见的做法——压缩历史记录——通常是错误的。编辑历史记录会使从编辑处开始的缓存前缀失效,并将读取的价格从 0.1x 变成 1.25x 或 2.0x 的写入价格。你无法通过压缩来摆脱上下文成本,只能选择不让令牌进入上下文。
这个领域中的每种工具都会公布基于自身测试样例测得的节省比例。但没有任何工具公布其分母:它能处理真实会话中的多大比例,以及按提示词缓存定价计算后,这部分内容的成本是多少。distil 会在 Agent 实际生成的对话记录上测量这两项数据。
哪些是已有成果,哪些不是。 下文的缓存计算并非新发现。Anthropic 的上下文编辑文档指出,清除工具结果会使缓存前缀失效,并提供了 clear_at_least,确保只有当清除的内容足以抵消成本时才会触发清除。盈亏平衡规则也已公开:对于 5 分钟缓存,清除的令牌数乘以两次清除之间的请求次数,必须大于保留令牌数的 11.5 倍。本 README 中的表格原样复现了该规则——这是独立推导出的结果,可用于核验计算,而非一项贡献。
空白之处在于实证数据。每个资料来源都建议根据自己的工作负载进行校准,但没有任何一个提供校准方法,也没有公布实际测得的数值。这正是此 crate 的用途:测量所需数据,帮助你选择 clear_at_least,或决定完全不执行清除。
完整测量结果
于 2026-08-29 对 13,814 份本地 Claude Code 转录记录进行测量,共 410,742 轮助手对话、2.127 亿个不重复文本 token。你可以用 distil-bench ~/.claude/projects 在自己的语料上复现;语料会增长,因此测量日期比小数点后的精度更重要。
| token 数 | 占比 | |
|---|---|---|
| 工具结果 | 127,371,430 | 59.9% |
| 工具调用 | 38,065,121 | 17.9% |
| 用户文本 | 29,818,536 | 14.0% |
| 助手文本 | 15,402,077 | 7.2% |
| 思考内容 | 2,076,716 | 1.0% |
这 2.127 亿个不重复 token 被计费为 1,169 亿个输入 token——每个 token 付费 550 次,因为每次请求都会重新发送完整历史记录。
按实际缓存倍率计算(读取为 0.1 倍,写入为 1.25 倍〔5 分钟 TTL〕和 2.0 倍〔1 小时 TTL〕):
| token 占比 | 费用占比 | |
|---|---|---|
| 缓存读取 | 97.9% | 71.8% |
| 缓存写入 | 2.0% | 27.6% |
缓存写入占 token 数的 2%,却占账单的 28%。 编辑历史记录会使编辑位置及之后的缓存前缀失效,将按 0.1 倍计费的读取转换为按 1.25 倍或 2.0 倍计费的写入。因此,改写必须将失效部分压缩到以下比例以下:
| 剩余轮数 | 5 分钟 TTL | 1 小时 TTL |
|---|---|---|
| 1 | 8.0% | 5.0% |
| 10 | 46.5% | 34.5% |
| 20 | 63.5% | 51.3% |
| 100 | 89.7% | 84.0% |
这个表格以另一种形式呈现了已公布的盈亏平衡规则:每一行中,cleared x turns / kept 都等于 11.5(5 分钟档)。用它来选择 clear_at_least 的值,再用 distil-bench 找出要填入的轮数和尾部大小——它们取决于工作负载,而这部分数据没有人公布。
以每单位历史记录计算,在剩余 10 轮时:保留它的成本为 1.00,压缩它的成本为 2.15,而一开始就不纳入它的成本为 0。你无法通过压缩摆脱上下文成本,只能选择不纳入这些 token。
这对使用此 crate 意味着什么
不改动历史记录的层处于上述成本计算的有利一侧:CacheAlignLayer(调整内容顺序,让稳定前缀保持可缓存)和 ScratchpadLayer(将工作状态保存在上下文窗口之外)。
改写历史记录的层——MaskingLayer、SummarizationLayer、CompactionLayer——在常见情况下,成本高于节省的费用。仅在一个边界情况下使用它们:上下文溢出,此时替代方案是请求失败,缓存价格也不再是比较依据。BudgetLayer 正是为这种情况设计的。
RegistryLayer 和 CodeModeLayer 早于 Anthropic 的 Tool Search Tool 和 Programmatic Tool Calling;后两者以原生方式实现相同功能,而且做得更好。优先使用原生功能。
要清除旧的工具结果,优先使用提供方的 clear_tool_uses 上下文编辑,而不是 MaskingLayer:它在服务端运行,接受 clear_at_least,而且只需使用一个 API 参数,无须引入依赖。只有在需要 API 不支持的行为时,才使用此处的层。
测量
cargo build --features bench --release
# Where tokens are, what they cost, and the break-even table
./target/release/distil-bench ~/.claude/projects --json baseline.json
# Sessions that called a given tool, against those that did not
./target/release/distil-bench ~/.claude/projects --split-by-tool mcp__codeindex__
# Export real traffic so other compressors run on the same input
./target/release/distil-bench ~/.claude/projects --export-sessions ./sessions --min-turns 40
外部工具对比、公平性规则,以及最初导致数字错误的两个测试框架错误,请参阅 bench/README.md。
保留能力
只有当模型仍能回答原始上下文所能回答的问题时,节省才算真正的节省。
# No LLM judge: file paths checked against ground truth from the transcript
python bench/artifact_retention.py ./sessions 12
# LLM-graded probes (recall / artifact / continuation / decision)
cargo build --features probe --release
./target/release/distil-probe <session.jsonl> --probes 6 --model qwen2.5:3b
探测分类法来自 Factory.ai;他们的文章对其进行了定义,但没有提供测试框架。评判器是 Completer,而非 Summarizer——总结器可能会引入总结式框架,进而同时改写探测格式和评分指令。
将其用作库
use distil::{CacheAlignLayer, Ctx, EstimateCounter, Pipeline};
let pipeline = Pipeline::builder()
.counter(EstimateCounter)
.layer(CacheAlignLayer::generic())
.build();
let mut ctx = Ctx::new(messages, tools, turn);
let result = pipeline.optimize(&mut ctx);
println!("{result}");
此示例保持可编译,位于 examples/readme_quickstart.rs——运行 cargo run --example readme_quickstart 即可执行。
每一层都实现 Layer,并报告 tokens_before、tokens_after 和一行详细信息,因此可以单独测量每一层。
功能
| 功能 | 添加内容 |
|---|---|
corpus | 转录文本加载器(无额外依赖) |
bench | distil-bench,需要 tiktoken |
probe | distil-probe,HTTP 评估器需要 proxy |
tiktoken | 使用精确的 BPE 计数,而非字符数除以 3.5 的估算值 |
proxy | distil-proxy HTTP 服务 |
mcp | distil-mcp MCP 服务 |
metrics | Prometheus /metrics |
安装
./install.sh # binaries, the skill, and the MCP server
/plugin marketplace add munhq/distil
/plugin install distil # Claude Code: skill and server in one step
install.sh 会安装两个二进制文件,将技能放入它找到的每个 Claude 主目录,并在用户级别注册 MCP 服务。如果插件已安装,它只会安装二进制文件,因为插件本身会声明该服务并附带技能。
插件通过 npx -y @munhq/distil 启动服务,因此需要 Node。它无法使用相对于插件的路径:Claude Code 会展开 ${CLAUDE_PLUGIN_ROOT},而其他程序不会,因此插件一旦声明该路径,其他所有客户端拿到的都将是一个不存在的字面路径。对于没有 Node 的用户,仍可使用 install.sh 和预构建的二进制文件。
平台支持
| 平台 | 二进制文件 | 脚本 |
|---|---|---|
| Linux x86_64 / arm64 | 已发布,已测试 | 支持 |
| macOS x86_64 / arm64 | 已发布,在 CI 中构建 | 支持 |
| Windows x86_64 / arm64 | 已发布,在 CI 中构建 | 需要 Shell:Git Bash、MSYS2 或 WSL |
发布版本提供六种目标平台,plugin/test_platform.sh 会根据这张表测试安装程序和插件启动器,以确保资源名称与请求的名称一致。install.sh 和启动器都是 Bash 脚本,因此在 Windows 上需要 Shell——cmd 和 PowerShell 无法运行它们。Linux 二进制文件是静态 musl 构建,因此不需要匹配的 glibc。
注意事项
语料库来自一位开发者的机器。发现的是比例;绝对总量因人而异。计数使用 cl100k_base,其结果与 Claude 的分词器相差几个百分点。盈亏平衡模型假设只有一个缓存断点,因此只改写尾部内容的成本低于表中所示——这会细化结论,但不会推翻结论。
贡献
构建和测试说明、基准测试变更必须遵守的规则,以及拉取请求在评审前需要满足的条件:CONTRIBUTING.md。
请私下报告漏洞——SECURITY.md。
许可证
MIT。请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。