stratumiops/docs/es/architecture/adrs/002-stratum-llm.md
Jesús Pérez 0ae853c2fa
Some checks failed
Rust CI / Security Audit (push) Has been cancelled
Rust CI / Check + Test + Lint (nightly) (push) Has been cancelled
Rust CI / Check + Test + Lint (stable) (push) Has been cancelled
chore: create stratum-embeddings and stratum-llm crates, docs
2026-01-24 02:03:12 +00:00

280 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR-002: Stratum-LLM - Biblioteca Unificada de Providers LLM
## Estado
**Propuesto**
## Contexto
### Estado Actual: Conexiones LLM Fragmentadas
El ecosistema stratumiops tiene 4 proyectos con funcionalidad IA, cada uno con su propia implementación:
| Proyecto | Implementación | Providers | Duplicación |
| ------------ | -------------------------- | ---------------------- | --------------------- |
| Vapora | `typedialog-ai` (path dep) | Claude, OpenAI, Ollama | Base compartida |
| TypeDialog | `typedialog-ai` (local) | Claude, OpenAI, Ollama | Define la abstracción |
| Provisioning | Custom `LlmClient` | Claude, OpenAI | 100% duplicado |
| Kogral | `rig-core` | Solo embeddings | Diferente stack |
### Problemas Identificados
#### 1. Duplicación de Código
Provisioning reimplementa lo que TypeDialog ya tiene:
- reqwest HTTP client
- Headers: x-api-key, anthropic-version
- JSON body formatting
- Response parsing
- Error handling
**Impacto**: ~500 líneas duplicadas, bugs arreglados en un lugar no se propagan.
#### 2. Solo API Keys, No CLI Detection
Ningún proyecto detecta credenciales de CLIs oficiales:
```text
Claude CLI: ~/.config/claude/credentials.json
OpenAI CLI: ~/.config/openai/credentials.json
```
**Impacto**: Usuarios con Claude Pro/Max ($20-100/mes) pagan API tokens cuando podrían usar su suscripción.
#### 3. Sin Fallback Automático
Cuando un provider falla (rate limit, timeout), la request falla completamente:
```text
Actual: Request → Claude API → Rate Limit → ERROR
Deseado: Request → Claude API → Rate Limit → OpenAI → Success
```
#### 4. Sin Circuit Breaker
Si Claude API está caído, cada request intenta conectar, falla, y propaga el error:
```text
Request 1 → Claude → Timeout (30s) → Error
Request 2 → Claude → Timeout (30s) → Error
Request 3 → Claude → Timeout (30s) → Error
```
**Impacto**: Latencia acumulada, UX degradado.
#### 5. Sin Caching
Requests idénticas van siempre a la API:
```text
"Explain this Rust error" → Claude → $0.003
"Explain this Rust error" → Claude → $0.003 (mismo resultado)
```
**Impacto**: Costos innecesarios, especialmente en desarrollo/testing.
#### 6. Kogral No Integrado
Kogral tiene guidelines y patterns que podrían enriquecer el contexto de LLM, pero no hay integración.
## Decisión
Crear `stratum-llm` como crate unificado que:
1. **Consolide** las implementaciones existentes de typedialog-ai y provisioning
2. **Detecte** credenciales CLI y subscripciones antes de usar API keys
3. **Implemente** fallback automático con circuit breaker
4. **Añada** caching de requests para reducir costos
5. **Integre** Kogral para enriquecer contexto
6. **Sea usado** por todos los proyectos del ecosistema
### Arquitectura
```text
┌─────────────────────────────────────────────────────────┐
│ stratum-llm │
├─────────────────────────────────────────────────────────┤
│ CredentialDetector │
│ ├─ Claude CLI → ~/.config/claude/ (subscription) │
│ ├─ OpenAI CLI → ~/.config/openai/ │
│ ├─ Env vars → *_API_KEY │
│ └─ Ollama → localhost:11434 (free) │
│ │ │
│ ▼ │
│ ProviderChain (ordered by priority) │
│ [CLI/Sub] → [API] → [DeepSeek] → [Ollama] │
│ │ │ │ │ │
│ └──────────┴─────────┴───────────┘ │
│ │ │
│ CircuitBreaker per provider │
│ │ │
│ RequestCache │
│ │ │
│ KogralIntegration │
│ │ │
│ UnifiedClient │
│ │
└─────────────────────────────────────────────────────────┘
```
## Justificación
### Por Qué No Usar Otra Crate Externa
| Alternativa | Por Qué No |
| -------------- | ------------------------------------------ |
| kaccy-ai | Orientada a blockchain/fraud detection |
| llm (crate) | Muy básica, sin circuit breaker ni caching |
| langchain-rust | Port de Python, no idiomático Rust |
| rig-core | Solo embeddings/RAG, no chat completion |
**Mejor opción**: Construir sobre typedialog-ai y añadir features faltantes.
### Por Qué CLI Detection es Importante
Análisis de costos para usuario típico:
| Escenario | Costo Mensual |
| ------------------------- | -------------------- |
| Solo API (actual) | ~$840 |
| Claude Pro + API overflow | ~$20 + ~$200 = $220 |
| Claude Max + API overflow | ~$100 + ~$50 = $150 |
**Ahorro potencial**: 70-80% detectando y usando subscripciones primero.
### Por Qué Circuit Breaker
Sin circuit breaker, un provider caído causa:
- N requests × 30s timeout = N×30s de latencia total
- Todos los recursos ocupados esperando timeouts
Con circuit breaker:
- Primera falla abre circuito
- Siguientes requests fallan inmediatamente (fast fail)
- Fallback a otro provider sin esperar
- Circuito se resetea después de cooldown
### Por Qué Caching
Para desarrollo típico:
- Mismas preguntas repetidas mientras se itera
- Testing ejecuta mismos prompts múltiples veces
Cache hit rate estimado: 15-30% en desarrollo activo.
### Por Qué Kogral Integration
Kogral tiene guidelines por lenguaje, patterns por dominio, y ADRs.
Sin integración el LLM genera código genérico;
con integración genera código que sigue convenciones del proyecto.
## Consecuencias
### Positivas
1. Single source of truth para lógica de LLM
2. CLI detection reduce costos 70-80%
3. Circuit breaker + fallback = alta disponibilidad
4. 15-30% menos requests en desarrollo (caching)
5. Kogral mejora calidad de generación
6. Feature-gated: cada feature es opcional
### Negativas
1. **Migration effort**: Refactorizar Vapora, TypeDialog, Provisioning
2. **New dependency**: Proyectos dependen de stratumiops
3. **CLI auth complexity**: Diferentes formatos de credenciales por versión
4. **Cache invalidation**: Respuestas obsoletas si no se gestiona bien
### Mitigaciones
| Negativo | Mitigación |
| ------------------- | -------------------------------------------- |
| Migration effort | Re-export API compatible desde typedialog-ai |
| New dependency | Path dependency local, no crates.io |
| CLI auth complexity | Version detection, fallback a API si falla |
| Cache invalidation | TTL configurable, opción de bypass |
## Métricas de Éxito
| Métrica | Actual | Objetivo |
| --------------------------- | ------ | --------------- |
| Líneas de código duplicadas | ~500 | 0 |
| CLI credential detection | 0% | 100% |
| Fallback success rate | 0% | >90% |
| Cache hit rate | 0% | 15-30% |
| Latency (provider down) | 30s+ | <1s (fast fail) |
## Análisis de Impacto en Costos
Basado en datos reales de uso ($840/mes):
| Escenario | Ahorro |
| ----------------------------- | ---------------- |
| CLI detection (Claude Max) | ~$700/mes |
| Caching (15% hit rate) | ~$50/mes |
| DeepSeek fallback para código | ~$100/mes |
| **Total potencial** | **$500-700/mes** |
## Estrategia de Migración
### Fases de Migración
1. Crear stratum-llm con API compatible con typedialog-ai
2. typedialog-ai re-exporta stratum-llm (backward compatible)
3. Vapora migra a stratum-llm directamente
4. Provisioning migra su LlmClient a stratum-llm
5. Deprecar typedialog-ai, consolidar en stratum-llm
### Adopción de Features
| Feature | Adopción |
| --------------- | --------------------------------------- |
| Basic providers | Inmediata (reemplazo directo) |
| CLI detection | Opcional, feature flag |
| Circuit breaker | Default on |
| Caching | Default on, configurable TTL |
| Kogral | Feature flag, requiere Kogral instalado |
## Alternativas Consideradas
### Alternativa 1: Mejorar typedialog-ai In-Place
**Pros**: No requiere nuevo crate
**Cons**: TypeDialog es proyecto específico, no infraestructura compartida
**Decisión**: stratum-llm en stratumiops es mejor ubicación para infraestructura cross-project.
### Alternativa 2: Usar LiteLLM (Python) como Proxy
**Pros**: Muy completo, 100+ providers
**Cons**: Dependencia Python, latencia de proxy, no Rust-native
**Decisión**: Mantener stack Rust puro.
### Alternativa 3: Cada Proyecto Mantiene su Implementación
**Pros**: Independencia
**Cons**: Duplicación, inconsistencia, bugs no compartidos
**Decisión**: Consolidar es mejor a largo plazo.
## Referencias
**Implementaciones Existentes**:
- TypeDialog: `typedialog/crates/typedialog-ai/`
- Vapora: `vapora/crates/vapora-llm-router/`
- Provisioning: `provisioning/platform/crates/rag/`
**Kogral**: `kogral/`
**Ubicación Objetivo**: `stratumiops/crates/stratum-llm/`