How I built a vision-token trimmer that prices images for one provider — and a reader caught it
说明与用途
Ankita 的裁剪器使用基于瓦片的公式估算图像令牌,仅适用于 OpenAI。当通过兼容 OpenAI 的代理服务 Claude 时,估算会低估令牌,导致请求被拒绝和意外的历史裁剪。
问题
The trimmer estimates image token cost using a formula that is only accurate for OpenAI-compatible vision endpoints, causing incorrect trimming when the provider is different (e.g., Claude behind an OpenAI-compatible proxy).
结果
The trimmer’s tile‑based estimator works for OpenAI but under‑estimates token cost for providers like Claude, causing over‑trimming or request rejection when used behind an OpenAI‑compatible proxy.
工作流
- 1. Load image URL and read header to get dimensions.
- 2. Fit image to 2048 pixels on the long side.
- 3. Scale short side to 768 pixels.
- 4. Compute tiles: ceil(width/512) * ceil(height/512).
- 5. Return 85 + 170 * tiles as estimated tokens.
- 6. Trim conversation history to fit within the provider’s token budget using this estimate.
证据
The trimmer was weighing a screenshot's base64 string as if it were text, so a 1.6 MB PNG looked like 1.6 MB of context and got deleted before the model ever saw it.
The estimator lives in src/core/history.mjs and takes exactly one argument: the image URL.
Take bickov's example, a 2560×1440 screenshot. Fit to 2048 on the long edge gives 2048×1152; scale the short side to 768 gives 1365×768; that is 3 × 2 tiles, so 85 + 170 × 6 = 1,105 tokens.
Claude does not bill in tiles. It bills roughly by pixels — width × height / 750 — and reads up to a 2576-pixel long edge. The same screenshot comes out at 4,784 tokens on bickov's numbers.
- 记录日期: 2026-11-03T11:28:50.753Z