TOON 与 JSON:一种用于降低 LLM 成本的 Token 优化数据格式
上个月,我亲眼目睹一个生产环境中的 RAG 流水线在一个周末就烧掉了 1940 美元。罪魁祸首仅仅是一张包含 500 行数据的客户表,它以传统的 JSON 格式进行编码。而同样的数据如果用 TOON 处理,成本仅为 760 美元。同样的模型,同样的结果,同样的延迟,但 TOON 的令牌数量却减少了 61%。
你可能也有过这样的经历。你给上下文有效负载添加了一个额外的字段,令牌计数器就飙升了几百。突然间,你不得不精简键值,或者祈祷模型能正确读取结构。我们都只能想办法应对,因为 JSON 已经作为默认格式使用了二十年。
大多数开发者都忽略了一个细节。JSON诞生于2001年,比iPhone早5年,比GPT-1早14年。Douglas Crockford最初设计JSON是为了浏览器和服务器之间的Ajax往返通信,而不是为了那些按令牌计费的、拥有万亿参数的模型。在当时没有推理计费的世界里,每一个带引号的键、数组中每一个重复的字段名、每一个花括号都显得合情合理。
到 2025 年,这些符号将需要真金白银来购买。
TOON 可以消除这种成本。它保留了 JSON 数据模型的所有元素(对象、数组、数字和空值),但会重写文本,使其更易于阅读,而您实际上需要为 LLM 本身付费。它将多个键行替换为单个标题行,删除不必要的引号,使用缩进代替花括号,并添加显式长度保护,以防止模型猜测数组大小。
本文详细阐述了为什么 JSON 会意外地成为 AI 工作的负担,TOON 如何在语法层面消除这种负担,以及如何在不重写技术栈的情况下将其添加到您的代码中。
如果您购买代币,请继续阅读。您的下一张账单取决于此。
JSON 的传承:一种 Web 标准,而非 AI 标准
JSON 仍然是通用数据交换的黄金标准。它的带引号的键、大括号、方括号和逗号保证了所有编程语言都能进行明确的解析,并且使得在浏览器控制台中轻松检查有效负载成为可能。
JSON 诞生之初,这些属性解决了实际问题。带宽是主要限制因素,而基于代币的定价机制当时并不存在。
如今,限制条件已发生变化。取一个对象
{
"id": 1,
"name": "Alice"
}
它使用约 26 个词元,而不是人工计数的 6-8 个。在现代 BPE 分词器中,引号、冒号、逗号和大括号都变成了单独的子词。
当该对象出现在一个包含 500 行的数组中时,其键字符串和周围的标点符号会重复数百次。实际基准测试记录显示,格式化后的 JSON 数据重复了 11,842 个词元,而压缩后的版本则重复了 4,617 个词元。语言模型无法从这些重复中获取任何额外信息;它们存在的唯一目的就是为了确保传统解析器的语法正确性。
对于 REST API、配置文件以及任何无需进行令牌计数的系统而言,JSON 仍然是最佳选择。然而,在 LLM 提示符中,同样的语法却会造成不必要的开销,直接增加成本并减少可用上下文信息。
什么是TOON?
TOON(Token-Optimized Object Notation,标记优化对象表示法)是一种用于结构化数据的即插即用型文本表示法,它保留了完整的 JSON 数据模型,包括对象、数组、字符串、数字、布尔值和空值。此外,它还移除了 LLM 提示符中导致标记计数增加的标点符号和重复项。
TOON 不是将每个对象都用花括号括起来,也不是在每一行重复键值:
- 使用缩进而不是
{}and, - 预先声明数组结构,这样字段就不会重复。
- 显式地保留顺序和模式
- 以基于行的形式清晰地传输 RAG 管道的数据流
- 无损往返转换回 JSON
它不是一种新的数据库标准,也不是一种压缩算法。TOON 以模型偏好的形式提供它们所需的数据:更少的语法、更多的信号、更少的词法单元。
TOON 如何在不改变数据的情况下降低令牌负载
当使用 JSON 作为模型输入时,其语法就成了一种负担;解析所需的字符会增加标记数量并减少可用的推理空间。
TOON 的方法是保留 JSON 的全部表达能力,同时改变其在页面上的呈现方式。它以分词器而非运行时环境为主要使用者。
注意: TOON 对重复结构优化效果极佳,但它并非通用压缩器。对于高度嵌套或无模式的数据,优化效果会比较有限。
下面我们将更详细地探讨这一变化背后的机制。
基于缩进的层级结构,而非基于符号的分隔符
JSON 依赖标点符号来表达作用域。大括号定义对象,方括号定义数组,逗号分隔数组元素。分词器会将这些符号拆分成各自的子词。
TOON 将此结构含义移至空白处:
- 两个空格代表一个嵌套层级
- 引入子对象时,每个键都另起一行。
- 上下文决定解释,而不是花括号。
嵌套对象翻译示例:
{
"user": {
"profile": {
"city": "Paris"
}
}
}
变成
user:
profile:
city: Paris
这样既减少了语法字符,又保持了确定性的解析性。解析器跟踪的是缩进级别而不是标点符号。对于模型来说,这是一个更容易学习的信号。
头驱动数组用声明式结构取代重复代码
统一数组在实际数据中很常见。JSON 必须为每个元素重复所有字段名和标点符号。TOON 通过将形状提取到单个声明中来压缩这种格式:
items[<row count>]{<field order>}:
接下来就只剩下数值了:
items[3]{sku,qty,price}:
A12,4,19.99
B18,1,12.50
C22,3,9.25
内部构造:
- 钥匙出现一次
- 保证列顺序
- 行是固定宽度的逻辑元组
对于包含 500 行的数据集,这种结构通常可以将标记数量减少一半以上。改进效果与数组长度呈线性关系。
技术检测逻辑
编码器在以下情况下会折叠数组:
- 所有元素都是对象
- 它们共用一套相同的钥匙。
- 密钥顺序稳定
- 空字段仍然是有效的内联值
否则,TOON 将回退到逐个对象扩展。不会出现歧义或隐性错误。
图式和基数传播到提示中
JSON 蕴含结构,TOON 则将其展现出来。模型受益于清晰定义的边界。
两个设计选择至关重要:
[N]明确设置预期行数
•{field1,field2,…}静态强制执行列顺序
这些引导提取任务的方式是标点符号无法实现的。一个模型如果人为地增加了一行,就会与声明的基数相矛盾。一个位置错误的字段会明显出现错位。
这可以减少以下情况的幻觉:
- 表格重建
- RAG 答案接地
- 工具响应需要有效的 JSON 输出
基准测试表明,LLM 解码 TOON 时比解码 JSON 时在精确匹配指标方面有所改进,并且错误输出更少。
针对分词器而非解析器进行了优化
BPE 和一元词法分词器不会将结构字符视为原子字符:
- 引号通常被标记化为
",加上键的前 1-2 个字符。 - 大括号会成为独特的标记片段,不会在其他地方重复使用。
- 重复的键名在提示符中被反复分割。
TOON 利用语言标记合并技术:
- 字母数字键通常映射到单个令牌。
- 缩进和换行符属于低成本的空白区域。
- 类似 CSV 的模式会触发高重用分词器。
包含 100 行的表格的示例标记比较:
JSON 压缩后:约 2,540 个词元
TOON 代币等值:约 1,020 个代币
语义相同,分词行为却截然不同。
确定性往返和流式传输支持
编码器是一个纯粹的转换层,它不会压缩或解释值。解码过程会逐字节地还原原始 JSON 数据(数字中的空格和可选的引号除外)。
两个主要 API 至关重要:
import { encode, decode, encodeLines } from '@toon-format/toon';
const text = encode(data); // Buffer → TOON text
const obj = decode(text); // TOON text → JSON structure
for await (const chunk of encodeLines(largeData)) {
// Suitable for incremental context injection in RAG
}
大型结构化有效载荷可以以流式传输的方式进行,而无需将整个文档加载到内存中。这有利于提示信息会动态变化的场景,例如代理管道。
设计目的就是轰轰烈烈地失败,而不是悄无声息地失败。
JSON 接受一些结构,这些结构在被模型解析时可能会变得不稳定,例如缺少逗号、字段顺序错误以及尾随结构。有时,模型看起来是正确的,但输出的 JSON 却在语义上存在问题。
TOON严格的格式使得偏差更容易被发现:
- 错误的缩进会破坏结构解析
- 行数不匹配的问题会立即显现。
- 字段顺序不匹配是错误,不能容忍重新排序。
与其调试 LLM,不如让格式本身来判断。
为什么这些选择至关重要
LLM(逻辑逻辑模型)是概率引擎,而非解析器。它们在信号强且需求明确时效果最佳。TOON 的编码策略减少了每个结构边界处的可能解释数量,同时降低了词元成本。
它并非一种新的数据模型,而只是对我们现有模型的一种更易于理解和使用的表示形式。
基于真实数据的基准测试
评判数据格式最客观的方法是观察其在实际管道和模型中的表现。TOON 基准测试套件专注于开发人员日常使用的工作负载,例如员工目录、订单历史记录、分析日志、配置对象和嵌套产品目录。
总共有 209 个结构化提取任务。测试涵盖了四个当前的模型系列:GPT 5 Nano、Gemini Flash、Claude Haiku 和 Grok 4。使用 o200k 基础分词器测量词元数量,因此结果与实际计费相符。
以下是混合数据形状的平均结果:
| 格式 | 准确性 | 代币 | 分数* | 节省与 JSON |
|---|---|---|---|---|
| 卡通 | 73.9% | 2,744 | 26.9 | 减少39.6% |
| JSON 压缩 | 70.7% | 3,081 | 22.9 | 没有任何 |
| YAML | 69.0% | 3,719 | 18.6 | 不适用 |
| JSON | 69.7% | 4,545 | 15.3 | 基线 |
| XML | 67.1% | 5,167 | 13.0 | 不适用 |
得分显示每1000个输入词元的正确提取次数。它是成本指标的直接数值。
统一数组展现出最大的优势。一个包含 500 行的电商订单数据集,如果使用 JSON 格式需要 11,842 个令牌,而使用 TOON 格式仅需 4,617 个令牌。这相当于减少了 61%。假设每天处理 1,000 个 GPT 4o 提示,仅此一项工作负载每月就能节省约 1,740 美元。
准确率也得到了提升。GPT 5 Nano 的重构测试准确率从 92.5% 提高到了 99.4%。显式的字段对齐和声明的行计数有助于模型避免丢失或捏造条目。底层信息本身并没有改变。模型只是需要解释的噪声更少,上下文窗口中有更多空间来处理重要数据。
团队如何在生产中使用 TOON
采用 TOON 格式通常无需进行重大更改。JSON 仍然是数据库和服务的主要数据源。唯一的区别在于,数据在成为模型输入时会被转换为 TOON 格式。这消除了仅在提示信息中出现的令牌开销,而不会影响存储或 API。
典型的检索增强工作流程如下所示:
from toon import encode
records = db.fetch_customers()
prompt = "Answer using this context:\n" + encode(records)
该模型将 TOON 读取为结构化文本,无需特殊指令。如果响应需要返回类型化对象,则同一个库会将其转换回 JSON。这样可以保持堆栈的其余部分不变。
代理系统也变得更加稳定。当工具返回结果列表时,TOON 明确的行数和列顺序有助于模型避免错位错误,否则这些错误会破坏循环中的下一步。
流式管道也能从中受益。由于 TOON 是面向行的,因此可以逐步构建提示,而无需等待右大括号或括号补全。这样一来,从检索到推理的切换速度就更快了。
TOON何时有用,JSON何时仍然适用
TOON 在模型读取大量记录时展现出其优势。在这些提示信息中,大部分长度来自于格式而非数据本身。去除这些格式后,模型可以用更小的空间获取相同的信息。
并非所有数据都能以同样的方式受益。复杂、不规则的对象几乎没有可以简化的结构,因此令牌总数仍然接近 JSON。除了提示信息之外,JSON 仍然是存储、API 和日志记录等无需令牌成本的可靠标准。
正确的方法是使用您自己的有效载荷进行测试。测量模型实际识别的词元数量以及它重建结果的可靠性。TOON 在结构可预测地重复出现且成本压力较高的情况下最为有效。
结论
格式通常反映了它们最初旨在解决的问题。JSON 的诞生是为了尽可能减少浏览器和服务器之间的数据传输阻力。它的标点符号和重复正是其成功之处。
当同样的格式应用于语言模型时,情况就不同了。模型会将每个字符视为一个计算单元,标点符号也成为它们必须先处理才能理解其所描述信息的内容。结果是消耗了更多的词元,而留给真正重要的细节的空间却减少了。
TOON 利用我们已有的数据,并以模型更容易读取的方式呈现。它移除了仅供传统解析器使用的结构,同时保留了语义的完整性。这种差异会迅速体现在词元使用率、延迟以及结构化提取的准确性上。
无需改变数据本身即可获得更好的结果。这正是开发者目前面临的实际机遇。
文章来源:https://dev.to/arindam_1729/toon-vs-json-a-token-optimized-data-format-for-reducing-llm-costs-5pl





