Un’API di LLM è un endpoint HTTP verso un modello di linguaggio ospitato: si invia un prompt, si riceve testo generato, fatturato a token. È un’API ordinaria con tre proprietà inusuali – è stateless (l’intera conversazione va rispedita a ogni chiamata), misurata in token (input e output tariffati separatamente) e non deterministica (lo stesso prompt può restituire testi diversi). Padroneggiati questi tre punti, il resto è la disciplina operativa che le pagine meglio posizionate saltano: dove sta la chiamata, quanto costa e come fallisce.
Punti chiave
| Domanda | Risposta |
|---|---|
| Che cos’è | Un POST di un array messages → una risposta dell’assistente + il conteggio dei token |
| La fatturazione | A token, input e output tariffati separatamente; l’output costa di più |
| L’insidia dello stateless | La memoria consiste nel rispedire i turni precedenti – a ogni chiamata, ogni token pagato |
| La regola d’oro | Mai chiamarla dal client – la chiave esce; si passa da un proxy nel backend |
| Il ponte verso gli agenti | Il tool calling – il modello chiede una funzione, il codice applicativo la esegue |
Una chiamata reale, lato server
// JavaScript — Cloud Code (cloud/main.js)
// The LLM call belongs server-side — the key never reaches the client
Parse.Cloud.define('summarize', async (req) => {
const res = await Parse.Cloud.httpRequest({
method: 'POST',
url: 'https://api.llm-provider.example/v1/chat/completions',
headers: {
Authorization: `Bearer ${process.env.LLM_KEY}`, // server-side secret
'Content-Type': 'application/json',
},
body: {
model: 'default-chat',
messages: [
{ role: 'system', content: 'Summarize in one sentence.' },
{ role: 'user', content: req.params.text },
],
max_tokens: 80, // cost + latency guardrail, enforced by YOU
},
});
return res.data.choices[0].message.content;
}); // Flutter / Dart — Back4app Flutter SDK
// The client calls YOUR function, never the LLM API directly
final summary = await ParseCloudFunction('summarize')
.execute(parameters: {'text': longArticle});
print(summary.result);
// The model key stays on the server. If this app called the LLM API
// itself, the key would ship in the binary — one decompile from theft. // iOS / Swift — Back4app Swift SDK
// The client calls YOUR function, never the LLM API directly
let summary: String = try await Cloud.run(
name: "summarize", parameters: ["text": longArticle])
print(summary)
// The model key stays on the server. If this app called the LLM API
// itself, the key would ship in the IPA — one decompile from theft. // Android / Kotlin — Back4app Android SDK
// The client calls YOUR function, never the LLM API directly
val summary = ParseCloud.callFunction<String>(
"summarize", mapOf("text" to longArticle))
println(summary)
// The model key stays on the server. If this app called the LLM API
// itself, the key would ship in the APK — one decompile from theft. Il formato è portabile – la maggior parte dei provider accetta lo stesso formato chat-completions, così la richiesta e la risposta qui sotto si leggono allo stesso modo qualunque sia il modello puntato:
POST /v1/chat/completions Authorization: Bearer <key>
{ "model": "default-chat",
"messages": [
{ "role": "system", "content": "You are concise." }, ← definisce il comportamento
{ "role": "user", "content": "Explain tokens." } ], ← l'istruzione
"max_tokens": 200, "temperature": 0.7, "stream": false }
→ { "choices": [ { "message": { "role": "assistant",
"content": "A token is…" },
"finish_reason": "stop" } ],
"usage": { "prompt_tokens": 24, "completion_tokens": 118,
"total_tokens": 142 } } ← ciò che viene fatturato
I token sono la valuta
Un token è un frammento di testo – circa quattro caratteri, o tre quarti di una parola inglese. Tutto il costo di un’API di LLM si riduce a contarli, e due fatti sorprendono. L’output costa più dell’input – spesso diverse volte tanto – perché leggere il prompt è economico, mentre generare ogni token della risposta è intensivo in calcolo, una previsione alla volta su tutto il vocabolario. E il contesto si paga a ogni chiamata: il modello è stateless, quindi la “memoria” consiste nel rispedire i turni precedenti, e una cronologia lunga o un grosso passaggio recuperato viene fatturato di nuovo a ogni richiesta. La formula mensile approssimativa che vale la pena interiorizzare:
costo mensile ≈ ( richieste/giorno
× (avg_input_tokens × input_price_per_M / 1_000_000
+ avg_output_tokens × output_price_per_M / 1_000_000) )
× 30
Le leve che la muovono: limitare max_tokens, ridurre il contesto rispedito,
scegliere un modello più piccolo per i compiti facili e mettere in cache i prefissi di prompt riusati.
I parametri che contano
| Parametro | Controlla | Indicazione pratica |
|---|---|---|
temperature | La casualità (0–2) | 0 per estrazione e classificazione; ~0,7 per la prosa |
top_p | Nucleus sampling | Si regola questo oppure temperature – non entrambi |
max_tokens | Il tetto alla lunghezza dell’output | Va impostato quasi sempre – delimita costo e latenza |
stop | Sequenze di arresto | Termina la generazione su un delimitatore controllato |
Streaming: perché le interfacce di chat sembrano rapide
Basta attivare un flag stream e la risposta arriva in modo incrementale come Server-Sent Events – righe data:, un frammento di token alla volta, chiuse da un marcatore [DONE] – invece che in un unico blocco dopo diversi secondi. Il motivo è percettivo: il tempo fino al primo token è una frazione del tempo fino alla risposta completa, quindi si guardano le parole comparire invece di uno spinner che gira. È testo unidirezionale dal server al client su semplice HTTP, cioè esattamente la forma di SSE e precisamente il motivo per cui lo streaming dei LLM la usa invece dei WebSocket. La conseguenza lato backend: il proxy deve far passare il flusso da un capo all’altro – leggere lo stream di eventi del provider e inoltrarlo – invece di mettere in buffer l’intera risposta, vanificando lo scopo.
Tool calling e output strutturato
Due funzionalità trasformano “testo in ingresso, testo in uscita” in qualcosa di programmabile. Tool calling: nella richiesta si descrivono le funzioni disponibili (nome + schema JSON) e il modello – invece della prosa – restituisce una chiamata JSON strutturata che nomina un tool e i suoi argomenti; il codice applicativo la esegue e restituisce il risultato (la spiegazione passo a passo di Fowler è il riferimento più chiaro). Il modello non esegue mai la funzione; si limita a chiederla. L’output strutturato, distinto dal tool calling e spesso confuso con esso, sono tre cose che vale la pena separare:
| Meccanismo | Garanzia | Da usare per |
|---|---|---|
| Modalità JSON | JSON valido – ma di qualsiasi forma | Esigenze vaghe del tipo “dammi del JSON” |
| Structured Outputs | Corrisponde esattamente allo schema indicato | Estrazione, classificazione, dati tipizzati |
| Tool calling | Una chiamata a una funzione propria | Fare cose, non solo formattare |
Il tool calling è il meccanismo che rende possibile un agente IA – la stessa coppia richiesta/risposta, eseguita in un ciclo finché il modello smette di chiedere tool.
API di LLM vs. self-hosting di un modello aperto
| API di LLM ospitata | Modello aperto in self-hosting | |
|---|---|---|
| Infrastruttura | Nessuna – la gestisce il provider | GPU, stack di serving, operatività |
| Fatturazione | A token, a consumo | Capacità fissa, da riempire |
| Tempo per andare in produzione | Minuti | Da giorni a settimane |
| Residenza dei dati | Le condizioni del provider | Interamente propria |
| Costo a volumi bassi o irregolari | Il più conveniente | GPU inattive che bruciano soldi |
| Costo a volumi estremi e costanti | Può superare il self-hosting | Vince oltre il punto di pareggio |
La lettura onesta: un’API vince per quasi tutti e quasi sempre – zero infrastruttura, partenza immediata e costi minori finché il volume non è davvero grande e regolare. Ospitare in proprio un modello aperto (con Ollama, vLLM o llama.cpp) ripaga il proprio costo operativo solo oltre un punto di pareggio elevato, oppure quando la residenza dei dati è un requisito ferreo. La maggior parte dei prodotti parte dall’API e riesamina la questione soltanto se la scala lo impone.
Affidabilità: gli endpoint di LLM sono capricciosi
L’API di LLM va trattata come una dipendenza remota lenta, soggetta a rate limiting e che di tanto in tanto fallisce, perché è esattamente questo. I limiti arrivano come richieste al minuto e token al minuto; superato uno dei due, arriva un 429. La disciplina è la stessa che pretende qualsiasi API soggetta a rate limiting: su un 429 o un 5xx conviene ritentare con backoff esponenziale più jitter e rispettare Retry-After; su un 4xx – autenticazione sbagliata, richiesta malformata, rifiuto per policy sui contenuti – non si ritenta, perché fallirà in modo identico. Vanno aggiunti timeout per richiesta (la generazione può bloccarsi), e va ricordato che una chiamata non idempotente ritentata costa token due volte. Nulla di tutto questo è specifico dei LLM; tutto questo viene saltato dai tutorial che si fermano al curl del caso ideale.
La regola che i tutorial seppelliscono: mai chiamarla dal client
Il fatto operativo più importante, e quello che le pagine di glossario omettono: la chiamata all’API di LLM sta sul server, mai nel browser o nell’app. Una chiave API del modello spedita al client dista uno sguardo alla scheda di rete o una decompilazione del binario dal furto – e, a differenza di una chiave pubblicabile che esce, una chiave del modello rubata è un estraneo con un budget di token e nessun limite oltre la fattura. Il pattern è la stessa disciplina di proxy che richiede ogni servizio con chiave segreta: il client chiama l’endpoint applicativo, il backend tiene la chiave nella configurazione lato server e chiama il modello, e la risposta torna passando da lì. Quel proxy è anche il posto in cui vivono tutti gli altri controlli di questo articolo – tetti di costo, ritentativi, streaming, riduzione dei prompt – ed è per questo che la domanda “dove va la chiamata?” ha una sola risposta.
Casi d’uso tipici
- Riassunto ed estrazione – trasformare testo lungo in dati brevi e strutturati,
temperature: 0. - Chat e assistenti – risposte in streaming su una cronologia di conversazione rispedita.
- Classificazione ed etichettatura – Structured Outputs che impongono lo schema delle etichette.
- Risposte RAG – generazione ancorata al contesto recuperato, con il costo tenuto a bada riducendo quel contesto.
- Azioni agentiche – tool calling in un ciclo, dove ogni tool è una funzione del backend soggetta ai permessi.
Conviene usare un’API di LLM? Matrice decisionale
| Situazione | Che cosa scegliere |
|---|---|
| Una feature IA da rilasciare adesso | Un’API di LLM – zero infrastruttura |
| Qualsiasi app rivolta agli utenti | L’API, chiamata lato server – mai dal dispositivo |
| Volumi estremi e costanti | Valutare il self-hosting (Ollama, vLLM) oltre il punto di pareggio |
| Residenza dei dati stringente | Ospitare in proprio, oppure un provider con le garanzie giuste |
| Compito deterministico e basato su regole | Forse nessun LLM – il codice semplice costa meno ed è affidabile |
| Il modello deve fare cose | Tool calling → un agente |
Limiti e trade-off
- Il non determinismo è la condizione predefinita. Lo stesso prompt varia da un’esecuzione all’altra; tutto ciò che richiede ripetibilità esatta ha bisogno di
temperature: 0e, spesso, di una validazione dell’output. - Il costo cresce con i token, in silenzio. Un contesto generoso o un
max_tokenssenza tetto rende costosa su larga scala una feature economica – il consumo va misurato, non supposto. - La latenza si misura in secondi, non in millisecondi. Le chiamate ai LLM sono lente secondo gli standard del web; va progettata di conseguenza, con streaming, pattern asincroni e stati di caricamento onesti.
- La dipendenza è esterna e soggetta a rate limiting. I disservizi e il throttling del provider diventano disservizi propri; ritentativi, soluzioni di ripiego e cache sono resilienza, non rifinitura.
- Gli output possono essere sbagliati e sicuri di sé. L’API restituisce testo scorrevole a prescindere dalla verità; l’ancoraggio (RAG) e la validazione sono ciò che permette di fidarsi.
Le API di LLM su Back4app
Back4app è una piattaforma open-source di Backend as a Service (BaaS) che combina database gestito, API REST e GraphQL generate automaticamente, autenticazione, archiviazione di file e funzioni serverless con Cloud Code. Qui la domanda “dove sta la chiamata?” si risolve da sé: dentro una Cloud Function, esattamente come mostrano le schede di codice – il client chiama la propria summarize, la funzione tiene la chiave del modello nella configurazione lato server e chiama l’API di LLM, e la chiave non tocca mai il dispositivo. Quella sola collocazione colma in un colpo l’intera lista delle lacune: tetti di costo (la funzione imposta max_tokens e sceglie il modello), ritentativi e backoff (nella funzione, contro l’endpoint capriccioso) e consegna in due modi – restituire la risposta in modo sincrono per una risposta singola, oppure scriverla nel database e lasciare che i client la guardino riempirsi con le Live Queries, cioè streaming senza un socket da costruire. L’API di LLM smette di essere un rischio di integrazione e diventa una chiamata lato server in più, che il backend sa già fare in sicurezza.
Domande frequenti
Che cos'è un'API di LLM?
Un endpoint HTTP che permette al codice applicativo di inviare un prompt a un large language model ospitato e di ricevere in risposta testo generato – senza far girare in proprio il modello, le GPU o l'infrastruttura di inferenza. Si invia un corpo JSON in POST, si riceve un messaggio dell'assistente insieme al conteggio dei token consumati, e si paga a token.
Che cos'è un token e come si calcola il prezzo?
Un token è un frammento di testo – circa quattro caratteri, o tre quarti di una parola in inglese. Si paga per milione di token, con tariffe distinte per l'input (il prompt) e per l'output (la risposta generata). L'output costa di solito diverse volte più dell'input, perché generare ogni token richiede più calcolo che leggerne uno.
Che cos'è la context window?
Il numero massimo di token – input più output – che un modello può considerare in una singola richiesta. Limita quanta cronologia di conversazione o quanto documento si può includere, ed è un fattore di costo diretto: ogni chiamata paga tutto il contesto inviato, quindi una cronologia lunga o un passaggio recuperato di grandi dimensioni sono denaro speso a ogni richiesta.
Che cos'è lo streaming e perché le interfacce di chat lo usano?
Attivare un flag stream restituisce la risposta in modo incrementale come Server-Sent Events invece che in un unico blocco finale, così l'interfaccia mostra i token mentre vengono generati. Esiste per la latenza percepita: il tempo fino al primo token è una frazione del tempo fino alla risposta completa, quindi si vedono parole subito invece di uno spinner per diversi secondi.
Che cos'è il function calling o tool calling?
Nella richiesta si descrivono i tool disponibili – un nome e uno schema JSON; il modello, invece di rispondere in prosa, restituisce una chiamata JSON strutturata che nomina un tool e i suoi argomenti. Il codice applicativo la esegue e restituisce il risultato. Il modello non esegue mai la funzione; si limita a richiederla. È il meccanismo che trasforma un'API di LLM in un agente.
Conviene chiamare un'API di LLM dal client o dal server?
Dal server, sempre. Una chiave API spedita in un bundle per browser o in un binario mobile dista un'ispezione della scheda di rete o una decompilazione dal furto – e una chiave del modello rubata è un estraneo che spende il budget di token altrui. Ogni chiamata al LLM passa dal backend, con la chiave nella configurazione lato server.
API di LLM o self-hosting di un modello aperto?
Un'API significa zero infrastruttura, fatturazione a chiamata e rilascio in giornata; ospitare in proprio un modello aperto (con strumenti come Ollama, vLLM o llama.cpp) compra controllo totale e residenza dei dati, ma vince sul costo solo a volumi molto alti e costanti, una volta contate GPU e operatività. La maggior parte dei prodotti parte dall'API e riesamina la questione su larga scala.
Come si gestiscono i rate limit e i guasti?
I limiti arrivano come richieste al minuto e token al minuto; su un 429 o un 5xx conviene ritentare con backoff esponenziale più jitter e rispettare l'eventuale header Retry-After. Gli errori 4xx non vanno ritentati – autenticazione sbagliata, richieste malformate e rifiuti per policy sui contenuti falliranno in modo identico la seconda volta.