--- id: ARQUITECTURA-IA-ERP-CORE title: Arquitectura IA - ERP Core type: Architecture status: Published version: 1.0.0 created_date: 2026-01-10 updated_date: 2026-01-10 --- # Arquitectura IA - ERP Core > Detalle de la arquitectura de inteligencia artificial ## Resumen ERP Core implementa una arquitectura de IA que permite integracion con multiples modelos de lenguaje (LLM), herramientas de negocio via MCP, y comunicacion inteligente a traves de WhatsApp. --- ## 1. Diagrama de Arquitectura ```mermaid graph TB subgraph "Clientes" WA[WhatsApp] WEB[Web Chat] MOB[Mobile App] API[API REST] end subgraph "Capa de Orquestacion" WAS[WhatsApp Service] MCP[MCP Server] end subgraph "Gateway LLM" OR[OpenRouter] subgraph "Modelos" CL[Claude 3] GPT[GPT-4] GEM[Gemini] MIS[Mistral] end end subgraph "Herramientas MCP" T1[Products Tools] T2[Inventory Tools] T3[Orders Tools] T4[Customers Tools] T5[Fiados Tools] end subgraph "Backend" BE[Express API] PRED[Prediction Service] end subgraph "Database" PG[(PostgreSQL)] MSG[messaging schema] AI[ai schema] end WA --> WAS WEB --> MCP MOB --> MCP API --> MCP WAS --> MCP MCP --> OR OR --> CL OR --> GPT OR --> GEM OR --> MIS MCP --> T1 MCP --> T2 MCP --> T3 MCP --> T4 MCP --> T5 T1 --> BE T2 --> BE T3 --> BE T4 --> BE T5 --> BE BE --> PG WAS --> MSG MCP --> AI PRED --> PG ``` --- ## 2. MCP Server (Model Context Protocol) ### 2.1 Concepto El MCP Server implementa el protocolo Model Context Protocol de Anthropic, que permite exponer herramientas (tools) de negocio a los modelos de lenguaje de manera estandarizada. ### 2.2 Herramientas Disponibles #### 2.2.1 Products Tools ```typescript // Herramientas de productos const productTools = { list_products: { description: 'Lista productos filtrados por categoria, nombre o precio', parameters: { category?: string, search?: string, min_price?: number, max_price?: number, limit?: number }, returns: 'Array de productos con id, nombre, precio, stock' }, get_product_details: { description: 'Obtiene detalles completos de un producto', parameters: { product_id: string }, returns: 'Producto con todos sus atributos, variantes y precios' }, check_product_availability: { description: 'Verifica si hay stock suficiente de un producto', parameters: { product_id: string, quantity: number }, returns: '{ available: boolean, current_stock: number }' } }; ``` #### 2.2.2 Inventory Tools ```typescript const inventoryTools = { check_stock: { description: 'Consulta el stock actual de productos', parameters: { product_ids?: string[], warehouse_id?: string }, returns: 'Array de { product_id, quantity, location }' }, get_low_stock_products: { description: 'Lista productos que estan por debajo del minimo', parameters: { threshold?: number }, returns: 'Array de productos con stock bajo' }, record_inventory_movement: { description: 'Registra un movimiento de inventario', parameters: { product_id: string, quantity: number, movement_type: 'in' | 'out' | 'adjustment', reason?: string }, returns: 'Movimiento registrado' }, get_inventory_value: { description: 'Calcula el valor total del inventario', parameters: { warehouse_id?: string }, returns: '{ total_value: number, items_count: number }' } }; ``` #### 2.2.3 Orders Tools ```typescript const orderTools = { create_order: { description: 'Crea un nuevo pedido', parameters: { customer_id: string, items: Array<{ product_id: string, quantity: number }>, payment_method?: string, notes?: string }, returns: 'Pedido creado con id y total' }, get_order_status: { description: 'Consulta el estado de un pedido', parameters: { order_id: string }, returns: 'Estado del pedido y detalles' }, update_order_status: { description: 'Actualiza el estado de un pedido', parameters: { order_id: string, status: 'pending' | 'confirmed' | 'preparing' | 'ready' | 'delivered' | 'cancelled' }, returns: 'Pedido actualizado' } }; ``` #### 2.2.4 Customers Tools ```typescript const customerTools = { search_customers: { description: 'Busca clientes por nombre, telefono o email', parameters: { query: string, limit?: number }, returns: 'Array de clientes encontrados' }, get_customer_balance: { description: 'Obtiene el saldo actual de un cliente', parameters: { customer_id: string }, returns: '{ balance: number, credit_limit: number }' } }; ``` #### 2.2.5 Fiados Tools (Credito) ```typescript const fiadoTools = { get_fiado_balance: { description: 'Consulta el saldo de credito de un cliente', parameters: { customer_id: string }, returns: '{ balance: number, available_credit: number }' }, create_fiado: { description: 'Registra una venta a credito', parameters: { customer_id: string, amount: number, order_id?: string, description?: string }, returns: 'Registro de fiado creado' }, register_fiado_payment: { description: 'Registra un abono a la cuenta de credito', parameters: { customer_id: string, amount: number, payment_method?: string }, returns: 'Pago registrado y nuevo saldo' }, check_fiado_eligibility: { description: 'Verifica si un cliente puede comprar a credito', parameters: { customer_id: string, amount: number }, returns: '{ eligible: boolean, reason?: string }' } }; ``` ### 2.3 Recursos MCP ```typescript const mcpResources = { 'erp://config/business': { description: 'Configuracion del negocio', returns: '{ name, address, phone, hours, policies }' }, 'erp://catalog/categories': { description: 'Categorias de productos', returns: 'Array de categorias' }, 'erp://inventory/summary': { description: 'Resumen de inventario', returns: '{ total_products, total_value, low_stock_count }' } }; ``` --- ## 3. Gateway LLM (OpenRouter) ### 3.1 Arquitectura ```mermaid graph LR APP[Aplicacion] --> OR[OpenRouter API] OR --> |"Route"| M1[Claude 3 Haiku] OR --> |"Route"| M2[Claude 3 Sonnet] OR --> |"Route"| M3[GPT-4o-mini] OR --> |"Route"| M4[GPT-3.5 Turbo] OR --> |"Route"| M5[Mistral 7B] OR --> |"Route"| M6[Llama 3] ``` ### 3.2 Modelos Soportados | Modelo | ID | Input/1M | Output/1M | Uso Recomendado | |--------|----|---------:|----------:|-----------------| | Claude 3 Haiku | anthropic/claude-3-haiku | $0.25 | $1.25 | Default (rapido) | | Claude 3 Sonnet | anthropic/claude-3-sonnet | $3.00 | $15.00 | Premium | | GPT-4o-mini | openai/gpt-4o-mini | $0.15 | $0.60 | Fallback economico | | GPT-3.5 Turbo | openai/gpt-3.5-turbo | $0.50 | $1.50 | Fallback | | Mistral 7B | mistralai/mistral-7b | $0.06 | $0.06 | Ultra-economico | | Llama 3 | meta-llama/llama-3-8b | $0.20 | $0.20 | Open source | ### 3.3 Configuracion por Tenant ```typescript interface TenantLLMConfig { provider: 'openrouter' | 'openai' | 'anthropic' | 'ollama'; api_key: string; // encriptada model: string; max_tokens: number; temperature: number; system_prompt: string; } // Ejemplo de configuracion const config: TenantLLMConfig = { provider: 'openrouter', api_key: 'sk-or-v1-...', model: 'anthropic/claude-3-haiku', max_tokens: 1000, temperature: 0.7, system_prompt: 'Eres un asistente de ventas amigable...' }; ``` ### 3.4 Estrategia de Fallback ```typescript async function callLLM(messages: Message[]): Promise { const models = [ config.model, // Modelo preferido del tenant 'anthropic/claude-3-haiku', // Fallback 1 'openai/gpt-3.5-turbo' // Fallback 2 ]; for (const model of models) { try { const response = await openrouter.chat({ model, messages, max_tokens: config.max_tokens, temperature: config.temperature }); return response; } catch (error) { if (error.code === 'rate_limit_exceeded') { continue; // Intentar siguiente modelo } throw error; } } // Si todos fallan, respuesta predefinida return { content: 'Lo siento, no puedo procesar tu solicitud ahora.' }; } ``` ### 3.5 Tracking de Tokens ```sql -- Schema: ai CREATE TABLE ai.configs ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), tenant_id UUID NOT NULL REFERENCES tenants.tenants(id), provider VARCHAR(20) NOT NULL, model VARCHAR(100) NOT NULL, temperature DECIMAL(3,2) DEFAULT 0.7, max_tokens INTEGER DEFAULT 1000, system_prompt TEXT, is_active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE ai.usage ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), tenant_id UUID NOT NULL, model VARCHAR(100) NOT NULL, operation VARCHAR(50), -- chat, completion, embedding input_tokens INTEGER NOT NULL, output_tokens INTEGER NOT NULL, cost_usd DECIMAL(10,6), latency_ms INTEGER, success BOOLEAN DEFAULT true, error_message TEXT, created_at TIMESTAMPTZ DEFAULT NOW() ); -- Indice para reportes de uso CREATE INDEX idx_ai_usage_tenant_date ON ai.usage(tenant_id, created_at DESC); ``` --- ## 4. WhatsApp Service con IA ### 4.1 Flujo de Mensaje ```mermaid sequenceDiagram participant C as Cliente participant WA as WhatsApp participant META as Meta API participant WS as WhatsApp Service participant LLM as LLM Service participant MCP as MCP Server participant BE as Backend C->>WA: Envia mensaje WA->>META: Webhook META->>WS: POST /webhook WS->>WS: Verificar firma WS->>WS: Extraer tenant WS->>LLM: Procesar mensaje LLM->>LLM: Cargar contexto LLM->>MCP: Llamar con tools alt Necesita datos MCP->>BE: Ejecutar tool BE-->>MCP: Resultado end MCP-->>LLM: Respuesta con datos LLM-->>WS: Texto de respuesta WS->>META: Enviar mensaje META->>WA: Entrega WA->>C: Muestra mensaje ``` ### 4.2 Tipos de Mensaje Soportados #### Entrantes | Tipo | Descripcion | Procesamiento | |------|-------------|---------------| | text | Texto simple | Directo a LLM | | audio | Nota de voz | Whisper -> LLM | | image | Imagen | Vision/OCR -> LLM | | location | Ubicacion | Extraer coords -> LLM | | interactive | Respuesta de botones | Mapear a accion | #### Salientes | Tipo | Uso | |------|-----| | text | Respuestas de texto | | template | Templates pre-aprobados | | interactive | Botones o listas | | media | Imagenes, documentos | ### 4.3 Contexto de Conversacion ```typescript interface ConversationContext { tenant_id: string; customer_id?: string; customer_name: string; phone_number: string; history: Message[]; // Ultimos 20 mensajes pending_action?: string; cart?: CartItem[]; } // Sistema mantiene contexto por 30 minutos de inactividad ``` ### 4.4 System Prompts #### Para Clientes ``` Eres el asistente virtual de {{BUSINESS_NAME}}, una tienda de barrio en Mexico. Ayudas a los clientes con: - Informacion sobre productos y precios - Hacer pedidos - Consultar su cuenta de fiado - Estado de sus pedidos Reglas: 1. Responde en espanol mexicano casual y amigable 2. Se breve pero calido 3. Nunca inventes precios, usa las herramientas 4. Para fiados, siempre verifica primero el saldo 5. Se proactivo sugiriendo opciones ``` #### Para Duenos ``` Eres el asistente de negocios de {{BUSINESS_NAME}}. Ayudas al dueno con: - Analisis de ventas y tendencias - Gestion de inventario - Recordatorios de cobranza - Sugerencias de negocio Se directo, profesional y accionable. Proporciona numeros concretos siempre. Sugiere acciones si detectas problemas. ``` --- ## 5. Prediccion de Inventario ### 5.1 Algoritmo de Demanda ```typescript // Promedio movil ponderado (4 semanas) function predictDemand(salesHistory: WeeklySales[]): number { const weights = [0.40, 0.30, 0.20, 0.10]; // Ultimas 4 semanas const recentWeeks = salesHistory.slice(-4).reverse(); let weightedSum = 0; for (let i = 0; i < weights.length; i++) { weightedSum += (recentWeeks[i]?.quantity ?? 0) * weights[i]; } return Math.ceil(weightedSum); } ``` ### 5.2 Punto de Reorden ```typescript function calculateReorderPoint( dailyDemand: number, leadTimeDays: number = 3, safetyStockDays: number = 2 ): number { const safetyStock = dailyDemand * safetyStockDays; const reorderPoint = (dailyDemand * leadTimeDays) + safetyStock; return Math.ceil(reorderPoint); } // Ejemplo: // dailyDemand = 10 unidades/dia // leadTime = 3 dias // safetyStock = 10 * 2 = 20 unidades // reorderPoint = (10 * 3) + 20 = 50 unidades ``` ### 5.3 Dias de Inventario ```typescript function daysOfInventory(currentStock: number, dailyDemand: number): number { if (dailyDemand === 0) return Infinity; return Math.floor(currentStock / dailyDemand); } // Alertas // < 3 dias: CRITICO // < 7 dias: BAJO // > 30 dias: EXCESO ``` ### 5.4 Endpoints de Prediccion ```typescript // GET /inventory/predictions { products: [ { product_id: 'uuid', name: 'Coca-Cola 600ml', current_stock: 24, predicted_weekly_demand: 50, reorder_point: 30, days_of_inventory: 3.4, suggested_order: 50, urgency: 'HIGH' } ] } // GET /inventory/low-stock { products: [ { product_id: 'uuid', name: 'Coca-Cola 600ml', current_stock: 5, minimum_stock: 20, shortage: 15 } ] } // GET /inventory/slow-moving { products: [ { product_id: 'uuid', name: 'Cafe Premium', current_stock: 10, days_without_sale: 45, last_sale_date: '2025-11-25' } ] } ``` --- ## 6. Modelo de Datos IA ### 6.1 Schema: messaging ```sql CREATE TABLE messaging.conversations ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), tenant_id UUID NOT NULL, phone_number VARCHAR(20) NOT NULL, contact_name VARCHAR(100), conversation_type VARCHAR(20) DEFAULT 'general', status VARCHAR(20) DEFAULT 'active', last_message_at TIMESTAMPTZ, last_message_preview TEXT, unread_count INTEGER DEFAULT 0, wa_conversation_id VARCHAR(100), created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE messaging.messages ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), conversation_id UUID NOT NULL REFERENCES messaging.conversations(id), direction VARCHAR(10) NOT NULL, -- in, out message_type VARCHAR(20) NOT NULL, -- text, audio, image, template content TEXT, media_url TEXT, media_mime_type VARCHAR(50), -- IA Processing processed_by_llm BOOLEAN DEFAULT false, llm_model VARCHAR(100), tokens_used INTEGER, tool_calls JSONB, -- WhatsApp wa_message_id VARCHAR(100), wa_status VARCHAR(20), -- sent, delivered, read, failed wa_timestamp TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT NOW() ); ``` ### 6.2 Indices ```sql -- Busqueda rapida de conversaciones CREATE INDEX idx_conversations_tenant_phone ON messaging.conversations(tenant_id, phone_number); CREATE INDEX idx_conversations_last_message ON messaging.conversations(tenant_id, last_message_at DESC); -- Busqueda de mensajes CREATE INDEX idx_messages_conversation ON messaging.messages(conversation_id, created_at DESC); ``` --- ## 7. Patrones de Extension IA ### 7.1 Agregar Herramientas MCP ```typescript // En vertical: erp-construccion // Registrar herramientas adicionales mcpServer.registerTool('construction.get_budget', { description: 'Obtiene presupuesto de construccion', parameters: { budget_id: { type: 'string', required: true } }, handler: async ({ budget_id }) => { return constructionService.getBudget(budget_id); } }); mcpServer.registerTool('construction.estimate_materials', { description: 'Estima materiales para un proyecto', parameters: { area_m2: { type: 'number', required: true }, project_type: { type: 'string', required: true } }, handler: async ({ area_m2, project_type }) => { return constructionService.estimateMaterials(area_m2, project_type); } }); ``` ### 7.2 System Prompts por Vertical ```typescript // Configuracion por vertical const systemPrompts = { 'erp-core': 'Eres un asistente de negocios general...', 'erp-construccion': 'Eres un asistente especializado en construccion...', 'erp-retail': 'Eres un asistente de punto de venta...' }; ``` ### 7.3 Modelos por Caso de Uso ```typescript // Diferentes modelos para diferentes tareas const modelConfig = { chat_simple: 'anthropic/claude-3-haiku', // Rapido y economico chat_complex: 'anthropic/claude-3-sonnet', // Alta calidad analysis: 'openai/gpt-4o', // Analisis profundo embedding: 'openai/text-embedding-3-small' // Embeddings }; ``` --- ## 8. Seguridad IA ### 8.1 Checklist - [ ] API keys encriptadas en base de datos - [ ] Rate limiting por tenant - [ ] Limite de tokens por request - [ ] Logs de todas las llamadas LLM - [ ] Sanitizacion de inputs - [ ] No exponer datos sensibles a LLM ### 8.2 Rate Limiting ```typescript // Limites por plan const rateLimits = { free: { tokensPerDay: 1000, requestsPerMinute: 5 }, starter: { tokensPerDay: 10000, requestsPerMinute: 20 }, pro: { tokensPerDay: 100000, requestsPerMinute: 60 }, enterprise: { tokensPerDay: -1, requestsPerMinute: 200 } }; ``` --- ## Referencias - [VISION-ERP-CORE.md](VISION-ERP-CORE.md) - Vision general - [INTEGRACIONES-EXTERNAS.md](INTEGRACIONES-EXTERNAS.md) - Integraciones - [Anthropic MCP](https://github.com/anthropics/anthropic-cookbook) - Documentacion MCP - [OpenRouter](https://openrouter.ai/docs) - Documentacion API --- *Actualizado: 2026-01-10*