Mlops modelos grandes

MLOps para Modelos Grandes

Versionamento de modelos, canary deployment, monitoring de drift, rate limiting, quota management. Atualizado em abril de 2026.


Visão Geral

Deployar um LLM em produção é diferente de deployar uma API tradicional. Os desafios específicos incluem:

  1. *odelos pesados*— 7B parâmetros = 14GB em FP16, 3.5GB em INT4
  2. *stado complexo*— KV cache, contexto, session state
  3. *usto variável*— cada request custa GPU time
  4. *ualidade subjetiva*— não há "erro 500" para resposta ruim
  5. *rift silencioso*— modelo não "quebra", só fica pior gradualmente

Este documento cobre como operar LLMs em produção de forma confiável e econômica.


1. Versionamento de Modelos

O que versionar

Artefato O que é Por quê
*eights* Arquivo .safetensors ou .pt O modelo em si
*onfig* config.json, tokenizer_config.json Hiperparâmetros, vocabulário
*okenizer* Arquivo do tokenizer Mesmo tokenizer = mesma tokenização
*heckpoint* Estado do treino (optimizer, scheduler) Para resume de treino
*dapter* LoRA/QLoRA weights Fine-tune específico
*rompt templates* Templates de sistema/instrução Mesmo prompt = mesmo comportamento
*val results* Resultados de avaliação Para comparação entre versões

Estrutura de versionamento

models/
── kode-coder/
│   ├── v0.1.0/              ← Versão base (Qwen2.5-Coder-32B)
│   │   ├── model/           ← Weights
│   │   ├── config.json
│   │   ├── tokenizer/
│   │   ├── eval/            ← Resultados de avaliação
│   │   │   ├── swe-bench.json
│   │   │   ├── human-eval.json
│   │   │   └── privado.json
│   │   └── metadata.json    ← Data, commit, notas
│   │
│   ├── v0.2.0/              ← Fine-tune SFT
│   │   ├── base: v0.1.0     ← Referência ao modelo base
│   │   ├── adapter/         ← LoRA weights
│   │   ├── config.json
│   │   ├── eval/
│   │   └── metadata.json
│   │
│   ├── v0.3.0/              ← Fine-tune SFT + DPO
│   │   ├── base: v0.2.0
│   │   ├── adapter/
│   │   ├── config.json
│   │   ├── eval/
│   │   ── metadata.json
│   │
│   ── current → v0.3.0     ← Symlink para versão ativa

Ferramentas de versionamento

Ferramenta Uso Prós
*VC* Versionamento de arquivos grandes Gitlike, opensource
*Lflow Models* Registry de modelos UI, experiment tracking
*eights & Biases Artifacts* Versionamento + lineage Integração com W&B
*uggingFace Hub* Host de modelos Comunidade, APIs
*CI Registry* Container de modelos Padrão cloud-native

*ecomendação para o Kode:*W&B Artifacts + HuggingFace Hub (privado).


2. Deployment

Padrões de deployment

A. Single model (mais simples)

Usuário → Load Balancer → Modelo v1 (vLLM)

*so:*Ambiente único, sem necessidade de A/B testing.

B. Blue-Green

                    ┌── Modelo v1 (blue) ──→ Produção
Usuário → LB ───────┤
                    └── Modelo v2 (green) ──→ Staging

*luxo:*

  1. Deploy v2 em green (não recebe tráfego)
  2. Testar v2 em staging
  3. Switch: LB aponta para green
  4. v1 fica em standby para rollback

*antagem:*Rollback imediato (segundos).

C. Canary

                    ┌── Modelo v1 ─→ 90% do tráfego
Usuário → LB ───────
                    └── Modelo v2 ──→ 10% do tráfego

*luxo:*

  1. v2 recebe 10% do tráfego
  2. Monitorar métricas por 24h
  3. Se OK → 25% → 50% → 100%
  4. Se problema → rollback para 0%

*antagem:*Exposição gradual, problema afeta poucos usuários.

D. Shadow

                    ┌── Modelo v1 ──→ Responde ao usuário
Usuário → LB ──────┤
                    └── Modelo v2 ──→ Roda em shadow (sem resposta)

*so:*Testar v2 sem afetar usuários. Comparar outputs de v1 vs v2.

Implementação com vLLM

# Deploy do modelo v1
vllm serve koder/kode-coder-v0.3.0 \
    --port 8000 \
    --tensor-parallel-size 2 \
    --max-model-len 8192

# Deploy do modelo v2 (canary)
vllm serve koder/kode-coder-v0.4.0 \
    --port 8001 \
    --tensor-parallel-size 2 \
    --max-model-len 8192

Implementação com Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kode-model-v0-3-0
spec:
  replicas: 3
  selector:
    matchLabels:
      app: kode-model
      version: v0.3.0
  template:
    metadata:
      labels:
        app: kode-model
        version: v0.3.0
    spec:
      containers:
      - name: vllm
        image: vllm/vllm-openai:latest
        args:
        - --model
        - koder/kode-coder-v0.3.0
        - --tensor-parallel-size
        - "2"
        resources:
          limits:
            nvidia.com/gpu: 2
---
apiVersion: v1
kind: Service
metadata:
  name: kode-model
spec:
  selector:
    app: kode-model
    # version: v0.3.0  ← mudar para v0.4.0 para trocar versão
  ports:
  - port: 80
    targetPort: 8000

3. Monitoring de Qualidade

Métricas de produção

Métrica Como medir Threshold
*atência p50* Tempo do primeiro token < 500ms
*atência p95* Tempo do primeiro token < 2000ms
*atência p99* Tempo do primeiro token < 5000ms
*hroughput* Tokens gerados / segundo > 50 tok/s por GPU
*axa de erro* Requests com erro / total < 1%
*axa de timeout* Requests timeout / total < 0.5%
*PU utilization* % GPU em uso > 70%
*PU memory* VRAM usada < 90%
*V cache hit rate* Reuso de cache > 30% (com RadixAttention)

Monitoring de qualidade de output

Métrica Como medir
*val score contínuo* Rodar eval automático em amostra de produção
*eedback do usuário* Thumbs up/down por resposta
*egeneração rate* % de vezes que usuário pede "try again"
*runcation rate* % de respostas cortadas (max tokens)
*mpty response rate* % de respostas vazias ou só whitespace

Pipeline de monitoring

Produção → Coleta de métricas (LangFuse, Prometheus) → Dashboard (Grafana)
                                        ↓
                               Alertas (Slack, email)
                                        ↓
                               Análise (semana)
                                        ↓
                               Decisão: manter, rollback, re-treinar

4. Detecção de Drift

Tipos de drift

Tipo Descrição Exemplo
*ata drift* Distribuição dos inputs muda Novas libs de código, novos frameworks
*oncept drift* O que é "bom" muda Boas práticas de código evoluem
*abel drift* Preferência do usuário muda Usuários preferem respostas mais curtas
*odel drift* Modelo degrada com uso KV cache corruption, quantização drift

Detecção automática

def detect_drift(current_eval, baseline_eval, threshold=0.05):
    """Detectar drift comparando eval atual com baseline."""
    metrics = ["code_pass_rate", "llm_judge_score", "latency_p95"]

    drifts = []
    for metric in metrics:
        current = current_eval[metric]
        baseline = baseline_eval[metric]
        change = abs(current - baseline) / baseline

        if change > threshold:
            drifts.append({
                "metric": metric,
                "change": change,
                "current": current,
                "baseline": baseline,
            })

    return drifts

# Uso
drifts = detect_drift(eval_semanal, eval_baseline)
if drifts:
    alert(f"Drift detectado: {drifts}")

Ações por tipo de drift

Drift detectado Ação
Data drift Adicionar novos dados ao dataset de treino
Concept drift Re-treinar com dados recentes
Label drift Atualizar reward model com preferências atuais
Model drift Reload do checkpoint, verificar hardware

5. Rate Limiting e Quota Management

Por que é necessário

LLMs são caros. Sem rate limiting:

  • Um usuário pode consumir toda a GPU
  • Loops infinitos de API calls esgotam quota
  • Attacks (prompt injection) geram custo

Estratégias

Estratégia Como funciona Uso
*ate limiting* Máximo de requests por minuto Todos os usuários
*oken quota* Máximo de tokens por dia Usuários free tier
*oncurrency limit* Máximo de requests simultâneos Prevenir overload
*riority queue* Usuários premium têm prioridade Multi-tenant
*ircuit breaker* Parar se erro rate > threshold Prevenir cascata

Implementação

# Rate limiting com Redis
import redis
import time

class RateLimiter:
    def __init__(self, redis_client, max_requests=100, window=60):
        self.redis = redis_client
        self.max_requests = max_requests
        self.window = window

    def is_allowed(self, user_id):
        key = f"rate_limit:{user_id}"
        current = self.redis.get(key)

        if current is None:
            self.redis.setex(key, self.window, 1)
            return True

        if int(current) >= self.max_requests:
            return False

        self.redis.incr(key)
        return True

# Token quota
class TokenQuota:
    def __init__(self, redis_client, daily_limit=100000):
        self.redis = redis_client
        self.daily_limit = daily_limit

    def check_and_consume(self, user_id, tokens):
        key = f"token_quota:{user_id}:{date.today()}"
        used = int(self.redis.get(key) or 0)

        if used + tokens > self.daily_limit:
            return False

        self.redis.incrby(key, tokens)
        return True

Tiers de quota

Tier Tokens/dia Requests/min Prioridade
*ree* 10K 10 Baixa
*ro* 100K 50 Média
*nterprise* 1M 200 Alta
*nternal* Ilimitado 500 Máxima

6. Rollback

Quando fazer rollback

Sinal Ação
Eval score cai > 5% Rollback imediato
Taxa de erro > 5% Rollback imediato
Latência p95 > 5s Rollback em 1h
Feedback negativo > 20% Investigar, possivelmente rollback
Drift detectado Avaliar, possivelmente rollback

Procedimento de rollback

# 1. Switch para versão anterior (Kubernetes)
kubectl set image deployment/kode-model \
    vllm=vllm/vllm-openai:latest \
    --record

# 2. Ou mudar symlink (file-based)
ln -sfn models/kode-coder/v0.3.0 models/kode-coder/current

# 3. Ou trocar weight no vLLM (hot reload)
curl -X POST http://localhost:8000/v1/reload \
    -d '{"model": "koder/kode-coder-v0.3.0"}'

# 4. Verificar health
curl http://localhost:8000/health

# 5. Notificar equipe

*empo alvo de rollback:*< 5 minutos.


7. Escalabilidade

Scaling horizontal

                   ┌── Pod 1 (vLLM) ──→ GPU 1
Load Balancer ─────┼── Pod 2 (vLLM) ──→ GPU 2
                   ┼── Pod 3 (vLLM) ──→ GPU 3
                   └── Pod N (vLLM) ──→ GPU N

*uto-scaling:*

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: kode-model-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: kode-model
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Pods
    pods:
      metric:
        name: gpu_utilization
      target:
        type: AverageValue
        averageValue: 80

Scaling vertical (model parallelism)

Se o modelo não cabe em uma GPU:

Técnica Quando usar
*ensor Parallelism* Modelo > VRAM de 1 GPU Dividir weights entre GPUs
*ipeline Parallelism* Modelo muito grande Dividir layers entre GPUs
*V cache offloading* Contexto longo Mover KV cache para CPU/disco

8. Custo por Request

Cálculo

Custo por request = (GPU-hours por request) × (custo por GPU-hour)

GPU-hours por request = (tokens gerados × tempo por token) / 3600

Exemplo:
  - 500 tokens gerados
  - 50ms por token = 25s total
  - 25s / 3600 = 0.007 GPU-hours
  - Custo A100: $2.80/hora
  - Custo por request: 0.007 × $2.80 = $0.02

Otimização de custo

Técnica Economia
*atching* 30–50% (processar múltiplos requests juntos)
*peculative decoding* 30–50% (menos tokens gerados)
*uantização* 0% custo, mas permite GPU menor (50% economia)
*V cache reuse* 20–40% (RadixAttention para prompts repetidos)
*odel switching* 50–80% (usar modelo menor para tasks simples)

Para o Kode

Stack de MLOps recomendado

Versionamento: W&B Artifacts + HuggingFace Hub (privado)
Deployment: Kubernetes + vLLM
Monitoring: Prometheus + Grafana + LangFuse
Alertas: Slack + PagerDuty
Rate limiting: Redis + NGINX
CI/CD: GitHub Actions → build Docker → push → deploy

Pipeline de deployment

1. Novo checkpoint → Eval automático (SWE-bench, eval privado)
2. Se eval OK → Push para HuggingFace Hub + W&B
3. Deploy canary (10% do tráfego)
4. Monitorar 24h
5. Se OK → Gradual ramp-up (25% → 50% → 100%)
6. Se problema → Rollback automático

Configuração inicial

Item Configuração
Modelos v0.1.0 (base) + v0.2.0 (fine-tune)
GPUs 2× RTX 4090 (desenvolvimento)
Serving vLLM com tensor parallelism
Monitoring LangFuse + Prometheus
Rate limit 100 requests/min por usuário
Quota 100K tokens/dia (free), 1M (pro)

Referências

Recurso Descrição
vLLM docs Serving de LLMs com alta throughput
LangFuse Observabilidade de LLMs
W&B Artifacts Versionamento de modelos
Prometheus Monitoring de métricas
Kubernetes HPA Auto-scaling horizontal

Source: ../home/koder/dev/koder/meta/docs/ia/compendium/11-infraestrutura/mlops-modelos-grandes.md