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
- 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>
19 KiB
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
- VISION-ERP-CORE.md - Vision general
- INTEGRACIONES-EXTERNAS.md - Integraciones
- Anthropic MCP - Documentacion MCP
- OpenRouter - Documentacion API
Actualizado: 2026-01-10