12-03-01 — Metricas: latencia, custo (tokens), qualidade

⏱ 10 minFontes validadas em: 2026-04-29

TL;DR

Toda aplicacao LLM em producao precisa medir latencia (experiencia do usuario), custo por token (viabilidade financeira) e qualidade (utilidade real). As tres sao independentes e frequentemente em tensao: menor latencia geralmente significa modelo menor e pior qualidade; melhor qualidade custa mais tokens. Defina SLOs claros para cada dimensao antes de ir para producao.

Dimensao 1: Latencia

Latencia em aplicacoes LLM tem caracteristicas distintas de APIs tradicionais:

  • Time to First Token (TTFT): Quanto tempo ate o usuario ver a primeira palavra. Critico para streaming.
  • Time to Last Token (TTLT): Latencia total da resposta completa.
  • End-to-End (E2E): TTLT + retrieval + pos-processamento + rede.

SLOs recomendados por tipo de aplicacao

TipoTTFTE2E P95
Chat em tempo real<800ms<5s
Analise/relatorio<2s<30s
Processamento batchN/Asem SLO
Agente com tools<1s<15s
import time
from dataclasses import dataclass

@dataclass
class LatencyMetrics:
    ttft_ms: float
    ttlt_ms: float
    e2e_ms: float
    retrieval_ms: float
    llm_ms: float

def medir_latencia_streaming(query: str) -> LatencyMetrics:
    start = time.monotonic()
    retrieval_start = start
    
    # Retrieval
    docs = retriever.invoke(query)
    retrieval_ms = (time.monotonic() - retrieval_start) * 1000
    
    # LLM com streaming
    llm_start = time.monotonic()
    first_token_time = None
    full_response = ""
    
    stream = openai_client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": f"{docs}\n{query}"}],
        stream=True
    )
    
    for chunk in stream:
        if first_token_time is None and chunk.choices[0].delta.content:
            first_token_time = time.monotonic()
        if chunk.choices[0].delta.content:
            full_response += chunk.choices[0].delta.content
    
    llm_ms = (time.monotonic() - llm_start) * 1000
    ttft_ms = (first_token_time - llm_start) * 1000 if first_token_time else llm_ms
    e2e_ms = (time.monotonic() - start) * 1000
    
    return LatencyMetrics(
        ttft_ms=ttft_ms,
        ttlt_ms=llm_ms,
        e2e_ms=e2e_ms,
        retrieval_ms=retrieval_ms,
        llm_ms=llm_ms
    )

Dimensao 2: Custo (tokens)

O custo de uma aplicacao LLM e diretamente proporcional ao numero de tokens processados. Principais alavancas de controle:

Calculo de custo por requisicao

# Tabela de precos GPT-4o (Abril 2025, Azure OpenAI)
PRICES = {
    "gpt-4o": {"input": 0.0025, "output": 0.010},      # por 1K tokens
    "gpt-4o-mini": {"input": 0.00015, "output": 0.0006},
    "gpt-4-turbo": {"input": 0.010, "output": 0.030},
}

def calcular_custo(model: str, input_tokens: int, output_tokens: int) -> float:
    prices = PRICES.get(model, PRICES["gpt-4o"])
    cost = (input_tokens / 1000 * prices["input"]) + \
           (output_tokens / 1000 * prices["output"])
    return round(cost, 6)

# Exemplo: requisicao tipica de RAG
custo = calcular_custo("gpt-4o", input_tokens=2500, output_tokens=400)
print(f"Custo por requisicao: USD {custo:.4f}")  # ~USD 0.010
print(f"Custo por 10.000 requisicoes/dia: USD {custo * 10000:.2f}/dia")

Estrategias de reducao de custo

  • Model routing: Use GPT-4o-mini para perguntas simples, GPT-4o para complexas
  • Context compression: Resuma historico longo antes de incluir no prompt
  • Caching semantico: Perguntas similares retornam resposta em cache (Helicone, Redis + embeddings)
  • Limite de output tokens: Configure max_tokens apropriado para cada caso de uso

Dimensao 3: Qualidade

Qualidade e a mais complexa das tres dimensoes porque nao tem uma metrica unica. E composta por:

Sub-metricas de qualidade

Sub-metricaO que medeComo medir
CorretudeA resposta e factualmente correta?Ground truth, LLM-judge
RelevanciaA resposta responde a pergunta?LLM-judge, RAGAS
CompletudeA resposta cobre todos os aspectos?LLM-judge com criterios
GroundednessA resposta e suportada pelo contexto RAG?RAGAS, Phoenix eval
SegurancaSem conteudo toxico ou prejudicial?Azure Content Safety

Score de qualidade composto

def calcular_quality_score(
    corretude: float,      # 0.0 a 1.0
    relevancia: float,
    groundedness: float,
    seguranca: float
) -> dict:
    """Score composto ponderado por importancia para o negocio."""
    pesos = {
        "corretude": 0.35,
        "relevancia": 0.30,
        "groundedness": 0.25,
        "seguranca": 0.10
    }
    
    score_final = (
        corretude * pesos["corretude"] +
        relevancia * pesos["relevancia"] +
        groundedness * pesos["groundedness"] +
        seguranca * pesos["seguranca"]
    )
    
    return {
        "score": round(score_final, 3),
        "nivel": "ALTO" if score_final >= 0.8 else "MEDIO" if score_final >= 0.6 else "BAIXO",
        "detalhes": {
            "corretude": corretude,
            "relevancia": relevancia,
            "groundedness": groundedness,
            "seguranca": seguranca
        }
    }

SLOs e alertas recomendados

✅ SLO baseline para agente RAG corporativo
— Latencia E2E P95 < 8s
— Custo medio por sessao < USD 0.05
— Score de qualidade medio > 0.75
— Taxa de erros tecnicos < 1%
Revise e ajuste esses valores depois de 2 semanas em producao.

Como isso se conecta

  • 12-01-01 Por que IA e diferente: Essas tres dimensoes sao o que o APM classico nao cobre
  • 12-03-02 Avaliacoes offline: Como medir qualidade de forma sistematica antes de producao
  • 12-03-04 Drift detection: Monitorar degradacao dessas metricas ao longo do tempo
  • 12-03-05 Desafio RAG: Aplica essas metricas em um cenario concreto

Fontes

  1. Microsoft Docs — Built-in evaluation metrics for Azure AI Foundry (2025)
  2. RAGAS Documentation — RAG evaluation metrics (2025)
  3. OpenAI — API Pricing (2025)