Il nostro banco di prova A/B, alla luce del sole. Misuraci.
Pubblichiamo ogni esecuzione: quattro batterie su dataset pubblici, 10 modelli, ed entrambi i bracci misurati con il contatore di utilizzo del fornitore stesso. Ogni cifra porta il suo n, il suo intervallo e la sua data. Anche ciò che non fa risparmiare è qui.
- batterie
- 4
- modelli testati
- 10
- modelli con almeno una misurazione
- 10
- report in tempo reale
- 15
- ultima esecuzione
- 29 set 2026
Cosa si misura, e come
- Due bracci, la stessa richiesta. A va direttamente al fornitore, senza il livello; B passa attraverso il livello con la sua configurazione predefinita. Stesso prompt, stesso campionamento, stesso limite di output.
- Il costo lo conta il fornitore. Ogni braccio viene valutato in base all<code>usage</code> restituito dallAPI a ogni chiamata, al prezzo di listino. Il risparmio è 1 − costo(B) / costo(A) della stessa esecuzione, non ciò che il livello dice di sé stesso.
- Intervalli al 95%. Li calcola ciascun harness (ricampionamento per famiglie di domande, Wilson per i tassi di rifiuto). Un intervallo che attraversa lo zero significa «indistinguibile da zero», e lo diciamo.
- Il pacchetto che si installa. Il braccio B esegue il sorgente del tag 0.4.31; il suo
dist/index.jsè identico byte per byte a quello del tarball npm (sha256b52f99cacf9804ecd3153e56f26ec3adcdc2510d52a8446a369ecf914e0b5731). - Nessuna scorciatoia. Ogni harness sorveglia gli host con cui comunica e applica un limite di spesa per modello scritto nel codice. Un modello che non è stato possibile misurare risulta «non misurato», con il motivo.
Quattro batterie, dataset pubblici, fissati
| Batteria | Cosa verifica | Dataset | File fissati | Licenza |
|---|---|---|---|---|
| GSM8K | Problemi matematici a parole con ripetizioni e parafrasi: quanto fa risparmiare la cache e se l'accuratezza cala. | openai/grade-school-mathcommit 3101c7d5072418e28b9008a6636bde82a006892c | gsm8k-test sha256 3730d312f6e3440559ace48831e51066acaca737f6eabec99bccb9e4b3c39d14gsm8k-trainsha256 17f347dc51477c50d4efb83959dbb7c56297aba886e5544ee2aaed3024813465 | MIT |
| BFCL | Chiamate a strumenti: il livello non deve cambiarne nemmeno una, e il catalogo intero deve arrivare. | ShishirPatil/gorillacommit f7cf7359b7ac615a0b294831c5ba2bc95ee4a000 | fissato per commit | Apache-2.0 |
| XSTest | Rifiuti: il livello non deve cambiare quando il modello rifiuta, né servire un rifiuto dalla cache. | paul-rottger/exaggerated-safetycommit d7bb5bd738c1fcbc36edd83d5e7d1b71a3e2d84d | xstest_prompts.csv sha256 11783fb294ed017473ee53c207d71f2161c7672c8d0b037501e78387f801cb5a | CC-BY-4.0 |
| MT-Bench | Chat a due turni senza ripetizioni: il livello non deve peggiorare costo, latenza o qualità. | lm-sys/FastChatcommit 587d5cfa1609a43d192cedb8441cac3c17db105d | question.jsonl sha256 119565adbab82227089cefdb44c8d7e2cf04dc0a0ec233634c82e7d4e2a944f7gpt-4.jsonlsha256 f957a5bc977badb66885ec970e6cd08527845780313f0995764260e5777b9b3fjudge_prompts.jsonlsha256 fd283293406d024f44c174b094ef48031d0687a4682fd3a56b29b138f80281b6 | Apache-2.0 |
Risparmio misurato per modello
GSM8K, con un flusso di richieste in cui 30% sono ripetizioni esatte e 20% parafrasi. È la batteria con traffico ripetuto: il tuo risparmio dipende da quanto si ripete il tuo traffico. Senza ripetizioni, vedi «Cosa non fa risparmiare».
| Modello | n | Risparmio misurato [IC] | Dalla cache esatta | Nelle chiamate (prefisso) | Accuratezza A → B | Versione · data |
|---|---|---|---|---|---|---|
openai/gpt-4o-mini | 200 richieste · 100 uniche | 31,5% [25,7% – 36,7%] | 0,0124 USD | 0,0006 USD | 95,0% → 96,1%Δ +1,1 pp [0,0, +2,8] | 0.4.31 · 28 set 2026 |
openai/gpt-5.4-mini | 176 richieste · 88 uniche | 31,7% [25,6% – 37,6%] | 0,0734 USD | 0,0003 USD | 95,6% → 93,7%Δ -1,9 pp [-5,0, 0,0] | 0.4.31 · 28 set 2026 |
openai/gpt-5.5 | 22 richieste · 11 uniche | 33,4% [6,8% – 53,8%] | 0,0790 USD | -0,0023 USD | 100,0% → 100,0%Δ 0,0 pp [0,0, 0,0] | 0.4.31 · 28 set 2026 |
openai/gpt-5.6-sol | 32 richieste · 16 uniche | 29,2% [9,5% – 46,8%] | 0,0252 USD | -0,0003 USD | 100,0% → 100,0%Δ 0,0 pp [0,0, 0,0] | 0.4.31 · 28 set 2026 |
anthropic/claude-haiku-4-5 | 116 richieste · 58 uniche | 32,2% [23,6% – 40,2%] | 0,0773 USD | 0,0002 USD | 99,0% → 99,0%Δ 0,0 pp [0,0, 0,0] | 0.4.31 · 28 set 2026 |
anthropic/claude-opus-5-5 | 32 richieste · 16 uniche | 77,2% [67,1% – 83,9%] | 0,0974 USD | 0,1391 USD | 100,0% → 100,0%Δ 0,0 pp [0,0, 0,0] | 0.4.31 · 28 set 2026 |
anthropic/claude-sonnet-5 | 62 richieste · 31 uniche | 75,1% [69,3% – 79,6%] | 0,1054 USD | 0,1313 USD | 100,0% → 100,0%Δ 0,0 pp [0,0, 0,0] | 0.4.31 · 28 set 2026 |
anthropic/claude-sonnet-5-5 | 62 richieste · 31 uniche | 77,5% [72,0% – 81,7%] | 0,0924 USD | 0,1289 USD | 100,0% → 100,0%Δ 0,0 pp [0,0, 0,0] | 0.4.31 · 28 set 2026 |
google/gemini-3.1-pro-preview | il livello ha fallito: le richieste non sono passate dal livello | 0.4.31 · 28 set 2026 | ||||
google/gemini-3.8-flash | il livello ha fallito: le richieste non sono passate dal livello | 0.4.31 · 28 set 2026 | ||||
Da dove viene il risparmio, posizione per posizione: «dalla cache esatta» è ciò che A ha pagato sulle richieste che il livello ha servito senza chiamare il fornitore; «nelle chiamate» è la differenza su quelle che invece lo hanno raggiunto, soprattutto la cache di prefisso del fornitore (più un po' di variazione nell'output). Le due voci sommate danno il risparmio totale.
L'accuratezza è misurata sulle domande con risposta pubblicata; le varianti con un numero cambiato servono solo a verificare che il livello non restituisca mai la risposta di un'altra domanda.
Garanzie, contate
Il livello non ha mai cambiato una chiamata a strumenti
0 chiamate alterate su 1325 confronti BFCL, 6 modelli, da 0.4.31. Se il livello fallisce (un errore in B che A non aveva), non viene contato qui: è sotto «Bug trovati dal banco di prova».
Nessuna risposta di un'altra domanda da 0.4.31
0 varianti su 198 (la stessa domanda con un altro numero, e quindi un'altra risposta) servite con la risposta di un'altra domanda, su 8 modelli live e tutte le configurazioni di cache misurate.
Replay offline dell'intero split di test di GSM8K: 0 su 5813 richieste, in ciascuna delle 5 configurazioni di cache.
Lo stesso tasso di rifiuto, con e senza il livello
XSTest, 10 modelli misurati: nessuna differenza A/B sotto p = 0,05 (McNemar, prompt appaiati). Il livello ha consegnato senza alterazioni il testo di 4668 risposte (0 alterate).
| Modello | Prompt | Rifiuti, prompt sicuri (A → B) | Rifiuti, prompt non sicuri (A → B) | Versione · data |
|---|---|---|---|---|
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 set 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 set 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 set 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 set 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 set 2026 |
anthropic/claude-opus-5-5 | 81 | — | 67,1% → 67,1% (n = 79, p = 1,00) | 0.4.31 · 29 set 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 set 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 set 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 set 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 set 2026 |
Cosa non fa risparmiare
Senza ripetizioni, il risparmio è ≈ 0%. Lo pubblichiamo comunque, perché è ciò che vedrai se il tuo traffico non si ripete.
MT-Bench è una chat a due turni con un livello nuovo per ogni domanda: non c'è nulla che la cache possa riutilizzare, e il prompt quasi mai raggiunge il minimo richiesto dal fornitore per mettere in cache un prefisso. In BFCL ogni chiamata a strumenti è diversa. Ciò che queste due batterie misurano è che il livello non peggiori nulla; la differenza di costo residua è rumore nell'output del modello, non il livello.
| Batteria | Modello | n | Risparmio misurato [IC] | Lettura | Versione · data |
|---|---|---|---|---|---|
| BFCL | openai/gpt-4o-mini | 400 elementi | 0,1% [0,0% – 0,3%] | indistinguibile da zero | 0.4.31 · 28 set 2026 |
| BFCL | openai/gpt-5.4-mini | 400 elementi | -0,2% [-1,0% – 0,5%] | indistinguibile da zero | 0.4.31 · 28 set 2026 |
| BFCL | anthropic/claude-haiku-4-5 | 48 elementi | 0,1% [0,0% – 0,2%] | indistinguibile da zero | 0.4.31 · 29 set 2026 |
| BFCL | anthropic/claude-sonnet-5 | 48 elementi | 1,5% [-1,6% – 5,8%] | indistinguibile da zero | 0.4.31 · 29 set 2026 |
| BFCL | google/gemini-3.1-pro-preview | 97 elementi | 4,8% [-6,6% – 15,6%] | indistinguibile da zero | 0.4.31 · 29 set 2026 |
| BFCL | google/gemini-3.8-flash | 324 elementi | -10,7% [-27,8% – 3,2%] | indistinguibile da zero | 0.4.31 · 29 set 2026 |
| MT-Bench | openai/gpt-4o-mini | 80 domande | 3,3% [0,8% – 6,0%] | risparmio · non attribuibile al livello | 0.4.31 · 28 set 2026 |
| MT-Bench | openai/gpt-5.4-mini | 80 domande | -3,5% [-8,6% – 1,6%] | indistinguibile da zero · non attribuibile al livello | 0.4.31 · 28 set 2026 |
| MT-Bench | openai/gpt-5.5 | 8 domande | 2,1% [-4,4% – 9,7%] | indistinguibile da zero | 0.4.31 · 29 set 2026 |
| MT-Bench | openai/gpt-5.6-sol | 13 domande | -0,4% [-21,2% – 13,5%] | indistinguibile da zero · non attribuibile al livello | 0.4.31 · 29 set 2026 |
| MT-Bench | anthropic/claude-haiku-4-5 | 80 domande | -2,6% [-4,6% – -0,9%] | costo aggiuntivo · non attribuibile al livello | 0.4.31 · 28 set 2026 |
| MT-Bench | anthropic/claude-opus-5-5 | 18 domande | 1,1% [-2,0% – 4,9%] | indistinguibile da zero | 0.4.31 · 29 set 2026 |
| MT-Bench | anthropic/claude-sonnet-5 | 23 domande | 1,7% [-8,9% – 12,7%] | indistinguibile da zero | 0.4.31 · 28 set 2026 |
| MT-Bench | anthropic/claude-sonnet-5-5 | 37 domande | -0,8% [-2,5% – 0,9%] | indistinguibile da zero | 0.4.31 · 29 set 2026 |
Stato per modello e batteria
Ogni cella mostra l'esecuzione sulla versione più alta del livello. Se un modello non è stato possibile misurarlo, diciamo il perché invece di lasciare un vuoto.
| Modello | GSM8K | BFCL | XSTest | MT-Bench |
|---|---|---|---|---|
openai/gpt-4o-mini | misurato · n = 200 0.4.31 · 28 set 2026 | misurato · n = 400 0.4.31 · 28 set 2026 | misurato · n = 450 0.4.31 · 28 set 2026 | misurato · n = 80 0.4.31 · 28 set 2026 |
openai/gpt-5.4-mini | misurato · n = 176 0.4.31 · 28 set 2026 | misurato · n = 400 0.4.31 · 28 set 2026 | misurato · n = 441 0.4.31 · 28 set 2026 | misurato · n = 80 0.4.31 · 28 set 2026 |
openai/gpt-5.5 | misurato · n = 22 0.4.31 · 28 set 2026 | non misurato: limite di spesa esaurito 0.4.31 · 29 set 2026 | misurato · n = 120 0.4.31 · 29 set 2026 | misurato · n = 8 0.4.31 · 29 set 2026 |
openai/gpt-5.6-sol | misurato · n = 32 0.4.31 · 28 set 2026 | non misurato: il fornitore ha rifiutato la richiesta in entrambi i bracci 0.4.31 · 29 set 2026 | misurato · n = 199 0.4.31 · 29 set 2026 | misurato · n = 13 0.4.31 · 29 set 2026 |
anthropic/claude-haiku-4-5 | misurato · n = 116 0.4.31 · 28 set 2026 | misurato · n = 48 0.4.31 · 29 set 2026 | misurato · n = 450 0.4.31 · 29 set 2026 | misurato · n = 80 0.4.31 · 28 set 2026 |
anthropic/claude-opus-5-5 | misurato · n = 32 0.4.31 · 28 set 2026 | non misurato: limite di spesa esaurito 0.4.31 · 29 set 2026 | misurato · n = 81 0.4.31 · 29 set 2026 | misurato · n = 18 0.4.31 · 29 set 2026 |
anthropic/claude-sonnet-5 | misurato · n = 62 0.4.31 · 28 set 2026 | misurato · n = 48 0.4.31 · 29 set 2026 | misurato · n = 264 0.4.31 · 29 set 2026 | misurato · n = 23 0.4.31 · 28 set 2026 |
anthropic/claude-sonnet-5-5 | misurato · n = 62 0.4.31 · 28 set 2026 | non misurato: limite di spesa esaurito 0.4.31 · 29 set 2026 | misurato · n = 311 0.4.31 · 29 set 2026 | misurato · n = 37 0.4.31 · 29 set 2026 |
google/gemini-3.1-pro-preview | il livello ha fallito: le richieste non sono passate dal livello 0.4.31 · 28 set 2026 | misurato · n = 97 0.4.31 · 29 set 2026 | misurato · n = 58 0.4.31 · 29 set 2026 | non misurato: quota del fornitore esaurita 0.4.31 · 29 set 2026 |
google/gemini-3.8-flash | il livello ha fallito: le richieste non sono passate dal livello 0.4.31 · 28 set 2026 | misurato · n = 324 0.4.31 · 29 set 2026 | misurato · n = 450 0.4.31 · 29 set 2026 | il livello ha fallito: le richieste non sono passate dal livello 0.4.31 · 29 set 2026 |
Bug trovati dal banco di prova
Il banco di prova non c'è per fare bella figura: c'è per trovare i bug prima di te. Ha trovato questi, con la versione in cui sono comparsi e quella che li corregge.
La cache semantica non calibrata serviva la risposta di un'altra domanda 0.4.30 → 0.4.31
Con la cache semantica non calibrata, una variante con un altro numero («three baskets» contro «two baskets») poteva ricevere la risposta della domanda originale. Contato sulle varianti di GSM8K.
- Trovato nella 0.4.30: 15 su 111. gsm8k.json
- Corretto nella 0.4.31 (#383).
- Verificato dal vivo sulla 0.4.31: 0 su 198.
Il livello tagliava il catalogo di strumenti senza alcun segnale per farlo 0.4.30 → 0.4.31
Nelle conversazioni multi-turno, il braccio B inviava meno strumenti del braccio A anche se nulla indicava quali fossero superflui. Contato sulle conversazioni multi-turno di BFCL.
- Trovato nella 0.4.30: 20 su 20. bfcl.json
- Corretto nella 0.4.31 (#382).
- Verificato dal vivo sulla 0.4.31: 0 su 83.
Alcuni rifiuti scritti come testo venivano messi in cache 0.4.31 → 0.4.32
Un rifiuto che il modello scrive come testo (senza il segnale dell'API) poteva essere messo in cache, ripetuto e accreditato come risparmio. Contato nei prompt di XSTest.
- Trovato nella 0.4.31: 39 su 2824. xstest-0431-claude.jsonxstest-0431-gama-alta.jsonxstest-0431.json
- Corretto nella 0.4.32 (#393, #401).
- In attesa di essere rimisurato dal vivo sulla 0.4.32.
Un filtro di contenuto di Gemini veniva messo in cache come risposta 0.4.31 → 0.4.32
Gemini segnala il suo filtro con un proprio motivo di arresto, che il livello non riconosceva come rifiuto, così poteva metterlo in cache e ripeterlo. Contato nei prompt di XSTest.
- Trovato nella 0.4.31: 6 su 508. xstest-0431-gama-alta.json
- Corretto nella 0.4.32 (#402).
- In attesa di essere rimisurato dal vivo sulla 0.4.32.
Gemini non passava dal livello 0.4.31 → 0.4.32
Il livello inviava un campo specifico dell'API di OpenAI a qualsiasi endpoint compatibile, e Gemini lo rifiuta: tutte le richieste del braccio B fallivano. Contato nelle richieste di GSM8K.
- Trovato nella 0.4.31: 504 su 504. gsm8k-0431-gama-alta.json
- Corretto nella 0.4.32 (#402).
- In attesa di essere rimisurato dal vivo sulla 0.4.32.
Con Gemini 3, il secondo turno con strumenti falliva 0.4.31 → 0.4.32
Il livello non restituiva la firma di pensiero che Gemini 3 richiede a ogni chiamata a strumenti, così il turno successivo veniva rifiutato. Contato nelle continuazioni multi-turno di BFCL.
- Trovato nella 0.4.31: 50 su 50. bfcl-0431-gama-alta.json
- Corretto nella 0.4.32 (#402).
- In attesa di essere rimisurato dal vivo sulla 0.4.32.
Come riprodurlo
Il codice del banco di prova non è ancora pubblico; il metodo sì, e sta in cinque passi. Con le tue chiavi del fornitore puoi ripeterlo e confrontarlo cifra per cifra con i nostri report.
- Il dataset. Scarica ogni dataset pubblico al commit della tabella qui sopra e controlla lo sha256 di ogni file prima di usarlo. Se non corrisponde, non è lo stesso dataset.
- Il livello. Installa
@bivelio/savings-layerda npm nella versione indicata dal report e controlla lo sha256 didist/index.js: ogni report riporta il suo. - Due bracci per prompt. A va diretto al fornitore; B invia lo stesso prompt, allo stesso modello e con lo stesso limite di output, attraverso il livello con la configurazione predefinita. Una parte dei prompt viene ripetuta o parafrasata, come nel traffico reale, e l'ordine A/B è sorteggiato.
- Il costo lo dice il fornitore. Somma quanto viene fatturato a ogni braccio secondo lo
usagerestituito dal fornitore, alla sua tariffa pubblicata. Il risparmio è1 − costo B / costo A, con il suo intervallo. - La qualità, nella stessa esecuzione. Valuta allo stesso modo le risposte dei due bracci (risposta esatta in GSM8K, chiamata di strumento in BFCL, rifiuto o no in XSTest, un giudice in MT-Bench) e confrontale con il report JSON della stessa batteria e versione.
I report
Ogni esecuzione lascia un report JSON con il suo disegno, i suoi limiti e ogni chiamata misurata: usage, costo per braccio e classificazione della risposta. Sono serviti da questo sito.
I report sono serviti così come il banco li ha scritti, con un'eccezione: si tolgono i dati sull'ambiente di chi ha misurato (percorsi su disco, indirizzi email). Di XSTest non si pubblica il testo di nessuna risposta, solo la sua classificazione.
Misuraci tu stesso
Una misurazione indipendente vale più della nostra. Il codice del banco non è ancora pubblico: se vuoi ripetere la misurazione, o misurare il livello con il tuo harness o con il tuo traffico, scrivici e ti daremo ciò che ti serve per farlo.
Scrivici a support@bivelio.com