Cost Optimization

LLM Pool Management

Sistema de gestão de pools LLM com separação tool-calling vs chat, rotação automática de keys, fallback inteligente e 40% de redução de custos com latência otimizada.

40%
Redução de Custo
<200ms
Latência p95
99.9%
Disponibilidade
N
Providers Simultâneos

O Problema

Sistemas de AI conversacional enterprise enfrentam desafios críticos de custo e latência:

  • Custos explosivos: GPT-4 para tudo é caro. Nem toda tarefa precisa do modelo mais poderoso
  • Tool-calling é caro: Modelos que suportam function calling custam mais que modelos simples
  • Rate limits: Uma única API key atinge limites rapidamente em produção
  • Vendor lock-in: Dependência de um único provider (OpenAI) é arriscado
  • Gestão de keys: API keys em código ou env vars é inseguro

A Solução

Arquitetura de Pools Separados

Sistema de pools com separação explícita entre chat (conversação) e tools (function calling)

💬 Chat Pool
  • • Modelo otimizado para conversação
  • supports_tools: false
  • • Custo mais baixo (gpt-4o-mini)
  • • Usado para respostas humanizadas
🔧 Tools Pool
  • • Modelo com function calling
  • supports_tools: true
  • • Custo mais alto (gpt-4o)
  • • Usado só quando precisa chamar tools

Resultado: 40% de redução de custos usando modelo barato para chat e modelo premium só para operações que realmente precisam de tool calling.

Key Groups

Separação entre pools (configuração de modelo) e key groups (vault de chaves): pools (configuração de modelo) e key groups (vault de chaves)

Key Group: "openai-production"
├── provider_type: "openai"
├── base_url: "https://api.openai.com/v1"
└── keys: [
      {key_id: "k1", fingerprint: "sk-...7f2a", status: "valid"},
      {key_id: "k2", fingerprint: "sk-...9b3c", status: "valid"},
      {key_id: "k3", fingerprint: "sk-...4d1e", status: "invalid"}
    ]

Pool: "gpt4o-mini-chat"
├── key_group_id: "openai-production"  ← Reference
├── model: "gpt-4o-mini"
├── supports_tools: false
└── is_active: true
              
  • Criptografia Fernet: Chaves armazenadas criptografadas em repouso
  • Fingerprint: UI mostra apenas fingerprint (sk-...7f2a), nunca a chave completa
  • Validação automática: Sistema valida chaves periodicamente e marca status

Seleção Automática

Escolha inteligente de modelo baseada em tipo de tarefa, custo e disponibilidade.

1Request chega para pool gpt4o-mini-chat
2Sistema busca key_group openai-production
3Filtra apenas chaves com status: valid|active
4Seleciona chave (round-robin ou random)
5Se rate limit → marca cooldown → tenta próxima chave

Defaults Globais

Configuração centralizada com override por tenant.

# Priority resolution:
1. tenant.chat_provider_id    → Tenant-specific pool
2. global.chat_provider_id    → Global default pool
3. ❌ FAIL-FAST               → Error (no hardcoded fallback)

# Frontend can:
- Select specific pool for tenant
- Leave empty to use "Global Default"
- Badge "⚡ using default" indicates inheritance
              

Fallback Cross-Pool

Se um pool falha, o sistema tenta automaticamente outro.

!Chat pool exausto (todas as chaves em rate limit)
Tenta tools_pool (se suporta chat)
Tenta global defaults
Request completa com latência mínima adicional

QuotaEnforcer: Tracked provider health com cooldown de 60s por chave.

Integração Frontend

Dashboard para monitoramento de custos e uso em tempo real.

Pool Management
  • • CRUD de pools
  • • Toggle <code>supports_tools</code>
  • • Toggle <code>is_active</code>
  • • Seleção de key_group
Key Management
  • • Adicionar/remover chaves
  • • Reveal com vault password
  • • Validação em batch
  • • Status por chave (valid/invalid)

🏗️ Arquitetura

┌─────────────────────────────────────────────────────────────┐
│                    LLM POOL SYSTEM                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                  KEY GROUPS (Vault)                 │  │
│   │  ┌──────────────┐  ┌──────────────┐                │  │
│   │  │ openai-prod  │  │ groq-prod    │                │  │
│   │  │ keys: [k1,k2]│  │ keys: [k3]   │                │  │
│   │  │ base_url:... │  │ base_url:... │                │  │
│   │  └──────┬───────┘  └──────┬───────┘                │  │
│   └─────────┼─────────────────┼─────────────────────────┘  │
│             │                 │                             │
│   ┌─────────▼─────────────────▼─────────────────────────┐  │
│   │                    POOLS                             │  │
│   │  ┌──────────────┐  ┌──────────────┐  ┌───────────┐ │  │
│   │  │ gpt4o-mini   │  │ gpt4o-tools  │  │ groq-fast │ │  │
│   │  │ chat only    │  │ tool calling │  │ chat only │ │  │
│   │  │ key_group:   │  │ key_group:   │  │ key_group:│ │  │
│   │  │ openai-prod  │  │ openai-prod  │  │ groq-prod │ │  │
│   │  └──────────────┘  └──────────────┘  └───────────┘ │  │
│   └─────────────────────────────────────────────────────┘  │
│                           │                                 │
│   ┌───────────────────────▼─────────────────────────────┐  │
│   │                 GLOBAL DEFAULTS                      │  │
│   │  chat_provider_id: "gpt4o-mini"                     │  │
│   │  tools_provider_id: "gpt4o-tools"                   │  │
│   └─────────────────────────────────────────────────────┘  │
│                           │                                 │
│   ┌───────────────────────▼─────────────────────────────┐  │
│   │              TENANT OVERRIDE (optional)              │  │
│   │  tenant_A.chat_provider_id: "groq-fast" (override)  │  │
│   │  tenant_B.chat_provider_id: null (uses default)     │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

🎯 Decisões Técnicas

Por que separar pools e key groups?

Pools definem configuração de modelo (model, temperature, supports_tools). Key groups definem credenciais (provider_type, base_url, keys). Essa separação permite reusar o mesmo vault de chaves em múltiplos pools com modelos diferentes.

Por que fail-fast e não fallback para env vars?

Em produção, chaves em código/env vars são anti-pattern de segurança. Fail-fast força configuração correta no sistema e evita "funciona na minha máquina" com chaves diferentes.

Por que cache de 60s para provider configs?

Balance entre consistência e performance. 60s é suficiente para propagar mudanças de configuração sem bombardear Memory Engine a cada request. TTLCache com lock thread-safe.

Por que QuotaEnforcer com cooldown de 60s?

Rate limits de providers (OpenAI, Groq) tipicamente resetam em 60s. Cooldown evita retry storms que piorariam o rate limit. Cross-pool fallback garante continuidade.

Stack Técnico

Python 3.12FastAPISQLAlchemy 2.0Fernet (AES)cachetools TTLCacheHTTPX (async)LangChainVue.js 3