Elke token die je naar een LLM API stuurt kost geld. Niet veel per token — maar wanneer je prompt een dataset bevat met 50 rijen gebruikersdata opgemaakt als JSON, betaal je voor elke accolade, elke herhaalde sleutelnaam, elk aanhalingsteken. Op een dataset met 10 velden en 100 rijen verbrand JSON ruwweg 60–70% van zijn tokens aan structurele ruis. TOON is gebouwd om precies dit op te lossen. Dit artikel laat je zien hoe je @toon-format/toon gebruikt om je prompt-tokentellingen te verlagen — soms met meer dan de helft — zonder enige structuur te verliezen die het model nodig heeft.

Hoe LLM-tokenprijzen werken

Modellen zoals GPT-4o en Claude rekenen per invoertoken en per uitvoertoken. Het OpenAI Tokenizer-hulpmiddel laat je tekst plakken en precies zien hoeveel tokens het kost. Globaal genomen: 1 token ≈ 4 tekens Engelse tekst — maar JSON's structurele tekens (aanhalingstekens, dubbele punten, accolades) worden vaak individueel getokeniseerd, dus JSON-zware prompts tokeniseren slechter dan gewone proza bij hetzelfde tekenantal. Je betaalt een structurele belasting op elk verzoek.

Voor een typische SaaS-app die duizenden verzoeken per dag uitvoert met gestructureerde data in elke prompt, loopt die belasting snel op. De architectuur van grote taalmodellen betekent dat het model die opmaakruis echt niet nodig heeft — het kan gestructureerde data prima lezen zonder JSON's breedsprakigheid, zolang het formaat ondubbelzinnig en goed uitgelegd is.

JSON vs TOON — Een concreet tokenvergelijking

Laten we dit concreet maken. Hier is een 10-rijen gebruikersdataset in 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 }
]

Dat JSON-blok tokeniseert naar ruwweg 310–330 tokens. Hier zijn dezelfde data in TOON-tabulaire notatie:

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

De TOON-versie tokeniseert naar ruwweg 135–150 tokens — ongeveer 55% minder. Op schaal is dat geen afrondingsfout. Als je 10.000 van dergelijke queries per dag uitvoert tegen GPT-4o-prijzen, is het verschil tussen JSON en TOON in je prompt alleen al substantieel.

Tokenbesparing schaalt met rijen, niet met kolommen. Hoe meer rijen je dataset heeft, hoe groter de winst — omdat TOON de kolomheaderkosten één keer betaalt, terwijl JSON de sleutelnaamkosten op elke afzonderlijke rij betaalt. Een tabel van 100 rijen in TOON bespaart ruwweg hetzelfde percentage als dit 10-rijen voorbeeld.

Installeren en data converteren in Node.js

Installeer het pakket via npm. Het werkt in Node.js 18+ en moderne browsers:

bash
npm install @toon-format/toon

De import is een enkele destructurering:

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

Praktisch patroon: Fetch → Encode → Prompt → Decode

De workflow voor het gebruik van TOON met een LLM API bestaat uit vier stappen. Haal je data op van welke bron dan ook (database, REST API, CSV-bestand), codeer het naar TOON, bouw je prompt en decodeer optioneel gestructureerde TOON terug uit de reactie van het model.

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);
}

Hetzelfde patroon werkt voor de Anthropic Claude API — wissel gewoon de client uit. De promptstructuur en TOON-codering zijn identiek ongeacht de provider. Je kunt de volledige OpenAI API-documentatie raadplegen voor details over authenticatie-instellingen en modelselectie.

Wanneer het het meest uitmaakt

TOON loont het meest in deze scenario's:

  • Grote datasets in context. Elke keer dat je meer dan ~20 rijen gestructureerde data in een prompt plaatst, bespaart TOON-tabulaire notatie je aanzienlijk meer tokens dan JSON-arrays van objecten.
  • Herhaalde gestructureerde queries. Als je applicatie dezelfde vorm van query duizenden keren per dag uitvoert (denk aan: "analyseer de activiteit van deze gebruiker" met een gebruikersrecord in elke prompt), zijn de cumulatieve besparingen substantieel.
  • Batchverwerkingstaken. Scripts die duizenden records per dag door een LLM verwerken — classificatie, tagging, verrijking, samenvatting — profiteren enorm. Minder tokens per aanroep betekent snellere doorvoer en lagere kosten.
  • Contextvenster-beperkte taken. Wanneer je een grote dataset probeert in te passen in een contextvenster van 128k naast een lang systeem-prompt en weinig-shot voorbeelden, telt elke token. TOON laat je meer rijen in hetzelfde venster passen.
  • Kostengevoel-productie API's. Gratis-tier hobbyprojecten zullen het niet merken. Productie-apps die betalende gebruikers op schaal bedienen zeker wel.

De ene kanttekening: LLMs moeten het formaat kennen

TOON staat niet in de trainingsdata van een LLM zoals JSON dat doet. Het model heeft nog nooit een .toon-bestand gezien. Dit betekent dat je een korte formaatbeschrijving in je systeem-prompt moet opnemen — anders zal het model de invoer weigeren of verkeerd parsen. Het goede nieuws is dat de beschrijving kort is en je er maar één keer voor betaalt per gesprek of verzoek.

Een minimale systeemprompttevoeging die betrouwbaar werkt:

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.

Dat blok voegt ruwweg 60 tokens toe aan je systeem-prompt — een eenmalige kost die snel terugverdiend wordt op elke dataset groter dan 5–6 rijen. Voor applicaties die veel API-aanroepen doen met TOON-data worden de formaatbeschrijvingstokens afgeschreven tot bijna nul. Gebruik JSON naar TOON om je data te converteren voordat je de prompt bouwt, en TOON Formatter om te controleren of het er goed uitziet.

Samenvatting

Het argument voor TOON in LLM-workflows is eenvoudig: je betaalt per token, gestructureerde data in JSON is tokeninefficiënt, en TOON is een directe oplossing. De tabulaire notatie alleen al verlaagt het tokengebruik met 50–60% op typische rijgebaseerde datasets. Het npm-pakket — @toon-format/toon — is klein, de API heeft twee functies, en de integratie in een bestaande API-aanroep is een klusje van vijf minuten. Het enige om te onthouden is de formaatbeschrijving in je systeem-prompt — zonder die raadt het model. Met die lees je data correct op de helft van de tokenkosten. Begin met JSON naar TOON om je bestaande data te converteren, valideer het met de TOON Validator, en gebruik TOON naar JSON of decode() om gestructureerde antwoorden terug te converteren wanneer nodig.