# Design Doc: Observabilidade de LLMs — da GPU à Qualidade de Resposta

Este documento propõe uma arquitetura de observabilidade fim a fim para plataformas de inferência LLM rodando em Amazon SageMaker AI e Amazon Bedrock, cobrindo desde métricas de hardware (GPU utilization, memória) até qualidade semântica de resposta, drift de comportamento e custo por tenant. O design integra CloudWatch, Amazon Managed Grafana, rastreamento por prompt e alarmes de regressão automáticos, com separação clara de responsabilidades entre camadas de coleta, armazenamento, avaliação e alerta.

- URL: https://fernando.moretes.com/studies/design-doc-llm-observability-quality-cost-sagemaker-bedrock

- Markdown: https://fernando.moretes.com/studies/design-doc-llm-observability-quality-cost-sagemaker-bedrock/study.md?lang=pt

- Type: Design Doc / RFC

- Company: LLM operations platform (cenário)

- Domain: Observabilidade / IA

- Date: 2026-06-06

- Tags: llm-observability, sagemaker, bedrock, cloudwatch, grafana, mlops, gpu-metrics, eval-driven-ops

- Reading time: 13 min

---

Operar LLMs em produção sem observabilidade estruturada é voar às cegas: você não sabe se o modelo está degradando, se um tenant está monopolizando GPU, ou se a qualidade das respostas caiu silenciosamente depois de um hot-patch. Este documento especifica a arquitetura completa de observabilidade para uma plataforma multi-tenant de inferência LLM sobre SageMaker AI e Bedrock — da telemetria de hardware ao eval score semântico, com rastreamento por prompt, alarmes de regressão e custo atribuível por cliente.

## O Problema: Lacunas de Visibilidade em Inferência LLM

Plataformas de inferência LLM introduzem uma classe de problemas de observabilidade que as ferramentas tradicionais de APM não foram projetadas para resolver. Em sistemas convencionais, latência alta e erro de aplicação são suficientes para diagnosticar a maioria dos incidentes. Em LLMs, você pode ter latência aceitável, zero erros HTTP e ainda assim estar entregando respostas semanticamente incorretas, truncadas ou com alucinações crescentes — e nenhum alarme vai disparar.

O cenário que este documento endereça é uma plataforma multi-tenant onde múltiplos clientes consomem endpoints de inferência provisionados no SageMaker AI (modelos proprietários fine-tuned) e no Amazon Bedrock (modelos fundacionais via API gerenciada). Cada tenant tem SLAs distintos, volumes de token distintos e tolerâncias de custo distintas. As lacunas de visibilidade identificadas são:

**1. Camada de hardware desconectada da camada de aplicação.** Métricas de GPU (utilization, memória HBM, temperatura) existem no CloudWatch via `/aws/sagemaker/Endpoints`, mas não são correlacionadas automaticamente com latência de inferência ou qualidade de saída. Um pico de GPU utilization a 98% pode significar throughput ótimo ou pode ser o sinal precursor de um OOM que vai derrubar o endpoint.

**2. Ausência de rastreamento por prompt.** Requests de inferência LLM não são idempotentes nem uniformes: um prompt de 4.000 tokens tem perfil de latência e custo radicalmente diferente de um de 200 tokens. Sem trace ID propagado do cliente até o endpoint, é impossível correlacionar uma reclamação de qualidade de um tenant específico com o request real que a causou.

**3. Qualidade de resposta não é uma métrica nativa.** Nenhum serviço AWS emite automaticamente uma métrica de qualidade semântica. Eval scores (RAGAS, G-Eval, BERTScore ou avaliadores LLM-as-judge) precisam ser calculados assincronamente e injetados no pipeline de métricas como métricas customizadas. Sem isso, degradação de qualidade só é detectada via ticket de suporte — tarde demais.

**4. Custo por tenant é invisível no modelo padrão.** Bedrock cobra por token; SageMaker cobra por hora de instância. Em um ambiente multi-tenant, a alocação de custo por cliente requer instrumentação explícita: contagem de tokens de entrada/saída por tenant, mapeamento para SKU de instância e agregação temporal. Sem isso, o produto não consegue precificar corretamente nem identificar tenants que estão consumindo recursos desproporcionais.

## Objetivos e Não-Objetivos

- ✅ OBJETIVO: Coletar e correlacionar métricas de GPU (utilization, memória, temperatura) com métricas de inferência (tokens/s, latência p50/p99, tamanho de batch) em tempo real.
- ✅ OBJETIVO: Implementar rastreamento distribuído por prompt com trace ID propagado do cliente ao endpoint, armazenado no AWS X-Ray e correlacionado com logs de inferência.
- ✅ OBJETIVO: Calcular e emitir eval scores de qualidade (LLM-as-judge + métricas de referência) de forma assíncrona para cada request amostrado, injetando-os como métricas customizadas no CloudWatch.
- ✅ OBJETIVO: Calcular custo por tenant por período (diário/mensal) com granularidade de tokens de entrada e saída, separando custos de SageMaker e Bedrock.
- ✅ OBJETIVO: Detectar drift de comportamento do modelo via monitoramento de distribuição de eval scores ao longo do tempo, com alarmes automáticos de regressão.
- ✅ OBJETIVO: Disponibilizar dashboards operacionais no Amazon Managed Grafana com visões por tenant, por endpoint e por modelo.

## Ficha Técnica do Cenário

- **Plataforma:** LLM Operations Platform (cenário composto)
- **Serviços de inferência:** Amazon SageMaker AI (endpoints dedicados) + Amazon Bedrock (API gerenciada)
- **Escala estimada:** ~50 tenants ativos, ~2M requests/dia, ~8B tokens/dia (estimativa)
- **Instâncias SageMaker:** ml.g5.12xlarge e ml.p4d.24xlarge com multi-model endpoints
- **Modelos:** Llama 3 fine-tuned (SageMaker) + Claude 3.5 Sonnet / Titan (Bedrock)
- **Stack de observabilidade:** CloudWatch Metrics + Logs + X-Ray, Amazon Managed Grafana, Lambda (eval async), Kinesis Data Streams, DynamoDB (custo/tenant)
- **SLA de latência alvo:** p50 < 800ms, p99 < 4s (first token); throughput > 50 tokens/s por endpoint
- **Retenção de dados de observabilidade:** Métricas: 15 meses (CloudWatch); Logs: 90 dias hot, 2 anos S3 Glacier IR; Traces: 30 dias (X-Ray)

## Design Proposto: Arquitetura em Quatro Camadas

A arquitetura de observabilidade é organizada em quatro camadas com responsabilidades distintas e interfaces bem definidas entre elas. O princípio central é separar coleta de armazenamento, armazenamento de avaliação e avaliação de alerta — cada camada pode evoluir independentemente.

### Camada 1 — Instrumentação e Coleta

Todo request de inferência passa por um **Inference Proxy** (Lambda ou ECS Fargate), que é o ponto de entrada único para ambos os backends (SageMaker e Bedrock). O proxy tem três responsabilidades de observabilidade:

- **Geração de trace ID**: cada request recebe um `x-trace-id` UUID v4 que é propagado como header HTTP para o endpoint downstream e como atributo de segmento no X-Ray. O trace ID é também injetado no payload de log estruturado (JSON) emitido para o CloudWatch Logs.
- **Contagem de tokens**: antes de despachar o request, o proxy tokeniza o prompt com o tokenizador correspondente ao modelo (via biblioteca `tiktoken` ou `transformers`) e registra `input_token_count` como métrica customizada no CloudWatch com dimensões `tenant_id`, `model_id` e `endpoint_type`. A contagem de tokens de saída é registrada na resposta.
- **Captura de latência**: o proxy mede `time_to_first_token` (TTFT) e `total_latency` com precisão de milissegundos e os emite como métricas CloudWatch com resolução de 1 segundo (high-resolution metrics).

Para endpoints SageMaker, métricas nativas de GPU (`GPUUtilization`, `GPUMemoryUtilization`, `DiskUtilization`) já são emitidas automaticamente para o namespace `/aws/sagemaker/Endpoints`. Para Bedrock, métricas de invocação (`InvocationLatency`, `InputTokenCount`, `OutputTokenCount`) são emitidas para `/aws/bedrock/modelinvocations`. Ambas as fontes são consumidas diretamente pelo Grafana via CloudWatch data source.

### Camada 2 — Pipeline de Avaliação Assíncrona

Qualidade de resposta não pode ser avaliada no caminho crítico sem impactar latência. O design usa amostragem: **100% dos requests têm metadados capturados** (prompt hash, tenant, modelo, tokens, latência), mas apenas uma fração configurável (padrão: 5% por tenant, ajustável por SLA) passa pelo pipeline de eval completo.

O proxy publica um evento para um **Kinesis Data Stream** (`llm-eval-stream`) contendo: `trace_id`, `tenant_id`, `model_id`, `prompt` (truncado a 2.000 chars para controle de custo), `completion`, `timestamp` e metadados de contexto (ex: RAG chunks se aplicável). Uma função Lambda consumidora (`eval-worker`) processa esses eventos em micro-batches e executa:

1. **LLM-as-judge**: invoca um modelo avaliador no Bedrock (Claude 3 Haiku por custo) com um prompt de rubrica estruturado que retorna scores de 1-5 para relevância, coerência, fidelidade factual e ausência de alucinação.
2. **Métricas de referência** (quando ground truth disponível): BERTScore F1 para similaridade semântica.
3. **Emissão de métricas customizadas**: os scores são emitidos para CloudWatch no namespace `LLMPlatform/EvalScores` com dimensões `tenant_id`, `model_id` e `eval_dimension`.

Os resultados completos de eval são armazenados em **DynamoDB** (tabela `eval-results`, TTL de 90 dias) para consulta ad-hoc e em **S3** (formato Parquet, particionado por `date/tenant/model`) para análise histórica e treinamento de avaliadores.

### Camada 3 — Custo por Tenant

Uma função Lambda agendada (`cost-aggregator`, execução horária) lê as métricas customizadas de token count do CloudWatch via `GetMetricData` e aplica a tabela de preços vigente (Bedrock: preço por token por modelo; SageMaker: preço por hora de instância dividido pelo número de tenants ativos no período via peso de tokens). O resultado é escrito no DynamoDB (tabela `tenant-cost`, chave `tenant_id#date`) e exposto via API Gateway para o sistema de billing.

### Camada 4 — Alertas e Dashboards

Alarmes CloudWatch cobrem três categorias: (a) **infraestrutura**: GPU utilization > 90% por 5 minutos, latência p99 > threshold por tenant; (b) **qualidade**: eval score médio por tenant caindo mais de 15% em relação à baseline rolling de 7 dias; (c) **custo**: consumo de tokens de um tenant ultrapassando 120% do budget diário configurado. Alarmes de regressão de qualidade usam **CloudWatch Anomaly Detection** com banda de 2 desvios padrão sobre a série histórica de eval scores.

O Amazon Managed Grafana consome CloudWatch como data source principal e X-Ray para visualização de traces. Dashboards são organizados em três camadas: visão executiva (custo e qualidade por tenant), visão operacional (GPU, latência, throughput por endpoint) e visão de debug (trace individual por `trace_id`).

## Arquitetura de Observabilidade LLM — Fluxo Completo

O diagrama mostra o fluxo de dados de observabilidade desde o request do cliente até os dashboards e alarmes, cobrindo as quatro camadas: coleta, avaliação assíncrona, custo e alertas.

### 👤 Clients / Tenants

- Tenant Client SDK / REST (user)

### 🔀 Inference Proxy Layer

- Inference Proxy Lambda / ECS Fargate (compute)
- AWS X-Ray Trace ID propagation (security)

### 🤖 Inference Backends

- SageMaker AI ml.g5 / ml.p4d endpoints (ai)
- Amazon Bedrock Claude / Titan / Llama (ai)

### 📊 Metrics & Logs Collection

- CloudWatch Metrics GPU / latency / tokens high-res 1s (data)
- CloudWatch Logs Structured JSON trace_id + tenant_id (storage)

### ⚡ Async Eval Pipeline

- Kinesis Data Stream llm-eval-stream 5% sample (messaging)
- eval-worker Lambda LLM-as-judge BERTScore (compute)
- Bedrock Evaluator Claude 3 Haiku rubric scoring (ai)
- DynamoDB eval-results TTL 90d (storage)
- S3 Parquet date/tenant/model historical (storage)

### 💰 Cost Attribution

- cost-aggregator Lambda (hourly) GetMetricData (compute)
- DynamoDB tenant-cost tenant_id#date (storage)
- API Gateway billing endpoint (edge)

### 🔔 Alerting & Dashboards

- CloudWatch Alarms GPU / quality / cost Anomaly Detection (data)
- SNS PagerDuty / Slack routing by severity (messaging)
- Amazon Managed Grafana exec / ops / debug dashboards (frontend)

### Fluxos

- tenant -> proxy: request + tenant header
- proxy -> xray: trace segment
- proxy -> sagemaker: inferência dedicada
- proxy -> bedrock: inferência gerenciada
- proxy -> cw_metrics: tokens, TTFT, latência
- proxy -> cw_logs: log JSON estruturado
- proxy -> kinesis: 5% amostra eval
- sagemaker -> cw_metrics: GPU / mem nativo
- bedrock -> cw_metrics: invocation metrics
- kinesis -> eval_lambda: micro-batch
- eval_lambda -> bedrock_eval: rubric prompt
- eval_lambda -> cw_metrics: eval scores custom
- eval_lambda -> eval_dynamo: resultado completo
- eval_lambda -> eval_s3: Parquet histórico
- cw_metrics -> cost_lambda: GetMetricData tokens
- cost_lambda -> cost_dynamo: custo agregado
- cost_dynamo -> billing_api: leitura billing
- cw_metrics -> cw_alarms: threshold / anomaly
- cw_alarms -> sns: alarm state change
- cw_metrics -> grafana: data source
- xray -> grafana: trace visualization
- eval_dynamo -> grafana: eval scores query

## Alternativas de Design Avaliadas

### Opção A (escolhida): CloudWatch + Grafana Gerenciado + Kinesis Eval

**Pros**
- Integração nativa com SageMaker e Bedrock — zero instrumentação adicional para métricas de GPU e invocação
- Amazon Managed Grafana elimina overhead operacional de cluster Grafana auto-hospedado
- Kinesis Data Streams oferece replay e reprocessamento de eventos de eval sem perda
- CloudWatch Anomaly Detection nativo para alarmes de regressão sem modelo externo

**Cons**
- CloudWatch GetMetricData tem custo por API call — agregação de custo horária precisa ser otimizada para evitar bill surprise
- Latência de eval assíncrono (minutos) significa que alarmes de qualidade não são em tempo real

**Verdict:** Melhor equilíbrio entre integração nativa, custo operacional e maturidade para o cenário descrito

### Opção B: OpenTelemetry + Prometheus + Grafana OSS auto-hospedado

**Pros**
- Stack completamente open-source, sem lock-in de vendor para a camada de observabilidade
- OpenTelemetry oferece instrumentação padronizada e portável entre clouds

**Cons**
- Prometheus não foi projetado para métricas de alta cardinalidade (tenant_id × model_id × eval_dimension) — risco de cardinality explosion
- Overhead operacional significativo: cluster Prometheus HA, Thanos ou Cortex para retenção longa, Grafana cluster com HA
- Integração com métricas nativas de SageMaker/Bedrock requer exporters customizados

**Verdict:** Válida para ambientes multi-cloud ou com requisito de zero lock-in, mas custo operacional elevado para time pequeno

### Opção C: Datadog LLM Observability (produto dedicado)

**Pros**
- Produto dedicado para LLM observability com LLM-as-judge integrado, rastreamento de prompts e dashboards pré-construídos
- Time-to-value mais rápido para equipes sem experiência em construir pipelines de eval

**Cons**
- Custo por host/span pode ser proibitivo em escala de 2M requests/dia — estimativa de custo 3-5x maior que Opção A
- Vendor lock-in em ferramenta externa; dados de prompt/completion saem do perímetro AWS — risco de compliance para tenants regulados
- Custo por tenant não é nativo — requer customização similar à Opção A

**Verdict:** Adequada para prova de conceito ou times pequenos; não recomendada em produção com dados sensíveis ou escala alta

## Decisões de Design Críticas e Trade-offs

### Taxa de Amostragem do Pipeline de Eval

A decisão de amostrar 5% dos requests para eval completo é o trade-off mais importante deste design. Eval a 100% com LLM-as-judge é tecnicamente viável mas economicamente inviável: a 2M requests/dia usando Claude 3 Haiku como avaliador (estimativa de 500 tokens por avaliação), o custo adicional seria da ordem de $1.500-2.000/dia apenas em chamadas de eval — sem contar latência adicional se feito em sincrono. A 5%, o custo cai para ~$75-100/dia e a cobertura estatística é suficiente para detectar regressões de qualidade com confiança para volumes acima de 10.000 requests/dia por tenant.

A taxa de amostragem é configurável por tenant via parâmetro no Systems Manager Parameter Store (`/llm-platform/{tenant_id}/eval_sample_rate`), permitindo aumentar para 100% temporariamente durante investigações de incidente ou para tenants com SLA de qualidade premium.

### Granularidade de Métricas vs. Custo de CloudWatch

Métricas de alta resolução (1 segundo) no CloudWatch custam $0.30/métrica/mês, versus $0.10/métrica/mês para resolução padrão de 1 minuto. Para latência TTFT e throughput de tokens, a resolução de 1 segundo é necessária para detectar spikes de latência que se resolvem dentro de um minuto. Para métricas de custo e eval score, resolução de 1 minuto é suficiente. O design usa alta resolução seletivamente apenas para as métricas de latência críticas, reduzindo o custo de métricas em ~60% comparado a instrumentar tudo em alta resolução.

### Isolamento de Dados de Prompt por Tenant

Prompts de tenants regulados (financeiro, saúde) não devem ser enviados ao pipeline de eval se isso implicar transmissão para um modelo externo ou armazenamento não criptografado. O design resolve isso com duas medidas: (1) o pipeline de eval usa exclusivamente modelos Bedrock na mesma conta AWS, sem egress de dados; (2) prompts são truncados a 2.000 caracteres antes de entrar no Kinesis stream, e a tabela DynamoDB `eval-results` usa CMK (Customer Managed Key) via AWS KMS com chave por tenant. Tenants podem optar por desabilitar completamente o armazenamento de prompt via flag de configuração — nesse caso, apenas o hash do prompt é armazenado para correlação.

### Detecção de Drift vs. Alarmes de Threshold Fixo

Alarmes de threshold fixo para eval score (ex: "alerta se score < 3.0") são frágeis porque a distribuição de scores varia por domínio de aplicação e por modelo. Um modelo de sumarização pode ter score médio de 3.8; um modelo de geração de código pode ter score médio de 4.2. Um threshold único geraria falsos positivos em um e falsos negativos em outro. A solução é usar CloudWatch Anomaly Detection com modelo de ML treinado na série histórica de eval scores por `(tenant_id, model_id)`. O alarme dispara quando o score cai mais de 2 desvios padrão abaixo da banda esperada para aquele contexto específico — detectando regressão relativa, não absoluta.

## Plano de Rollout em Fases

1. **Fase 1 — Semanas 1-2: Fundação de Coleta** — Deploy do Inference Proxy (Lambda) com geração de trace ID, contagem de tokens e emissão de métricas customizadas para CloudWatch. Validação de que métricas nativas de GPU do SageMaker estão chegando corretamente. Configuração do X-Ray com sampling rate de 10% para todos os requests. Criação dos namespaces CloudWatch e dashboards básicos de latência e throughput no Grafana.

2. **Fase 2 — Semanas 3-4: Pipeline de Avaliação Assíncrona** — Deploy do Kinesis Data Stream `llm-eval-stream` e da função `eval-worker`. Implementação do LLM-as-judge com Claude 3 Haiku no Bedrock. Configuração de amostragem a 5% por padrão. Setup das tabelas DynamoDB `eval-results` com KMS CMK e bucket S3 para Parquet histórico. Validação de que eval scores estão chegando como métricas customizadas no CloudWatch.

3. **Fase 3 — Semanas 5-6: Custo por Tenant e Alertas** — Deploy da função `cost-aggregator` com lógica de precificação para SageMaker e Bedrock. Criação da tabela `tenant-cost` no DynamoDB e exposição via API Gateway. Configuração de alarmes CloudWatch para as três categorias (infra, qualidade, custo). Treinamento inicial dos modelos de Anomaly Detection (requer pelo menos 2 semanas de dados históricos de eval scores).

4. **Fase 4 — Semanas 7-8: Dashboards e Hardening** — Construção dos dashboards completos no Grafana (executivo, operacional, debug). Configuração de roteamento de alarmes via SNS para PagerDuty (severidade crítica) e Slack (severidade warning). Revisão de segurança: validação de isolamento de dados por tenant, teste de KMS key rotation, revisão de IAM policies do Inference Proxy. Load testing do pipeline de eval com 10x o volume esperado para validar que o Kinesis stream não se torna gargalo.

5. **Fase 5 — Semanas 9-10: Rollout Gradual por Tenant** — Ativação do pipeline completo para tenants piloto (2-3 tenants não-regulados de menor volume). Coleta de feedback operacional e ajuste de thresholds de alarme. Ativação progressiva para todos os tenants ao longo de 2 semanas, com monitoramento intensivo de custo do pipeline de observabilidade em si (meta: overhead de observabilidade < 3% do custo total de inferência).

> **Riscos Críticos e Mitigações:** **1. Cardinality explosion em métricas CloudWatch.** Com 50 tenants × 10 modelos × 8 dimensões de eval, o número de séries temporais únicas pode exceder 4.000. CloudWatch cobra por métrica única — a $0.30/métrica/mês em alta resolução, isso é $1.200/mês apenas em métricas de eval. Mitigação: usar dimensões compostas (`tenant_model_eval` como string concatenada) para reduzir cardinalidade, e revisar mensalmente o custo de métricas via Cost Explorer com tag `observability-layer`.

**2. O avaliador LLM pode se tornar o gargalo.** Se o `eval-worker` não conseguir processar o Kinesis stream na mesma velocidade que os eventos chegam, o lag cresce e os alarmes de qualidade ficam obsoletos. Mitigação: configurar Enhanced Fan-Out no Kinesis, auto-scaling da Lambda baseado em `IteratorAge` (alarme se > 5 minutos), e circuit breaker que reduz a taxa de amostragem automaticamente se o lag exceder threshold.

**3. Drift de qualidade do próprio avaliador LLM.** Se a Anthropic atualizar o Claude 3 Haiku (o avaliador), os scores históricos podem se tornar incomparáveis com os novos scores — invalidando a baseline de Anomaly Detection. Mitigação: versionar o prompt de rubrica do avaliador, armazenar a versão do modelo avaliador junto com cada score no DynamoDB, e re-calcular a baseline quando o modelo avaliador mudar.

**4. Dados de prompt em logs de CloudWatch.** Se o Inference Proxy logar o payload completo de request/response para debug, dados de prompt de tenants regulados ficam no CloudWatch Logs sem o mesmo nível de controle do pipeline de eval. Mitigação: configurar log filtering no proxy para mascarar campos `prompt` e `completion` por padrão, com opt-in explícito por tenant para logging completo com retenção reduzida a 7 dias.

**5. Custo do pipeline de observabilidade excedendo o budget.** Em escala alta, o custo de Kinesis + Lambda + Bedrock eval + DynamoDB pode surpreender. Mitigação: implementar budget alert no AWS Budgets específico para a tag `observability-layer`, com alarme a 80% do budget mensal e ação automática de redução de sampling rate.

## Métricas de Sucesso e Targets

- **Cobertura de rastreamento:** 100% dos requests com trace ID propagado; X-Ray sampling ≥ 10% para análise de latência
- **Latência de alarme de qualidade:** Regressão de qualidade detectada em < 15 minutos após início da degradação (com 5% sampling)
- **Precisão de custo por tenant:** Custo atribuído com erro < 2% comparado a fatura real AWS (validado mensalmente)
- **Overhead de observabilidade:** Custo total do pipeline de observabilidade < 3% do custo total de inferência
- **Latência adicionada pelo proxy:** < 5ms de overhead de latência introduzido pelo Inference Proxy (p99)
- **Disponibilidade do pipeline de eval:** ≥ 99.5% (degradação graceful: falha no eval não impacta inferência)
- **Cobertura de dashboards:** 100% dos tenants com dashboard individual; MTTD de anomalia de GPU < 3 minutos

> **Minha Perspectiva Senior:** O erro mais comum que vejo em plataformas LLM em produção é tratar observabilidade como uma feature de segunda fase — "vamos instrumentar depois que estiver funcionando". Em LLMs, isso é especialmente perigoso porque degradação de qualidade é silenciosa: o sistema continua respondendo HTTP 200 enquanto entrega respostas progressivamente piores. Quando o cliente reclama, você não tem dados para diagnosticar quando começou, qual tenant foi afetado primeiro, ou se foi uma mudança de modelo, um pico de carga ou um prompt específico que desencadeou o problema.

A decisão mais importante neste design não é tecnológica — é a separação entre métricas de infraestrutura (GPU, latência) e métricas de qualidade semântica. São dois loops de feedback com velocidades diferentes: infra você monitora em segundos, qualidade você monitora em minutos com amostragem. Tentar fazer os dois com a mesma ferramenta e a mesma granularidade é o caminho para ou custo exorbitante ou cobertura insuficiente.

Sobre o LLM-as-judge: é uma solução pragmática, mas precisa ser tratada como um componente que tem seu próprio ciclo de vida e pode degradar. Eu versiono o prompt de rubrica como código, armazeno o hash do prompt avaliador junto com cada score, e tenho um processo de re-calibração trimestral onde comparo scores do avaliador automático com avaliação humana em uma amostra de 200-500 requests. Sem isso, você está medindo qualidade com uma régua que pode estar se encurtando.

Por fim: o custo do pipeline de observabilidade precisa ser um cidadão de primeira classe no budget do produto. Em escala, Kinesis + Lambda + Bedrock eval + CloudWatch high-res metrics somam valores não triviais. Eu sempre implemento o `observability-layer` como uma tag de billing separada e monitoro esse custo com a mesma disciplina que monitoro o custo de inferência. A meta de < 3% do custo de inferência é razoável e atingível com as otimizações descritas — mas requer atenção ativa, não é automático.

## Veredicto

Esta arquitetura resolve um problema real e frequentemente negligenciado: a lacuna entre saber que um LLM está respondendo e saber que ele está respondendo bem. O design é deliberadamente conservador em suas escolhas tecnológicas — CloudWatch, Kinesis, Lambda, Grafana gerenciado — porque em plataformas de inferência o risco operacional já é alto o suficiente sem adicionar complexidade desnecessária na camada de observabilidade.

Os trade-offs centrais são claros: amostragem de 5% para eval é o ponto de equilíbrio entre cobertura estatística e custo; CloudWatch Anomaly Detection é menos flexível que um modelo de drift customizado mas elimina uma dependência operacional significativa; o Inference Proxy como ponto único de instrumentação é um ponto de falha potencial que precisa ser tratado com redundância e circuit breakers.

O que este design não resolve — e que seria o próximo passo natural — é o loop de feedback entre observabilidade e melhoria do modelo: usar os dados de eval coletados para alimentar pipelines de fine-tuning ou RLHF. Isso está explicitamente fora do escopo aqui, mas a arquitetura foi desenhada para que os dados necessários (Parquet histórico no S3, scores por prompt no DynamoDB) estejam disponíveis quando esse loop precisar ser fechado.

## Referências

- [AWS Machine Learning Blog — LLM Inference Observability](https://aws.amazon.com/blogs/machine-learning/)
- [Amazon Managed Grafana — Product Page](https://aws.amazon.com/grafana/)
- [Amazon CloudWatch — Product Page](https://aws.amazon.com/cloudwatch/)
- [Amazon SageMaker AI — Monitor Endpoints with CloudWatch](https://docs.aws.amazon.com/sagemaker/latest/dg/monitoring-cloudwatch.html)
- [Amazon Bedrock — Model Invocation Logging](https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html)
- [AWS X-Ray — Distributed Tracing](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html)
- [CloudWatch Anomaly Detection](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Anomaly_Detection.html)
- [RAGAS — Retrieval Augmented Generation Assessment](https://github.com/explodinggradients/ragas)

## Fontes do caso

- [AWS AI Blog — LLM inference observability](https://aws.amazon.com/blogs/machine-learning/)
- [Amazon Managed Grafana](https://aws.amazon.com/grafana/)
- [Amazon CloudWatch](https://aws.amazon.com/cloudwatch/)
