工作原理
sift 按内容类型分发到专用压缩器(detectContentType 自动判断)。无损优先:先尝试无损重排(JSON minify、日志 Drain 模板化),缩小到 ≤80% 即短路;不够再走有损路径,原文入 stash store。整个流程守住三条安全底线:
- 只在消息内压缩,绝不跨消息丢弃内容 —— 每条消息独立处理,tool_use / tool_result 配对受保护。
- 冻结前缀字节不动 ——
cache_control标记以下的消息是 prompt cache 锚点,压缩绝不触碰。 - 有损压缩必须可恢复 —— 原文进 stash store,输出留
«stash:HASH»标记,端到端无损。
压缩管线
请求 body
│ detectRequestFormat ──→ anthropic / chat_completions / responses
│ (floor = cache_control 冻结下界)
▼
逐消息 text block
│ detectContentType ──→ json_array / build_output / search_results /
│ git_diff / source_code / plain_text / html
│ mixed_content:同一 block 内分段路由;嵌入 JSON span 递归处理
▼
无损重排(JsonMinifier / LogTemplate-Drain)─≤80%─→ 短路返回
▼
有损压缩(OffloadTransform)── 原文写 stash store,输出留 «stash:HASH»
▼
token 估算校验 ── 不达预期则回退原 block(blocksReverted)压缩器类型
| 内容类型 | 压缩器 | 策略 | 无损? |
|---|---|---|---|
| json_array | SmartCrusher | schema 去重 + 采样 + 关键行保留(错误行优先) | 可无损(minify)或有损 |
| build_output | LogCompressor | 错误 / 堆栈 / 摘要行保留,重复 warning 模板折叠 | 有损(可恢复) |
| search_results | SearchCompressor | grep / ripgrep 输出抽稀,保留匹配上下文 | 有损(可恢复) |
| git_diff | DiffCompressor | unified diff hunk 采样,改动行保留 | 有损(可恢复) |
| plain_text | TextCrusher | BM25 相关性 + 近重复折叠,支持中英文(CJK) | 有损(可恢复) |
| source_code | CodeCompressor | tree-sitter AST,8 语言,签名保留、函数体折叠 | 有损(可恢复) |
| html | — | 检测支持,压缩当前 no-op | — |
共用机制
- 相关性 query:有损压缩器用 BM25 对行打分,与 query 相关的内容优先保留。
- 保密检测:归一化 Shannon 熵 ≥0.85 且长度 ≥20 的片段(API key、凭证)强制不可丢弃。
- 标签保护:自定义 XML 标签先占位保护、压缩后恢复,不会被压坏。
- 混合内容同一 block 内含多种类型时,分段路由到各自的压缩器;嵌入的 JSON span 走递归平衡匹配。
- stash 恢复:一切有损输出的原文都在 stash store,输出留
«stash:HASH»标记,retrieve(key)取回。
走一个真实例子
假设一段工具输出(tool_result)里有 2000 行构建日志,sift 会这样处理它:
输入(节选):
[vite] building for production...
✓ 1420 modules transformed.
warning: chunk size exceeds 500 kB (vendor.js)
warning: chunk size exceeds 500 kB (utils.js)
warning: chunk size exceeds 500 kB (ui.js) ← 同类 warning 重复 47 次
ERROR in src/api/client.ts:52
TS2339: Property 'retry' does not exist on type 'Client'.
处理过程:
1. detectContentType → build_output → 路由到 LogCompressor
2. 先试无损(Drain 模板化)→ 仍 >80%,进入有损
3. 错误行 / 堆栈行 全部保留;47 条同类 warning 折成 1 条模板
4. 原文写入 stash store,压缩处留 «stash:a3f9…» 标记
输出(节选):
✓ 1420 modules transformed.
warning: chunk size exceeds 500 kB — 重复 47 次(vendor/utils/ui/…)
ERROR in src/api/client.ts:52
TS2339: Property 'retry' does not exist on type 'Client'.关键在于:模型看到的错误信息一字不差,被折叠的只是重复噪音;任何时候需要完整原文,都能用 stash 标记取回。其他内容类型同理 —— diff 保留改动行、代码保留函数签名、搜索结果保留匹配上下文,牺牲的永远是「重复」,不是「信息」。
设计取舍
- 纯逻辑核心:压缩逻辑只进
sift,node 桥零逻辑 —— 核心可复用(wasm、CLI 皆可接)。 - 无损优先短路:能无损解决就不引入信息损失,≤80% 是短路阈值。
- token 校验兜底:有损结果要过 token 估算校验,不达预期自动回退原 block。
- 缓存成本感知:policy 含缓存成本乘数,压缩决策考虑 prompt cache 经济学。
首页演示里可以逐类型查看真实输入与压缩输出的左右对比。