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.
⚡ 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)
- • Modelo otimizado para conversação
- •
supports_tools: false - • Custo mais baixo (gpt-4o-mini)
- • Usado para respostas humanizadas
- • 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.
gpt4o-mini-chatopenai-productionstatus: valid|activeDefaults 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.
QuotaEnforcer: Tracked provider health com cooldown de 60s por chave.
Integração Frontend
Dashboard para monitoramento de custos e uso em tempo real.
- • CRUD de pools
- • Toggle <code>supports_tools</code>
- • Toggle <code>is_active</code>
- • Seleção de key_group
- • 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.