erp-core/docs/00-vision-general/ARQUITECTURA-IA.md
rckrdmrd 0086695b4c
Some checks failed
ERP Core CI / Backend Lint (push) Has been cancelled
ERP Core CI / Backend Unit Tests (push) Has been cancelled
ERP Core CI / Backend Integration Tests (push) Has been cancelled
ERP Core CI / Frontend Lint (push) Has been cancelled
ERP Core CI / Frontend Unit Tests (push) Has been cancelled
ERP Core CI / Frontend E2E Tests (push) Has been cancelled
ERP Core CI / Database DDL Validation (push) Has been cancelled
ERP Core CI / Backend Build (push) Has been cancelled
ERP Core CI / Frontend Build (push) Has been cancelled
ERP Core CI / CI Success (push) Has been cancelled
Performance Tests / Lighthouse CI (push) Has been cancelled
Performance Tests / Bundle Size Analysis (push) Has been cancelled
Performance Tests / k6 Load Tests (push) Has been cancelled
Performance Tests / Performance Summary (push) Has been cancelled
[SIMCO-V38] feat: Actualizar a SIMCO v3.8.0 + cambios backend
- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8
- Actualizaciones en modulos CRM y OpenAPI

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 08:53:05 -06:00

19 KiB

id title type status version created_date updated_date
ARQUITECTURA-IA-ERP-CORE Arquitectura IA - ERP Core Architecture Published 1.0.0 2026-01-10 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

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

// 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

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

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

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)

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

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

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

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

async function callLLM(messages: Message[]): Promise<Response> {
    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

-- 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

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

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

// 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

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

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

// 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

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

-- 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

// 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

// 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

// 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

// 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


Actualizado: 2026-01-10