Aller au contenu

Crate Rust publié. npm et PyPI ensuite.

Chaque modèle a son écriture la moins chère.

Même charge utile, même information, même aller-retour sans perte. Changez seulement la façon dont les symboles sont écrits et la facture en tokens bouge d'un quart. Tokendoo mesure quelle écriture coûte le moins cher pour chaque modèle, et se maintient à jour à chaque nouvelle version des modèles les plus répandus.

0,3868

ratio de tokens médian, cl100k, alphabet dérivé, fixtures de référence

Ratio wire : charge compressée seule. La légende de format ajoute 97 à 174 tokens et peut effacer le gain sur les petites charges.

corpus synthétique publié · comptes cl100k_base exacts · 2026-08-06

Le JSON paie sa structure, encore et encore.

Un tableau JSON de 1 000 lignes répète ses clés 1 000 fois. Accolades, guillemets, noms de champs, chaînes répétées : l'API facture chacun d'eux, à chaque requête, au prix du token.

Le sens est dans les valeurs. Le volume, c'est surtout de la répétition qu'on peut retirer puis remettre à l'identique. C'est la seule partie que Tokendoo touche.

Quatre transformations, dans l'ordre.

Chaque étape est structurelle et réversible. On ne la garde que si la charge devient plus petite. Si rien n'aide, on émet l'entrée telle quelle et on le dit dans l'en-tête.

Canonicalisation

Espaces retirés, clés triées, nombres normalisés. Une entrée déterministe pour tout ce qui suit.

{ "sku": "a-114",  "qty": 2 }
{"qty":2,"sku":"a-114"}

Dictionnaire de clés, désactivé par défaut

Les clés répétées deviennent des ordinaux en base 36, plus une table. Sur le corpus de référence, il n'a pas passé la barre des ≥ 10 % de gain en tokens : il reste désactivé tant qu'il ne fait pas ses preuves.

{"quantity":2,"status":"active"}
{"0":2,"1":"active"}   k:["quantity","status"]

Repli tabulaire

Un tableau d'objets de même forme devient un schéma plus des lignes de valeurs. Les clés sont écrites une fois, pas une fois par enregistrement.

[{"qty":2,"sku":"a-114"},
 {"qty":1,"sku":"a-115"}]
["__T",["qty","sku"],
 [[2,"a-114"],[1,"a-115"]]]

Internement des valeurs

Les chaînes qui se répètent rejoignent une table et sont référencées par ordinal. La table part avec la sortie, et chaque chiffre de cette page la compte.

"eu-west-1" × 40
"0" × 40   v:["eu-west-1"]

Le résultat est une chaîne T3, T388:…, plus un dictionnaire JSON. Les deux comptent dans chaque ratio. Annoncer un gain sans le dictionnaire le surestimerait.

Le codec est gratuit. Savoir comment l'écrire ne l'est pas.

Les transformations tiennent en quatre cents lignes de code déterministe, publiées sous licence Apache 2.0 avec le corpus et le banc de mesure. Servez-vous. Le difficile n'est pas de compresser la charge utile, c'est de choisir les symboles vers lesquels elle est compressée.

Un symbole coûte ce que le tokenizer facture pour lui. Les caractères de contrôle semblaient évidents, un octet chacun, et se sont révélés le pire choix possible : ils ne participent à aucune fusion, donc chacun coûte un token entier sans rien encoder. Dériver les symboles du vocabulaire cible, de sorte que chacun vaille exactement un token, fait mieux encore.

Même codec, même corpus, mêmes fixtures. Seule l'écriture des symboles change.
alphabetratio de tokens médian
caractères de contrôle0,6575
préfixe imprimable0,5241
base 36 nue0,4207
dérivé du vocabulaire0,3868

Et la réponse ne se transporte pas. La table dérivée pour cl100k et celle dérivée pour un tokenizer Llama partagent 438 symboles sur 1 377 : deux tiers de l'écriture optimale d'une famille sont faux pour l'autre.

C'est tout le service. Une bibliothèque figée conserve la réponse du jour où elle a été copiée. Chaque famille de modèles qui sort est une colonne à remesurer, et un client qui applique la table de l'an dernier au modèle de cette année le paie sans jamais s'en apercevoir.

Les chiffres sur lesquels on décide.

Comptes cl100k_base exacts sur un corpus synthétique publié, mesuré le 2026-08-07 avec les réglages livrés : alphabet derived_cl100k_v1, repli tabulaire et internement activés, dictionnaire de clés désactivé. Chaque compte de sortie inclut le dictionnaire.

Ratios de tokens et d'octets par fixture, comptes cl100k_base exacts, derived_cl100k_v1, 2026-08-07
fixturenaturetokens avanttokens aprèsratio tokensratio octets
homogeneous_100100 enregistrements, un schéma2 9031 2290,42340,327
homogeneous_10001 000 enregistrements, un schéma29 0038 3870,28920,246
realistic_apiréponse d'API mixte3 2002 4150,75470,689
size_10kcharge mixte ≈ 10 Ko3 8601 4930,38680,304
size_100kcharge mixte ≈ 100 Ko39 98311 6630,29170,246
size_250kcharge mixte ≈ 250 Ko98 60329 1560,29570,247
prose_heavylongues valeurs textuelles, structure mince2 9652 9801,00511,002

fixtures de référence, ratio de tokens médian 0,3868. Le corpus et le banc sont dans le dépôt ; relancer le banc reproduit chaque compte.

La dernière ligne, c'est le cas où l'outil ne fait rien. La compression structurelle n'a pas de prise sur la prose, et prose_heavy ressort 0,5 % plus gros. On garde la ligne : c'est le cas où l'outil n'aide pas, on reste transparent.

L'aller-retour est garanti dans le dépôt public : des tests par propriétés exigent que decompress(compress(x)) soit égal à x sur les valeurs JSON.

Installer le crate Rust.

Une ligne dans le manifeste. Le code sur GitHub ; les versions sur crates.io.

cargo add tokendoo

Le branchement qu'on refuse.

Ce qu'on ne fait jamais

# On ne se place jamais devant le fournisseur de modèle.
#   appelant ──(votre clé OpenAI/Anthropic)──▶ tokendoo-proxy ──▶ modèle   ✗
#   appelant ──▶ compress (local) ──▶ vous ──(votre clé)──▶ modèle          ✓
# On ne reçoit jamais votre clé fournisseur.
# On ne voit jamais la réponse du modèle.
# On ne reçoit jamais votre charge utile.

Langage pas encore couvert ? Le codec est publié sous Apache 2.0 : environ quatre cents lignes de code déterministe. Réimplémentez-le. Il n'y aura pas d'API de compression à attendre.

Rien à fuiter, par construction.

La charge utile ne quitte pas la machine. Nous ne la gardons pas, parce que nous ne la recevons jamais.

Le seul appel sortant, c'est le rafraîchissement quotidien des tables, prévu. Il porte une clé de compte et rien d'autre : pas de charge utile, pas de compteurs, pas d'identifiants.

L'avis de confidentialité, c'est cette section.

Il n'y a pas de champ de collage sur cette page, exprès. Un produit fondé sur la non-collecte des charges utiles ne vous demande pas d'envoyer du JSON pour prouver qu'il n'en garde pas.

Ce qui est livré, ce qu'on mesure, ce qui est prévu.

au 2026-08-08

Livré

  • tokendoo 0.1.0 sur crates.io ; documentation sur docs.rs/tokendoo
  • Aller-retour sans perte sur les valeurs JSON, vérifié par plus de 1 000 cas de tests par propriétés
  • Bibliothèque Rust locale ; la compression ne passe par aucun réseau
  • Mode JSON uniquement ; entrées jusqu'à 256 Kio

En cours de mesure

  • Si un modèle répond aussi bien sur l'entrée compressée que sur l'originale. Nous ne l'affirmons pas. Le banc existe, et les résultats seront publiés quels qu'ils soient.
  • Coût de la légende qui apprend le format au modèle : 97 à 174 tokens, de quoi effacer le gain sur les petites charges. Compté, pas caché.

Prévu

  • Mode code : pour être utile, il est nécessairement avec perte, ce qui casse la garantie d'aller-retour. Il attend qu'on puisse dire ce compromis clairement.
  • Mode texte : la prose est à un ratio de 1,005. La compression structurelle y est inefficace.
  • Bibliothèque sur npm et PyPI, à partir du même cœur Rust.
  • Endpoint de distribution de tables : tables d'alphabet versionnées seulement, jamais de charges utiles. Le format filaire doit porter un identifiant de table versionnée distante ; l'en-tête T3 d'aujourd'hui encode un id d'alphabet dans les drapeaux, pas cet identifiant.
  • Abonnement : tables d'alphabet à jour, par famille de modèles couverte.

Vous payez les tables à jour, pas la compression.

Prévu. Structure des paliers seulement ; les prix arriveront quand les paliers existeront.

Une bibliothèque locale ne peut pas facturer l'usage honnêtement : un compteur autodéclaré se manipule, et détecter l'usage non déclaré exigerait la télémétrie que nous refusons. L'abonnement vend donc l'accès aux tables d'alphabet, comme les bases GeoIP se vendent, pas les lookups. Le moteur ne casse pas quand les tables vieillissent ; il vieillit. C'est tout l'argument.

Gratuit

Tables figées à la version de la bibliothèque. Pas de mises à jour. Elle compresse, l'aller-retour tient, elle marche hors ligne indéfiniment. Pas bridée : elle vieillit, c'est tout.

Une famille

Tables à jour pour OpenAI, Anthropic, Google ou Llama.

Toutes les familles

Tables à jour pour chaque famille que nous couvrons.

Sur mesure

Tables dérivées de vos propres charges utiles. La réponse à « vos fixtures sont synthétiques », pas un upsell premium.

Aucune facture ne dépend d'un compte de tokens : la question du tokenizer exact en production se referme.

Nous ne retenons pas une meilleure table à un client payant pour fabriquer de la rétention. L'axe, c'est la couverture, pas la cadence de mise à jour.

Les objections, avant que vous ne les posiez.

Sept questions qui vous sont probablement déjà passées par la tête en lisant nos mesures.

Pourquoi ne pas simplement gzipper la charge utile ?
Parce que le modèle ne décompresse rien. Il lit du texte. Un blob gzippé en base64 lui est illisible et coûte plus de tokens que l'original. La compression doit rester lisible par le modèle : c'est toute la contrainte, et la raison pour laquelle le problème n'est pas trivial.
Le prompt caching ne règle-t-il pas déjà la question ?
Sur un segment que nous ne cherchons pas à disputer, si. Le cache s'applique à un préfixe commun entre des requêtes différentes, à un dixième du prix d'entrée en lecture, et aucun cache local ne reproduit cela. Mais le TTL par défaut est de cinq minutes, le préfixe minimal cachable est de 1 024 tokens, et l'écriture coûte 1,25 fois le tarif de base. Il paie donc sur des préfixes stables avec un trafic soutenu, et ne fait rien pour des charges qui changent à chaque appel, un trafic sporadique, ou un contexte multi-locataire où aucun préfixe n'est partagé. Les deux se combinent d'ailleurs : écritures et lectures de cache sont facturées au token, donc compresser d'abord réduit les deux. Nous ne remplaçons pas le cache, nous réduisons l'assiette sur laquelle il est facturé.
Le modèle comprend-il vraiment la forme compressée ?
Cette question n'a pas de réponse unique, parce qu'il s'agit d'une propriété de chaque modèle et non du codec. Un modèle a un tokenizer, qui détermine ce que la forme compressée coûte, et une capacité à la lire, qui détermine ce qu'elle vous coûte en précision. Les deux sont mesurées par modèle et publiées ensemble, avec l'alphabet optimal pour ce modèle. Lorsqu'un modèle n'est pas encore couvert, la page de couverture le dit au lieu de laisser croire l'inverse. Et si une transformation coûte de la précision sur un modèle donné, elle est livrée désactivée pour ce modèle.
Pourquoi un abonnement ? Ce sont quatre cents lignes de code.
En effet, et elles sont publiées sous licence Apache 2.0, avec le corpus et le banc de mesure. Servez-vous. Ce que l'abonnement vend n'est pas la transformation mais le fait de savoir laquelle appliquer : l'alphabet de symboles optimal est une propriété du tokenizer, pas du codec, et chaque nouvelle famille de modèles invalide la réponse. Une bibliothèque figée conserve la décision du jour où elle a été copiée. Les modèles, eux, évoluent sans cesse.
Vos fixtures sont synthétiques et c'est vous qui les avez écrites.
C'est exact, et c'est pourquoi elles sont publiées et reproductibles. Deux d'entre elles figurent sur cette page précisément parce qu'elles sont défavorables : une réponse d'API réaliste gagne à peine, et un JSON dominé par la prose ressort légèrement plus gros. Faites le test vous-même sur vos propres charges utiles.
Zéro rétention. Comment le vérifier ?
Trois choses, dans l'ordre de ce qui vous protège vraiment. D'abord, il n'y a rien à conserver : le corps de la requête vit le temps du calcul, en mémoire, et n'est écrit nulle part. Ni journal, ni cache, ni base. Il n'y a pas de politique de rétention à vous faire lire, parce qu'il n'y a pas de donnée à retenir. Ensuite, nous n'en sommes pas seuls juges. Tokendoo est une entité européenne, soumise au RGPD pour l'ensemble de ses traitements, où que soient ses clients. La minimisation des données n'est pas notre argument commercial, c'est une obligation dont le manquement se sanctionne, et notre régulateur peut le constater sans nous demander notre avis. Enfin, le codec et ses tests sont publics. Nous ne prétendrons pas que cela prouve ce qui tourne en production : publier un code et en déployer un autre reste possible. C'est un élément de vérification, pas une preuve, et nous préférons le dire.
Vous ajoutez un aller-retour réseau pour économiser quelques centimes.
Non. La compression tourne chez vous ; il n'y a pas d'aller-retour de compression à payer. Le palier gratuit, c'est cette bibliothèque avec les tables figées à sa version. Abonnez-vous seulement si vous voulez ces tables tenues à jour quand les modèles sortent.

Laissez un e-mail. Nous en envoyons un quand la bibliothèque arrive sur npm et PyPI.

Le crate Rust est publié. Un e-mail quand npm et PyPI seront là, rien avant, rien après.