Введение: Знакомство с TOON
TOON (Token-Oriented Object Notation) — это новый формат, разработанный специально для экономии токенов в Large Language Models (LLM).
Он компактен, удобочитаем, чрезвычайно легок и оптимизирован для рабочих процессов искусственного интеллекта, где важен каждый токен.
По сравнению с JSON, TOON существенно уменьшает информационный шум, избегает ненужных скобок и кавычек, храня структурированные данные в плоском, эффективно расходующем токены виде.
С ростом популярности AI-промптинга и агентно-ориентированных архитектур, TOON быстро становится фаворитом среди разработчиков и ML-инженеров.
В этом руководстве вы узнаете, как создать полноценный двунаправленный парсер TOON на C#:
- TOON → JSON: Преобразование компактного TOON в стандартный JSON.
- JSON → TOON: Преобразование стандартного JSON в экономичный TOON.
- Полностью автоматическое, масштабируемое решение, которое не требует внешних зависимостей.
Это решение работает на .NET 6, .NET 8 и .NET 9.
TOON против JSON: Наглядный пример
Рассмотрим простой набор данных о продуктах, чтобы увидеть, как TOON обеспечивает экономию токенов.
TOON-формат
products[Collection]{id,name,price}
1,T-shirt,20.00
2,Jeans,55.50
3,Hat,15.00
JSON-формат
{
"products": [
{ "id": 1, "name": "T-shirt", "price": 20.00 },
{ "id": 2, "name": "Jeans", "price": 55.50 },
{ "id": 3, "name": "Hat", "price": 15.00 }
]
}
Обратите внимание, что в JSON названия ключей ("id", "name", "price") повторяются для каждого объекта, что расходует драгоценные токены. В TOON ключи определяются всего один раз в заголовке коллекции.
Шаг 1: Создание класса ToonConverter
Мы создадим вспомогательный класс, который будет включать три ключевых метода:
- ParseToon(): Преобразует TOON в C# словарь (Dictionary).
- ToonToJson(): Преобразует TOON в строку JSON.
- JsonToToon(): Преобразует JSON обратно в TOON.
Создайте новый файл ToonConverter.cs и добавьте следующие директивы:
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
public static class ToonConverter
{
// ... Реализация методов
}
Шаг 2: Реализация TOON → Dictionary (ParseToon)
Метод ParseToon является основой, которая читает формат TOON построчно, разбивает его на коллекции и значения, а затем собирает в структуру C#:
// --------------------------------------
// 1. TOON → OBJECT (Dictionary)
// --------------------------------------
public static Dictionary<string, List<Dictionary<string, string>>> ParseToon(string toon)
{
var result = new Dictionary<string, List<Dictionary<string, string>>>();
var lines = toon.Split('\n', StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Trim()).ToList();
int i = 0;
while (i < lines.Count)
{
if (!lines[i].Contains("{"))
{
i++;
continue;
}
string header = lines[i];
i++;
string name = header[..header.IndexOf("[")];
string fieldBlock = header[(header.IndexOf("{") + 1)..header.IndexOf("}")];
string[] fields = fieldBlock.Split(',')
.Select(f => f.Trim()).ToArray();
var rows = new List<Dictionary<string, string>>();
while (i < lines.Count && !lines[i].Contains("{"))
{
if (string.IsNullOrWhiteSpace(lines[i]))
{
i++;
continue;
}
var vals = lines[i].Split(",").Select(v => v.Trim()).ToArray();
var obj = new Dictionary<string, string>();
for (int f = 0; f < fields.Length; f++)
obj[fields[f]] = vals[f];
rows.Add(obj);
i++;
}
result[name] = rows;
}
return result;
}
Шаг 3: Реализация TOON → JSON (ToonToJson)
Как только мы получили структурированный словарь C# из TOON, преобразование его в JSON становится тривиальной задачей благодаря встроенному классу System.Text.Json.JsonSerializer:
// --------------------------------------
// 2. TOON → JSON
// --------------------------------------
public static string ToonToJson(string toon)
{
var obj = ParseToon(toon);
return JsonSerializer.Serialize(obj, new JsonSerializerOptions { WriteIndented = true });
}
Шаг 4: Реализация JSON → TOON (JsonToToon)
Обратное преобразование (JSON → TOON) требует, чтобы мы сначала проанализировали JSON с помощью JsonNode.Parse, а затем вручную перебрали коллекции и их элементы, чтобы создать плоскую структуру TOON. Этот подход гарантирует, что мы сможем обрабатывать структурированный JSON, который был создан нашими другими методами.
// --------------------------------------
// 3. JSON → TOON
// --------------------------------------
public static string JsonToToon(string json)
{
var root = JsonNode.Parse(json).AsObject();
var sb = new StringBuilder();
foreach (var collection in root)
{
var name = collection.Key;
var array = collection.Value.AsArray();
if (array.Count == 0) continue;
// 1. Извлекаем поля из первого объекта, чтобы создать заголовок TOON
var firstObject = array.AsObject();
var fields = firstObject.Select(p => p.Key).ToList();
var fieldBlock = string.Join(",", fields);
// 2. Записываем заголовок TOON
sb.AppendLine($"{name}[Collection]{{{fieldBlock}}}");
// 3. Записываем строки данных
foreach (var item in array.OfType<JsonNode>())
{
var rowVals = new List<string>();
var itemObject = item.AsObject();
foreach (var field in fields)
{
// Извлекаем значение (или пустую строку, если значение null)
rowVals.Add(itemObject[field]?.ToString() ?? "");
}
sb.AppendLine(string.Join(",", rowVals));
}
sb.AppendLine(); // Добавляем пустую строку между коллекциями
}
return sb.ToString().Trim();
}
}
Заключение: Почему это важно
Создав этот двунаправленный парсер, вы вооружаете свои приложения C# возможностью использовать формат TOON, который становится стандартом де-факто для высокооптимизированного обмена данными с LLM.
Это не только позволяет сократить расходы на API за счет уменьшения количества токенов в промптах, но и делает структуру данных более понятной для моделей ИИ и облегчает отладку человеком.
С помощью этого простого класса ToonConverter вы можете легко переключаться между универсальностью JSON и эффективностью TOON в любой среде .NET.