TOON 协议与 AIDotNet.Toon 实践指南+Java使用指南

TOON 协议与 AIDotNet.Toon 实践指南

一、TOON 是什么

官方定义要点摘录(来源:toon-format/toon 仓库 README):

  • Token-efficient:通常比 JSON 少 30–60% 的 tokens(Key Features 列表)
  • LLM-friendly guardrails:显式长度与字段,便于验证
  • Minimal syntax:移除冗余标点(大括号、方括号、许多引号)
  • Indentation-based structure:类似 YAML,以空白缩进代替大括号
  • Tabular arrays:一次声明列头,数据按行流式书写

官方基准与工具:

  • README 的 Benchmarks 表格展示了多个数据集下的 token 节省比例;此外提供“Format Tokenization Playground”可交互比较不同格式的 token 用量
  • 当前规范版本:v1.3(README 徽章与 SPEC.md 指向的专用仓库)

规范入口与一致性:

  • 规范迁移至独立仓库:https://github.com/toon-format/spec(SPEC.md 明确“moved to a dedicated repository”)
  • 跨语言一致性依赖 conformance tests(README 的 Other Implementations 区块提供说明)

二、为什么 TOON 相比 JSON 更省 tokens

本质原因是“以结构换冗余”:在 LLM 语境下,重复的键名和标点都会占用 tokens。TOON 通过以下策略显著减少冗余(均可在 README 与语法速查中找到实例):

  • 表格数组:为均匀对象数组声明一次列头,如 users[2]{id,name}: 后续行直接写 1,Alice
  • 行内原子数组:tags[3]: a,b,c,避免多余方括号与引号
  • 键名可不加引号:安全键裸写,减少引号数量
  • 缩进代替大括号:以空白表达层级

同时,官方 README 也清晰指出边界:对于深度嵌套或非均匀结构的数据,JSON 可能更高效。这意味着在“树深且分支不规则”的任务上应优先评估 JSON。

三、语法速查与对照示例

下列示例与含义对应自 README 的 Syntax Cheatsheet 与“Why TOON”示例(术语与格式请以规范 v1.3 为准):

  • 对象 { id: 1, name: 'Ada' }  →  id: 1  换行  name: Ada

  • 嵌套对象 { user: { id: 1 } }  →  user: 换行缩进 id: 1

  • 行内原子数组 { tags: ['foo', 'bar'] }  →  tags[2]: foo,bar

  • 表格数组(均匀对象) { items: [ { id: 1, qty: 5 }, { id: 2, qty: 3 } ] } →  items[2]{id,qty}: 换行缩进 1,5 换行缩进 2,3

  • 混合或非均匀数组 { items: [ 1, { a: 1 }, 'x' ] }  →  items[3]: 换行缩进 - 1 换行缩进 - a: 1 换行缩进 - x

四、AIDotNet.Toon:.NET 实现概览

AIDotNet.Toon 对齐 upstream 规范与设计,面向 .NET 提供与 System.Text.Json 风格一致的 API。关键入口如下:

  • 序列化: C#.ToonSerializer.Serialize() · C#.ToonSerializer.Serialize()
  • 反序列化: C#.ToonSerializer.Deserialize() · C#.ToonSerializer.Deserialize()
  • 编码实现: C#.ToonEncoder.Encode()
  • 解码实现: C#.ToonDecoder.DecodeToJsonString()
  • 选项模型: C#.ToonSerializerOptions · 分隔符枚举 C#.ToonDelimiter · 默认实例 C#.ToonSerializerOptions.Default
  • 错误模型: C#.ToonFormatException

实现思路(节选自源码注释与 README):

  • Encode 路径:.NET 对象 → JsonElement → Encoders 结构化写出(对象、行内原子数组、表格数组、列表回退等)
  • Decode 路径:TOON → 规范化 JSON 字符串 → System.Text.Json 反序列化为目标类型
  • 数值与特殊值:允许命名浮点字面量,经编码阶段将 NaN 与 ±Infinity 规范化为 null,-0 规范化为 0(细节见编码器与选项)

五、安装与快速开始

通过 NuGet(发布后)或源码引入本库:

dotnet add package AIDotNet.Toon
using AIDotNet.Toon;

var options = new ToonSerializerOptions
{
    Indent = 2,
    Delimiter = ToonDelimiter.Comma,
    Strict = true,
    LengthMarker = null
};

var data = new
{
    users = new[] { new { id = 1, name = "Alice" }, new { id = 2, name = "Bob" } },
    tags = new[] { "a", "b", "c" },
    numbers = new[] { 1, 2, 3 }
};

var text = ToonSerializer.Serialize(data, options);
// users[2]{id,name}:
//   1,Alice
//   2,Bob
// tags[3]: a,b,c
// numbers[3]: 1,2,3

读取原子值:

var s = ToonSerializer.Deserialize<string>("hello", options);   // "hello"
var n = ToonSerializer.Deserialize<double>("3.1415", options);  // 3.1415

互操作:TOON ↔ JSON ↔ .NET

// 将 TOON 文本转为目标类型,内部先经 [C#.ToonDecoder.DecodeToJsonString()](src/AIDotNet.Toon/ToonDecoder.cs:15)
var user = ToonSerializer.Deserialize<Dictionary<string, object>>("id: 1", options);

// 将 .NET 对象经 JSON DOM 编码为 TOON
var t = ToonSerializer.Serialize(new { id = 1, name = "Ada" }, options);

六、选项与行为

统一选项入口 C#.ToonSerializerOptions 与默认预设 C#.ToonSerializerOptions.Default:

  • Indent:每级缩进空格数,默认 2
  • Delimiter:分隔符,枚举 C#.ToonDelimiter,用于行内与表格;底层转换为具体字符见 C#.ToonSerializerOptions.GetDelimiterChar()
  • Strict:严格模式,校验缩进、空行、计数一致性等
  • LengthMarker:数组长度标记,仅支持 # 或 null
  • JsonOptions:直通 System.Text.Json;默认启用 AllowNamedFloatingPointLiterals,并注册转换器以将 NaN 与 ±Infinity 写出为 null

七、错误模型与定位

解码错误统一抛出 C#.ToonFormatException 并包含错误分类与位置信息:

  • 工厂方法:Syntax C#.ToonFormatException.Syntax() · Range C#.ToonFormatException.Range() · Validation C#.ToonFormatException.Validation() · Indentation C#.ToonFormatException.Indentation() · Delimiter C#.ToonFormatException.Delimiter()

八、进阶示例

  1. 表格数组写出
var rows = new[] { new { id = 1, name = "alice" }, new { id = 2, name = "bob" } };
var toon = ToonSerializer.Serialize(rows, options);
// [2]{id,name}:
//   1,alice
//   2,bob
  1. 行内原子数组
var arr = new[] { 1, 2, 3 };
var t2 = ToonSerializer.Serialize(arr, options); // "[3]: 1,2,3"
  1. 混合数组回退为列表
var mixed = new object[] { 1, new { a = 1 }, "x" };
var t3 = ToonSerializer.Serialize(mixed, options);
// [3]:
//   - 1
//   - a: 1
//   - x

九、何时使用 TOON,何时选 JSON

基于官方 README 的定位:当你的数据是“均匀对象数组、字段重复较多、需要给 LLM 更大输入上下文”时,TOON 通常更省 tokens 且更易校验验证;当数据“深度嵌套、非均匀或树形变化大”时,JSON 可能更高效更直接。

十、数据流与实现关系图

图片

十一、来源与参考

  • 官方仓库与 README:https://github.com/toon-format/toon
  • 规范仓库 v1.3:https://github.com/toon-format/spec
  • README“Key Features”“Benchmarks”“Syntax Cheatsheet”“Other Implementations”板块提供了本文引用的特性描述、节省比例与示例
  • 本文 .NET 实现地址:https://github.com/AIDotNet/Toon.NET

十二、结语

TOON 让 LLM 输入里的结构化数据更加紧凑、可校验、可读;AIDotNet.Toon 则在 .NET 世界提供熟悉的 API 体验与选项模型。建议从表格数组与行内原子数组的典型场景开始落地,并结合规范 v1.3 与测试数据持续验证。

Special thanks to the upstream project toon-format.

附:官方 Benchmarks 数据集节选

以下数字直接摘录自官方 README 的 Benchmarks「Token Efficiency」小节,原文与上下文见:https://github.com/toon-format/toon#benchmarks(其中提示这些数据集偏向 TOON 的优势场景:均匀表格化数据,真实效果取决于数据结构)。交互式对比工具:

Token 效率

⭐ GitHub Repositories       ██████████████░░░░░░░░░░░    8,745 tokens vs JSON (-42.3%)           15,145 vs JSON compact (-23.7%)   11,455 vs YAML (-33.4%)           13,129 vs XML (-48.8%)            17,095

📈 Daily Analytics           ██████████░░░░░░░░░░░░░░░    4,507 tokens vs JSON (-58.9%)           10,977 vs JSON compact (-35.7%)    7,013 vs YAML (-48.8%)            8,810 vs XML (-65.7%)            13,128

🛒 E-Commerce Order          ████████████████░░░░░░░░░      166 tokens vs JSON (-35.4%)              257 vs JSON compact (-2.9%)       171 vs YAML (-15.7%)              197 vs XML (-38.7%)               271

───────────────────────────────────────────────────────────────────── Total                        ██████████████░░░░░░░░░░░   13,418 tokens vs JSON (-49.1%)           26,379 vs JSON compact (-28.0%)   18,639 vs YAML (-39.4%)           22,136 vs XML (-56.0%)            30,494

检索准确率

4 种大型语言模型在 154 个数据检索问题上的准确率:

gpt-5-nano → TOON           ███████████████████░    96.1% (148/154)

 CSV            ██████████████████░░    91.6% (141/154) 

YAML  ██████████████████░░    91.6% (141/154) 

JSON compact   ██████████████████░░    91.6% (141/154) 

XML            █████████████████░░░    87.0% (134/154) 

JSON           █████████████████░░░    86.4% (133/154)

claude-haiku-4-5-20251001 JSON           ██████████░░░░░░░░░░    50.0% (77/154) YAML           ██████████░░░░░░░░░░    49.4% (76/154) → TOON           ██████████░░░░░░░░░░    48.7% (75/154) XML            ██████████░░░░░░░░░░    48.1% (74/154) CSV            █████████░░░░░░░░░░░    47.4% (73/154) JSON compact   █████████░░░░░░░░░░░    44.2% (68/154)

gemini-2.5-flash 

CSV            ██████████████████░░    87.7% (135/154) 

XML            ██████████████████░░    87.7% (135/154) 

→ TOON           █████████████████░░░    86.4% (133/154) 

YAML           ████████████████░░░░    79.9% (123/154) 

JSON compact   ████████████████░░░░    79.9% (123/154) JSON           ███████████████░░░░░    76.6% (118/154)

grok-4-fast-non-reasoning → TOON           ██████████░░░░░░░░░░    49.4% (76/154) JSON           ██████████░░░░░░░░░░    48.7% (75/154) XML            █████████░░░░░░░░░░░    46.1% (71/154) YAML           █████████░░░░░░░░░░░    46.1% (71/154) JSON compact   █████████░░░░░░░░░░░    45.5% (70/154) CSV            █████████░░░░░░░░░░░    44.2% (68/154)

注意:上述样本强调 TOON 在“均匀对象数组/表格化数据”场景的节省效果;对于深度嵌套或非均匀数据,官方 README 指出 JSON 可能更高效。建议在落地前结合自身数据结构评估与小规模验证。

 

LLM调用的最佳数据格式:TOON,成本直降50%|附Java使用指南

TOON logo with step‑by‑step guide

在大模型逐渐融入业务系统的阶段,结构化数据输入/输出已成为落地应用的必需:RAG 检索结果、Agent 工具调用参数、业务查询结果、批处理列表等都需要让自然语言与“可机读”的结构化格式互通。事实标准是 JSON,但在高频调用、海量数据场景下,JSON 的标点开销会显著推高 token 成本。

如下JSON格式的例子:

{
  "users": [
    {"id": 1, "name": "Alice", "role": "admin"},
    {"id": 2, "name": "Bob", "role": "user"}
  ]
}

Tokens 为 47:

图片

采用 TOON 格式之后,内容明显减少:

users[2]{id,name,role}:
  1,Alice,admin
  2,Bob,user

Tokens 为:24

图片

差异的核心在于:TOON 用“缩进 + 一次性字段声明”的方式消除了绝大部分语法标点的冗余;当你在生产环境每天传输成千上万条记录时,冗余标点的累计开销会直接转化为可观的 API 费用。实践表明,TOON 在输入侧常带来 40–60% 的 token 节省。

基准测试:TOKEN减少、准确率上升

TOON格式在LLM调用时候除了在Token数量上的优化之外,不可忽略的是LLM检索准确率。如果单纯Token数量减少了,而准确率下降了,那意义就不大了。

以下是TOON官方仓库给出的综合效率排名:

TOON           ████████████████████   26.9  │  73.9% acc  │  2,744 tokens
JSON compact   █████████████████░░░   22.9  │  70.7% acc  │  3,081 tokens
YAML           ██████████████░░░░░░   18.6  │  69.0% acc  │  3,719 tokens
JSON           ███████████░░░░░░░░░   15.3  │  69.7% acc  │  4,545 tokens
XML            ██████████░░░░░░░░░░   13.0  │  67.1% acc  │  5,167 tokens

TOON 的准确率达到 73.9% (JSON 的准确率为 69.7%),同时使用的标记数减少了 39.6% 。可以看到TOON不仅在Token数量上有优势,在准确率上也有明显优势。更多基准测试结果请参考TOON官方仓库:

https://github.com/toon-format/toon

什么时候不用 TOON

TOON 格式在处理统一类型的对象数组时表现出色,但在某些情况下,其他格式更为合适:

  • • 嵌套过深或结构不规则 (表格适用性 ≈ 0%):JSON-compact 通常使用较少的标记。例如:具有多个嵌套层的复杂配置对象。
  • • 半均匀数组 (约 40-60% 符合表格格式):Token节省量减少。如果您的pipline已经依赖于 JSON,则建议优先使用 JSON。
  • • 纯表格数据 :对于平面表格,CSV 比 TOON 格式文件更小。TOON 格式仅需少量额外开销(约 5-10%)即可提供结构信息(数组长度声明、字段头、分隔符作用域),从而提高 LLM 的可靠性。
  • • 对延迟要求严格的应用 :如果端到端响应时间是您的首要考虑因素,请在您的实际环境中进行基准测试。某些部署(尤其是像 Ollama 这样的本地/量化模型)即使 TOON 的Token数量较少,处理紧凑型 JSON 的速度也可能更快。请测量两种格式的 TTFT、每秒Token数和总时间,并使用速度更快的格式。

Java 中如何使用 TOON

对于数据格式转换,各主流语言都有好用的SDK可以直接拿来使用。以Java为例,可以使用:

<dependency>
    <groupId>com.felipestanzani</groupId>
    <artifactId>jtoon</artifactId>
    <version>0.1.2</version>
</dependency>

用法也是非常简单,核心API如下:

// Java 对象 → TOON 字符串
String toon = JToon.encode(object);

// JSON 字符串 → TOON
String toon = JToon.encodeJson(jsonString);

// TOON → Java 对象
Object obj = JToon.decode(toonString);

// TOON → JSON 字符串
String json = JToon.decodeToJson(toonString);

小结

本文介绍了LLM调用时JSON格式调用在Token消耗的劣势,从而引出TOON格式。对于合适场景,如果目前Token消耗量偏高的应用,可以考虑在数据格式上进行优化,从而实现成本的优化。目前你都用什么格式呢?是否有用过TOON呢?留言区可以聊一聊。

LLM调用的最佳数据格式:TOON,成本直降50%|附Java使用指南

 

posted @ 2025-12-05 14:06  CharyGao  阅读(5)  评论(0)    收藏  举报