Każdy token wysyłany do API LLM kosztuje pieniądze. Nie dużo za token — ale gdy Twój prompt zawiera zbiór danych z 50 wierszami danych użytkowników sformatowanymi jako JSON, płacisz za każdy nawias klamrowy, każdą powtórzoną nazwę klucza, każdy cudzysłów. W zbiorze danych z 10 polami i 100 wierszami JSON spala mniej więcej 60–70% swoich tokenów na strukturalny szum. TOON powstał dokładnie po to, by to naprawić. Ten artykuł pokazuje, jak używać @toon-format/toon do redukcji liczby tokenów w promptach — czasem o ponad połowę — bez utraty żadnej struktury potrzebnej modelowi.

Jak działa cennik tokenów LLM

Modele takie jak GPT-4o i Claude pobierają opłaty za token wejściowy i za token wyjściowy. Narzędzie Tokenizer OpenAI pozwala wkleić dowolny tekst i zobaczyć dokładnie ile tokenów kosztuje. Mówiąc w przybliżeniu, 1 token ≈ 4 znaki angielskiego tekstu — ale strukturalne znaki JSON (cudzysłowy, dwukropki, nawiasy) są często tokenizowane indywidualnie, więc prompty z dużą ilością JSON są tokenizowane gorzej niż zwykła proza przy tej samej liczbie znaków. Płacisz strukturalny podatek od każdego żądania.

Dla typowej aplikacji SaaS obsługującej tysiące żądań dziennie z danymi strukturalnymi w każdym prompcie, ten podatek szybko się kumuluje. Architektura dużych modeli językowych oznacza, że model naprawdę nie potrzebuje całego tego formatowania szumu — może czytać dane strukturalne dobrze bez gadatliwości JSON, o ile format jest jednoznaczny i dobrze wyjaśniony.

JSON vs TOON — konkretne porównanie tokenów

Uczyńmy to konkretnym. Oto zbiór danych użytkowników z 10 wierszami w JSON:

json
[
  { "id": 1, "username": "alice_dev", "email": "[email protected]", "plan": "pro", "active": true },
  { "id": 2, "username": "bob_writer", "email": "[email protected]", "plan": "free", "active": true },
  { "id": 3, "username": "carol_ops", "email": "[email protected]", "plan": "pro", "active": false },
  { "id": 4, "username": "dan_qa", "email": "[email protected]", "plan": "team", "active": true },
  { "id": 5, "username": "eve_design", "email": "[email protected]", "plan": "pro", "active": true },
  { "id": 6, "username": "frank_sec", "email": "[email protected]", "plan": "team", "active": true },
  { "id": 7, "username": "grace_ml", "email": "[email protected]", "plan": "pro", "active": false },
  { "id": 8, "username": "henry_be", "email": "[email protected]", "plan": "free", "active": true },
  { "id": 9, "username": "iris_fe", "email": "[email protected]", "plan": "pro", "active": true },
  { "id": 10, "username": "jack_devrel", "email": "[email protected]", "plan": "team", "active": true }
]

Ten blok JSON tokenizuje się do mniej więcej 310–330 tokenów. Oto dokładnie te same dane w notacji tabelarycznej TOON:

text
users[10]{id,username,email,plan,active}:
  1,alice_dev,[email protected],pro,true
  2,bob_writer,[email protected],free,true
  3,carol_ops,[email protected],pro,false
  4,dan_qa,[email protected],team,true
  5,eve_design,[email protected],pro,true
  6,frank_sec,[email protected],team,true
  7,grace_ml,[email protected],pro,false
  8,henry_be,[email protected],free,true
  9,iris_fe,[email protected],pro,true
  10,jack_devrel,[email protected],team,true

Wersja TOON tokenizuje się do mniej więcej 135–150 tokenów — około 55% mniej. W skali to nie jest błąd zaokrąglenia. Jeśli przeprowadzasz 10 000 takich zapytań dziennie przy cenach GPT-4o, różnica między JSON a TOON tylko w Twoim prompcie jest materialna.

Oszczędności tokenów rosną wraz z wierszami, nie kolumnami. Im więcej wierszy ma Twój zbiór danych, tym większa wygrana — ponieważ TOON płaci koszt nagłówka kolumny raz, podczas gdy JSON płaci koszt nazwy klucza w każdym pojedynczym wierszu. Tabela 100 wierszy w TOON oszczędza mniej więcej taki sam procent jak ten przykład 10 wierszy.

Instalacja i konwersja danych w Node.js

Zainstaluj pakiet z npm. Działa w Node.js 18+ i nowoczesnych przeglądarkach:

bash
npm install @toon-format/toon

Import to pojedyncze destrukturyzowanie:

js
import { encode, decode } from '@toon-format/toon';

// Convert a JS array/object to TOON before sending to an LLM
const users = [
  { id: 1, username: 'alice_dev', email: '[email protected]', plan: 'pro', active: true },
  { id: 2, username: 'bob_writer', email: '[email protected]', plan: 'free', active: true },
  // ... more rows
];

const toonData = encode(users, { indent: 2 });
console.log(toonData);
// users[2]{id,username,email,plan,active}:
//   1,alice_dev,[email protected],pro,true
//   2,bob_writer,[email protected],free,true

Praktyczny wzorzec: Pobierz → Zakoduj → Prompt → Dekoduj

Przepływ pracy do używania TOON z API LLM to cztery kroki. Pobierz swoje dane z dowolnego źródła (baza danych, API REST, plik CSV), zakoduj je do TOON, zbuduj swój prompt i opcjonalnie dekoduj wszelki strukturalny TOON z odpowiedzi modelu.

js
import { encode, decode } from '@toon-format/toon';
import OpenAI from 'openai';

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

async function analyseUsers(users) {
  // Step 1: encode data to TOON
  const toonData = encode(users, { indent: 2 });

  // Step 2: build the prompt
  const systemPrompt = [
    'You analyse user datasets. Data is provided in TOON (Token-Optimised Object Notation).',
    'TOON tabular format: name[count]{col1,col2,...}: followed by comma-separated rows, one per line.',
    'Respond with plain prose unless asked to return data, in which case use TOON format.'
  ].join('\n');

  const userPrompt = `Here is the user dataset:\n\n${toonData}\n\nWhich plan has the most active users?`;

  // Step 3: call the API
  const response = await openai.chat.completions.create({
    model: 'gpt-4o',
    messages: [
      { role: 'system', content: systemPrompt },
      { role: 'user', content: userPrompt }
    ]
  });

  return response.choices[0].message.content;
}

// Step 4 (optional): if the model returns TOON, decode it back
const rawResponse = await analyseUsers(myUserArray);
try {
  const structured = decode(rawResponse);
  console.log('Structured result:', structured);
} catch {
  console.log('Prose response:', rawResponse);
}

Ten sam wzorzec działa dla Anthropic Claude API — po prostu zamień klienta. Struktura promptu i kodowanie TOON są identyczne niezależnie od dostawcy. Możesz sprawdzić pełną dokumentację OpenAI API dla szczegółów konfiguracji uwierzytelniania i wyboru modelu.

Kiedy ma to największe znaczenie

TOON opłaca się najbardziej w tych scenariuszach:

  • Duże zbiory danych w kontekście. Za każdym razem, gdy wstawiasz do promptu więcej niż ~20 wierszy danych strukturalnych, notacja tabelaryczna TOON zaoszczędzi Ci znaczące tokeny w porównaniu z tablicami obiektów JSON.
  • Powtarzające się zapytania strukturalne. Jeśli Twoja aplikacja wykonuje ten sam kształt zapytania tysiące razy dziennie (pomyśl: "przeanalizuj aktywność tego użytkownika" z rekordem użytkownika w każdym prompcie), kumulatywne oszczędności są znaczące.
  • Zadania przetwarzania wsadowego. Skrypty przetwarzające tysiące rekordów przez LLM — klasyfikacja, tagowanie, wzbogacanie, podsumowanie — odnoszą ogromne korzyści. Mniej tokenów na wywołanie oznacza szybszą przepustowość i niższy koszt.
  • Zadania ograniczone oknem kontekstowym. Gdy próbujesz zmieścić duży zbiór danych w oknie kontekstowym 128k obok długiego promptu systemowego i przykładów few-shot, każdy token ma znaczenie. TOON pozwala zmieścić więcej wierszy w tym samym oknie.
  • Produkcyjne API wrażliwe na koszty. Projekty hobbystyczne na darmowym tierze tego nie zauważą. Produkcyjne aplikacje obsługujące płacących użytkowników w skali absolutnie tak.

Jedno zastrzeżenie: LLM muszą znać format

TOON nie jest w danych treningowych żadnego LLM tak jak JSON. Model nigdy nie widział pliku .toon. Oznacza to, że musisz dołączyć krótki opis formatu w swoim prompcie systemowym — w przeciwnym razie model albo odrzuci wejście, albo nieprawidłowo je sparsuje. Dobra wiadomość jest taka, że opis jest krótki i płacisz za niego tylko raz na rozmowę lub żądanie.

Minimalne dodanie do promptu systemowego, które działa niezawodnie:

text
Data is provided in TOON (Token-Optimised Object Notation).
TOON syntax:
- Objects: {key:value,key2:value2} — keys are never quoted
- Arrays: [val1,val2,val3]
- Tabular: name[rowCount]{col1,col2,...}:
    rowval1,rowval2,...
    rowval1,rowval2,...
Parse each row by matching values to the column headers in order.
Strings containing commas are double-quoted.

Ten blok dodaje mniej więcej 60 tokenów do Twojego promptu systemowego — jednorazowy koszt, który jest szybko odzyskiwany dla każdego zbioru danych większego niż 5–6 wierszy. Dla aplikacji wykonujących wiele wywołań API z danymi TOON, tokeny opisu formatu są amortyzowane do prawie zera. Użyj JSON do TOON, aby przekonwertować swoje dane przed budowaniem promptu, i Formattera TOON, aby sprawdzić, czy wygląda dobrze.

Podsumowanie

Argument za TOON w przepływach pracy LLM jest prosty: płacisz za token, dane strukturalne w JSON są nieefektywne tokenowo, a TOON jest bezpośrednim rozwiązaniem. Sama notacja tabelaryczna redukuje zużycie tokenów o 50–60% w typowych zestawach danych opartych na wierszach. Pakiet npm — @toon-format/toon — jest mały, API to dwie funkcje, a integracja z istniejącym wywołaniem API to pięciominutowa praca. Jedyną rzeczą do zapamiętania jest opis formatu w Twoim prompcie systemowym — bez niego model zgaduje. Z nim otrzymujesz model, który poprawnie odczytuje Twoje dane przy połowie kosztu tokenów. Zacznij od JSON do TOON, aby przekonwertować istniejące dane, sprawdź je za pomocą Walidatora TOON i użyj TOON do JSON lub decode(), aby przekonwertować strukturalne odpowiedzi z powrotem, gdy zajdzie potrzeba.