- Backend NestJS con módulos de autenticación, inventario, créditos - Frontend React con dashboard y componentes UI - Base de datos PostgreSQL con migraciones - Tests E2E configurados - Configuración de Docker y deployment Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
7.6 KiB
7.6 KiB
ADR-0003: Abstraccion de Proveedores IA
id: ADR-0003 type: ADR status: Aceptado created_date: 2026-01-10 updated_date: 2026-01-10 decision_date: 2026-01-10 deciders: ["Tech Lead", "ML Engineer"]
Estado
Aceptado
Contexto
El procesamiento de imagenes para deteccion de productos puede usar diferentes proveedores de IA:
- OpenAI GPT-4 Vision
- Anthropic Claude 3 Vision
- Google Cloud Vision
- Modelo custom/fine-tuned
Cada proveedor tiene:
- Diferentes APIs y formatos
- Diferentes costos por imagen/token
- Diferentes capacidades y precision
- Diferentes limites de rate
Necesitamos poder:
- Cambiar de proveedor sin modificar codigo
- Usar multiples proveedores (fallback)
- Comparar precision y costos
- Escalar con nuevos proveedores
Decision
Implementar una capa de abstraccion de proveedores con:
-
Interface comun
- Todos los proveedores implementan la misma interface
- Metodos estandar: detectProducts, getCost, isAvailable
-
Adapter pattern
- Cada proveedor tiene su propio adapter
- El adapter traduce requests/responses al formato comun
-
Configuracion dinamica
- Proveedor activo configurable por variable de entorno
- Cambio en runtime via admin panel
-
Fallback automatico
- Si proveedor principal falla, usar secundario
- Reintentar con diferentes proveedores
-
Registro de COGS
- Cada request registra proveedor y costo
- Permite analisis de costos por proveedor
Opciones Consideradas
Opcion A: Acoplamiento directo a OpenAI
| Aspecto | Valor |
|---|---|
| Complejidad | Baja |
| Flexibilidad | Nula |
| Riesgo | Alto (vendor lock-in) |
| Velocidad | Rapida |
Descartada: Lock-in inaceptable, no permite optimizar costos.
Opcion B: Servicio de IA externo (AWS Rekognition)
| Aspecto | Valor |
|---|---|
| Complejidad | Media |
| Flexibilidad | Baja |
| Costo | Fijo por imagen |
| Precision | Generica |
Descartada: Precision insuficiente para productos de tienda.
Opcion C: Abstraccion multi-proveedor (Seleccionada)
| Aspecto | Valor |
|---|---|
| Complejidad | Alta inicial |
| Flexibilidad | Maxima |
| Escalabilidad | Alta |
| Mantenimiento | Medio |
Seleccionada: Flexibilidad maxima y proteccion contra cambios de precios/disponibilidad.
Consecuencias
Positivas
- Sin vendor lock-in: Cambiar proveedor facilmente
- Optimizacion de costos: Comparar y elegir el mejor
- Resiliencia: Fallback a otro proveedor
- A/B testing: Comparar precision entre proveedores
- Futuro-proof: Agregar nuevos proveedores facilmente
Negativas
- Complejidad inicial: Mas codigo para abstraer
- Mantenimiento: Actualizar adapters si APIs cambian
- Testing: Probar cada adapter
- Potencial inconsistencia: Resultados pueden variar entre proveedores
Arquitectura
┌─────────────────────────────────────────────────────────────────┐
│ ABSTRACCION IA PROVIDER │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ IAProviderService │ │
│ │ ───────────────────────────────────────────────────── │ │
│ │ - activeProvider: string │ │
│ │ - providers: Map<string, IAProvider> │ │
│ │ │ │
│ │ + detectProducts(frames): Detection[] │ │
│ │ + getActiveProvider(): IAProvider │ │
│ │ + switchProvider(name): void │ │
│ │ + calculateCOGS(session): number │ │
│ └────────────────────────┬────────────────────────────────┘ │
│ │ implements IAProvider │
│ ┌──────────────┼──────────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ OpenAI │ │ Claude │ │ Custom │ │
│ │ Adapter │ │ Adapter │ │ Adapter │ │
│ │─────────-│ │─────────-│ │─────────-│ │
│ │GPT-4V API│ │Claude API│ │Local/API │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Interface
interface IAProvider {
readonly name: string;
// Core functionality
detectProducts(
frames: Buffer[],
options?: DetectionOptions
): Promise<Detection[]>;
// Cost tracking
getCostPerFrame(): number;
getCostPerToken(): number;
// Health check
isAvailable(): Promise<boolean>;
// Optional: identification
identifyProduct?(
image: Buffer,
detection: Detection
): Promise<ProductMatch>;
}
interface Detection {
frameNumber: number;
boundingBox: BoundingBox;
confidence: number;
label?: string;
embedding?: number[];
metadata?: Record<string, any>;
}
interface DetectionOptions {
minConfidence?: number;
maxProducts?: number;
categories?: string[];
}
Configuracion
# Proveedor activo
IA_ACTIVE_PROVIDER=openai
# OpenAI
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4-vision-preview
OPENAI_COST_PER_FRAME=0.02
# Claude
ANTHROPIC_API_KEY=sk-ant-...
CLAUDE_MODEL=claude-3-opus
CLAUDE_COST_PER_FRAME=0.015
# Fallback
IA_FALLBACK_PROVIDER=claude
IA_RETRY_WITH_FALLBACK=true
Metricas por Proveedor
| Proveedor | Precision | Latencia | Costo/frame | Disponibilidad |
|---|---|---|---|---|
| OpenAI | 87% | 2.5s | $0.02 | 99.5% |
| Claude | 85% | 3.0s | $0.015 | 99.8% |
| Custom | 82% | 0.5s | $0.005 | 99.9% |
Estrategia de Migracion
- Fase 1: Implementar con OpenAI como unico proveedor
- Fase 2: Agregar adapter de Claude como fallback
- Fase 3: Comparar precision y costos en produccion
- Fase 4: Evaluar modelo custom si volumen lo justifica
Referencias
- INT-006 - Detalles de integracion
- MII-005 - Epic de procesamiento
- Adapter Pattern
Ultima Actualizacion: 2026-01-10