同一20行产品表在不同格式下GPT-4o token计数:CSV 300Tokens,JSON缩进884Tokens,XML达1088Tokens,JSON比CSV多花3倍。
大多数人会把数据粘贴到prompt里,通常是直接用JSON.stringify(data, null, 2)。我从来没有测量过这样会消耗多少token,所以找了一张表格,用七种格式写入并计数。
结论:带缩进的JSON比CSV多消耗约3倍的token。
一张产品表:20行,5个字段(id、nome、preço、em_estoque、categoria)。CSV格式的一行:
1001,Wireless Mouse,9.99,false,electronics
同一份数据用七种格式,用GPT-4o和OpenAI最新模型的tokenizer o200k_base计数:
import { getEncoding } from "js-tiktoken";
const enc = getEncoding("o200k_base");
const count = (s) => enc.encode(s).length;
count(csv); // 300
count(JSON.stringify(rows)); // 525
count(JSON.stringify(rows, null, 2)); // 884
用旧的tokenizer(cl100k_base)数字几乎一样:所有格式的差异都不到2%。
键名在每行都会重复。JSON、YAML和XML要把"name":和"price":写二十遍。CSV只写一次,就是表头那行。
标点符号也是token。左引号、右引号、花括号、冒号都要算。XML最糟糕:每个值都有一个开始标签和一个结束标签。
缩进是为了人类。模型不需要它。仅格式化就比压缩后的JSON多了359个token(+68%)。
YAML是个有趣的特例:字符数比压缩后的JSON还少,但token数却更多,因为每个字段都单独占一行,且每行都有键名。
编程Agent会发送大量代码,所以我测试了一些场景:
缩进几乎不花钱。 当前的tokenizer会把多个连续空格合并成一个token。为了省token而重新格式化代码不值得。
代码压缩后只用一半token,但别这么做。 你会丢失subtotal和taxRate这样的变量名,而这些恰恰是帮助模型理解代码的关键。
UUID很贵。 如果你的prompt里有一列很长的ID,改成行号,在代码里做映射转换回来。
如果值里包含逗号,用TSV,这样就不需要引号了。
能正确解析比省几个token更重要;如果你的API支持,用结构化输出。
手动扁平化成CSV往往得不偿失。
只比CSV多24%。
避免在prompt里用带缩进的JSON和XML,除非某个工具强制要求。
删除没用到的字段、null值和多余的小数位也有帮助。
假设每次请求附一张20行的表,每天1000次请求,每月30000次,输入token每百万2美元:
一次请求看不出区别,但一个产品里会显示,而且随着表格变大、RAG结果增多、API响应变长,成本会持续增长。
一张表和一个tokenizer。Claude和Gemini的tokenizer计算方式不同,所以绝对数字会变化。但顺序(键名和标签重复会贵)是格式本身结构决定的,应该保持一致。
如果某种格式在你的场景下会影响响应质量,就两种都测。便宜的prompt换来更差的回答,其实并不便宜。
我做了一个免费的token计数器。它在浏览器内运行同样的o200ktokenizer,所以你粘贴的内容不会发送到任何服务器。把你的数据用两种格式粘贴进去,比较token和每个模型的费用。