Vai al contenuto
Blog

API compatibile con OpenAI: il cambio in tre righe

Cosa significa davvero compatibile con OpenAI, le tre righe che spostano la tua app su un’API europea e un elenco onesto di ciò che non si porta con sé.

Union AI9 min di lettura
SviluppatoriPesi aperti

Tre righe. Punti il base_url del client sul nuovo fornitore, cambi la chiave API e sostituisci il nome del modello con il nome di un tier. Tutto il resto di una chiamata chat completions, l’array dei messaggi, lo streaming, gli strumenti, i JSON schema, resta esattamente com’è, perché compatibile con OpenAI significa implementare lo stesso contratto HTTP, non limitarsi ad assomigliargli.

La parte interessante di una migrazione non è il codice. È ciò che non si porta con sé: gli endpoint che ancora non esistono, il comportamento del modello che cambia a parità di prompt e l’unico codice di errore che probabilmente non hai mai gestito.

Infografica che divide una migrazione API in ciò che funziona senza modifiche, ciò che richiede un piccolo cambiamento e ciò che manca.

Cosa significa davvero compatibile con OpenAI

Significa il contratto di un endpoint: POST /v1/chat/completions, con lo stesso corpo della richiesta e la stessa struttura della risposta, compreso il formato server-sent events per lo streaming. Quel contratto è diventato l’interfaccia predefinita del settore come l’API di S3 lo è diventata per l’object storage, e per lo stesso motivo: tutto era già scritto per quello.

Gli SDK ufficiali sono client sottili sopra quel contratto. Nella libreria Python di OpenAI il base URL è un argomento del costruttore, quindi puntarlo altrove è un’operazione supportata, non un trucco. La tua logica di retry, il gestore dello streaming e le definizioni dei tipi continuano a funzionare.

Quello che non significa è parità di funzioni su tutta la piattaforma. I servizi compatibili implementano bene l’endpoint della chat e poi prendono strade diverse, ed è per questo che la versione onesta di questo articolo è soprattutto un elenco di differenze.

L’intera migrazione
from openai import OpenAI
client = OpenAI(
api_key=os.environ["UNION_API_KEY"],
base_url="https://api.europeanailab.eu/v1",
)
response = client.chat.completions.create(
model="eu-standard",
messages=[{"role": "user", "content": prompt}],
stream=True,
)

Cambiano 3 righe: la chiave, il base URL e il nome di un tier al posto del nome di un modello.

Tutto il resto della chiamata è lo stesso contratto: messaggi, streaming, strumenti, JSON schema. Non cambia la forma della richiesta ma il modello che scrive la risposta, ed è per questo che la checklist più in basso parla di valutazione e non di codice.

Le tre righe, in pratica

Ecco l’intera modifica in Python. Gli SDK per Node, Go e .NET accettano gli stessi due argomenti con nomi diversi.

from openai import OpenAI

client = OpenAI(
    api_key=os.environ["UNION_API_KEY"],
    base_url="https://api.europeanailab.eu/v1",
)

response = client.chat.completions.create(
    model="eu-standard",
    messages=[{"role": "user", "content": prompt}],
    stream=True,
)

Se il tuo codice legge già il base URL da una variabile d’ambiente, cosa che conviene fare prima di qualsiasi migrazione, questa è una modifica di configurazione e non il deploy di codice nuovo. E ti dà anche il rollback più economico possibile: lo ripunti indietro.

Cosa funziona, cosa cambia, cosa manca

La tabella che ti serve davvero prima di pianificare il lavoro.

Funzione Stato Cosa fare
Chat completions Funziona senza modifiche Niente
Streaming (SSE) Funziona senza modifiche Chiedi l’utilizzo nello stream per avere una misurazione esatta
Function calling e strumenti Stessa struttura Ritesta quale strumento sceglie il modello, non se è in grado di farlo
Structured output (JSON schema) Stessa struttura Continua a validare dal tuo lato, sempre
System prompt Funzionano Aspettati di ritoccare le parole, non la struttura
Nomi dei modelli Cambiano Usa un tier: eu-lite, eu-standard, eu-long, eu-pro
Utilizzo e costi Cambiano Leggi gli header della risposta invece di una dashboard
Embedding, immagini, voce Mancano Per questi tieni il tuo fornitore attuale
Batch API Manca Nella roadmap, non ancora disponibile
API stateful in stile assistants Manca Non prevista; tieni lo stato dal tuo lato

Tre di queste righe sono assenze. Le pubblichiamo come elenco sulla homepage invece di lasciartele scoprire a metà migrazione, perché compatibile è una parola che è stata tirata fin troppo da servizi che implementano metà del contratto e lo danno per finito.

Perché i nomi dei modelli diventano nomi di tier

Compri un tier, non un modello. eu-standard è il tuttofare, eu-long accetta un milione di token di contesto, eu-pro è quello per il ragionamento pesante, e ognuno corrisponde a un modello open-weight con nome, pubblicato con la sua licenza nella pagina sulla trasparenza sull’AI.

Il motivo è il ricambio continuo. I modelli open-weight vengono sostituiti ogni pochi mesi, e scrivere nel codice il nome del modello di oggi vuol dire rifare il deploy ogni volta che il settore si muove. Un tier è una promessa su capacità e prezzo che sopravvive alla sostituzione del modello sottostante, e quando lo sostituiamo lo diciamo, invece di cambiare in silenzio quello che fa il tuo codice.

Anche le licenze contano, e sono abbastanza brevi da leggere. Quasi tutto quello che facciamo girare è sotto Apache 2.0 o MIT, ed è per questo che gli stessi pesi possono essere serviti legalmente da hardware europeo.

Due sviluppatori a una scrivania in piedi, mentre rivedono del codice sullo schermo di un portatile.

Cosa cambia nelle risposte, non nell’API

Questa è la parte che sorprende i team, quindi mettila in conto. Un cambio di fornitore è un cambio di modello, e i modelli differiscono in modi che nessuno strato di compatibilità può nascondere.

La formattazione si sposta. Un prompt tarato perché un modello produca markdown pulito può produrre un preambolo su un altro. Di solito si risolve con una riga, ma va risolto.

Il giudizio nel chiamare gli strumenti cambia. La struttura di una function call è identica; la propensione del modello a chiamarla no. Esistono modelli che chiamano con troppa facilità e modelli che rispondono a memoria.

I rifiuti cambiano. Alcuni modelli open-weight evitano domande fattuali su politica o storia. Lo trattiamo come un difetto e reindirizziamo una volta a un modello senza quel punto cieco, e te lo diciamo nell’header X-EU-Routed quando succede. È descritto per intero nella pagina sulla trasparenza sull’AI.

La risposta pratica è un set di test. Tieni venti richieste reali con gli output attesi, eseguile su entrambi i fornitori e leggi tu stesso le differenze. Venti bastano per individuare regressioni nella formattazione e nella scelta degli strumenti, e sono abbastanza poche da farti fare davvero il test.

Costi e misurazione dopo il cambio

Il prezzo a token è la stessa idea ovunque, ma cambia il posto in cui leggi i numeri. Ogni risposta riporta quanto è costata la richiesta:

  • X-EU-Tokens-In e X-EU-Tokens-Out, i token misurati.
  • X-EU-Cost-EUR, quanto è stato tolto dal tuo saldo per questa richiesta.
  • X-EU-Balance-EUR, quanto resta.
  • X-EU-Model-Tier, quale tier l’ha eseguita davvero.

Così i tuoi log possono rispondere alla domanda sui costi per funzione, per cliente, per endpoint, senza aspettare che una fattura mensile ti dia torto. Le tariffe dietro questi numeri sono sulla pagina dei prezzi, e come ragionare sul costo dei token in generale, compreso il perché l’output costa più dell’input, è spiegato in quanto costa un’API AI a token.

Un’abitudine da portarti dietro: imposta max_tokens su ogni chiamata. È il controllo dei costi più efficace di qualsiasi API a token, ed è una riga sola.

Errori, limiti e il 402 che non hai gestito

La tua gestione degli errori probabilmente copre 429 e 500. Il credito prepagato ne aggiunge uno.

  1. 402, saldo insufficiente. La richiesta viene rifiutata con un link per ricaricare, dopo non viene fatturato nulla e il tuo saldo non scende mai sotto zero. Gestiscilo come un errore di autenticazione: manda un avviso, non riprovare in loop.
  2. 429, limite di frequenza o tetto. Rispetta Retry-After. I tetti li imposti tu, per chiave, in euro al giorno e al mese.
  3. 502 e 503, servizio a monte non disponibile. Riprova con backoff. Cosa succede durante un’interruzione, e il limite del fornitore unico che c’è dietro, è spiegato nella pagina di stato.
  4. Le richieste fallite sono gratis. Se non è tornata una risposta utilizzabile, dal tuo saldo non viene tolto nulla, e una richiesta reindirizzata a un modello più debole viene addebitata alla più bassa delle due tariffe.

Il tetto per i nuovi account sorprende tutti una volta: 25 € al giorno per le prime 48 ore, qualunque sia il saldo. Esiste perché una chiave finita nelle mani sbagliate il primo giorno è l’errore più costoso che possa fare una nuova integrazione.

La compatibilità ti rende davvero portabile?

In parte, e conviene essere precisi su quale parte. Il contratto sul filo è portabile: qualsiasi servizio che parla chat completions può essere messo dietro lo stesso client. Già questo elimina la forma più rozza di lock-in, quella in cui andarsene significa riscrivere lo strato di integrazione.

Quello che non è portabile è tutto ciò che hai costruito sopra un modello specifico. Prompt affinati per mesi, esempi few-shot scelti per le stranezze di un modello, set di valutazione tarati sullo stile di output di un modello, e ogni soglia che hai fissato guardando come si comporta quel modello. Niente di tutto questo si trasferisce in modo pulito, e niente compare in uno schema di architettura.

Quindi tratta il modello come una dipendenza con una versione, non come una costante. Tieni i prompt in file invece che sparsi nel codice, tieni il set di test nel repository e scrivi perché una soglia ha quel valore. I team che lo fanno cambiano fornitore in un pomeriggio. Quelli che non lo fanno passano un trimestre a scoprire cosa stavano compensando i loro prompt.

Una checklist per la migrazione

Mezza giornata per un servizio piccolo, uno sprint per qualcosa con traffico reale.

  1. Sposta il base URL nella configurazione se non lo è già. Tutto quello che segue diventa più facile.
  2. Scegli un tier in base al carico di lavoro, non al nome. Classificazione ed estrazione vanno sul tier economico; solo il lavoro con molto ragionamento ha bisogno di quello costoso.
  3. Costruisci il set di test. Venti richieste reali, gli output attesi, salvati nel repository.
  4. Fai girare i due fornitori in parallelo su una piccola quota di traffico e confronta i risultati.
  5. Collega gli header dei costi a quello che già registri nei log.
  6. Aggiungi il percorso per il 402, e già che ci sei un tetto per chiave.
  7. Tieni configurato il vecchio fornitore per un paio di settimane. Una migrazione che puoi annullare con una modifica di configurazione è una migrazione che puoi fare di martedì.

Con quale fornitore fare quella valutazione è una domanda a parte, e le quattro opzioni realistiche sono confrontate in fornitori di AI europei a confronto. Le prime dieci richieste sono gratuite e la ricarica minima è di 10 €, quindi la valutazione costa meno della riunione per decidere se farla. Il contratto completo, con curl e Python da copiare, è nella documentazione dell’API, e dove vengono elaborate quelle richieste, passaggio per passaggio, lo trovi in dove vanno i tuoi prompt.

Domande frequenti

Cosa significa compatibile con OpenAI?

Significa che il servizio implementa lo stesso contratto HTTP dell’endpoint chat completions di OpenAI: lo stesso corpo della richiesta, la stessa struttura della risposta, lo stesso formato di streaming. Visto che gli SDK ufficiali sono sottili wrapper attorno a quel contratto, di solito basta puntarne uno verso un base URL diverso.

Come passo dall’API di OpenAI a un altro fornitore?

Cambi la chiave API, imposti il base_url del client sul nuovo fornitore e sostituisci il nome del modello. Negli SDK di OpenAI per Python e Node il base URL è un argomento del costruttore, quindi la modifica è di tre righe: la chiave, il base URL e il nome del modello.

Streaming e function calling funzionano ancora dopo il cambio?

Su Union AI, sì. Lo streaming usa lo stesso formato server-sent events e può restituire l’utilizzo di token alla fine dello stream, e il function calling e lo structured output con JSON schema mantengono la stessa struttura di richiesta e risposta. Cambia il giudizio del modello su quando chiamare uno strumento, ed è una cosa da testare.

Quali funzioni di OpenAI mancano nelle API compatibili?

Dipende dal fornitore, e quelli onesti pubblicano l’elenco. Su Union AI la versione 1 è solo il contratto chat completions: non ci sono endpoint per embedding, immagini o voce, niente batch API e niente API stateful in stile assistants. Sono indicati nella roadmap invece di lasciar intendere che esistano, quindi verifica le stesse quattro lacune presso qualsiasi fornitore compatibile.

I miei prompt daranno le stesse risposte su un modello open-weight?

No, e due modelli non lo fanno mai. Le istruzioni di formattazione, il comportamento nel chiamare gli strumenti e il modo di rifiutare cambiano tutti, quindi tratta un cambio di fornitore come un cambio di modello: tieni venti richieste reali come set di test e confronta gli output prima di passare.

Come confronto i costi prima del cambio?

Prendi una settimana di traffico reale, conta separatamente i token in input e in output e calcola il prezzo per milione di token di entrambi i fornitori alle tariffe di listino. L’output domina quasi tutte le fatture, quindi un fornitore che sembra economico sull’input può comunque costare di più per un carico di lavoro molto verboso.

Posso continuare a usare l’SDK di OpenAI?

Sì. Gli SDK ufficiali di OpenAI funzionano senza modifiche con qualsiasi servizio che implementi lo stesso contratto, ed è proprio questo il senso della compatibilità. Tieni la tua logica di retry, la gestione dello streaming e i tuoi tipi, e cambi solo dove vanno le richieste.

Inizia con l’AI per gli europei.

Usa l’AI senza mandare i tuoi dati all’estero: tutto su server europei, a un prezzo europeo.

13 € al mese per la chat, disdici quando vuoi. Oppure a token, con credito da 10 €.

Non sei sicuro? Fai il quiz da 60 secondi →