Observabilidade de LLMs em Produção: Do GPU à Qualidade da Resposta
Ouvir artigo
Voz do FernandoFernando · 20:49
Com tecnologia Amazon Polly + OmniVoice
Colocar um LLM em produção no SageMaker é a parte fácil. O difícil é saber, em tempo real, se ele está respondendo bem, consumindo GPU de forma eficiente e custando o que você planejou. Este artigo detalha a stack de observabilidade que eu construiria hoje para inferência LLM financeira-grade.
Quando um LLM entra em produção num ambiente financeiro — seja para geração de relatórios regulatórios, triagem de documentos ou assistência a analistas — a pergunta que o time de plataforma precisa responder não é 'o endpoint está up?', mas sim: 'a resposta gerada é confiável, está dentro do SLA de latência, o custo por token está dentro do orçamento e o modelo não está alucinando sobre dados de clientes?' Essas quatro dimensões — disponibilidade, latência, custo e qualidade semântica — exigem instrumentação em camadas que vai muito além do CloudWatch básico. Este artigo é um conjunto de notas de campo sobre como eu monto essa stack hoje.
O Problema Real: Três Camadas de Cegueira Operacional
A maioria dos times que implanta LLMs no SageMaker começa com o mesmo conjunto de métricas que usaria para qualquer endpoint de ML: Invocations, ModelLatency, OverheadLatency e Invocation4XXErrors. Isso é necessário, mas completamente insuficiente para inferência de linguagem.
A primeira camada de cegueira é a infraestrutura de GPU. Um endpoint ml.g5.12xlarge com 4xA10G pode estar com GPUUtilization em 40% enquanto o GPUMemoryUtilization está em 95% — o modelo está thrashing na VRAM, causando latência de P99 de 8s enquanto o P50 parece saudável em 1.2s. Sem separar essas duas métricas por instância e por modelo carregado, você vai escalar horizontalmente quando o problema é vertical (batch size, quantização, tensor parallelism).
A segunda camada é a semântica de tokens. ModelLatency mede do request ao response, mas não distingue Time to First Token (TTFT) de Inter-Token Latency (ITL). Para um usuário interagindo com um chat financeiro, TTFT de 3s é inaceitável mesmo que o throughput total seja alto. O LMI (Large Model Inference) container do SageMaker expõe TimeToFirstByte via CloudWatch, mas só se você configurar OPTION_OUTPUT_FORMATTER=jsonlines e instrumentar o cliente para registrar o timestamp do primeiro chunk.
A terceira camada — e a mais negligenciada — é a qualidade semântica. O modelo pode estar respondendo rápido, com GPU eficiente, e ainda assim produzindo respostas com hallucinations, recusas excessivas ou drift de tom que viola políticas de compliance. Isso só é detectável com avaliação assíncrona pós-geração.
Pipeline de Observabilidade LLM: Do GPU à Qualidade Semântica
Fluxo de dados de observabilidade para inferência LLM no SageMaker, cobrindo métricas de infraestrutura, tokens e qualidade semântica
- API Gateway · WAF + Auth
- SageMaker Endpoint · ml.g5.12xlarge LMI
- GPU Metrics · Util / VRAM / TTFT
- CloudWatch · Metrics + Logs Insights
- Kinesis Firehose · log streaming
- S3 · raw inference logs
- OTEL Collector · sidecar / Lambda
- Lambda Evaluator · async quality scorer
- Bedrock Claude · LLM-as-judge
- DynamoDB · quality scores + trace
- Grafana · Unified Dashboard
- SNS + PagerDuty · SLO breach alerts
Instrumentando o SageMaker LMI para Métricas de Token
O container LMI do SageMaker (baseado em DJL Serving) expõe métricas de token via o endpoint /metrics do servidor interno, mas elas não chegam automaticamente ao CloudWatch. A abordagem que funciona em produção é um sidecar OTEL Collector rodando no mesmo task definition (para SageMaker Multi-Container) ou como um Lambda invocado assincronamente pelo próprio endpoint via destino de invocação.
As métricas críticas a capturar são:
ttft_ms(Time to First Token): P50/P95/P99 por modelo e porrequest_typeitl_ms(Inter-Token Latency): distribuição — alta variância aqui indica contenção de GPUtokens_per_second: throughput real de geração, não confundir com invocações por segundoprompt_tokensecompletion_tokens: essenciais para custo e para detectar prompt injection que infla o contextocache_hit_rate: se você usa KV-cache com prefix caching (disponível no TGI e vLLM backends do LMI)
Para publicar essas métricas no CloudWatch com dimensões corretas, use put_metric_data com namespace LLMInference/SageMaker e dimensões ModelName, EndpointName e InstanceType. O custo de métricas customizadas no CloudWatch é $0.30/métrica/mês — com 6 métricas × 3 dimensões × 2 endpoints, estamos falando de ~$10/mês, completamente justificável.
Um detalhe crítico: configure SAGEMAKER_CONTAINER_LOG_LEVEL=20 (INFO) no endpoint e ative DataCaptureConfig com SamplingPercentage=100 para ambientes de staging e SamplingPercentage=10 para produção com alto volume. Capturar 100% em produção com modelos grandes pode gerar custos de S3 e Firehose significativos.
Playbook: Montando a Stack de Observabilidade LLM em 7 Passos
- 1
1. Baseline de infraestrutura GPU
Ative o CloudWatch Container Insights para SageMaker. Configure alertas em
GPUMemoryUtilization > 85%(não em GPUUtilization) como sinal primário de pressão de memória. Crie um dashboard separando P50 e P99 de ModelLatency — se a diferença for maior que 5x, há contenção. - 2
2. Instrumentar TTFT no cliente
Use streaming response (
stream=Trueno boto3invoke_endpoint_with_response_stream). Registretime.time()antes do invoke e no recebimento do primeiro chunk. Publique como métrica customizadaTTFT_mscom dimensãomodel_id. SLA recomendado para chat financeiro: P95 < 1500ms. - 3
3. Pipeline de log de inferência para S3
Configure
DataCaptureConfigno endpoint comS3OutputPathapontando para bucket com SSE-KMS (chave gerenciada pelo cliente). Ative lifecycle policy: 90 dias em S3 Standard, depois Glacier Instant Retrieval. Isso satisfaz requisitos de auditoria de 7 anos sem custo linear. - 4
4. Avaliador assíncrono de qualidade
Crie um Lambda com trigger em S3 (prefixo do DataCapture). O Lambda lê o par prompt/resposta, chama Bedrock Claude 3 Haiku (mais barato, suficiente para scoring) com um rubric de avaliação (factualidade, recusa indevida, tom). Armazene o score em DynamoDB com TTL de 180 dias. Custo estimado: $0.25 por 1000 avaliações com Haiku.
- 5
5. Dashboard unificado no Grafana
Use Amazon Managed Grafana com data sources CloudWatch (métricas de infra e token) e DynamoDB (via Lambda datasource ou AWS Data API). Organize em três rows: Infrastructure (GPU, latência), Token Economics (tokens/s, custo/request, cache hit rate) e Quality (scores de factualidade, taxa de recusa, drift semanal).
- 6
6. SLOs e alertas de SLO burn rate
Defina SLOs no CloudWatch com
ServiceLevelObjective: TTFT P95 < 1500ms, availability > 99.5%, quality score > 0.75 (escala 0-1). Configure alertas de burn rate: 14x em 1h (critical) e 6x em 6h (warning). Roteie via SNS → PagerDuty com runbook link no alerta. - 7
7. Rastreabilidade de custo por caso de uso
Adicione tag
use_caseno header de cada invocação (via API Gateway context) e propague para os logs de DataCapture. Use Cost Explorer com taguse_casepara separar custo de instância GPU por produto. Isso é mandatório em ambientes financeiros onde cada linha de negócio precisa de chargeback.
KV-Cache e Prefix Caching: O Multiplicador de Eficiência Mais Subestimado
Se você tem um system prompt fixo ou semi-fixo (ex: instruções de compliance, contexto do produto), ative prefix caching no backend vLLM do LMI. Em testes com prompts de 512 tokens de prefixo fixo, a redução de TTFT chega a 60-70% e o custo de GPU cai proporcionalmente. Monitore cache_hit_rate como KPI primário de eficiência — se estiver abaixo de 40% com prompts repetitivos, revise a estratégia de construção de contexto.
LLM-as-Judge em Escala: Armadilhas e Calibração
O padrão de usar um LLM para avaliar outro LLM (LLM-as-judge) é poderoso, mas tem falhas específicas que eu já vi causar falsos positivos de qualidade em produção financeira.
O primeiro problema é o viés de posição: modelos como Claude tendem a avaliar melhor respostas mais longas, independentemente da precisão. Para mitigar, use rubricas estruturadas com scoring por dimensão (factualidade: 1-5, completude: 1-5, tom: 1-5) em vez de um score único. Inclua exemplos few-shot no prompt do juiz com casos de respostas curtas e corretas que devem pontuar alto.
O segundo problema é o custo de avaliação em escala. Avaliar 100% das inferências com Claude 3 Sonnet é proibitivo — para um endpoint processando 10.000 requests/dia com resposta média de 300 tokens, o custo seria ~$180/dia só em avaliação. A estratégia correta é amostragem estratificada: 100% de amostras com score de confiança baixo (detectado por entropia do logit, se disponível), 10% aleatório do restante, e 100% de qualquer request que acionou um guardrail.
O terceiro problema é drift do juiz: o modelo juiz também pode mudar com atualizações de versão do Bedrock. Use model versioning explícito (anthropic.claude-3-haiku-20240307-v1:0) e nunca claude-3-haiku sem versão em produção. Mantenha um golden dataset de 200 pares prompt/resposta com scores humanos para recalibrar o juiz mensalmente — isso é equivalente ao teste de regressão de um sistema de ML clássico.
Para ambientes com requisitos de soberania de dados (LGPD, regulação bancária brasileira), o pipeline de avaliação deve garantir que dados de clientes não saiam do boundary de VPC. Use Bedrock via VPC endpoint (com.amazonaws.region.bedrock-runtime) e nunca roteie logs de inferência por redes públicas.
Benchmarks de Referência para LLM Inference Observability
Segurança e Governança no Pipeline de Observabilidade
O pipeline de observabilidade de LLM é, paradoxalmente, uma superfície de ataque. Os logs de DataCapture contêm prompts e respostas completas — em contexto financeiro, isso pode incluir dados de clientes, números de conta, análises de portfólio. Tratar esse pipeline com menos rigor do que o endpoint em si é um erro grave.
As camadas de controle que implemento obrigatoriamente:
Criptografia em trânsito e em repouso: O bucket S3 de DataCapture deve ter SSE-KMS com chave CMK separada do endpoint. A política da chave deve permitir decrypt apenas para a role do Lambda avaliador e para a role de auditoria — não para a role do endpoint em si (princípio de separação de duties).
Mascaramento de PII antes da avaliação: O Lambda avaliador deve passar o texto por Amazon Comprehend detect_pii_entities antes de enviar para o Bedrock judge. Substitua entidades PII por placeholders ([ACCOUNT_NUMBER], [CPF]) no payload de avaliação. Isso garante que dados sensíveis não entrem no contexto do modelo avaliador.
IAM com condições de contexto: A role do Lambda avaliador deve ter bedrock:InvokeModel com condição aws:SourceVpc restrita ao VPC do pipeline. Adicione aws:RequestedRegion para garantir que invocações só ocorram na região primária — relevante para compliance com BACEN e LGPD que exigem processamento em território nacional.
Auditoria de acesso aos logs: Configure CloudTrail com S3 data events no bucket de DataCapture. Qualquer acesso ao bucket deve gerar evento auditável. Em ambientes com SOC 2 ou ISO 27001, isso é requisito de controle, não opcional.
Um detalhe que frequentemente é esquecido: o endpoint SageMaker em si deve ter KmsKeyId configurado no ProductionVariant para criptografar o volume EBS da instância. Sem isso, os pesos do modelo e o KV-cache ficam em disco não criptografado.
Anti-Padrões Comuns em Observabilidade de LLM
- Usar apenas ModelLatency como proxy de saúde: ModelLatency mede o tempo total de inferência, não a experiência do usuário. TTFT pode estar 3x acima do SLA enquanto ModelLatency parece normal em P50.
- Avaliar qualidade 100% em produção com modelos grandes: Usar Claude 3 Sonnet para avaliar cada resposta em produção de alto volume custa mais do que o endpoint principal. Use Haiku com amostragem estratificada.
- Não versionar o modelo juiz: Atualizar o modelo de avaliação sem um golden dataset de referência invalida séries históricas de qualidade. Scores de semanas diferentes se tornam incomparáveis.
- DataCapture sem lifecycle policy: Logs de inferência crescem linearmente. Sem lifecycle para Glacier após 90 dias, o custo de S3 pode superar o custo de GPU em 6 meses.
- Escalar horizontalmente antes de otimizar o batch: Adicionar instâncias quando
GPUMemoryUtilization > 85%sem primeiro testarMaxConcurrentRequestseMaxBatchSizeno LMI. Muitas vezes, dobrar o batch size resolve o problema sem custo adicional. - Logs de inferência sem mascaramento de PII: Enviar prompts brutos para o avaliador externo sem passar por Comprehend. Em contexto financeiro, isso é uma violação de LGPD e possivelmente de regulação bancária.
Perguntas Frequentes
Devo usar SageMaker ou Bedrock para inferência LLM em produção financeira?
Depende do controle necessário. Bedrock oferece observabilidade nativa menor (sem acesso a métricas de GPU, sem TTFT granular) mas simplifica compliance com modelos aprovados. SageMaker dá controle total sobre o stack de inferência, quantização, KV-cache e métricas — essencial se você tem SLAs de latência agressivos ou modelos customizados. Para modelos foundation sem fine-tuning, Bedrock com Guardrails é o ponto de partida. Para modelos fine-tuned ou com requisitos de latência P95 < 1s, SageMaker com LMI.
Como detectar prompt injection via observabilidade?
Monitore prompt_tokens por request. Prompt injection que tenta injetar contexto adicional geralmente causa picos anômalos no tamanho do prompt. Configure alarme em prompt_tokens > P99 + 3σ como sinal de anomalia. Combine com Bedrock Guardrails (se usando Bedrock) ou com um classificador leve de pré-processamento no Lambda de entrada para SageMaker.
Qual a diferença entre observabilidade de LLM e MLOps tradicional?
MLOps tradicional monitora drift de features e acurácia de predição — métricas determinísticas. LLM observability adiciona três dimensões não-determinísticas: qualidade semântica (que requer avaliação por outro modelo), latência de token (TTFT/ITL, não apenas latência total) e custo por token (que varia com o tamanho do contexto). O modelo de dados de observabilidade é fundamentalmente diferente: você precisa armazenar pares prompt/resposta, não apenas features numéricas.
Como calcular o custo real por request em SageMaker?
Custo por request = (custo/hora da instância) / (requests/hora). Para um ml.g5.12xlarge a ~$5.67/hora processando 3600 requests/hora (1 req/s), o custo é ~$0.0016/request. Mas isso ignora utilização real. A métrica correta é: custo por token gerado = (custo/hora) / (tokens_per_second × 3600). Monitore tokens_per_second como KPI de eficiência e calcule o custo/token em tempo real no dashboard.
Operacionalizando SLOs de Qualidade: O Que Ninguém Te Conta
Definir um SLO de qualidade para LLM é conceitualmente simples — 'quality score > 0.75 em 95% das respostas' — mas operacionalizar isso em CloudWatch com burn rate alerts exige uma arquitetura de dados específica.
O problema é que quality scores são produzidos assincronamente (pelo Lambda avaliador, segundos ou minutos após a resposta original), enquanto SLOs de latência são síncronos. Para unificar no mesmo framework de SLO, você precisa de uma janela de avaliação diferida: o SLO de qualidade opera sobre uma janela de 1 hora com delay de 5 minutos (tempo de avaliação), não em tempo real.
A implementação prática usa DynamoDB Streams: quando o Lambda avaliador escreve o score no DynamoDB, o stream aciona outro Lambda que publica a métrica QualityScore no CloudWatch com timestamp retroativo (usando put_metric_data com Timestamp explícito, não o tempo atual). Isso permite que o CloudWatch SLO calcule o burn rate corretamente sobre a janela histórica.
Um aspecto crítico para ambientes financeiros: o SLO de qualidade deve ter thresholds diferenciados por tipo de request. Uma pergunta sobre saldo de conta tem threshold de factualidade diferente de uma pergunta sobre estratégia de investimento. Use a dimensão request_type no CloudWatch para criar SLOs separados por categoria — isso é mais trabalhoso para configurar mas evita que respostas de baixo risco diluam o sinal de qualidade em requests de alto risco.
Por fim, documente o SLO de qualidade como um ADR (Architecture Decision Record) com a justificativa do threshold escolhido, o modelo juiz utilizado, o golden dataset de calibração e o processo de revisão trimestral. Em auditorias de compliance, a capacidade de demonstrar que você tem um processo formal de avaliação de qualidade de IA é tão importante quanto os números em si.
Lentes do Well-Architected Framework
Segurança
SSE-KMS com CMK separado para DataCapture, IAM com condições de VPC e região, mascaramento de PII via Comprehend antes de qualquer avaliação externa, CloudTrail com S3 data events no bucket de logs.
Confiabilidade
SLOs com burn rate alerts em três dimensões (disponibilidade, latência, qualidade), DataCapture com retry automático, Lambda avaliador com DLQ para garantir que nenhum par prompt/resposta seja perdido na avaliação.
Eficiência de performance
Prefix caching para redução de TTFT, monitoramento de P99/P50 como sinal de contenção, otimização de batch size antes de escalonamento horizontal, cache_hit_rate como KPI primário de eficiência.
Na prática, o maior gap que vejo em times implantando LLMs em produção financeira não é falta de métricas — é falta de propriedade clara sobre o que 'qualidade' significa para aquele caso de uso específico. Antes de montar qualquer pipeline de avaliação, eu forço uma sessão com o product owner e o time de compliance para definir o rubric de avaliação em linguagem natural, com exemplos concretos de respostas boas e ruins. Sem isso, você vai construir um avaliador tecnicamente impecável que mede a coisa errada. A lição mais dura que aprendi: um LLM com quality score de 0.85 que responde perguntas erradas com confiança é mais perigoso do que um com score de 0.65 que recusa quando não sabe.
Veredicto: Observabilidade de LLM Não É Opcional em Produção Financeira
A stack descrita aqui — métricas de GPU + TTFT/ITL via OTEL, DataCapture para S3 com SSE-KMS, avaliação assíncrona com LLM-as-judge amostrado, SLOs em três dimensões no CloudWatch e dashboard unificado no Grafana — é o mínimo viável para operar um LLM em produção financeira com responsabilidade. O custo incremental dessa instrumentação é marginal comparado ao custo da instância GPU: estimativa de $50-150/mês para um endpoint de médio porte. O custo de não ter isso — uma resposta incorreta sobre dados de cliente que passa despercebida por semanas — é incalculável. Implante o playbook em staging primeiro, calibre o modelo juiz com um golden dataset humano, e só então leve para produção. Não pule a etapa de calibração.
Referências
Deep dives de arquitetura, AWS, IA e mercado — direto no seu email. Grátis.
Sem spam · cancele quando quiser
Pergunte ao Fernando sobre isto
Receba uma resposta focada sobre este artigo do meu assistente de IA, baseada no meu trabalho.
Participe da conversa
Entre para comentar
Confirme seu e-mail para participar — você também recebe a newsletter. Sem senha.
Continue lendo
Inteligência de arquitetura, na sua caixa de entrada
Sinais curados e análises originais sobre AWS, IA, sistemas distribuídos e mercado — do jeito que um arquiteto de soluções lê.
- Curadoria de AWS · IA · arquitetura · mercado
- Novos estudos de arquitetura e deep-dives quando saem
- Sínteses diretas — profundidade sem ruído
- Sem spam · double opt-in · cancele quando quiser