Onze A/B-benchmark, in het open. Meet ons.
We publiceren elke run: vier batterijen op openbare datasets, 10 modellen, en beide armen gemeten met de eigen gebruiksteller van de provider. Elk cijfer draagt zijn n, zijn interval en zijn datum. Wat niet bespaart staat hier ook.
- batterijen
- 4
- geteste modellen
- 10
- modellen met een meting
- 10
- live rapporten
- 15
- laatste run
- 29 sep 2026
Wat wordt gemeten, en hoe
- Twee armen, hetzelfde verzoek. A gaat rechtstreeks naar de provider, zonder de laag; B loopt via de laag met de standaardconfiguratie. Dezelfde prompt, dezelfde sampling, dezelfde outputgrens.
- De provider telt de kosten. Elke arm wordt geprijsd op basis van de
usagedie de API bij elke aanroep teruggeeft, tegen de lijstprijs. De besparing is 1 − kosten(B) / kosten(A) van dezelfde run, niet wat de laag zelf beweert. - 95%-intervallen. Elke harness berekent ze (resampling van hele vraagfamilies, Wilson voor weigeringspercentages). Een interval dat nul kruist betekent “niet te onderscheiden van nul”, en dat zeggen we ook.
- Het pakket dat je installeert. Arm B draait de broncode van tag 0.4.31; de
dist/index.jsis byte-voor-byte identiek aan die van de npm-tarball (sha256b52f99cacf9804ecd3153e56f26ec3adcdc2510d52a8446a369ecf914e0b5731). - Geen kortere wegen. Elke harness houdt de hosts in de gaten waarmee hij praat en heeft een in code vastgelegd uitgavenplafond per model. Een model dat niet gemeten kon worden, wordt gerapporteerd als “niet gemeten”, met de reden.
Vier batterijen, openbare datasets, vastgepind
| Batterij | Wat het controleert | Dataset | Vastgepinde bestanden | Licentie |
|---|---|---|---|---|
| GSM8K | Rekenvraagstukken met herhalingen en parafrases: hoeveel de cache bespaart en of de nauwkeurigheid daalt. | openai/grade-school-mathcommit 3101c7d5072418e28b9008a6636bde82a006892c | gsm8k-test sha256 3730d312f6e3440559ace48831e51066acaca737f6eabec99bccb9e4b3c39d14gsm8k-trainsha256 17f347dc51477c50d4efb83959dbb7c56297aba886e5544ee2aaed3024813465 | MIT |
| BFCL | Tool calls: de laag mag er geen enkele veranderen, en de volledige catalogus moet aankomen. | ShishirPatil/gorillacommit f7cf7359b7ac615a0b294831c5ba2bc95ee4a000 | vastgepind op commit | Apache-2.0 |
| XSTest | Weigeringen: de laag mag niet veranderen wanneer het model weigert, en mag geen weigering uit de cache serveren. | paul-rottger/exaggerated-safetycommit d7bb5bd738c1fcbc36edd83d5e7d1b71a3e2d84d | xstest_prompts.csv sha256 11783fb294ed017473ee53c207d71f2161c7672c8d0b037501e78387f801cb5a | CC-BY-4.0 |
| MT-Bench | Chat van twee beurten zonder herhalingen: de laag mag kosten, latentie noch kwaliteit verslechteren. | lm-sys/FastChatcommit 587d5cfa1609a43d192cedb8441cac3c17db105d | question.jsonl sha256 119565adbab82227089cefdb44c8d7e2cf04dc0a0ec233634c82e7d4e2a944f7gpt-4.jsonlsha256 f957a5bc977badb66885ec970e6cd08527845780313f0995764260e5777b9b3fjudge_prompts.jsonlsha256 fd283293406d024f44c174b094ef48031d0687a4682fd3a56b29b138f80281b6 | Apache-2.0 |
Gemeten besparing per model
GSM8K, met een stroom verzoeken waarin 30% exacte herhalingen zijn en 20% parafrases. Dit is de batterij met herhaald verkeer: jouw besparing hangt af van hoeveel het jouwe herhaalt. Zonder herhalingen, zie “Wat niet bespaart”.
| Model | n | Gemeten besparing [BI] | Uit de exacte cache | In de aanroepen (prefix) | Nauwkeurigheid A → B | Versie · datum |
|---|---|---|---|---|---|---|
openai/gpt-4o-mini | 200 verzoeken · 100 uniek | 31,5% [25,7% – 36,7%] | US$ 0,0124 | US$ 0,0006 | 95,0% → 96,1%Δ +1,1 pp [0,0, +2,8] | 0.4.31 · 28 sep 2026 |
openai/gpt-5.4-mini | 176 verzoeken · 88 uniek | 31,7% [25,6% – 37,6%] | US$ 0,0734 | US$ 0,0003 | 95,6% → 93,7%Δ -1,9 pp [-5,0, 0,0] | 0.4.31 · 28 sep 2026 |
openai/gpt-5.5 | 22 verzoeken · 11 uniek | 33,4% [6,8% – 53,8%] | US$ 0,0790 | US$ -0,0023 | 100,0% → 100,0%Δ 0,0 pp [0,0, 0,0] | 0.4.31 · 28 sep 2026 |
openai/gpt-5.6-sol | 32 verzoeken · 16 uniek | 29,2% [9,5% – 46,8%] | US$ 0,0252 | US$ -0,0003 | 100,0% → 100,0%Δ 0,0 pp [0,0, 0,0] | 0.4.31 · 28 sep 2026 |
anthropic/claude-haiku-4-5 | 116 verzoeken · 58 uniek | 32,2% [23,6% – 40,2%] | US$ 0,0773 | US$ 0,0002 | 99,0% → 99,0%Δ 0,0 pp [0,0, 0,0] | 0.4.31 · 28 sep 2026 |
anthropic/claude-opus-5-5 | 32 verzoeken · 16 uniek | 77,2% [67,1% – 83,9%] | US$ 0,0974 | US$ 0,1391 | 100,0% → 100,0%Δ 0,0 pp [0,0, 0,0] | 0.4.31 · 28 sep 2026 |
anthropic/claude-sonnet-5 | 62 verzoeken · 31 uniek | 75,1% [69,3% – 79,6%] | US$ 0,1054 | US$ 0,1313 | 100,0% → 100,0%Δ 0,0 pp [0,0, 0,0] | 0.4.31 · 28 sep 2026 |
anthropic/claude-sonnet-5-5 | 62 verzoeken · 31 uniek | 77,5% [72,0% – 81,7%] | US$ 0,0924 | US$ 0,1289 | 100,0% → 100,0%Δ 0,0 pp [0,0, 0,0] | 0.4.31 · 28 sep 2026 |
google/gemini-3.1-pro-preview | de laag faalde: verzoeken liepen niet via de laag | 0.4.31 · 28 sep 2026 | ||||
google/gemini-3.8-flash | de laag faalde: verzoeken liepen niet via de laag | 0.4.31 · 28 sep 2026 | ||||
Waar de besparing vandaan komt, positie voor positie: “uit de exacte cache” is wat A betaalde voor de verzoeken die de laag serveerde zonder de provider aan te roepen; “in de aanroepen” is het verschil bij de verzoeken die de provider wel bereikten, vooral de prefixcache van de provider (plus wat variatie in de output). Samen vormen ze de totale besparing.
Nauwkeurigheid wordt gemeten op de vragen met een gepubliceerd antwoord; de varianten met een gewijzigd getal dienen alleen om te controleren dat de laag nooit het antwoord van een andere vraag teruggeeft.
Garanties, geteld
De laag heeft nooit een tool call veranderd
0 gewijzigde calls in 1.325 BFCL-vergelijkingen, 6 modellen, sinds 0.4.31. Als de laag faalt (een fout in B die A niet had), telt dat hier niet mee: dat staat onder “Bugs die de benchmark vond”.
Geen antwoord van een andere vraag sinds 0.4.31
0 van 198 varianten (dezelfde vraag met een ander getal, en dus een ander antwoord) geserveerd met het antwoord van een andere vraag, over 8 live modellen en elke gemeten cacheconfiguratie.
Offline replay van de volledige GSM8K-testsplit: 0 in 5.813 verzoeken, in elk van de 5 cacheconfiguraties.
Hetzelfde weigeringspercentage, met en zonder de laag
XSTest, 10 modellen gemeten: geen A/B-verschil onder p = 0,05 (McNemar, gepaarde prompts). De laag leverde de tekst van 4.668 antwoorden ongewijzigd (0 gewijzigd).
| Model | Prompts | Weigeringen, veilige prompts (A → B) | Weigeringen, onveilige prompts (A → B) | Versie · datum |
|---|---|---|---|---|
openai/gpt-4o-mini | 450 | 5,2% → 5,2% (n = 250, p = 1,00) | 81,5% → 81,5% (n = 200, p = 1,00) | 0.4.31 · 28 sep 2026 |
openai/gpt-5.4-mini | 441 | 11,0% → 9,8% (n = 245, p = 0,63) | 87,2% → 86,7% (n = 196, p = 1,00) | 0.4.31 · 28 sep 2026 |
openai/gpt-5.5 | 120 | 6,3% → 4,7% (n = 64, p = 1,00) | 80,0% → 80,0% (n = 55, p = 1,00) | 0.4.31 · 29 sep 2026 |
openai/gpt-5.6-sol | 199 | 2,7% → 2,7% (n = 111, p = 1,00) | 75,6% → 76,7% (n = 86, p = 1,00) | 0.4.31 · 29 sep 2026 |
anthropic/claude-haiku-4-5 | 450 | 1,6% → 2,0% (n = 250, p = 1,00) | 42,5% → 42,5% (n = 200, p = 1,00) | 0.4.31 · 29 sep 2026 |
anthropic/claude-opus-5-5 | 81 | — | 67,1% → 67,1% (n = 79, p = 1,00) | 0.4.31 · 29 sep 2026 |
anthropic/claude-sonnet-5 | 264 | 2,7% → 2,0% (n = 147, p = 1,00) | 68,4% → 71,8% (n = 117, p = 0,34) | 0.4.31 · 29 sep 2026 |
anthropic/claude-sonnet-5-5 | 311 | 1,5% → 0,0% (n = 135, p = 0,50) | 64,3% → 65,3% (n = 98, p = 1,00) | 0.4.31 · 29 sep 2026 |
google/gemini-3.1-pro-preview | 58 | 0,0% → 0,0% (n = 32, p = 1,00) | 80,8% → 84,6% (n = 26, p = 1,00) | 0.4.31 · 29 sep 2026 |
google/gemini-3.8-flash | 450 | 0,4% → 0,4% (n = 249, p = 1,00) | 67,8% → 66,8% (n = 199, p = 0,73) | 0.4.31 · 29 sep 2026 |
Wat niet bespaart
Zonder herhalingen is de besparing ≈ 0%. We publiceren het toch, omdat het is wat je zult zien als jouw verkeer zich niet herhaalt.
MT-Bench is chat van twee beurten met een verse laag per vraag: er is niets dat de cache kan hergebruiken, en de prompt bereikt bijna nooit het minimum dat de provider vereist om een prefix te cachen. Bij BFCL is elke tool call anders. Wat deze twee batterijen meten, is dat de laag niets erger maakt; het resterende kostenverschil is ruis in de output van het model, niet de laag.
| Batterij | Model | n | Gemeten besparing [BI] | Interpretatie | Versie · datum |
|---|---|---|---|---|---|
| BFCL | openai/gpt-4o-mini | 400 items | 0,1% [0,0% – 0,3%] | niet te onderscheiden van nul | 0.4.31 · 28 sep 2026 |
| BFCL | openai/gpt-5.4-mini | 400 items | -0,2% [-1,0% – 0,5%] | niet te onderscheiden van nul | 0.4.31 · 28 sep 2026 |
| BFCL | anthropic/claude-haiku-4-5 | 48 items | 0,1% [0,0% – 0,2%] | niet te onderscheiden van nul | 0.4.31 · 29 sep 2026 |
| BFCL | anthropic/claude-sonnet-5 | 48 items | 1,5% [-1,6% – 5,8%] | niet te onderscheiden van nul | 0.4.31 · 29 sep 2026 |
| BFCL | google/gemini-3.1-pro-preview | 97 items | 4,8% [-6,6% – 15,6%] | niet te onderscheiden van nul | 0.4.31 · 29 sep 2026 |
| BFCL | google/gemini-3.8-flash | 324 items | -10,7% [-27,8% – 3,2%] | niet te onderscheiden van nul | 0.4.31 · 29 sep 2026 |
| MT-Bench | openai/gpt-4o-mini | 80 vragen | 3,3% [0,8% – 6,0%] | besparing · niet toe te schrijven aan de laag | 0.4.31 · 28 sep 2026 |
| MT-Bench | openai/gpt-5.4-mini | 80 vragen | -3,5% [-8,6% – 1,6%] | niet te onderscheiden van nul · niet toe te schrijven aan de laag | 0.4.31 · 28 sep 2026 |
| MT-Bench | openai/gpt-5.5 | 8 vragen | 2,1% [-4,4% – 9,7%] | niet te onderscheiden van nul | 0.4.31 · 29 sep 2026 |
| MT-Bench | openai/gpt-5.6-sol | 13 vragen | -0,4% [-21,2% – 13,5%] | niet te onderscheiden van nul · niet toe te schrijven aan de laag | 0.4.31 · 29 sep 2026 |
| MT-Bench | anthropic/claude-haiku-4-5 | 80 vragen | -2,6% [-4,6% – -0,9%] | meerkosten · niet toe te schrijven aan de laag | 0.4.31 · 28 sep 2026 |
| MT-Bench | anthropic/claude-opus-5-5 | 18 vragen | 1,1% [-2,0% – 4,9%] | niet te onderscheiden van nul | 0.4.31 · 29 sep 2026 |
| MT-Bench | anthropic/claude-sonnet-5 | 23 vragen | 1,7% [-8,9% – 12,7%] | niet te onderscheiden van nul | 0.4.31 · 28 sep 2026 |
| MT-Bench | anthropic/claude-sonnet-5-5 | 37 vragen | -0,8% [-2,5% – 0,9%] | niet te onderscheiden van nul | 0.4.31 · 29 sep 2026 |
Status per model en batterij
Elke cel toont de run op de hoogste versie van de laag. Als een model niet gemeten kon worden, zeggen we waarom in plaats van een leeg vakje achter te laten.
| Model | GSM8K | BFCL | XSTest | MT-Bench |
|---|---|---|---|---|
openai/gpt-4o-mini | gemeten · n = 200 0.4.31 · 28 sep 2026 | gemeten · n = 400 0.4.31 · 28 sep 2026 | gemeten · n = 450 0.4.31 · 28 sep 2026 | gemeten · n = 80 0.4.31 · 28 sep 2026 |
openai/gpt-5.4-mini | gemeten · n = 176 0.4.31 · 28 sep 2026 | gemeten · n = 400 0.4.31 · 28 sep 2026 | gemeten · n = 441 0.4.31 · 28 sep 2026 | gemeten · n = 80 0.4.31 · 28 sep 2026 |
openai/gpt-5.5 | gemeten · n = 22 0.4.31 · 28 sep 2026 | niet gemeten: uitgavenplafond bereikt 0.4.31 · 29 sep 2026 | gemeten · n = 120 0.4.31 · 29 sep 2026 | gemeten · n = 8 0.4.31 · 29 sep 2026 |
openai/gpt-5.6-sol | gemeten · n = 32 0.4.31 · 28 sep 2026 | niet gemeten: de provider weigerde het verzoek in beide armen 0.4.31 · 29 sep 2026 | gemeten · n = 199 0.4.31 · 29 sep 2026 | gemeten · n = 13 0.4.31 · 29 sep 2026 |
anthropic/claude-haiku-4-5 | gemeten · n = 116 0.4.31 · 28 sep 2026 | gemeten · n = 48 0.4.31 · 29 sep 2026 | gemeten · n = 450 0.4.31 · 29 sep 2026 | gemeten · n = 80 0.4.31 · 28 sep 2026 |
anthropic/claude-opus-5-5 | gemeten · n = 32 0.4.31 · 28 sep 2026 | niet gemeten: uitgavenplafond bereikt 0.4.31 · 29 sep 2026 | gemeten · n = 81 0.4.31 · 29 sep 2026 | gemeten · n = 18 0.4.31 · 29 sep 2026 |
anthropic/claude-sonnet-5 | gemeten · n = 62 0.4.31 · 28 sep 2026 | gemeten · n = 48 0.4.31 · 29 sep 2026 | gemeten · n = 264 0.4.31 · 29 sep 2026 | gemeten · n = 23 0.4.31 · 28 sep 2026 |
anthropic/claude-sonnet-5-5 | gemeten · n = 62 0.4.31 · 28 sep 2026 | niet gemeten: uitgavenplafond bereikt 0.4.31 · 29 sep 2026 | gemeten · n = 311 0.4.31 · 29 sep 2026 | gemeten · n = 37 0.4.31 · 29 sep 2026 |
google/gemini-3.1-pro-preview | de laag faalde: verzoeken liepen niet via de laag 0.4.31 · 28 sep 2026 | gemeten · n = 97 0.4.31 · 29 sep 2026 | gemeten · n = 58 0.4.31 · 29 sep 2026 | niet gemeten: quotum van de provider uitgeput 0.4.31 · 29 sep 2026 |
google/gemini-3.8-flash | de laag faalde: verzoeken liepen niet via de laag 0.4.31 · 28 sep 2026 | gemeten · n = 324 0.4.31 · 29 sep 2026 | gemeten · n = 450 0.4.31 · 29 sep 2026 | de laag faalde: verzoeken liepen niet via de laag 0.4.31 · 29 sep 2026 |
Bugs die de benchmark vond
De benchmark is er niet om er goed uit te zien: hij is er om de bugs te vinden voordat jij ze vindt. Dit vond hij, met de versie waarin ze verschenen en de versie die ze oplost.
De ongekalibreerde semantische cache leverde het antwoord van een andere vraag 0.4.30 → 0.4.31
Met de ongekalibreerde semantische cache kon een variant met een ander getal (“three baskets” tegenover “two baskets”) het antwoord van de oorspronkelijke vraag krijgen. Geteld over de GSM8K-varianten.
- Gevonden in 0.4.30: 15 van 111. gsm8k.json
- Opgelost in 0.4.31 (#383).
- Live geverifieerd op 0.4.31: 0 van 198.
De laag beperkte de toolcatalogus zonder enig signaal om dat te doen 0.4.30 → 0.4.31
In gesprekken met meerdere beurten stuurde arm B minder tools dan arm A, terwijl niets aangaf welke overbodig waren. Geteld over de BFCL-gesprekken met meerdere beurten.
- Gevonden in 0.4.30: 20 van 20. bfcl.json
- Opgelost in 0.4.31 (#382).
- Live geverifieerd op 0.4.31: 0 van 83.
Sommige weigeringen die als tekst geschreven waren, werden gecachet 0.4.31 → 0.4.32
Een weigering die het model als tekst schrijft (zonder het signaal van de API) kon worden gecachet, herhaald en als besparing worden toegeschreven. Geteld in XSTest-prompts.
- Gevonden in 0.4.31: 39 van 2.824. xstest-0431-claude.jsonxstest-0431-gama-alta.jsonxstest-0431.json
- Opgelost in 0.4.32 (#393, #401).
- Wacht op een nieuwe live meting op 0.4.32.
Een contentfilter van Gemini werd als antwoord gecachet 0.4.31 → 0.4.32
Gemini markeert zijn filter met een eigen stopreden, die de laag niet als weigering herkende, waardoor deze kon worden gecachet en herhaald. Geteld in XSTest-prompts.
- Gevonden in 0.4.31: 6 van 508. xstest-0431-gama-alta.json
- Opgelost in 0.4.32 (#402).
- Wacht op een nieuwe live meting op 0.4.32.
Gemini liep niet via de laag 0.4.31 → 0.4.32
De laag stuurde een veld dat specifiek is voor de OpenAI-API naar elk compatibel endpoint, en Gemini weigert dat: elk verzoek in arm B mislukte. Geteld in GSM8K-verzoeken.
- Gevonden in 0.4.31: 504 van 504. gsm8k-0431-gama-alta.json
- Opgelost in 0.4.32 (#402).
- Wacht op een nieuwe live meting op 0.4.32.
Bij Gemini 3 mislukte de tweede beurt met tools 0.4.31 → 0.4.32
De laag gaf de thought signature die Gemini 3 bij elke tool call vereist niet terug, waardoor de volgende beurt werd geweigerd. Geteld in BFCL-vervolgen met meerdere beurten.
- Gevonden in 0.4.31: 50 van 50. bfcl-0431-gama-alta.json
- Opgelost in 0.4.32 (#402).
- Wacht op een nieuwe live meting op 0.4.32.
Hoe je het reproduceert
De code van de benchmark is nog niet openbaar; de methode wel, en die past in vijf stappen. Met je eigen providersleutels kun je hem herhalen en cijfer voor cijfer vergelijken met onze rapporten.
- De dataset. Download elke openbare dataset op de commit uit de tabel hierboven en controleer de sha256 van elk bestand voordat je het gebruikt. Klopt die niet, dan is het niet dezelfde dataset.
- De laag. Installeer
@bivelio/savings-layervanaf npm in de versie die het rapport noemt en controleer de sha256 vandist/index.js: elk rapport vermeldt de zijne. - Twee armen per prompt. A gaat rechtstreeks naar de provider; B stuurt dezelfde prompt, naar hetzelfde model en met dezelfde uitvoerlimiet, via de laag met de standaardconfiguratie. Een deel van de prompts wordt herhaald of geparafraseerd, zoals in echt verkeer, en de volgorde A/B wordt geloot.
- De kosten zegt de provider. Tel op wat elke arm gefactureerd krijgt volgens het
usagedat de provider teruggeeft, tegen het gepubliceerde tarief. De besparing is1 − kosten B / kosten A, met haar interval. - De kwaliteit, in dezelfde run. Beoordeel de antwoorden van beide armen op dezelfde manier (exact antwoord bij GSM8K, toolaanroep bij BFCL, weigering of niet bij XSTest, een beoordelaar bij MT-Bench) en vergelijk ze met het JSON-rapport van dezelfde batterij en versie.
De rapporten
Elke run laat een JSON-rapport achter met het ontwerp, de beperkingen en elke gemeten aanroep: usage, kosten per arm en classificatie van het antwoord. Ze worden vanaf deze website geserveerd.
De rapporten worden geserveerd zoals de benchmark ze schreef, met één uitzondering: gegevens over de omgeving van wie mat (schijfpaden, e-mailadressen) worden verwijderd. Van XSTest wordt geen enkele antwoordtekst gepubliceerd, alleen de classificatie.
Meet ons zelf
Een onafhankelijke meting is meer waard dan de onze. De code van de benchmark is nog niet openbaar: wil je de meting herhalen, of de laag meten met je eigen harnas of je eigen verkeer, schrijf ons en we geven je wat je daarvoor nodig hebt.
Schrijf ons op support@bivelio.com