1. Visión General
El archivo database_config.json configura la integración con bases de datos MySQL para realizar búsquedas híbridas combinando:
- FAISS Vectorstore: Documentos estáticos (PDFs, manuales, políticas) - Búsqueda semántica
- MySQL Database: Datos estructurados en tiempo real (productos, clientes, inventario) - Consultas SQL
Configuración en Entrenamiento: Las credenciales de base de datos NO se configuran en variables de entorno. Se envían UNA SOLA VEZ durante el entrenamiento (POST /v1/add_data) y se almacenan de forma segura.
Ubicación: resources/vectorstore/{suffix}/database_config.json
2. Arquitectura Hybrid Search
Diferencias Clave: FAISS vs Database
| Aspecto |
FAISS |
MySQL Database |
| Tipo de búsqueda |
Similarity search (vectorial) |
SQL queries (exacta) |
| Contenido |
Documentos estáticos pre-cargados |
Datos estructurados en tiempo real |
| Indexación |
Embeddings de OpenAI |
Índices SQL nativos |
| Actualización |
Manual (POST /v1/add_data) |
Automática (datos en vivo) |
| Uso típico |
Políticas, manuales, guías |
Stock, precios, clientes, transacciones |
Flujo de Clasificación Inteligente
Usuario: "¿Cuál es el precio del producto XYZ?"
↓
GPT-4o Clasificador decide: "Necesito consultar la base de datos"
↓
Text-to-SQL: Genera query SQL dinámicamente
↓
Ejecuta: SELECT price FROM products WHERE name = 'XYZ'
↓
Resultado: $99.99
↓
GPT-4o responde: "El precio del producto XYZ es $99.99"
3. Estructura de database_config.json
{
"enabled": true,
"host": "db.miempresa.com",
"port": 3306,
"database": "productos_db",
"username": "readonly_bot",
"password": "contraseña_segura",
"allowed_tables": ["products", "categories", "inventory"]
}
IMPORTANTE: Este archivo se genera automáticamente cuando envías database_config en POST /v1/add_data. NO necesitas crearlo manualmente.
4. Campos de Configuración
enabled
Type: boolean | OBLIGATORIO
Descripción: Activa o desactiva la integración con base de datos.
Valores: true | false
Ejemplo:
"enabled": true
Uso: Si false, el chatbot solo usará FAISS (documentos estáticos).
host
Type: string | OBLIGATORIO
Descripción: Dirección del servidor MySQL.
Formato: Hostname o IP sin protocolo
Ejemplos:
"host": "db.miempresa.com"
"host": "192.168.1.100"
"host": "localhost"
port
Type: integer | OPCIONAL (default: 3306)
Descripción: Puerto del servidor MySQL.
Ejemplo:
"port": 3306
database
Type: string | OBLIGATORIO
Descripción: Nombre de la base de datos a la cual conectarse.
Ejemplo:
"database": "productos_db"
username
Type: string | OBLIGATORIO
Descripción: Usuario de MySQL para conexión.
SEGURIDAD CRÍTICA: SIEMPRE usar un usuario de SOLO LECTURA (permisos SELECT únicamente).
Ejemplo:
"username": "readonly_bot"
password
Type: string | OBLIGATORIO
Descripción: Contraseña del usuario MySQL.
Almacenamiento: La contraseña se almacena en el archivo. Asegurar permisos adecuados del sistema de archivos.
Ejemplo:
"password": "contraseña_segura_12345"
allowed_tables
Type: array[string] | OBLIGATORIO
Descripción: Lista de tablas permitidas para consultas.
Uso: El sistema SOLO ejecutará queries sobre estas tablas. Cualquier query a otra tabla será rechazado.
SEGURIDAD CRÍTICA: NO incluir tablas sensibles (usuarios, passwords, tokens, auth, admin).
Ejemplo:
"allowed_tables": [
"products",
"categories",
"inventory",
"customers",
"orders"
]
5. Seguridad
Capas de Seguridad Implementadas
1. Usuario de Solo Lectura
El usuario MySQL debe tener ÚNICAMENTE permisos SELECT.
-- Crear usuario read-only en MySQL
CREATE USER 'readonly_bot'@'%' IDENTIFIED BY 'contraseña_segura';
GRANT SELECT ON productos_db.products TO 'readonly_bot'@'%';
GRANT SELECT ON productos_db.inventory TO 'readonly_bot'@'%';
FLUSH PRIVILEGES;
2. Lista Blanca de Tablas
Solo las tablas en allowed_tables son accesibles.
Validación: Si el SQL generado menciona una tabla NO permitida, el query es rechazado inmediatamente.
3. Validación de Queries
El sistema valida que el SQL generado sea seguro:
- Solo queries SELECT permitidos
- Bloquea INSERT, UPDATE, DELETE, DROP, ALTER, CREATE
- Bloquea múltiples statements (protección SQL injection)
- Bloquea palabras clave sensibles (passwords, tokens, admin)
4. Timeout de Queries
Límite de tiempo de ejecución: 5 segundos (configurable)
Previene queries complejos que bloqueen el sistema.
5. Límite de Resultados
Máximo de registros retornados: 100 rows (configurable)
Previene sobrecarga de memoria con datasets grandes.
6. Flujo de Trabajo
Configuración (Una sola vez)
- Preparar MySQL: Crear usuario readonly_bot con permisos SELECT
- Enviar configuración: POST /v1/add_data con parámetro database_config
- WeirdBot almacena: Guarda credenciales en resources/vectorstore/{suffix}/database_config.json
- Listo: El chatbot puede consultar la base de datos
Uso en Runtime
- Usuario pregunta: "¿Cuál es el stock del producto ABC?"
- Clasificador GPT-4o: Decide que necesita consultar base de datos
- Text-to-SQL GPT-4o: Genera query SQL basado en el esquema
SELECT stock_quantity FROM inventory WHERE product_code = 'ABC'
- Validación: Sistema verifica que query es seguro (solo SELECT, tabla permitida)
- Ejecución: Ejecuta query con credenciales almacenadas
- Resultado: Retorna datos (ej: stock_quantity: 45)
- Respuesta GPT-4o: "El stock actual del producto ABC es de 45 unidades"
7. Ejemplos de Uso
Ejemplo 1: E-commerce (Productos + Inventario)
{
"enabled": true,
"host": "db.tienda.com",
"port": 3306,
"database": "ecommerce_db",
"username": "readonly_bot",
"password": "pass_seguro_123",
"allowed_tables": [
"products",
"categories",
"inventory",
"product_reviews"
]
}
Queries típicos:
- "¿Qué productos hay en la categoría laptops?"
- "¿Cuál es el precio del producto XYZ?"
- "¿Cuántas reviews tiene el producto ABC?"
- "¿Qué productos tienen stock bajo?"
Ejemplo 2: CRM (Clientes)
{
"enabled": true,
"host": "crm.empresa.com",
"port": 3306,
"database": "crm_db",
"username": "bot_readonly",
"password": "crm_pass_789",
"allowed_tables": [
"customers",
"orders",
"tickets"
]
}
Queries típicos:
- "¿Cuál es mi número de teléfono registrado?"
- "¿Cuáles son mis últimas 3 órdenes?"
- "¿Tengo tickets de soporte abiertos?"
8. Troubleshooting
Error: "Connection refused"
Posibles causas:
- Host o puerto incorrecto
- Firewall bloqueando conexión
- MySQL no está corriendo
Solución: Verificar conectividad con
telnet host port
Error: "Access denied"
Posibles causas:
- Usuario o contraseña incorrectos
- Usuario no tiene permisos en esa base de datos
- Usuario no puede conectar desde la IP de WeirdBot
Solución: Verificar credenciales y permisos GRANT
Error: "Table not in allowed list"
Causa: El query menciona una tabla no incluida en allowed_tables
Solución: Agregar la tabla a la lista o modificar el query
Error: "Query timeout"
Causa: Query tardó más de 5 segundos
Solución: Optimizar índices de MySQL o simplificar la consulta
El chatbot no consulta la base de datos
Verificar:
- "enabled": true en database_config.json
- El archivo existe en resources/vectorstore/{suffix}/database_config.json
- La pregunta es clara y específica sobre datos estructurados
9. SQL Chat — Text-to-SQL conversacional puro
Además del modo Hybrid Search (FAISS + MySQL), WeirdBot ofrece un modo Text-to-SQL puro para casos donde el único origen de datos es una base de datos relacional — sin necesidad de documentos ni vectorstore.
| Aspecto |
Hybrid Search (/v1/chatbotdb) |
SQL Chat puro (/v1/sql_chat) |
| Requiere FAISS |
Sí (cargado con /v1/add_data) |
No |
| Configuración BD |
vía /v1/add_data (database_config) |
vía /v1/sql_config |
| Contexto de sesión |
customer (historial completo) |
session_id (historial ligero) |
| Operaciones |
SELECT + INSERT + UPDATE + DELETE |
Solo SELECT |
| Llamadas OpenAI |
3-4 por query |
1-2 por query |
| Caso de uso típico |
Chatbot de negocio completo |
Reportes / consultas analíticas |
Flujo de configuración SQL Chat
- Configurar BD una sola vez con
POST /v1/sql_config:
curl -X POST https://model.apconecta.com/v1/sql_config \
-H "Authorization: Bearer TOKEN" \
-F "suffix=reportes" \
-F 'database_config={
"host": "db.empresa.com",
"username": "reader",
"password": "pass_seguro",
"database": "ventas_db",
"port": 3306,
"allowed_tables": ["facturas", "clientes", "productos"]
}' \
-F "b_template=La tabla facturas usa id_factura como PK. Los montos están en USD."
- Consultar en lenguaje natural con
POST /v1/sql_chat:
curl -X POST https://model.apconecta.com/v1/sql_chat \
-H "Authorization: Bearer TOKEN" \
-F "query=¿Cuáles son las 5 facturas más altas de este mes?" \
-F "suffix=reportes" \
-F "session_id=user_456"
- Respuesta estructurada:
{
"success": true,
"answer": "Las 5 facturas más altas de este mes son:\n1. Factura #1023 — $18,500 (Cliente: Acme Corp)\n2. ...",
"sql": "SELECT id_factura, monto, cliente FROM facturas WHERE MONTH(fecha) = 3 ORDER BY monto DESC LIMIT 5",
"data": [{ "id_factura": 1023, "monto": 18500, "cliente": "Acme Corp" }, ...],
"rows_count": 5,
"columns": ["id_factura", "monto", "cliente"],
"session_id": "user_456"
}
Limpiar historial de sesión
Para reiniciar el contexto conversacional de una sesión:
curl -X DELETE https://model.apconecta.com/v1/sql_chat/history \
-H "Authorization: Bearer TOKEN" \
-F "suffix=reportes" \
-F "session_id=user_456"
Nota: El historial se limpia automáticamente cuando se reconfigura la BD con /v1/sql_config para ese sufijo.
Reglas de negocio con b_template
El parámetro b_template en /v1/sql_config permite proveer contexto sobre el esquema para que GPT-4o genere mejores queries:
Ejemplo de b_template:
La tabla 'facturas' usa el campo 'id_cliente' (FK) que referencia 'clientes.id'.
Los montos están almacenados en centavos — dividir entre 100 para mostrar en USD.
Para filtrar por mes actual usar: MONTH(fecha_emision) = MONTH(CURDATE()).
No incluir registros donde estado = 'ANULADA' salvo que el usuario lo pida explícitamente.