- 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>
251 lines
7.6 KiB
Markdown
251 lines
7.6 KiB
Markdown
# 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:
|
|
|
|
1. **Interface comun**
|
|
- Todos los proveedores implementan la misma interface
|
|
- Metodos estandar: detectProducts, getCost, isAvailable
|
|
|
|
2. **Adapter pattern**
|
|
- Cada proveedor tiene su propio adapter
|
|
- El adapter traduce requests/responses al formato comun
|
|
|
|
3. **Configuracion dinamica**
|
|
- Proveedor activo configurable por variable de entorno
|
|
- Cambio en runtime via admin panel
|
|
|
|
4. **Fallback automatico**
|
|
- Si proveedor principal falla, usar secundario
|
|
- Reintentar con diferentes proveedores
|
|
|
|
5. **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
|
|
|
|
```typescript
|
|
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
|
|
|
|
```env
|
|
# 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
|
|
|
|
1. **Fase 1**: Implementar con OpenAI como unico proveedor
|
|
2. **Fase 2**: Agregar adapter de Claude como fallback
|
|
3. **Fase 3**: Comparar precision y costos en produccion
|
|
4. **Fase 4**: Evaluar modelo custom si volumen lo justifica
|
|
|
|
---
|
|
|
|
## Referencias
|
|
|
|
- [INT-006](../02-integraciones/INT-006-ia-provider.md) - Detalles de integracion
|
|
- [MII-005](../01-epicas/MII-005-procesamiento-ia.md) - Epic de procesamiento
|
|
- [Adapter Pattern](https://refactoring.guru/design-patterns/adapter)
|
|
|
|
---
|
|
|
|
**Ultima Actualizacion:** 2026-01-10
|