TOON:为大语言模型优化的紧凑结构化数据格式
在构建基于大语言模型(LLM)的应用时,我们常常需要在提示(prompt)中嵌入结构化数据。传统上,JSON 是最常用的选择,但它存在一个显著问题:冗余度高、token 消耗大。例如,在包含多个用户记录的数组中,每个对象都会重复字段名 "id"、"name"、"role",这不仅浪费 token,还可能增加模型解析出错的概率。
有没有一种既能保留 JSON 的语义完整性,又能像 CSV 一样紧凑、同时对 LLM 友好的格式?答案是:TOON(Token-Oriented Object Notation)。
本文将带你快速了解 TOON 是什么、它如何工作、为何特别适合 LLM 场景,并介绍其多语言生态支持。
什么是 TOON?
TOON(Token-Oriented Object Notation)是一种面向 token 优化的结构化数据表示格式,目标是在保持与 JSON 完全等价(lossless)的前提下,最小化 token 使用量,并提升 LLM 对数据结构的理解可靠性。
它的核心思想很简单:
声明结构一次,流式传输数据多次。
对于"均匀对象数组"(即所有对象具有相同字段结构的数组),TOON 会先声明字段名和数组长度,然后以类似 CSV 的方式逐行列出值。
示例对比
原始 JSON(235 tokens):
{
"hikes": [
{ "id": 1, "name": "Blue Lake Trail", "distanceKm": 7.5, "companion": "ana" },
{ "id": 2, "name": "Ridge Overlook", "distanceKm": 9.2, "companion": "luis" }
]
}
TOON 表示(仅 106 tokens):
hikes[2]{id,name,distanceKm,companion}:
1,Blue Lake Trail,7.5,ana
2,Ridge Overlook,9.2,luis
可以看到:
- 字段名 {id,name,...} 只声明一次;
- 数组长度 [2] 显式标注,便于验证;
- 数据行紧凑排列,无冗余括号或引号(除非必要);
- 整体结构清晰,人类可读,模型易解析。
TOON 的设计哲学
TOON 并非要取代 JSON,而是作为 JSON 到 LLM 之间的高效"翻译层":
- ✅ 完全 lossless:decode(encode(x)) === x(经类型标准化后);
- ✅ 确定性输出:相同输入始终生成相同 TOON 文本;
- ✅ 内置验证机制:通过 [N] 长度和 {fields} 头部,可检测截断或格式错误;
- ✅ 混合结构支持:非表格部分用 YAML 风格缩进,表格部分用 CSV 风格,自动适配。
它特别擅长处理以下场景:
- 用户列表、日志事件、商品目录等结构统一的记录集合;
- 需要向 LLM 传递大量上下文数据的 RAG 或 agent 应用;
- 要求模型输出结构化结果的指令(如"返回过滤后的用户列表")。
在 LLM 提示中使用 TOON
- 作为输入(In-context Learning)
将数据编码为 TOON 后,直接放入提示的代码块中:
以下是用户数据(TOON 格式):
toon
users[3]{id,name,role,lastLogin}:
1,Alice,admin,2025-01-15T10:30:00Z
2,Bob,user,2025-01-14T15:22:00Z
3,Charlie,user,2025-01-13T09:45:00Z
请总结活跃管理员的信息。
模型能自然理解这种类似 YAML + CSV 的混合结构,无需额外解释语法。
- 要求模型输出 TOON
明确指定输出格式,并提供头部模板:
"请返回 role 为 'user' 的用户,使用相同的 TOON 格式,更新 [N] 为实际数量。"
预期输出:
users[2]{id,name,role,lastLogin}:
2,Bob,user,2025-01-14T15:22:00Z
3,Charlie,user,2025-01-13T09:45:00Z
- 验证模型输出
使用 strict: true 模式解码,自动校验行数、字段数、转义字符等:
import { decode } from '@toon-format/toon';
try {
const data = decode(modelOutput, { strict: true });
// ✅ 有效 TOON
} catch (e) {
// ❌ 截断、格式错误或字段不匹配
}
这大大提升了系统鲁棒性。
高级特性
自定义分隔符
默认用逗号,但可改用制表符 t 或管道符 | 以进一步减少 token(尤其当数据含逗号时):
items[2|]{sku|name|price}:
A1|Widget|9.99
B2|Gadget|14.5
键折叠(Key Folding)
对深层单键嵌套对象(如 config.db.host),可折叠为点分路径,节省缩进和换行:
原始
config:
db:
host: localhost
折叠后
config.db.host: localhost
解码时可通过 expandPaths: 'safe' 还原结构。
多语言生态支持
TOON 不仅限于 JavaScript!官方已提供 TypeScript、Python、Rust、Java、Swift、Julia、Go(开发中) 等实现,社区还贡献了 C/C++、PHP、Ruby、Lua、Elixir、Scala 等十余种语言的库。
你可以在 Implementations 页面 找到对应语言的 GitHub 仓库,所有实现均遵循同一份规范,并通过共用的测试套件确保兼容性。
这意味着:无论你的后端是 Python FastAPI、Rust Actix,还是前端用 TypeScript,都能无缝使用 TOON 编解码。
何时使用?何时避免?
✅ 推荐使用 TOON 当:
- 数据包含大量结构一致的对象数组;
- 你希望降低 LLM prompt 的 token 成本;
- 需要模型生成可靠、可验证的结构化输出。
❌ 考虑其他格式当:
- 数据高度嵌套且非均匀(此时 compact JSON 可能更短);
- 纯表格数据(直接用 CSV 更小);
- 对延迟极度敏感(需实测 TOON vs JSON 解析速度)。
结语
TOON 是一个务实而优雅的解决方案------它没有试图发明新数据模型,而是在 JSON 的基础上,针对 LLM 的 token 消耗和结构解析痛点做了精准优化。
如果你正在构建需要频繁与 LLM 交换结构化数据的应用,不妨试试 TOON。它可能帮你省下 30%~60% 的 token 成本,同时让输出更可靠、调试更容易。
GitHub 规范:github.com/toon-format/spec
现在就开始,用更少的 token,传递更多的信息。