# INT-006: Integracion IA Provider --- id: INT-006 type: Integration status: Pendiente version: "1.0.0" created_date: 2026-01-10 updated_date: 2026-01-10 simco_version: "4.0.0" --- ## Metadata | Campo | Valor | |-------|-------| | **ID** | INT-006 | | **Servicio** | Proveedores de Vision IA | | **Proposito** | Deteccion e identificacion de productos | | **Criticidad** | P0 | | **Estado** | Pendiente | --- ## 1. Descripcion Capa de abstraccion para integrar multiples proveedores de Vision AI que permiten detectar e identificar productos en frames de video. --- ## 2. Proveedores Soportados | Proveedor | API | Uso | Costo Aprox | |-----------|-----|-----|-------------| | OpenAI | GPT-4 Vision | Deteccion + identificacion | $0.01-0.03/imagen | | Claude | Claude 3 Vision | Deteccion + identificacion | $0.01-0.02/imagen | | Google | Cloud Vision | Deteccion de objetos | $0.0015/imagen | | Custom | Modelo propio | Fine-tuned | Variable | --- ## 3. Arquitectura de Abstraccion ``` ┌─────────────────────────────────────────────────────────────────┐ │ IA PROVIDER ABSTRACTION │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ IAProviderService │ │ │ │ ───────────────────────────────────────────────────── │ │ │ │ + detectProducts(frames: Buffer[]): DetectionResult[] │ │ │ │ + getActiveProvider(): IAProvider │ │ │ │ + getCost(sessionId): COGSRecord │ │ │ │ + switchProvider(name: string): void │ │ │ └────────────────────────┬────────────────────────────────┘ │ │ │ │ │ ┌──────────────┼──────────────┐ │ │ ▼ ▼ ▼ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ OpenAI │ │ Claude │ │ Google │ │ │ │ Adapter │ │ Adapter │ │ Adapter │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 4. Interface del Provider ```typescript interface IAProvider { name: string; // Detectar productos en frames detectProducts(frames: Buffer[], options?: DetectionOptions): Promise; // Identificar un producto especifico identifyProduct(image: Buffer, detection: Detection): Promise; // Obtener costos getCostPerFrame(): number; getCostPerToken(): number; // Verificar disponibilidad isAvailable(): Promise; } interface Detection { frameNumber: number; boundingBox: { x: number; y: number; width: number; height: number; }; confidence: number; label?: string; embedding?: number[]; } interface ProductMatch { productId: string | null; productName: string | null; confidence: number; isKnown: boolean; alternatives?: Array<{ productId: string; productName: string; confidence: number; }>; } ``` --- ## 5. Implementacion OpenAI ### Configuracion ```env OPENAI_API_KEY=sk-... OPENAI_MODEL=gpt-4-vision-preview OPENAI_MAX_TOKENS=1000 ``` ### Adapter ```typescript @Injectable() export class OpenAIAdapter implements IAProvider { name = 'openai'; private client: OpenAI; constructor() { this.client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, }); } async detectProducts(frames: Buffer[]): Promise { const detections: Detection[] = []; for (let i = 0; i < frames.length; i++) { const base64 = frames[i].toString('base64'); const response = await this.client.chat.completions.create({ model: process.env.OPENAI_MODEL, max_tokens: parseInt(process.env.OPENAI_MAX_TOKENS), messages: [ { role: 'user', content: [ { type: 'text', text: `Analyze this shelf image and detect all products. Return a JSON array with detected products: [{ "name": "product name", "brand": "brand name", "presentation": "size/type", "quantity": estimated count, "confidence": 0-1, "boundingBox": {"x": %, "y": %, "width": %, "height": %} }]`, }, { type: 'image_url', image_url: { url: `data:image/jpeg;base64,${base64}`, }, }, ], }, ], }); const content = response.choices[0].message.content; const products = JSON.parse(content); for (const product of products) { detections.push({ frameNumber: i, boundingBox: product.boundingBox, confidence: product.confidence, label: `${product.brand} ${product.name} ${product.presentation}`, }); } } return detections; } getCostPerFrame(): number { return 0.02; // USD aproximado } getCostPerToken(): number { return 0.00001; } async isAvailable(): Promise { try { await this.client.models.retrieve('gpt-4-vision-preview'); return true; } catch { return false; } } } ``` --- ## 6. Implementacion Claude ```typescript @Injectable() export class ClaudeAdapter implements IAProvider { name = 'claude'; private client: Anthropic; constructor() { this.client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY, }); } async detectProducts(frames: Buffer[]): Promise { const detections: Detection[] = []; for (let i = 0; i < frames.length; i++) { const base64 = frames[i].toString('base64'); const response = await this.client.messages.create({ model: 'claude-3-opus-20240229', max_tokens: 1024, messages: [ { role: 'user', content: [ { type: 'image', source: { type: 'base64', media_type: 'image/jpeg', data: base64, }, }, { type: 'text', text: 'Detect all products on this shelf. Return JSON array with name, brand, quantity, confidence (0-1).', }, ], }, ], }); // Parse response similar to OpenAI const content = response.content[0].text; const products = JSON.parse(content); for (const product of products) { detections.push({ frameNumber: i, boundingBox: product.boundingBox || { x: 0, y: 0, width: 100, height: 100 }, confidence: product.confidence, label: `${product.brand} ${product.name}`, }); } } return detections; } getCostPerFrame(): number { return 0.015; } } ``` --- ## 7. Servicio Principal ```typescript @Injectable() export class IAProviderService { private providers: Map = new Map(); private activeProvider: string; constructor( private openai: OpenAIAdapter, private claude: ClaudeAdapter, private configService: ConfigService, ) { this.providers.set('openai', openai); this.providers.set('claude', claude); this.activeProvider = configService.get('IA_ACTIVE_PROVIDER', 'openai'); } async detectProducts(frames: Buffer[]): Promise { const provider = this.getActiveProvider(); return provider.detectProducts(frames); } getActiveProvider(): IAProvider { const provider = this.providers.get(this.activeProvider); if (!provider) { throw new Error(`Provider ${this.activeProvider} not found`); } return provider; } async switchProvider(name: string): Promise { const provider = this.providers.get(name); if (!provider) { throw new Error(`Provider ${name} not found`); } if (!(await provider.isAvailable())) { throw new Error(`Provider ${name} is not available`); } this.activeProvider = name; } calculateCOGS(framesProcessed: number, tokensUsed: number): number { const provider = this.getActiveProvider(); return ( framesProcessed * provider.getCostPerFrame() + tokensUsed * provider.getCostPerToken() ); } } ``` --- ## 8. Prompt Engineering ### Prompt para Deteccion ``` You are an expert product recognition system for Mexican convenience stores. Analyze this shelf image and detect ALL visible products. For each product, provide: 1. Brand name (e.g., "Coca-Cola", "Sabritas", "Bimbo") 2. Product name (e.g., "Original", "Refresco", "Pan Blanco") 3. Presentation/Size (e.g., "600ml", "45g", "680g") 4. Quantity visible (count of units) 5. Confidence score (0.0 to 1.0) Return ONLY valid JSON array. No explanations. Example output: [ {"brand": "Coca-Cola", "name": "Original", "presentation": "600ml", "quantity": 12, "confidence": 0.95}, {"brand": "Sabritas", "name": "Original", "presentation": "45g", "quantity": 8, "confidence": 0.88} ] ``` --- ## 9. Testing ### Mock Provider ```typescript @Injectable() export class MockIAAdapter implements IAProvider { name = 'mock'; async detectProducts(frames: Buffer[]): Promise { return [ { frameNumber: 0, boundingBox: { x: 10, y: 10, width: 20, height: 30 }, confidence: 0.95, label: 'Coca-Cola 600ml', }, ]; } getCostPerFrame(): number { return 0; } async isAvailable(): Promise { return true; } } ``` --- ## 10. Referencias - [OpenAI Vision API](https://platform.openai.com/docs/guides/vision) - [Claude Vision](https://docs.anthropic.com/claude/docs/vision) - [MII-005](../01-epicas/MII-005-procesamiento-ia.md) - Procesamiento IA - [ADR-0003](../97-adr/ADR-0003-abstraccion-proveedores-ia.md) --- **Ultima Actualizacion:** 2026-01-10