메뉴
HN
Hacker News 25일 전

코드를 이미지로 변환해 OCR로 읽게 하여 비용 60% 절감

IMP
8/10
핵심 요약

로컬 프록시 도구인 'pxpipe'는 대용량 텍스트(시스템 프롬프트, 문서 등)를 이미지로 변환하여 AI 모델에 전달함으로써 토큰 사용량을 획기적으로 줄여줍니다. 이를 통해 클로드 코드(Claude Code) 기반 작업의 엔드투엔드 비용을 최대 70%까지 절감할 수 있어, 토큰 기반 API 비용 절감에 획기적인 해결책으로 주목받고 있습니다.

번역된 본문

pxpipe(픽스파이프)는 방대한 문맥을 이미지로 렌더링하여 Claude Code의 입력 토큰을 대폭 줄여줍니다. 동일한 시스템 프롬프트, 도구 문서 및 기록을 단지 극소수의 토큰만으로 처리할 수 있습니다. 이미지의 토큰 비용은 내부에 텍스트가 얼마나 들어있는지가 아니라 픽셀 크기에 따라 고정되기 때문입니다. 실제 Claude Code 트래픽에서 텍스트 토큰당 약 1자가 처리되는 것과 비교했을 때, 밀집된 콘텐츠(코드, JSON, 도구 출력)는 이미지 토큰당 약 3.1자를 압축하여 담을 수 있습니다.

pxpipe는 이러한 토큰 격차를 활용하는 로컬 프록시입니다. 요청이 사용자의 컴퓨터를 떠나기 전에 요청의 무거운 부분(시스템 프롬프트, 도구 문서, 이전 기록)을 작은 PNG 이미지로 다시 작성합니다. 절약 효과는 작업 부하에 따라 다릅니다. pxpipe는 토큰이 밀집된 콘텐츠에서 빛을 발하며, 텍스트가 적거나 간단한 요청은 그대로 두므로, 아래의 수치는 고정적인 상수가 아닌 실제 측정된 결과입니다.

가장 핵심적이고 영구적인 결과는 입력 토큰 감소입니다. 방대한 시스템 프롬프트, 도구 문서 및 기록이 텍스트 대신 작은 이미지로 들어갑니다(위 예시에서는 약 25,000개의 텍스트 토큰이 약 2,700개의 이미지 토큰으로 렌더링됨). 모든 요청은 자체적인 count_tokens(토큰 계산) 반복 테스트를 통해 측정되었습니다. 비용은 토큰 수의 감소에 따라 자연스럽게 따라옵니다. 현재 Fable의 정가를 기준으로 할 때, 토큰 감소는 약 5970%의 엔드투엔드 청구 비용 절감 효과를 가져옵니다(압축된 요청의 경우 약 7274% 절감, 자세한 가격 계산은 FAQ 참조). 하지만 정가는 내일 당장 바뀔 수 있어도 토큰 수는 변하지 않으므로, 우리가 주목해야 할 핵심 지표는 달러(비용)가 아닌 '토큰 수'입니다. 이 모든 결과는 ~/.pxpipe/events.jsonl에서 재현할 수 있습니다.

다음은 모델이 텍스트 대신 보게 되는 내용입니다. 시스템 프롬프트와 도구 문서(이 리포지토리의 README, FINDINGS 및 소스 코드)의 약 48,000자를 텍스트로는 약 25,000 토큰으로 처리하지만, 이 페이지를 이미지화하면 약 2,700 이미지 토큰으로 줄어듭니다. 이는 실제 transformRequest 파이프라인을 통해 생성된 결과입니다. 공백이 최소화되고, ↵ 기호로 원래 줄바꿈을 표시하여 꽉 찬 행으로 재배치되며, 상단에 OCR 지시 배너가 함께 렌더링됩니다. 모델은 이렇게 렌더링된 이미지를 깨끗한 평가 환경에서 100/100의 정확도로 읽어냅니다(벤치마크 참조).

데모 - Fable 5 데모(기본값, 100/100 판독기): Fable-AB-Demo.mp4. 두 데모 모두 Fable 5에서 실행된 양쪽 화면을 보여줍니다(왼쪽은 일반, 오른쪽은 pxpipe). Fable은 Opus가 읽지 못하는 것을 읽어냅니다. Opus가 거부하는 이미지화된 구문 계산에 대해(아래 Opus 데모 참조), pxpipe를 적용한 측은 39개의 이미지화된 더미 파일에서 토큰을 정확히 10/10으로 계산하여(grep의 실제 값과 줄 단위로 일치함) 다단계 원장 계산(8037 → … → 15,021)을 정확하게 수행합니다. 동일한 답변을 얻지만 비용은 약 7배 더 저렴합니다. 두 데모 실행 후의 세션 총계는 다음과 같습니다. 일반의 경우 $42.21이 들고 컨텍스트는 96% 찼으며(964.5k/1M — 강제 압축까지 한 작업 남음), 반면 pxpipe는 컨텍스트 여유가 충분(73.5k/1M)하며 $6.06가 소요되었습니다.

클립에서 확인할 수 있는 솔직한 주의 사항: pxpipe를 적용한 측은 카운트에 먼저 답변했고, 요청된 한 줄 형식으로 원장 잔액도 출력하기 위해 한 번의 후속 지시가 필요했습니다. 반면 일반 측은 첫 시도부터 형식을 잘 따랐습니다. 가독성 문제는 Fable에서 해결되었으며, 단일 회신에서 형식을 완벽히 준수하는 것이 남은 과제입니다.

Opus 4.8 데모(Opus는 기본적으로 비활성화됨): Opus-AB-Demo.mp4. 나란히 실행된 화면 — 일반 Claude(왼쪽) 대 pxpipe(오른쪽), 모두 Opus 4.8에서 실행됨(선택 적용, pxpipe는 Fable에 맞게 조정됨 — 위의 Fable 클립 참조). 이미지를 클릭하여 시청하세요(Google Drive).

데모 1 — 실패한 테스트 스위트 수정: 양쪽 모두 통과했습니다. 대시보드는 pxpipe가 요청을 토큰의 극히 일부로 줄인 것을 보여줍니다(서버에서 실제로 측정한 컨텍스트/토큰 감소). 데모 2 — 대용량 파일 컨텍스트(40개 파일, 약 382k 토큰)와 수학 문제 및 '이 구문 세기' 작업: 수학 답변(작은 텍스트 조각)은 양쪽 모두에서 읽힙니다. 구문 계산은 이미지화된 더미를 읽어야 하므로 Opus의 pxpipe는 이를 읽지 못하고, 숫자를 조작하지 않겠다고 솔직하게 알립니다(정확한 값은 텍스트로 유지해야 한다는 공개된 손실 한계). 반면 일반 측은 파일별로 세느라 진창 늪에 빠집니다.

직접 사용해 보기 (30초 소요) npx pxpipe-proxy # 127.0.0.1:47821에서 프록시 실행 ANTHROPIC_BASE_URL=http://localhost:47821 claude # Claude Code를 이쪽으로 연결

http://127.0.0.1:47821/을 열면 실시간 대시보드를 볼 수 있습니다: 절약된 토큰, 세션별 통계, 모든 텍스트→이미지 변환 내역이 나란히 표시되며, 전역 종료 스위치 및 GPT 5.6과 GPT 5.5를 포함한 런타임 모델 칩을 제공합니다. 다른 것은 변경되지 않습니다. 응답은 정상적으로 스트리밍됩니다. pxpipe는 모델의 출력이 아닌, 오직 사용자가 보내는 컨텍스트(요청)만을 압축합니다.

원문 보기
원문 보기 (영어)
pxpipe Cut Claude Code's input tokens by rendering bulky context as images — the same system prompt, tool docs, and history, in a fraction of the tokens. An image's token cost is fixed by its pixel dimensions, not by how much text is inside it. Dense content (code, JSON, tool output) packs ~3.1 chars per image-token vs ~1 char per text-token on real Claude Code traffic. pxpipe is a local proxy that exploits that gap: it rewrites the bulky parts of your request (system prompt, tool docs, older history) into compact PNGs before the request leaves your machine. Savings are workload-dependent — pxpipe wins on token-dense content and leaves sparse/small requests untouched — so these are measured snapshots, not constants. The primary, durable result is input-token reduction : dense system prompts, tool docs, and history go in as compact images instead of text (the example above is ≈25k text tokens rendered as ≈2.7k image tokens), every request measured against its own count_tokens counterfactual. Dollars are downstream of that — at current Fable list prices the token cut lands as a ~59–70% lower end-to-end bill (~72–74% on compressed requests; full pricing math in the FAQ). But list prices can change tomorrow and the token count won't, so tokens — not dollars — are the number to watch. Reproduce both from ~/.pxpipe/events.jsonl . This is what the model sees instead of text: ~48k characters of system prompt + tool docs (this repo's own README, FINDINGS, and source), ≈25k tokens as text, ≈2.7k image tokens as this page. Produced by the real transformRequest pipeline: whitespace-minified, reflowed into full rows with ↵ marking original newlines, OCR instruction banner co-rendered on top. The model reads renders like this at 100/100 on a clean eval (see benchmarks). Demo Fable 5 demo (the default, 100/100 reader): Fable-AB-Demo.mp4 Both demos with both panes on Fable 5 (plain left, pxpipe right). Fable reads what Opus can't. The imaged phrase-count that Opus refuses (see the Opus demo below): the pxpipe arm counts the exact token 10/10 across 39 imaged filler files (matches grep ground truth line-for-line) and gets the multi-step ledger arithmetic right (8037 → … → 15,021). Same answers, ~7× cheaper. Session totals after both demos: plain $42.21 , context 96% full (964.5k/1M — one task away from forced compaction) vs pxpipe $6.06 with context to spare (73.5k/1M). Honest caveat, visible in the clip: the pxpipe arm answered the count first and needed one follow-up nudge to also print the ledger balance in the requested one-line format; the plain arm followed the format on the first try. Legibility is solved on Fable — single-reply format compliance is the remaining rough edge. Opus 4.8 demo (Opus disabled by default): Opus-AB-Demo.mp4 Side-by-side — plain Claude (left) vs pxpipe (right), both on Opus 4.8 (opt-in; pxpipe is tuned for Fable — see the Fable clip above). Click the image to watch (Google Drive). Demo 1 — fix a failing test suite: both pass; the dashboard shows pxpipe cut the request to a fraction of the tokens (real, server-measured context/token reduction ). Demo 2 — a big file-context (40 files, ~382k tokens) plus a math question and a "count this phrase" task: the math answer (a small text needle) reads on both. The phrase-count needs reading the imaged filler — so pxpipe-on-Opus can't read it and honestly surfaces that it won't fabricate a number (the documented lossy limit: exact values stay text). Plain, meanwhile, bogs down counting file-by-file. Try it (30 seconds) npx pxpipe-proxy # proxy on 127.0.0.1:47821 ANTHROPIC_BASE_URL=http://localhost:47821 claude # point Claude Code at it Open http://127.0.0.1:47821/ for a live dashboard: tokens saved, per-session stats, every text→image conversion side by side, a global kill switch, and runtime model chips including GPT 5.6 and GPT 5.5. Nothing else changes. Responses stream normally; pxpipe only compresses the request (your context going up), never the model's output. Recent turns stay text; the system prompt, tool docs, and older bulk history are imaged. The honest part, read before relying on it It is lossy. pxpipe is a gist tier, not a lossless store. In a needle-in-haystack eval, exact 12-char hex strings inside dense imaged content came back 0/15 on Opus and 13/15 on Fable 5, and the failure mode is silent confabulation : a plausible wrong value, not an error. Anything you need back byte-exact (IDs, hashes, secrets, exact numbers) must stay text. Recent turns do; a dedicated verbatim-risk guard is not built yet. Exact-recall escape hatch. pxpipe only images Fable requests ( PXPIPE_MODELS=claude-fable-5 ), so any subagent on a non-Fable model passes through as text. Route work that needs byte-exact values to one — globally with CLAUDE_CODE_SUBAGENT_MODEL=claude-sonnet-4-6 , or per-agent with model: sonnet in the agent frontmatter. It reads from source (file/JSONL), not the imaged history. This covers exact-recall you route on purpose; it does not catch a silent misread you did not expect — that is the unbuilt guard above. Does it break real work? Parity in what we measured: a 10-instance SWE-bench Lite pilot (the easy subset) resolved 10/10 on both arms , pxpipe ON at $27 vs OFF at $54 token-equivalent, and 19 SWE-bench Pro pairs (harder, long-horizon) resolved 14/19 ON vs 15/19 OFF at -60% per-request : verdicts agree on 18/19, and the single split (one ON fail) re-resolved 3/3 when replicated, i.e. run-to-run agentic variance, not compression. Small n, details and caveats below. Savings are workload-dependent. It wins on token-dense content (~1 char/token: code, JSON, hashes) and loses money on sparse English prose (~3.5 chars/token). The built-in gate only images content where the math wins, calibrated against N=391 production rows. Model scope: one PXPIPE_MODELS CSV controls which model bases get imaged across both families — default claude-fable-5,gpt-5.6 (GPT 5.5 is opt-in; it degrades on imaged context). Set PXPIPE_MODELS=off to disable imaging entirely, or use ~/.config/pxpipe/config.json with { "models": "off" } (or a list). For GPT, pxpipe keeps tool definitions in native JSON (only verbose schema prose moves into the image) so tool-calling stays reliable; unlike the Claude path, the GPT path does not add or depend on Anthropic cache_control prompt-cache markers. The dashboard chips can flip any model live without changing client configs. Opus 4.7/4.8 was the original Claude scope but misread ~7% of renders ( 10200 → 9400 ), so it was turned off by default once Fable 5 hit 100/100 with identical image billing — opt it back in at your own risk via PXPIPE_MODELS or the dashboard chips. Everything else passes through untouched. Benchmarks (reproducible) Measured with novel random-number problems the model cannot have memorized: test N text pxpipe (image) tokens novel arithmetic, claude-fable-5 100 100% 100% −38% novel arithmetic, claude-opus-4-8 100 100% 93% −38% gist recall A/B (decisions, values, paths, names, negations; with distractors; 15k-45k char sessions), Fable 5 98/arm 98/98 98/98 - state tracking (value mutated 3x, final/first/count), Fable 5 18/arm 18/18 18/18 - confabulation on never-stated facts (lower is better), Fable 5 16/arm 0/16 0/16 - verbatim 12-char hex recall, dense render, Opus 15 15/15 0/15 - verbatim 12-char hex recall, dense render, Fable 5 15 - 13/15 - SWE-bench Lite pilot (end-to-end task quality) 10 SWE-bench Lite instances, Claude Code + Fable 5, paired runs through pxpipe ON vs OFF, graded with the official swebench Docker harness: pxpipe ON OFF resolved 10/10 10/10 request size vs own uncompressed body −65% ±0 The −65% is per-request ( count_tokens probe of each body before compression), so it has no turn-count confound. n=10/arm, Lite skews easy. Run totals, receipts, caveats: eval/swe-bench/ . SWE-bench Pro bench (harder, long-horizon) 19 completed pairs across two runs (2 dropped: checkout failed both arms), same setup, official SWE-bench_Pro-os Doc