pxpipe
将庞大上下文渲染为图片,以此削减 Claude Code 的输入 token——同样的系统提示词、工具文档和历史记录,只需原来 token 数的一小部分。
一张图片的 token 成本由其像素尺寸决定,而非内含文本量。在真实的 Claude Code 流量中,密集内容(代码、JSON、工具输出)每个图片 token 约可容纳 3.1 个字符,而每个文本 token 仅约 1 个字符。pxpipe 是一个利用这一差异的本地代理:它在请求离开你的机器之前,将请求中的庞大部分(系统提示词、工具文档、较早的历史记录)重写为紧凑的 PNG 图片。
节省量取决于工作负载——pxpipe 在 token 密集内容上优势明显,而对稀疏/小型请求不做改动——因此这些是实测快照,并非固定值。主要且持久的结果是输入 token 的减少:密集的系统提示词、工具文档和历史记录以紧凑图片而非文本形式输入(上例中约 25k 文本 token 被渲染为约 2.7k 图片 token),每个请求都对照自身的 count_tokens 反事实进行测量。费用节省由此衍生——按当前 Fable 标价,token 削减带来约 59–70% 的整体账单降低(压缩请求上约 72–74%;完整定价计算见 FAQ)。但标价明天就可能变化,而 token 数量不会,因此应关注 token 而非美元。可从 ~/.pxpipe/events.jsonl 复现两者。
这就是模型看到的,而非文本:
约 4.8 万字符的系统提示词 + 工具文档(即本仓库自身的 README、FINDINGS 和源代码),作为文本约 25k token,作为此页面约 2.7k 图片 token。由真实的 transformRequest 管道生成:空白压缩,重新排列为满行,用 ↵ 标记原始换行,顶部叠加 OCR 指令横幅。模型在纯净评测中以 100/100 的成绩读取此类渲染(见基准测试)。
演示
Fable 5 演示(默认,阅读器得分 100/100):
Fable-AB-Demo.mp4- 双窗格演示(左侧为纯文本,右侧为 pxpipe),均在 Fable 5 上运行。
- Fable 能读取 Opus 无法处理的内容。Opus 拒绝处理的图片化短语计数(见下方 Opus 演示):pxpipe 分支在 39 个图片化填充文件中精确统计了 10/10 个 token(与 grep 真实结果逐行匹配),并正确完成了多步骤账本算术(8037 → … → 15,021)。
- 相同的答案,成本降低约7倍。两次演示后的会话总量:普通版本为42.21美元,上下文窗口已满96%(964.5k/1M——距离强制压缩仅差一个任务);而pxpipe版本为6.06美元,上下文空间充足(73.5k/1M)。
- 诚实的提醒,视频片段中可见:pxpipe分支先回答了计数问题,但需要一次后续提示才能按要求的一行格式打印账本余额;普通分支首次尝试就遵循了格式。在Fable上可读性已解决——单次回复格式遵循是剩下的粗糙边缘。
Opus 4.8演示(Opus默认禁用):
Opus-AB-Demo.mp4并排对比——普通Claude(左)与pxpipe(右),两者均运行在Opus 4.8上(需手动启用;pxpipe针对Fable进行了调优——参见上方Fable片段)。点击图片观看(Google Drive)。
- 演示1——修复失败的测试套件:两者均通过;仪表盘显示pxpipe将请求压缩至token数的一小部分(真实的、服务端测量的上下文/token缩减)。
- 演示2——一个大型文件上下文(40个文件,约382k token)加上一个数学问题和一个“统计此短语”任务:数学答案(一个小的文本“针”)两者均可读取。短语计数需要读取图像填充内容——因此运行在Opus上的pxpipe无法读取,并诚实地表明它不会编造数字(有文档记载的有损限制:精确数值保持为文本形式)。与此同时,普通版本在逐文件计数时陷入困境。
尝试一下(30秒)
npx pxpipe-proxy # proxy on 127.0.0.1:47821 ANTHROPIC_BASE_URL=http://localhost:47821 claude # point Claude Code at it
打开 http://127.0.0.1:47821/ 查看实时仪表盘:节省的token数、每会话统计、每次文本到图像转换的并排对比、全局终止开关,以及包括GPT 5.6和GPT 5.5在内的运行时模型芯片。
其他一切不变。响应正常流式输出;pxpipe仅压缩请求(即你发送的上下文),绝不压缩模型的输出。最近的轮次保持文本形式;系统提示词、工具文档和较旧的批量历史被转换为图像。
诚实的部分,在依赖之前请先阅读。
它有损。pxpipe 属于 gist 层级存储,并非无损存储。在一项“大海捞针”式评测中,密集图像内容里的精确 12 字符十六进制字符串,在 Opus 上返回结果为 0/15,在 Fable 5 上返回结果为 13/15,且失败模式是无声的虚构:给出一个看似合理但错误的值,而非报错。任何需要字节级精确返回的内容(ID、哈希值、密钥、精确数字)都必须保持文本形式。最近的版本已经实现了这一点;但尚未内置专门的逐字风险防护。
精确召回逃生通道。pxpipe 仅对 Fable 请求进行图像化处理(PXPIPE_MODELS=claude-fable-5),因此任何使用非 Fable 模型的子智能体都会以文本形式通过。将需要字节级精确值的工作路由到这类模型——全局设置 CLAUDE_CODE_SUBAGENT_MODEL=claude-sonnet-4-6,或在智能体 frontmatter 中按智能体设置 model: sonnet。它从源文件(file/JSONL)读取,而非从图像化历史中读取。这覆盖了你有意路由的精确召回场景;但无法捕获你未预料到的无声误读——正是上面提到的那项尚未构建的防护。
它会破坏实际工作吗?在我们衡量的指标上具有一致性:一个包含 10 个实例的 SWE-bench Lite 试点(简单子集),两组均解决了 10/10,pxpipe 开启时 token 等价成本为 $27,关闭时为 $54;19 对 SWE-bench Pro(更困难、长周期)测试中,开启组解决了 14/19,关闭组解决了 15/19,每次请求成本降低 60%:两组在 18/19 个案例上判定一致,唯一的分歧(一个开启组失败案例)在复制测试中 3/3 重新解决,即属于运行间智能体方差,而非压缩问题。样本量较小,详细说明和注意事项见下文。
节省成本取决于工作负载。它在 token 密集内容(约 1 字符/token:代码、JSON、哈希值)上表现优异,而在稀疏的英文散文(约 3.5 字符/token)上则不划算。内置门控仅对数学计算上划算的内容进行图像化处理,并基于 N=391 条生产数据行进行了校准。
模型范围:一个 PXPIPE_MODELS CSV 文件控制着两个模型族中哪些底座会被成像——默认是 claude-fable-5、gpt-5.6(GPT 5.5 为可选加入;它在成像上下文上会降级)。将 PXPIPE_MODELS 设为 off 可完全禁用成像,或使用 ~/.config/pxpipe/config.json 并写入 { "models": "off" }(或一个列表)。对于 GPT,pxpipe 以原生 JSON 格式保存工具定义(只有冗长的模式描述会被放入图像),因此工具调用保持可靠;与 Claude 路径不同,GPT 路径不会添加或依赖 Anthropic 的 cache_control 提示缓存标记。仪表盘上的面板可以实时切换任何模型,无需修改客户端配置。Opus 4.7/4.8 是初始的 Claude 范围,但它在约 7% 的渲染中发生了误读(10200→9400),因此在 Fable 5 达到 100/100 且图像计费相同后,默认关闭了它——你可以通过 PXPIPE_MODELS 或仪表盘面板自行选择重新开启,风险自负。其他所有内容原样通过。
可复现的基准测试
使用模型无法记住的新颖随机数问题进行测量:
| 测试 | 样本数 | 文本 | pxpipe(图像) | token数 |
|---|---|---|---|---|
| 新颖算术,claude-fable-5 | 100 | 100% | 100% | –38% |
| 新颖算术,claude-opus-4-8 | 100 | 100% | 93% | –38% |
| 要点回忆A/B(决策、数值、路径、名称、否定;含干扰项;15k-45k字符会话),Fable 5 | 98/arm | 98/98 | 98/98 | – |
| 状态跟踪(值变化3次,最终/首次/计数),Fable 5 | 18/arm | 18/18 | 18/18 | – |
| 对从未陈述的事实的虚构(越低越好),Fable 5 | 16/arm | 0/16 | 0/16 | – |
| 逐字12字符十六进制回忆,密集渲染,Opus | 15 | 15/15 | 0/15 | – |
| 逐字12字符十六进制回忆,密集渲染,Fable 5 | 15 | – | 13/15 | – |
SWE-bench Lite 试点(端到端任务质量)
10个SWE-bench Lite实例,Claude Code + Fable 5,通过pxpipe开启与关闭进行配对运行,使用官方swebench Docker框架评分:
| pxpipe 开启 | 关闭 | |
|---|---|---|
| 解决 | 10/10 | 10/10 |
| 请求大小与自身未压缩主体对比 | –65% | ±0 |
–65% 是每次请求(压缩前对每个主体进行count_tokens探测)的数据,因此没有轮次混淆。n=10/arm,Lite偏向简单。运行总计、收据、注意事项:eval/swe-bench/。
SWE-bench Pro 基准测试(更难,长期)
两次运行共完成19对(2对放弃:两个分支检出失败),相同设置,官方SWE-bench_Pro-os Docker框架:
| pxpipe 开启 | 关闭 | |
|---|---|---|
| 解决 | 14/19 | 15/19 |
| 请求大小 vs 自身未压缩的响应体 | −60% | ±0 |
在 19 个实例中,18 个的评价结果一致(三个实例的两端均失败,其中一个是两端字节完全相同的补丁)。唯一的分歧(navidrome,ON 端失败)在 ON 端重复了 3 次:三次运行均产生了相同的补丁并成功解决,因此最初的损失是运行间智能体方差造成的,与压缩无关。凭证:eval/swe-bench-pro/。
我们还运行了 GSM8K:获得了 96% 的成像结果。但 GSM8K 存在于训练数据中,因此模型会通过自身误读来回忆已记忆的答案,从而虚增分数,所以我们改用干净的新数字评测作为主要依据。复现方式:eval/gsm8k/ · eval/needle-haystack/ · eval/gist-recall/ · 完整分析见 FINDINGS.md。
常见问题
这个数据是端到端的,还是仅针对你处理过的请求?是端到端的,涵盖全部费用。大多数压缩工具只报告它们所处理的输入部分的节省量,这会让数字更好看。端到端的分母是所有生产请求:包括 pxpipe 正确保留的小请求、所有缓存写入和读取、以及所有输出 token(代理从不压缩输出)。在 13,709 个请求的快照中,节省了 59%(100 美元 → 约 41 美元);后续一个 8,904 个压缩请求的跟踪测得约 70%。仅压缩部分则更高(约 72–74%),并单独列出,从不作为标题数据。具体数据取决于工作负载——请在自己的日志上复现。
这个数学计算是如何完成的?对同一个请求的两端,在同一时刻进行。对于每个 /v1/messages POST,代理会并行地对原始未压缩体(反事实情况)发出一个免费的 count_tokens 探测,同时进行实际转发,并从响应中读取 Anthropic 实际计费的使用情况块。两端都会记录在 ~/.pxpipe/events.jsonl 的同一行中,因此不存在轮次或运行间混淆。美元换算使用 Fable 5 列表比率:输入 ×1.0,缓存写入 ×1.25,缓存读取 ×0.1,输出 ×5。缓存定价对两端相同,因此缓存折扣相互抵消,不会重复计算为“节省”。您可以从事件日志中自行推导:公式和字段名称在 src/core/baseline.ts 中有文档说明。
它实际上压缩了什么?三种输入块,每种都经过一个盈利性门控:
- 大型工具结果体(文件读取、命令输出、日志)中,超过约 6k 字符的密集 token 内容。
- 较早折叠的历史记录:位于实时尾部之后的轮次会被重新渲染为图像页面,而最近的轮次始终保留为文本。
- 静态系统提示词 + 工具文档模块。
其他所有内容都原样逐字节通过:你的消息、最近轮次、模型输出(它就是响应本身,代理从不触碰它)、稀疏的散文,以及任何太小以至于不值得转换的内容。非 Fable 模型则完全原样通过。
在真实场景中(基准测试之外)它真的失败过吗?是的,在数周的日常使用中发生过一次:模型从图像化的聊天历史中回忆了一个人的名字,并自信地给出了错误答案。没有报错,只是一个看似合理但错误的名字。这就是文档中记录的错误模式:图像化内容中的精确字符串不具备字节安全性。编码会话可以容忍这种情况,因为代理在编辑前会重新读取文件;纯聊天回忆则没有这样的检查。
工作原理
tool_result string ──► wrap at 1928px-wide columns ──► pack ~92,000 chars/page ──► PNG[]
代理拦截 /v1/messages,将符合条件的批量历史记录重写为图像块,然后以缓存友好的方式将它们拼接回去(保留静态前缀,使提示缓存继续工作),并转发。每次请求的事件记录到 ~/.pxpipe/events.jsonl。
经济性计算:一张 1928×1928 的图像需要约 4,761 个视觉 token,最多可容纳约 92,000 个字符(在观察到的密度下约相当于 48,000 个文本 token),因此纯文本只有在密度超过约 19 字符/token 时才更便宜。Claude Code 的转录内容远低于该密度(观察值为 1.91 字符/token,N=391)。运行时估算器(estimateImageCount)加上一个字符/token 阈值决定每次请求的处理方式;稀疏散文则保留为文本。
库使用(无代理)
同样的引擎,无代理。将文本渲染为 PNG,或运行完整的缓存安全转换:
import { renderTextToPngs, transformAnthropicMessages } from "pxpipe"; const imgs = await renderTextToPngs(toolResultText); // RenderedImage[] const { body, applied, info } = await transformAnthropicMessages({ body: requestBytes, model: "claude-fable-5", });
options.keepSharp(block) 将某些块强制保留为文本(覆盖对 ID、哈希值、路径的启发式判断);options.emitRecoverable 返回已图像化块的原始内容,以便有状态的调用方可以恢复它们——这是针对下面有损限制的保真契约的两个部分。运行环境为纯 JS(Node 和 edge/Workers);@napi-rs/canvas 仅在构建时使用。完整 API、类型和常量参见:src/core/index.ts。
开发
pnpm install && pnpm test # 376 tests pnpm run build # regenerates dist/
限制
- 有损:请参阅上方“诚实的一面”。从图像中逐字回忆是不可靠的。
- 渲染延迟:编码 PNG 会为大型请求在离开前增加额外时间(部分被模型消耗更少 token 所抵消)。响应正常流式输出。
- ASCII/Latin-1 已充分测试;CJK(中日韩字符)可用但处理较保守。
- 运行时是纯 JavaScript——可在 Node 和边缘/ Workers 上运行。@napi-rs/canvas 仅在构建时作为开发依赖使用(用于重新生成字形图集),不是运行时依赖。
- 仅支持 Fable 5。
路线图
以上所有内容均已实测。以下内容尚未实测。这些是假设,而非声明;它们要么作为带 n 前缀的数字发布,要么被砍掉。
- 更清晰的字形。13/15 逐字差距部分是由于字体可读性,而不仅仅是模型本身。跨渲染风格的逐字符混淆矩阵正在运行中(eval/glyph-matrix/);如果某种零成本风格能降低阅读错误,那么在相同保真度下,门控压缩会更激进。
- 有效上下文。密集文本作为图像传输时,token 消耗约为直接使用图像的 1/3。如果这一结论在实时窗口中成立(而不仅仅是账单层面),那么 1M token 实际上能承载约 2 倍的真实内容。开放问题:当一个需要约 2M 原始上下文的任务在 Fable 的 1M 上下文中运行时,如果大部分内容已被图像化,是否仍能执行?
- 更少的活跃文本,更锐利的模型。长上下文会随着填充而降低推理能力。将旧的大块内容图像化,可以缩小模型主动读取的范围,同时使其仍可访问。假设:相同信息,更小的活跃上下文,更好的长任务准确率。
一个赌注:更长的有效上下文和更锐利的长任务模型,来自同一个 Fable 5。要么出数字,要么撤回,中间不炒作。
许可证
MIT。
