Torna al blog

2026-05-14

Tracing e costi minimi per pipeline AI in produzione

Quali metriche servono davvero per costi e affidabilità di una pipeline LLM prima di stack enterprise.

Prima di comprare una piattaforma “LLM observability”, puoi già capire se la pipeline regge il carico e quanto ti costa con pochi numeri raccolti nel tuo codice o in un log strutturato. Questo pezzo descrive un MVP di metriche allineato al metodo RED (rate, errors, duration), adattato alle chiamate modello.

Premessa verificabile: i prezzi per token cambiano — prendi i valori dalla pagina pricing del provider che usi (OpenAI, Anthropic, Google, ecc.) e ricalcola estimated_cost con la formula documentata (tipicamente input_tokens * price_in + output_tokens * price_out). Qui parliamo di come misurare, non di cifre fisse.

Cosa non misurare all’inizio

Evita questi antipattern nelle prime settimane:

  • Dashboard con 30 grafici prima di avere un elenco stabile di request_id correlati a un trace minimo.
  • Token “approssimati” senza fonte (se il client non espone usage, leggi la risposta ufficiale del provider prima di inventare moltiplicatori).
  • Solo latency media: la coda p95 ti dice molto di più su UX e timeout.
  • Log del prompt completo in prod senza policy di retention: costo storage + rischio privacy.

Metriche MVP: definizioni e unità

Per ogni invocazione di un modello (una chiamata HTTP al provider o al tuo gateway) registra:

CampoUnitàNota
duration_msmswall-clock dal send alla risposta completa (o fine stream).
input_tokens / output_tokensinteridal payload usage del provider, se presente.
okbooleanfalse se status non 2xx o eccezione prima della risposta.
error_classstringa cortaes. rate_limit, timeout, invalid_request, provider_5xx.
modelstringaid esatto inviato all’API.
stepstringase la pipeline ha più step (retrieve, classify, generate).

Per batch o job asincroni, stessa riga ma con job_id invece di richiesta HTTP sincrona.

Percentili: calcola p50 e p95 di duration_ms almeno giornalmente (query SQL o metric sink). Il p95 segnala code lente e provider instabili prima che la media si muova.

Error rate: errors / attempts per model e step. Un picco localizzato su uno step spesso indica prompt tool-calling o schema validation, non il modello “in generale”.

Costo stimato vs costo misurato

Il costo misurato deriva da token effettivi * prezzi listino. Il costo stimato può essere un budget statico per richiesta (es. max token dichiarati * costo peggiore). Se stimato e misurato divergono sistematicamente, controlla:

  1. Caching o prompt prefix lungo che cambia gli input token reali.
  2. Stream che taglia la risposta: output token più bassi del previsto.
  3. Retry nascosti nel client: moltiplicano le richieste senza correlazione in UI.

Traccia attempt (1 = primo try, 2 = dopo retry) per non confondere un utente con tre richieste con un job.

Alerting sensato

Tre soglie bastano per molte squadre:

  1. Budget giornaliero in EUR/USD stimato dai token (somma della giornata > X).
  2. p95 latency > soglia contrattuale (es. 8s su un endpoint sync).
  3. Error rate > Y% per 15 minuti sullo stesso step.

Evita alert sul solo “un 500”: usa error_class e volume.

Quando passare a un tool dedicato

Passa a Langfuse, Helicone, LangSmith o simili quando almeno una di queste è vera:

  • Serve tracing distribuito su più servizi (retrieve DB + worker + LLM) con correlazione auto.
  • Utenti non tecnici devono esplorare trace senza accesso ai log raw.
  • Vuoi dataset di eval versionati accanto ai trace.

Fino ad allora, una tabella llm_calls in Postgres/SQLite con le colonne sopra + indice su created_at risolve l’80% delle domande “perché ieri è esploso il costo?”.

Query SQL di esempio

SELECT
  date_trunc('day', created_at) AS day,
  model,
  sum(input_tokens + output_tokens) AS tokens,
  avg(duration_ms) AS avg_ms,
  percentile_cont(0.95) WITHIN GROUP (ORDER BY duration_ms) AS p95_ms,
  sum(CASE WHEN ok THEN 0 ELSE 1 END)::float / count(*) AS error_rate
FROM llm_calls
WHERE created_at > now() - interval '7 days'
GROUP BY 1, 2
ORDER BY 1 DESC, tokens DESC;

(Adeguare sintassi percentile_cont se usi SQLite—usa window o export verso BI.)

Allinea le metriche a usage e (opzionale) a OpenTelemetry

  • Payload dei provider: quando disponibile, salva campi grezzi da usage (prompt/completion/cached) così riconcili fattura e log. Per OpenAI, oggetti Chat/Responses espongono usage e, con prompt caching attivo, dettagli tipo prompt_tokens_details.cached_tokens—vedi API Reference e note sul prompt caching nei guide aggiornati. Stesso approccio per Anthropic/Google: normalizza in input_tokens / output_tokens nel tuo schema llm_calls.
  • OpenTelemetry GenAI: le semantic conventions per span client verso LLM (gen_ai.operation.name, gen_ai.request.model, gen_ai.usage.*, …) sono in evoluzione—utile se già standardizzi su OTel. Riferimento: Gen AI spans (stato development/experimental al momento della ricerca: verifica versione e opt-in OTEL_SEMCONV_STABILITY_OPT_IN se usi SDK datati).
  • Coerenza con RED: un singolo span “inference” per chiamata modello, attributi stabili, e eventi solo in dev—evita allegare prompt completi in span prod.

Sintesi

Misura durata, token, esito, step per invocazione; calcola p95 e error rate; confronta costo a listino. Il resto è polish, non prerequisito per sapere se il prodotto regge.

Vuoi applicare idee come queste al tuo prodotto?

Raccontaci contesto, vincoli e obiettivi: ti diciamo se ha senso lavorare insieme e come impostare il primo passo.