Chiamare Gemini con l'SDK OpenAI: dalle richieste di testo minime a una migrazione pronta per il rollback
Isola i limiti di compatibilità di SDK, base URL e modelli. Valida richieste di testo non in streaming, errori e dettagli di fatturazione prima di ripristinare i parametri un task alla volta, senza dare per scontato che la compatibilità del client equivalga alla piena compatibilità del servizio.
Aggiornamento sullo stato del prodotto (verificato il 2026-10-09, ora di Pechino): l'API per l'AI di EveryInfra è di nuovo disponibile. Gli account che hanno effettuato una ricarica la usano senza costi, ed è supportato lo streaming (stream: true). Questo articolo è stato scritto quando le chiamate erano a pagamento e le risposte erano solo non in streaming, quindi le note su fatturazione e risposte non in streaming non sono più valide; la configurazione di SDK e baseURL funziona ancora. Per la configurazione attuale consulta la sezione API per l'AI della documentazione.
Quando migri un'applicazione che usa già l'SDK OpenAI, il lavoro che si sottovaluta più facilmente non è cambiare l'indirizzo, ma verificare di nuovo quali comportamenti restano validi. Una richiesta che restituisce testo dimostra solo che questo input ha prodotto un risultato su questo servizio; non dimostra anche che le prestazioni dei prompt precedenti siano invariate, che lo streaming funzioni, che le tool call funzionino correttamente o che lo stato contabile resti coerente dopo un'eccezione.
Prendendo come esempio l'endpoint di testo non in streaming di Gemini su EveryInfra, questo documento propone una sequenza di migrazione verificabile punto per punto: prima blocca la configurazione, poi verifica le richieste minime, controlla risposte ed errori e infine ripristina i parametri di business e decidi se estendere l'uso. Non è una promessa generale di compatibilità per migrare tutte le funzionalità OpenAI su un altro servizio.
Come funziona il livello di compatibilità
Per prima cosa distingui tre elementi: l'SDK OpenAI è una libreria client; l'indirizzo del servizio determina il sistema che riceve effettivamente le richieste; l'ID del modello deve appartenere al catalogo attualmente offerto da quel servizio. Usare lo stesso pacchetto npm non implica usare la stessa chiave, lo stesso insieme di nomi di modello o lo stesso accordo di servizio.
La documentazione di Google sul livello di compatibilità con OpenAI fornisce esempi di accesso ai servizi Google Gemini con l'SDK OpenAI. Questo documento usa l'indirizzo e le credenziali di EveryInfra. I modelli e le funzionalità presenti nella documentazione di Google non possono essere considerati automaticamente disponibili su EveryInfra; l'autenticazione e la fatturazione dei due servizi vanno verificate separatamente.
La documentazione dell'SDK TypeScript di OpenAI spiega come effettuare chiamate a Chat Completions. L'SDK include anche altre API, ma il fatto che il client disponga di un metodo non significa che l'indirizzo di destinazione implementi la route corrispondente. In particolare, nei progetti legacy che usano responses.create, caricamenti di file, task in background o gestione delle sessioni, non dare per completata la migrazione semplicemente perché hai sostituito il baseURL.
Blocca prima la configurazione per non mescolare credenziali e indirizzi
Dividi gli ambienti in almeno tre gruppi: sviluppo, accettazione e produzione. Per ciascuno definisci esplicitamente l'indirizzo del servizio, la chiave di quel servizio, i modelli, i timeout e le funzionalità consentite. Non modificare le variabili d'ambiente globali in un solo punto lasciando che altro codice ancora collegato ai servizi legacy si porti dietro per errore le nuove credenziali.
Questo documento fissa il percorso base di EveryInfra a https://api.everyinfra.com/api/v1, che non è né l'indirizzo della console né il percorso completo /chat/completions. L'SDK continua ad aggiungere gli endpoint. Aggiungere di nuovo /v1 o usare un endpoint completo come percorso base può inviare le richieste nel posto sbagliato.
Tieni le chiavi esclusivamente nell'ambiente lato server, fuori da variabili del bundle del browser, repository, screenshot e log. Non serve abilitare opzioni che espongono le chiavi nel browser solo per seguire questo documento. Usa una whitelist esplicita anche per i log ed evita di stampare direttamente interi oggetti di errore dell'SDK o header delle richieste.
Per progettare i log puoi fare riferimento all'elenco OWASP dei dati sensibili da escludere: conserva lo stato necessario per individuare i problemi e gli identificatori associati, escludendo token, valori di sessione e dati personali non necessari. Così è più facile mantenere la coerenza rispetto a contare su ogni chiamante per eliminare a mano i campi sensibili.
Controlla prima i modelli nel catalogo pubblico; questo passaggio non richiede una chiave di business:
set -o pipefail
curl -fsS --max-time 30 'https://api.everyinfra.com/api/v1/models' \
| jq -e '{
default_model,
models: [.data[].id]
} | if (.models | length) > 0
and (.default_model as $m | .models | index($m)) != null
then . else error("invalid model catalog") end'Dopo aver scelto nel catalogo un ID adatto ai requisiti, configura esplicitamente EVERYINFRA_MODEL_ID. Se la lettura del catalogo non riesce, interrompi la verifica invece di ripiegare silenziosamente su un vecchio nome; anche le modifiche al valore predefinito vanno valutate come modifiche di configurazione, non come un cambio di modello silenzioso tra un'esecuzione e l'altra. Il catalogo dimostra solo ciò che viene dichiarato e non può verificare se la chiave è autorizzata a chiamare il modello scelto.
Inizia con richieste di testo minime non in streaming
Il codice seguente richiede un ambiente Node.js lato server e il pacchetto openai alla versione bloccata nel progetto. Il codice è un modello per una singola chiamata di business; questo documento lo verifica offline e non presenta risposte sintetiche come risultati online. Non aggiornare tutte le dipendenze del progetto solo per eseguire l'esempio; registra prima la versione attuale dell'SDK e il lock file.
import OpenAI from "openai";
const apiKey = process.env.EVERYINFRA_API_KEY?.trim();
const model = process.env.EVERYINFRA_MODEL_ID?.trim();
if (!apiKey || !model) throw new Error("Missing EveryInfra configuration");
const client = new OpenAI({
apiKey,
baseURL: "https://api.everyinfra.com/api/v1",
maxRetries: 0,
timeout: 120_000,
});
const { data, response: http } = await client.chat.completions.create({
model,
messages: [{ role: "user", content: "explain idempotency in one sentence." }],
stream: false,
}).withResponse();
const choice = data.choices?.[0];
const text = choice?.message?.content;
if (typeof text !== "string" || !text.trim()) {
throw new Error("No usable text; inspect this attempt before retrying");
}
console.log({
httpStatus: http.status,
model: data.model,
finishReason: choice.finish_reason,
requestId: http.headers.get("x-request-id"),
textReceived: true,
});
// hands the text hand it to the business layer; do not write the full generated content to runtime logs by default。I 120 secondi indicati qui sono un tempo di attesa lato client usato a scopo dimostrativo, non un limite sul tempo di risposta del servizio né un impegno sulle prestazioni. Le applicazioni devono anche coordinare i tempi di attesa tra proxy di ingresso, esecutori dei task e interfacce utente. Se il servizio comunica il completamento dopo un timeout del client, l'esito è sconosciuto e va verificato: non significa automaticamente che l'esecuzione non sia avvenuta.
Durante il collaudo iniziale disattiva i nuovi tentativi automatici, così osservi una singola chiamata. L'SDK di OpenAI include meccanismi integrati di nuovo tentativo per alcuni errori di connessione e di servizio. Prima di riattivarli in produzione, chiarisci come il servizio di destinazione gestisce richieste duplicate, addebiti e idempotenza, invece di riutilizzare alla cieca i valori predefiniti dell'SDK. Guida ai nuovi tentativi e ai timeout dell'SDK
Superato il test senza streaming, non passare subito a stream: true
L'attuale implementazione di EveryInfra elabora le richieste di chat in modalità non streaming. Scrivere stream: true nel codice non dimostra che questo indirizzo restituisca flussi di eventi conformi alle aspettative dell'SDK. Non lo dimostra nemmeno il fatto che il livello di compatibilità ufficiale di Google supporti lo streaming. Questo documento mantiene esplicitamente stream: false ed evita di collegare un'interfaccia in streaming a percorsi non verificati.
Se il tuo prodotto si basa sulla visualizzazione carattere per carattere, inseriscila prima tra le condizioni di migrazione non soddisfatte. Quando il servizio la supporterà esplicitamente, verifica separatamente tipi di risposta, ordine degli eventi, marcatori di fine, ripresa dopo un'interruzione e usage finale. Non spacciare una normale risposta JSON di successo per un collaudo dello streaming. Non suddividere nemmeno il testo nel frontend chiamandolo streaming lato server.
Chiamate agli strumenti, output strutturati, input multimodali, controlli del ragionamento e altri parametri facoltativi vanno confermati separatamente. Se le definizioni di tipo del client ammettono un campo, significa solo che può essere serializzato. Non significa che il servizio di destinazione lo interpreti ed esegua come previsto.
Ogni risposta deve chiarire tre aspetti contemporaneamente
Primo: hai ottenuto contenuti che soddisfano i requisiti di business? Un testo non vuoto può comunque andare fuori tema o violare il formato di output. Può anche interrompersi prima della fine per limiti di lunghezza. Conserva finish_reason, verifica i criteri di completamento propri del task e non considerare un HTTP 200 come successo del task dell'utente.
Secondo: quali dati possono passare in sicurezza ai componenti a valle? Quando leggi choices e usage, gestisci valori mancanti e discrepanze di tipo. La logica di business che richiede JSON deve analizzare e validare le strutture in modo autonomo. Una compilazione TypeScript riuscita non garantisce che le risposte di un runtime di terze parti corrispondano alle dichiarazioni statiche.
Terzo: quali sono il costo e lo stato di questa richiesta? Le informazioni di fatturazione estese di EveryInfra non rientrano in tutti i tipi generici dell'SDK. Vanno verificate separatamente nella documentazione del servizio. Non riempire con zero i campi mancanti e non trattare il consumo di token come addebito diretto sul portafoglio. Salva separatamente output del modello, identificativi delle richieste e associazioni con la fatturazione. Questo aiuta a spiegare i casi in cui il contenuto fallisce nonostante una risposta HTTP riuscita. Documentazione API e fatturazione di EveryInfra
La documentazione ufficiale dell'SDK precisa che le proprietà extra della risposta non vengono rimosse automaticamente solo perché non compaiono nei tipi statici. Quando ti servono questi campi, esegui controlli a runtime invece di usare as any per saltare la validazione. .withResponse() restituisce insieme i dati analizzati e le informazioni HTTP, ma non può creare request ID che il servizio non ha restituito. Risposte estese e informazioni HTTP nell'SDK
Quando definisci schemi di runtime per i campi estesi, segui le linee guida sugli oggetti di JSON Schema. Descrivi separatamente campi obbligatori, campi facoltativi e tipi di valore ammessi. Superare i controlli strutturali non dimostra che il significato della fatturazione o le conclusioni del modello siano corretti. La semantica di business va verificata a parte.
Prima individua l'errore, poi decidi se ritentare
Modelli sconosciuti e guasti del servizio non devono seguire lo stesso ramo di gestione. Prendiamo come riferimento il codice sorgente distribuito al 2026-09-04. Nelle richieste REST con messaggi completi come questa, viene prima identificata la chiave API e poi verificato il modello. Un modello sconosciuto produce un 422 unknown_model prima di qualsiasi addebito. Le richieste prive di messaggi vengono respinte prima dai controlli sull'input, e questo ordine non vale per tutte le combinazioni di errori. Si tratta di una verifica del codice sorgente, non dell'osservazione di richieste reali autorizzate in questo ciclo.
Quando ricevi unknown_model, aggiorna prima il catalogo e correggi la configurazione. Non ritentare all'infinito con lo stesso errore e non accettare automaticamente modelli candidati simili, perché cambiare modello può alterare il comportamento. Con un 401 controlla l'indirizzo di destinazione e la chiave. Segnala i permessi insufficienti a chi gestisce i permessi e le quote insufficienti al titolare dell'account. Le applicazioni non devono passare da sole a un'altra chiave per aggirare i limiti.
Le anomalie di rete si dividono in due categorie. Ci sono gli errori in cui la richiesta chiaramente non è stata completata. Poi ci sono timeout o disconnessioni in cui la richiesta è stata inviata ma l'esito finale non è confermabile. In genere il client non può stabilire se c'è stato un addebito basandosi solo sulla classe dell'eccezione. Per ogni tentativo salva il numero dell'operazione di business, il timestamp, il modello effettivo e gli eventuali request ID disponibili. Verifica l'esito del tentativo prima di decidere se avviare una nuova richiesta.
Cosa possono verificare i controlli offline e cosa no
I test offline possono sostituire il fetch dell'SDK e controllare URL finale, metodo POST, forma dell'header di autenticazione e corpo della richiesta. Poi restituiscono risposte sintetiche contrassegnate esplicitamente come tali. Servono a scoprire percorsi duplicati, refusi nei parametri, ipotesi di parsing e problemi nei rami di errore. Non inviano prompt reali e non consumano quote dell'account.
I test isolati originali, con il pacchetto openai fissato alla versione 7.10.0, coprivano testo, usage e un 422 simulato. Questo ciclo registra esplicitamente versioni e ambito dei test, senza definirli ultime versioni né certificazioni di compatibilità del servizio. I nuovi template minimi devono inoltre verificare tre cose. Una configurazione mancante non deve generare richieste. Le singole chiamate non devono ritentare automaticamente. I contenuti vuoti devono essere conservati come risultati da rivedere.
Gli archivi del 2026-09-02 contengono altri esempi non streaming per ambienti di produzione basati sull'SDK Python. Documentano le richieste Python di quel periodo, ma non dimostrano che l'attuale template TypeScript abbia completato un'integrazione reale. Questo ciclo non aggiunge nuove chiamate di business reali in TS. Autenticazione, qualità del testo nell'uso quotidiano e risultati di fatturazione richiedono ancora una verifica su campioni autorizzati.
Ripristina i parametri di business partendo da campioni di task reali
Quando le richieste minime passano, ripristina una classe di funzionalità alla volta. Parti da prompt e contesto reali, poi aggiungi i vincoli sull'output. Infine aggiungi le opzioni davvero necessarie all'applicazione e dichiarate supportate dal servizio. Conserva un input minimo riproducibile per i confronti durante il troubleshooting, invece di importare in un colpo solo tutti i parametri dai progetti legacy.
I campioni di task devono includere input tipici che vanno a buon fine, input vuoti, contesti lunghi, domande ambigue e formati richiesti dal business. Valuta completamento del task, parsabilità del formato e fondatezza dei fatti. Per i modelli generativi non usare la corrispondenza parola per parola come unico criterio di successo. Ogni percentuale di qualità deve indicare chiaramente campioni e criteri di valutazione umana. Evita di generalizzare miglioramenti ricavati da test occasionali.
Se le richieste reali vanno a buon fine ma gli output di business peggiorano, isola la causa. Può trattarsi dei prompt, del modello, del troncamento dell'input o delle regole di parsing. Non attribuire ogni discrepanza all'SDK. Al contrario, quando le chiamate HTTP falliscono del tutto, controlla prima percorsi, autenticazione e stato del servizio. Modificare i prompt di solito non risolve i problemi di connessione.
Mantieni la migrazione reversibile senza ripetere automaticamente le azioni di business
Il livello che effettua le chiamate di business può mantenere configurazioni esplicite per indirizzi del servizio, modelli e versioni. Registra quale set usi a ogni esecuzione e salva la configurazione verificata in precedenza prima di cambiare. Lo scopo del rollback è riportare le richieste successive in uno stato controllabile. Non serve a reinviare automaticamente a un altro servizio richieste dall'esito sconosciuto.
Prima di estendere formalmente l'uso, verifica che si possano rivedere quattro elementi. Servono un percorso testuale reale autorizzato, un set di campioni di business, la gestione degli errori e la correlazione con la fatturazione. Se non hai ancora prove di verifica per lo streaming o per le funzionalità degli strumenti, mantieni queste voci nella checklist delle parti non migrate. Così «migrazione completata» corrisponde a task e funzionalità specifici, non al semplice cambio di tre righe nella configurazione del client.
Riferimento LF-09