viernes, 17 de abril de 2026

La Memoria Semántica de las IA (RAG)

Logos & Contexto · Inteligencia Artificial Aplicada

RAG: la memoria semántica
de las máquinas

Cómo la Generación Aumentada por Recuperación transforma un modelo de lenguaje en un investigador capaz de consultar su propia biblioteca de documentos — y por qué la distancia coseno es la brújula que lo guía.

Un modelo de lenguaje, por potente que sea, es fundamentalmente un sistema con amnesia selectiva: sabe mucho del mundo hasta la fecha de su entrenamiento, pero no sabe nada de tus documentos. RAG es la solución arquitectónica a ese problema — y su elegancia está en que no modifica el modelo, sino que le entrega el contexto exacto que necesita, justo antes de que responda.

En las últimas semanas he estado construyendo un sistema de consulta sobre mis investigaciones de geohistoria de Cumaná — específicamente sobre el colapso del Túnel de Transferencia Guamacán y la crisis hídrica que genera. El sistema usa n8n como orquestador, Ollama con modelos locales (llama3.1:8b y nomic-embed-text), y PostgreSQL + pgvector como motor de búsqueda vectorial. En este artículo explico la arquitectura desde sus fundamentos matemáticos hasta su implementación práctica.

· · ·

El problema que RAG resuelve

Los Large Language Models (LLMs) son, en esencia, compresores estadísticos del lenguaje humano. Durante el entrenamiento, el modelo ajusta billones de parámetros para minimizar la perplejidad sobre un corpus masivo de texto. El resultado es una red neuronal que ha interiorizado patrones sintácticos, semánticos y factuales — pero ese conocimiento está congelado en los pesos del modelo desde el momento del entrenamiento.

Esto genera tres patologías bien documentadas:

  1. Alucinaciones factuales: el modelo genera texto plausible pero incorrecto cuando no tiene información suficiente, porque su objetivo de entrenamiento es producir tokens probables, no verdaderos.
  2. Opacidad de fuentes: es imposible saber qué parte del corpus de entrenamiento respaldó una afirmación concreta — no hay trazabilidad documental.
  3. Conocimiento estático: el modelo no puede acceder a documentos privados, bases de datos propias, ni información posterior a su fecha de corte.

† Perplejidad (perplexity): métrica que cuantifica cuánta incertidumbre tiene el modelo al predecir el siguiente token en una secuencia. Formalmente, es la exponencial de la entropía cruzada media: un modelo con perplejidad 10 se comporta, estadísticamente, como si eligiera entre 10 opciones igualmente probables en cada paso. Perplejidad baja = predicciones confiadas y precisas; perplejidad alta = el modelo "titubea" con frecuencia. Los mejores LLMs modernos alcanzan perplejidades de un solo dígito en benchmarks estándar de inglés.

RAG ataca los tres problemas de raíz: en lugar de pedirle al modelo que recuerde, le proporcionamos los fragmentos relevantes de nuestra base documental en el propio prompt. El modelo pasa de ser un oráculo a ser un lector experto que sintetiza evidencia concreta.

La búsqueda semántica en el espacio vectorial no busca palabras exactas — busca proximidad de significado. Dos frases que nunca comparten una sola palabra pueden estar a milímetros de distancia en ese espacio si expresan la misma idea.

Fase I — Ingesta: construir la biblioteca vectorial

Antes de poder consultar nada, debemos transformar nuestros documentos en una representación que permita búsqueda semántica. Este proceso tiene tres etapas bien definidas.

  • Fragmentación recursiva (chunking)

    Un PDF de 40 páginas no se puede insertar como un solo vector. Los modelos de embeddings tienen una ventana de contexto limitada (típicamente 512 tokens para nomic-embed-text), y además, un fragmento demasiado largo diluye la señal semántica. El RecursiveCharacterTextSplitter divide el texto respetando jerarquías de separadores: primero párrafos, luego oraciones, luego palabras — garantizando que cada chunk sea coherente en sí mismo. Con chunkSize=500 y chunkOverlap=50, los chunks adyacentes comparten 50 tokens, preservando el contexto en las fronteras.

  • Proyección al espacio latente (embedding)

    Cada chunk de texto se pasa por un modelo de embeddings — en nuestro caso nomic-embed-text, que produce vectores de 768 dimensiones. Este modelo fue entrenado específicamente para representar la similitud semántica: textos con significado similar se proyectan a regiones cercanas del espacio vectorial, independientemente de las palabras exactas usadas. El resultado es un tensor float32[768] por cada chunk.

  • Persistencia en PostgreSQL + pgvector

    Los vectores se almacenan en una tabla de Postgres con la extensión pgvector, que añade un tipo de dato nativo vector(n) y operadores de distancia vectorial. Cada fila contiene el texto original del chunk, sus metadatos (página, documento de origen), y su vector embedding. Sobre la columna de embeddings se construye un índice especializado para búsqueda eficiente.

SQL — creación de tabla e índice
-- Habilitar la extensión vectorial
CREATE EXTENSION IF NOT EXISTS vector;

-- Tabla de documentos con embeddings de 768 dimensiones
CREATE TABLE documentos_investigacion (
  id        BIGSERIAL PRIMARY KEY,
  text      TEXT,
  metadata  JSONB,
  embedding vector(768)
);

-- Índice IVFFlat para búsqueda aproximada de vecinos cercanos
-- lists=100: particiona el espacio en 100 listas de Voronoi
CREATE INDEX ON documentos_investigacion
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
· · ·

La matemática de la búsqueda semántica

Aquí está el núcleo conceptual de todo el sistema. Cuando el usuario hace una pregunta, esa pregunta también se convierte en un vector de 768 dimensiones mediante el mismo modelo de embeddings. Luego el sistema busca los vectores almacenados que están más cerca de ese vector-consulta en el espacio multidimensional.

La métrica de distancia que usamos es la similitud coseno:

Similitud coseno entre vectores A y B
cos(θ) = (A · B) / (‖A‖ × ‖B‖)
El numerador es el producto escalar (dot product): suma de los productos elemento a elemento.
El denominador normaliza por las magnitudes, haciendo la métrica invariante a la escala.
Resultado: 1 = idénticos semánticamente · 0 = ortogonales · −1 = opuestos.

La intuición geométrica es poderosa: los vectores son flechas en un espacio de 768 dimensiones. Dos flechas que apuntan en la misma dirección tienen similitud coseno cercana a 1, sin importar qué tan largas sean. Un párrafo sobre "colapso de infraestructura hídrica" y una pregunta sobre "falla en el sistema de agua" apuntarán casi en la misma dirección en ese espacio — aunque no compartan ninguna palabra.

¿Por qué 768 dimensiones y no 3?

En 3 dimensiones, el espacio disponible para separar conceptos distintos es extremadamente limitado. A 768 dimensiones, el espacio crece exponencialmente: hay suficiente "lugar" para que conceptos sutilmente distintos ocupen regiones claramente diferenciadas, mientras los conceptos similares permanecen agrupados. Este fenómeno es la base del éxito de los embeddings modernos.

El problema de escala: búsqueda exacta vs. aproximada

Con 84 vectores almacenados, una búsqueda exhaustiva (comparar la consulta contra cada vector) es trivial. Pero en producción, con millones de documentos, una búsqueda exacta requeriría O(n) comparaciones — completamente inviable. Por eso pgvector implementa dos algoritmos de búsqueda aproximada de vecinos cercanos (ANN):

IVFFlat

Inverted File with Flat quantization. Divide el espacio vectorial en listas de Voronoi mediante k-means. Al buscar, solo examina las listas más cercanas al vector de consulta. Requiere un paso previo de entrenamiento con VACUUM ANALYZE. Ideal para datasets medianos con latencia predecible.

HNSW

Hierarchical Navigable Small World. Construye un grafo de proximidad multicapa: las capas superiores permiten saltos largos; las inferiores refinan la búsqueda. Búsqueda en O(log n). Mayor uso de memoria que IVFFlat, pero sin fase de entrenamiento.

Quantización vectorial

Los embeddings float32 ocupan 768 × 4 = 3.072 bytes por vector. Con quantización a 8-bit (int8), se reduce a 768 bytes — 4× menos memoria. La quantización a 1-bit (binary) lleva esto a 96 bytes por vector, con aceleración masiva mediante instrucciones SIMD.

· · ·

Fase II — Consulta: el ciclo RAG en acción

Una vez construida la biblioteca vectorial, el flujo de consulta es elegante en su simplicidad. Esto es lo que sucede "bajo el capó" cada vez que el usuario hace una pregunta:

┌─────────────────────────────────────────────────────────┐
                  CICLO RAG — FASE DE CONSULTA                
└─────────────────────────────────────────────────────────┘

  Usuario
     │
     │  "¿Qué papel juegan las arterias olvidadas enla estructura urbana histórica de Cumaná?"┌─────────────────────────┐
│   Modelo de Embeddings  │  ← nomic-embed-text
│   (vectoriza la query)  │
└─────────────────────────┘
     │
     │  vector float32[768] = [0.021, -0.143, 0.887, ...]┌─────────────────────────┐
│  PostgreSQL + pgvector  │  ← búsqueda ANN por similitud coseno
│  SELECT top-5 chunks    │  ← ORDER BY embedding <=> query_vector
└─────────────────────────┘
     │
     │  5 fragmentos de texto con mayor similitud semántica┌─────────────────────────┐
│      AI Agent (n8n)     │
│  construye el prompt    │  ← system prompt + chunks + pregunta
└─────────────────────────┘
     │
     ▼
┌─────────────────────────┐
│  LLM — llama3:8b        │  ← genera respuesta fundamentada
│  (Ollama, local)        │  ← en los chunks recuperados
└─────────────────────────┘
     │
     ▼
  Respuesta con trazabilidad documental
      

El operador <=> en pgvector calcula la distancia coseno entre vectores. La consulta SQL que ejecuta el retriever es:

SQL — búsqueda semántica en tiempo de consulta
SELECT text, metadata,
       1 - (embedding <=> '[0.021, -0.143, 0.887, ...]'::vector) AS similitud
FROM   documentos_investigacion
ORDER BY embedding <=> '[0.021, -0.143, 0.887, ...]'::vector
LIMIT  5;

La expresión 1 - distancia_coseno convierte la distancia en similitud: 1.0 sería idéntico, 0.0 sería ortogonal. En la práctica, fragmentos relevantes suelen tener similitud entre 0.75 y 0.95.

· · ·

La arquitectura completa en n8n

El sistema tiene dos workflows separados con responsabilidades bien delimitadas. La ingesta corre una vez por documento; la consulta corre en cada interacción del usuario.

Workflow 1 — Ingesta

Manual Trigger
      │ main
      ▼
Read/Write Files from Disk  ← PDF binario desde /home/node/.n8n-files/
      │ main ──────────────────────────────────────────┐
      ▼                                                 │ main
Postgres PGVector Store  (mode: insert)          Default Data Loader
      ▲                                                 │ ai_document
      │ ai_embedding              Text Splitter ──────┘(chunk 500, overlap 50)
Embeddings Ollama
(nomic-embed-text:latest)
      

Workflow 2 — Consulta (Chat RAG)

Chat Trigger  (interfaz web pública)
      │ main
      ▼
AI Agent  ← "Eres un agente en Nagasaki, asistente experto de Logos & Contexto..."
      ▲
      ├── Ollama Chat Model       (llama3:8b)         ai_languageModel
      ├── Window Buffer Memory    (últimas 10 turns)  ai_memory
      └── Postgres PGVector Store  (retrieve-as-tool)  ai_tool
                ▲
                └── Ollama Embeddings  (nomic-embed-text)  ai_embedding
      

El Window Buffer Memory con windowSize=10 mantiene las últimas 10 rondas de conversación en el contexto del agente, permitiendo que las preguntas de seguimiento referencien respuestas anteriores — algo imposible sin memoria explícita, dado que los LLMs son stateless por defecto.

· · ·

RAG vs. Fine-tuning: cuándo usar cada uno

Una pregunta frecuente es si RAG no puede ser reemplazado simplemente por hacer fine-tuning del modelo con nuestros documentos. La respuesta corta: son soluciones a problemas distintos.

Dimensión RAG Fine-tuning
Actualización de conocimiento Inmediata — agrega documentos a la BD Requiere reentrenamiento completo
Trazabilidad Alta — chunks recuperados son auditables Opaca — el conocimiento está en los pesos
Costo computacional Bajo — solo inferencia + búsqueda vectorial Alto — GPU hours para reentrenamiento
Estilo y tono Limitado al modelo base Superior — adapta personalidad y estilo
Conocimiento procedimental Depende del contenido de los documentos Superior — aprende patrones de razonamiento
Privacidad de datos Alta — documentos nunca salen del servidor Requiere enviar datos al proveedor de cómputo

Para el caso de Logos & Contexto — un corpus de investigación en crecimiento continuo, con necesidad de trazabilidad documental y ejecutado completamente en infraestructura local — RAG es la elección correcta. El fine-tuning tiene sentido cuando el objetivo es cambiar el comportamiento del modelo, no su conocimiento factual.

· · ·

El espacio vectorial como metáfora epistemológica

Hay algo filosóficamente interesante en la búsqueda vectorial que vale la pena explicitar. Cuando la computadora Nagasaki recibe la pregunta "¿qué papel juegan las arterias olvidadas en la estructura urbana de Cumaná?", el sistema no busca esas palabras exactas. Busca la región del espacio semántico donde vive ese concepto.

Si en mis documentos aparece un párrafo que dice "los ductos de distribución hídrica actúan como columna vertebral del tejido urbano histórico", ese fragmento estará geométricamente próximo a la consulta aunque no comparta ningún término. El modelo de embeddings ha aprendido que ductos de distribución y arterias son análogos funcionales, que tejido urbano y estructura urbana son sinónimos contextuales.

Esto es recuperación de información por similitud conceptual, no por coincidencia léxica. Y es exactamente lo que hace posible que un sistema responda preguntas sobre documentos usando formulaciones que los documentos mismos nunca usaron.

El vector no es el texto — es la huella semántica del texto en un espacio matemático donde la distancia es significado. Buscar en ese espacio es buscar ideas, no palabras.

Estado actual y próximos pasos

El sistema procesó exitosamente el documento Las arterias olvidadas de Cumaná (2026), generando 84 chunks vectorizados almacenados en documentos_investigacion con embeddings de 768 dimensiones. El workflow de consulta opera completamente en infraestructura local, sin dependencias externas de API.

  • Ampliar el corpus con los demás documentos del archivo personal sobre geohistoria de la región.
  • Implementar un índice HNSW a medida que el corpus crezca, para mantener la latencia de consulta por debajo de 100ms.
  • Integrar el sistema con el Monitor Situacional Cumaná, permitiendo que los reportes ciudadanos enriquezcan automáticamente la base de conocimiento.
  • Explorar modelos de embeddings multilingües para manejar la mezcla español/términos técnicos del corpus regional.

Este artículo documenta la implementación técnica de un sistema RAG local desarrollado en el marco de las actividades de investigación que adelanto, Cumaná, Venezuela. Todos los modelos de lenguaje e inferencia operan en hardware local sin transmisión de datos a servicios externos.

Logos & Contexto · Inteligencia Artificial Aplicada

sábado, 11 de abril de 2026

Túnel Guamacán: Entre tecnología LiDAR y Realidade

El Túnel Guamacán: Entre tecnología LiDAR y Realidades

🔍 Túnel Guamacán: Entre la tecnología LiDAR y la realidad del capital

Cuando el diagnóstico es de primer mundo, pero la solución requiere más que datos

📸 Buenas noticias... con matices importantes

Según las imágenes que han circulado en redes y grupos de WhatsApp como "Archivo-Vivo", estamos ante lo que parece ser la fase inicial de un procedimiento correcto. El equipo técnico está usando tecnología LiDAR para crear un modelo digital tridimensional del Túnel Guamacán. Esto es, sin duda, un avance significativo. También es alentador ver que implementaron carruchas o carretas para la extracción de escombros (aunque pensé que ese proceso iba más adelantado).

Pero antes de celebrar, necesitamos entender qué significa realmente esta tecnología, qué puede hacer, y —más importante aún— qué NO puede hacer por sí sola.

🤖 ¿Qué es el LiDAR y cómo funciona?

LiDAR significa Light Detection and Ranging (Detección y Medición por Luz). Es un escáner láser que funciona emitiendo millones de pulsos de luz que rebotan en las superficies y regresan al sensor, permitiendo calcular distancias con precisión milimétrica.

El resultado es una "nube de puntos" —millones de coordenadas espaciales que reproducen digitalmente cada detalle de la estructura. El equipo que están usando (aparentemente un modelo Cygnus o similar) complementa el escaneo láser con dos cámaras HD de aproximadamente 12 megapíxeles que capturan el color real de cada punto.

El resultado final: Una reconstrucción 3D fotorrealista del interior del túnel que permite visualizar grietas, deformaciones, desprendimientos y el estado general sin necesidad de interpretaciones subjetivas. 📐✨

🚶‍♂️ ¿Cómo funciona en la práctica?

Gracias a dos tecnologías complementarias, el operador puede recorrer el túnel mientras el equipo genera el modelo digital en tiempo real:

  • RTK (Real-Time Kinematic): Convierte el GPS tradicional (con error de 5-15 metros) en un sistema de precisión centimétrica (1-3 cm) usando correcciones en tiempo real desde una estación base.
  • SLAM (Simultaneous Localization and Mapping): Permite que el equipo se ubique con precisión incluso sin señal GPS (esencial dentro del túnel), usando los propios datos del láser y sensores inerciales.

Es decir: el técnico camina por el túnel con el escáner portátil, y este va construyendo el mapa 3D automáticamente, con precisión centimétrica continua dentro y fuera de la montaña. 🎯

💼 Utilidades del modelo digital

Este levantamiento LiDAR tiene múltiples aplicaciones prácticas:

  • Analizar deformaciones desde la oficina 🏢 — Los ingenieros pueden estudiar la estructura sin exposición continua al riesgo
  • Calcular volúmenes exactos 📊 — Determinar con precisión cuánto material está colapsado o comprometido
  • Planificar reparaciones 🛠️ — Diseñar con exactitud las intervenciones necesarias
  • Simular refuerzos 💻 — Probar digitalmente diferentes escenarios antes de ejecutarlos físicamente
  • Crear un registro histórico permanente 📚 — Fundamental para instituciones como AGHES, permite comparar futuros escaneos y monitorear la evolución de daños

Nota del autor: Ojalá las autoridades compartan estos datos con la Academia de GeoHistoria del Estado Sucre (AGHES) para documentar este momento crítico de nuestra infraestructura regional. La memoria histórica no solo está en los libros del pasado, también en los datos técnicos del presente.

⚠️ La verdad incómoda: El LiDAR solo es una "llave de tubo nueva"

Esta es solo la primera etapa con el túnel despejado. Lo fundamental aún está por venir.

El LiDAR es una herramienta de diagnóstico extraordinaria, pero no es la solución. Es como tener el mejor escáner médico del mundo para diagnosticar un hueso roto: te dice exactamente dónde está la fractura, su gravedad, el ángulo... pero no te opera, no te enyesa, no te rehabilita.

Lo que realmente resuelve el problema del Túnel Guamacán son tres elementos inseparables:

SOLUCIÓN REAL = Ingenieros especializados + Presupuesto suficiente + Voluntad política

🔧 Contexto tecnológico

El equipo LiDAR portátil que vemos en las imágenes es de uso general, no es de los equipos especializados que se utilizan en proyectos de envergadura mundial como:

Túnel Longitud Tecnología utilizada
🇨🇭 Gotthard Base (Suiza) 57 km Interferómetros láser, giroscopios inerciales, GPS triple frecuencia
🇯🇵 Seikan (Japón) 53.8 km (submarino) Control geodésico satelital, sistemas de navegación inercial
🇬🇧🇫🇷 Channel Tunnel 50 km (37 km bajo el mar) Precisión submilimétrica en decenas de kilómetros
🇻🇪 Guamacán (Venezuela) ~13 km LiDAR portátil disponible (adecuado para diagnóstico)

Pero seamos claros: el equipo actual cumple perfectamente para el diagnóstico inicial. Es lo que está disponible en el país, probablemente alquilado, y genera datos de alta calidad para la primera fase.

🏗️ Lo que realmente falta (y nadie está diciendo)

El escaneo nos dirá QUÉ HAY (estado actual de la estructura)

Los ingenieros deben determinar QUÉ HACER (soluciones técnicas)

El presupuesto definirá CUÁNTO TARDARÁ (cronograma real)

Para que el túnel vuelva a operar de manera segura, se necesita:

  1. Diagnóstico estructural profundo por ingenieros geotécnicos especializados en túneles (no cualquier ingeniero civil)
  2. Estudios geológicos actualizados del macizo rocoso circundante —¿por qué colapsó? ¿hay riesgo de nuevos colapsos?
  3. Modelado de elementos finitos para simular el comportamiento de la estructura bajo diferentes cargas y escenarios sísmicos
  4. Diseño de reforzamiento especializado:
    • Micropilotes para estabilización del terreno
    • Anclajes profundos en roca sana
    • Dovelas de concreto proyectado (shotcrete)
    • Marcos metálicos de soporte
    • Sistemas de drenaje y ventilación
  5. Y fundamentalmente: PRESUPUESTO 💰 — Obras de este tipo en túneles de 13 km pueden alcanzar decenas de millones de dólares

🔇 El silencio del Alto Gobierno

Mientras vemos técnicos trabajando con tecnología moderna, no escuchamos al Alto Gobierno hablar sobre:

  • Presupuesto asignado para las reparaciones
  • Cronograma realista de intervención
  • Responsables técnicos del proyecto
  • Estudios geotécnicos contratados
  • Empresas especializadas involucradas

Sin estos elementos, solo tenemos una bonita nube de puntos en 3D... y un túnel cerrado.

🎓 El rol del físico (y el especialista interdisciplinario)

PD del autor: Claro está, siempre requerirán de un Físico (lector de este blog, servidor) para que hable y se entienda con todos ellos, e incluso los coordine. 😉🔬

Esta observación, aparentemente en broma, toca un punto crítico: proyectos de esta complejidad requieren coordinación interdisciplinaria. No basta con tener:

  • Ingenieros estructurales (que diseñan el refuerzo)
  • Geólogos (que entienden el comportamiento del macizo rocoso)
  • Topógrafos (que levantan y controlan las mediciones)
  • Técnicos LiDAR (que operan el equipo)

Se necesita alguien que traduzca entre disciplinas, que coordine los datos, que entienda tanto la física de materiales como la geomecánica, que pueda interpretar modelos numéricos y validar simulaciones. Alguien que haga de "director de orquesta" técnico.

En proyectos internacionales, este rol lo cumple el Project Manager con formación técnica profunda. En Venezuela, donde los recursos son limitados, este tipo de coordinación es aún más crítica para no desperdiciar esfuerzos ni capital.

⏰ Entonces... ¿cuándo estará listo el túnel?

Estimación inicial del autor: "En el transcurso del año; pero no antes de tres meses."

Realidad actual: Esa estimación asume que el trabajo busca solventar los problemas por un largo período, con intervención estructural profunda y no solo reparaciones superficiales.

La verdad es que no tengo ni idea cuándo estará operativo, porque no sabemos:

  • ¿Qué nivel de reparación se está planificando? (¿parche temporal o reforzamiento definitivo?)
  • ¿Qué presupuesto hay disponible realmente?
  • ¿Qué empresas especializadas están contratadas?
  • ¿Qué prioridad política tiene este proyecto?

Lo que sí podemos decir es que:

Diagnóstico LiDAR = 2-4 semanas
Ingeniería de detalle = 2-3 meses
Reparación estructural profunda = 8-12 meses
TOTAL REALISTA = 12-18 meses

Esto asumiendo presupuesto disponible, equipos trabajando continuamente, y sin complicaciones geológicas adicionales. 🤞

🎯 Conclusión: Tecnología sí, pero no es magia

El uso de tecnología LiDAR en el Túnel Guamacán es un paso correcto y bienvenido. Demuestra que hay criterio técnico en el diagnóstico inicial. La tecnología acelera procesos, reduce riesgos para el personal, y genera datos objetivos de alta calidad.

Pero no caigamos en el fetichismo tecnológico.

La solución real requiere:

  • ✅ Ingenieros especializados (que interpreten los datos)
  • ✅ Capital suficiente (que ejecute las obras)
  • ✅ Voluntad política (que priorice y comunique)

Ecuación final:

LiDAR + Ingenieros + Capital + Gobierno = TÚNEL OPERATIVO

LiDAR sin lo demás = Nube de puntos bonita + Túnel cerrado

Esperemos que las autoridades no confundan diagnóstico con solución, y que pronto tengamos noticias sobre presupuesto, cronograma real, y empresas contratadas.

Mientras tanto, celebremos el diagnóstico moderno... pero sigamos exigiendo la obra real. 🏗️💪

Rommel Contreras
Físico | Miembro de AGHES
📍 Cumaná, Estado Sucre, Venezuela
📅 Abril 2026

"La tecnología sin capital es como un mapa sin camino:
te dice dónde estás y a dónde debes ir,
pero no te lleva."

miércoles, 8 de abril de 2026

MLflow: Filosofía, Componentes y Arquitectura

MLflow: Filosofía, Componentes y Arquitectura

🔬 MLflow: Filosofía, Componentes y Arquitectura

📅 Fecha: 2025-04-08
✍️ Autor: Rommel Contreras
🏛️ Contexto: Laboratorio de IA
#mlflow #machine-learning #mlops #ia-governance

¿Qué es MLflow?

MLflow es una plataforma de código abierto para gestionar el ciclo de vida completo del machine learning, desde experimentación hasta producción.

En una frase: MLflow transforma el caos de entrenar modelos en un sistema ordenado, reproducible y auditable.

El problema que resuelve

Imagina que eres un científico de datos:

  1. Entrenas un modelo con 1000 hiperparámetros diferentes
  2. Olvidas qué valores usaste en el mejor modelo
  3. Tu colega ejecuta el mismo código, obtiene resultados diferentes
  4. El modelo funciona en tu laptop pero no en producción
  5. Pasan meses, quieres saber qué datos usaste
  6. No hay auditoría de quién cambió qué

MLflow resuelve todo esto.

Filosofía de MLflow

Principios fundamentales

Principio Significado Ejemplo
Reproducibilidad Mismo código = Mismo resultado, siempre Ejecutas en 2025 y 2030, obtienes exactamente el mismo AUC
Trazabilidad Registro completo de decisiones Sé exactamente qué datos, código y parámetros produjo el mejor modelo
Interoperabilidad Funciona con cualquier librería ML TensorFlow, PyTorch, Scikit-learn, XGBoost, en el mismo sistema
Governance Control de quién deployea qué Auditoría de modelos, aprobaciones, rechazos
Simplicidad Mínimo boilerplate Agregar 3 líneas de código a tu script existente

Antes vs Después de MLflow

Aspecto Sin MLflow Con MLflow
Tracking de resultados Excel + notas Dashboard automático
Reproducibilidad "Corre mi notebook entero" Un comando: mlflow run
Versionado de modelos Carpetas (model_v1, model_REAL) Registry con control de versiones
Comparación de experimentos Manual, memorizando números UI interactiva con gráficas
Deploy "Copiar el .pkl a producción" Pipeline automático con control de versiones
Auditoría No existe Quién, cuándo, qué, por qué

Los 4 componentes principales

MLflow consiste en 4 módulos independientes que puedes usar por separado o juntos:

┌─────────────────────────────────────────────────────────────┐ │ MLflow Platform │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Tracking │ │ Projects │ │ Models │ │ │ │ │ │ │ │ │ │ │ │ • Loguear │ │ • Reproducir │ │ • Crear │ │ │ │ • Comparar │ │ • Empaquetar │ │ • Versionear│ │ │ │ • Visualizar │ │ • Colaborar │ │ • Servir │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ Registry (Modelo Central) │ │ │ │ • Versionado • Transiciones de estado │ │ │ │ • Governance • Auditoría completa │ │ │ └──────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘

Tracking: Logging de experimentos

¿Qué es Tracking?

Tracking = Sistema automático para registrar todo lo que sucede durante el entrenamiento de un modelo.

Qué registra MLflow Tracking

Un "Experimento" (corrida de entrenamiento) registra: ┌─ Parámetros (inputs) │ ├─ learning_rate: 0.01 │ ├─ batch_size: 32 │ ├─ num_epochs: 100 │ └─ optimizer: "adam" │ ├─ Métricas (outputs que cambian) │ ├─ accuracy: [0.7, 0.75, 0.82, 0.88, 0.91] │ ├─ loss: [2.3, 2.1, 1.8, 1.5, 1.2] │ └─ val_accuracy: [0.69, 0.74, 0.80, 0.85, 0.88] │ ├─ Artefactos (archivos) │ ├─ model.pkl │ ├─ scaler.pkl │ └─ feature_importance.png │ ├─ Metadata │ ├─ Timestamp: 2025-04-08T14:30:00 │ ├─ Usuario: rommel │ └─ Git commit: abc123def456 │ └─ Fuente de código ├─ Script: train.py └─ Versión Python: 3.11

Ejemplo práctico en Python

import mlflow
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, f1_score

# 1. Iniciar un experimento
mlflow.set_experiment("agua_clasificacion_v1")

# 2. Comenzar una corrida (run)
with mlflow.start_run():
    # 3. Definir hiperparámetros
    params = {
        "n_estimators": 100,
        "max_depth": 10,
        "random_state": 42
    }
    
    # 4. Loguear parámetros
    mlflow.log_params(params)
    
    # 5. Entrenar modelo
    model = RandomForestClassifier(**params)
    model.fit(X_train, y_train)
    
    # 6. Hacer predicciones
    predictions = model.predict(X_test)
    
    # 7. Loguear métricas
    accuracy = accuracy_score(y_test, predictions)
    f1 = f1_score(y_test, predictions)
    
    mlflow.log_metric("accuracy", accuracy)
    mlflow.log_metric("f1_score", f1)
    
    # 8. Loguear artefactos
    mlflow.sklearn.log_model(model, "model")
    
    # 9. Agregar tags
    mlflow.set_tag("modelo_tipo", "RandomForest")
    mlflow.set_tag("dataset", "agua_ciudadanos_2025")

Projects: Reproducibilidad

¿Qué es un MLflow Project?

Un MLflow Project es una forma estándar de empaquetar código ML para que cualquiera pueda ejecutarlo de forma idéntica.

Estructura de un MLflow Project

mi_proyecto_agua/ ├── MLproject ← Manifest del proyecto ├── conda.yaml ← Dependencias Python ├── train.py ← Script de entrenamiento ├── evaluate.py ← Script de evaluación ├── data/ │ ├── ciudadanos.csv │ └── reportes.csv └── README.md

Ejecutar un MLflow Project

# Ejecutar localmente con parámetros por defecto
mlflow run . --experiment-name "agua_exp_001"

# Ejecutar con parámetros custom
mlflow run . \
  --experiment-name "agua_exp_001" \
  -P model_type="xgboost" \
  -P n_estimators=200

# Ejecutar desde GitHub
mlflow run https://github.com/tu-usuario/agua-ml.git \
  --experiment-name "agua_exp_001"

Models: Gestión del ciclo de vida

¿Qué son MLflow Models?

Un MLflow Model es una forma estándar de empaquetar cualquier modelo ML con toda su metadata y dependencias.

Loguear modelos de diferentes frameworks

import mlflow
import tensorflow as tf
import torch
from sklearn.ensemble import RandomForestClassifier

# 1. TensorFlow
mlflow.tensorflow.log_model(tf_model, "model_tf")

# 2. PyTorch
mlflow.pytorch.log_model(torch_model, "model_torch")

# 3. Scikit-learn
mlflow.sklearn.log_model(sklearn_model, "model_sklearn")

# 4. Custom (función Python personalizada)
def predict_custom(model_input):
    return model.predict(model_input)

mlflow.pyfunc.log_model("model_custom", python_model=predict_custom)

Cargar y usar un modelo logueado

import mlflow

# Opción 1: Cargar desde un run específico
model = mlflow.pyfunc.load_model("runs/abc123/artifacts/model")
predictions = model.predict(X_test)

# Opción 2: Cargar desde el Registry
model = mlflow.pyfunc.load_model("models:/agua_clasificador/production")

# Opción 3: Servir automáticamente (REST API)
mlflow models serve -m runs/abc123/artifacts/model -p 1234

Registry: Versionado y governance

¿Qué es el Model Registry?

El Model Registry es un repositorio central de modelos con control de versiones, transiciones de estado y auditoría.

Model Registry (Central) │ ├─ agua_clasificador (modelo 1) │ ├─ v1 [archived] │ ├─ v2 [archived] │ ├─ v3 [staging] ← En pruebas │ └─ v4 [production] ← En producción ⭐ │ ├─ agua_predictor (modelo 2) │ ├─ v1 [production] │ └─ v2 [staging] │ └─ electricidad_demanda (modelo 3) └─ v1 [development]

Estados de un modelo (Model Stage)

Stage Significado Quién lo decide Auditoría
None Sin asignar Usuario Creación
Staging En pruebas, validación Data Scientist Quién movió, cuándo
Production En uso activo Reviewer/ML Engineer Cuándo se deployó
Archived Retirado, legacy Administrador Razón de retiro

Registrar un modelo en el Registry

import mlflow
from mlflow.tracking import MlflowClient

# Opción 1: Desde un run existente
mlflow.register_model(
    model_uri="runs/abc123def456/artifacts/model",
    name="agua_clasificador"
)

# Opción 2: Dentro del entrenamiento
with mlflow.start_run():
    model = train()
    mlflow.sklearn.log_model(model, "model")
    
    # Registrar automáticamente
    mlflow.register_model(
        model_uri=f"runs/{mlflow.active_run().info.run_id}/artifacts/model",
        name="agua_clasificador"
    )

Transicionar entre estados

from mlflow.tracking import MlflowClient

client = MlflowClient()

# Pasar de Staging a Production
client.transition_model_version_stage(
    name="agua_clasificador",
    version=4,
    stage="Production",
    archive_existing_versions=True
)

# Agregar descripción
client.update_model_version(
    name="agua_clasificador",
    version=4,
    description="Random Forest con 95% accuracy. Deployado en Cumaná."
)

Comparativa: MLflow vs Alternativas

Matriz comparativa

Característica MLflow Weights & Biases Neptune Kubeflow DVC
Tracking de experimentos ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐
Reproducibilidad ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Model Registry ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐
Costo ⭐⭐⭐⭐⭐ (Gratis) ⭐⭐ (Pago) ⭐⭐ (Pago) ⭐⭐⭐⭐ (Gratis) ⭐⭐⭐⭐⭐ (Gratis)
Control on-prem ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Facilidad de uso ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐

¿Por qué MLflow para tu laboratorio?

Razón Beneficio
Código abierto Control total, sin vendor lock-in
Standalone Funciona on-prem, sin internet requerido
Simple 3 líneas de código vs 50 líneas en Kubeflow
Multi-framework TensorFlow, PyTorch, Scikit-learn, XGBoost...
Bajo costo Gratis (contrario a Weights & Biases, Neptune)
Auditoría Importante para gobierno (rastreo completo)

Arquitectura para tu laboratorio

Stack recomendado: MLflow + Otras herramientas

┌─────────────────────────────────────────────────────────────────┐ │ Laboratorio de IA (Cumaná) │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Datos (Entrada) │ │ │ │ ├─ PostgreSQL (datos ciudadanos, reportes) │ │ │ │ └─ MinIO (fotos, GeoJSON, archivos) │ │ │ └──────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Entrenamiento (MLflow Projects) │ │ │ │ ├─ train.py (código ML) │ │ │ │ ├─ MLproject (reproducibilidad) │ │ │ │ └─ conda.yaml (dependencias) │ │ │ └──────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Tracking (MLflow Tracking) │ │ │ │ ├─ Parámetros logged automáticamente │ │ │ │ ├─ Métricas (accuracy, F1, AUC) │ │ │ │ └─ Dashboard UI (http://localhost:5000) │ │ │ └──────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Model Registry (MLflow Registry) │ │ │ │ ├─ agua_clasificador v4 [production] │ │ │ │ ├─ agua_predictor v2 [staging] │ │ │ │ └─ electricidad_anomalía v1 [development] │ │ │ └──────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Deployment (MLflow Models) │ │ │ │ ├─ REST API (mlflow models serve) │ │ │ │ ├─ Batch predictions │ │ │ │ └─ Integración con Vercel/backend │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘

Configuración local de MLflow

# 1. Instalar MLflow
pip install mlflow

# 2. Crear directorio de almacenamiento
mkdir -p ~/mlflow_server
cd ~/mlflow_server

# 3. Iniciar server
mlflow server \
  --backend-store-uri sqlite:///mlflow.db \
  --default-artifact-root ./artifacts \
  --host 0.0.0.0 \
  --port 5000

# 4. Abrir navegador
# http://localhost:5000

Flujo práctico: De experimento a producción

Scenario: Clasificador de reportes de agua

PASO 1: Data Scientist inicia experimento
$ mlflow run . -P model_type=random_forest

✓ MLflow registra:
  - Parámetros: {"model_type": "random_forest"}
  - Métricas: {"accuracy": 0.92, "f1": 0.90}
  - Modelo: artifact/model
  - Timestamp: 2025-04-08 14:30:00
  - Usuario: rommel
PASO 2: Registrar en el Registry
from mlflow.tracking import MlflowClient

client = MlflowClient()
client.copy_model_version(
    src_model_uri="runs/abc123def456/artifacts/model",
    dst_model_name="agua_clasificador"
)

✓ Modelo registrado como "agua_clasificador" v1
PASO 3: Pasar a Staging para validación
client.transition_model_version_stage(
    name="agua_clasificador",
    version=1,
    stage="Staging"
)

✓ Modelo en Staging (pasa tests automáticos)
PASO 4: Aprobar y mover a Production
client.transition_model_version_stage(
    name="agua_clasificador",
    version=1,
    stage="Production",
    archive_existing_versions=True
)

✓ Modelo en Production (auditoría registrada)
PASO 5: Servir en producción
mlflow models serve \
  --model-uri models:/agua_clasificador/production \
  --port 8000

✓ Modelo sirviendo en REST API

MiNio un almacen de objetos de alto rendimiento

MinIO: Filosofía, Potencialidades y Comparativa

🗄️ MinIO: Filosofía, Potencialidades y Comparativa

📅 Fecha: 2025-04-08
✍️ Autor: Rommel Contreras
🏛️ Contexto: Laboratorio de Inteligencia Artificial
#object-storage #minio #cloud-native #civic-tech

Filosofía de MinIO

MinIO es un Object Store, no un filesystem tradicional. Esta es la distinción fundamental:

Aspecto Filesystem (Linux/Windows) MinIO (Object Store)
Estructura Árbol jerárquico de carpetas Bucket + Key (path plano)
"Carpetas" Reales, con permisos, metadatos Ilusión visual (prefijos)
Acceso Por ruta física Por identificador único (key)
Metadata Permisos, owner, timestamps Tags, content-type, custom metadata
Escalabilidad Limitada por estructura Millones de objetos sin límite

¿Por qué esto importa?

En un filesystem, cuando almacenas:

agua/reportes/2025/febrero/reporte.csv

El sistema crea realmente carpetas anidadas con inodos, permisos, y metadatos de cada nivel.

En MinIO, almacenas una key única:

agua/reportes/2025/febrero/reporte.csv

El "/" es solo delimitación visual. Internamente, MinIO lo trata como un identificador de cadena plano. Sin jerarquía, sin inodos, sin overhead.

Conceptos clave

1. Bucket

El contenedor raíz. Equivalente a un "drive" o "volumen":

Reglas inmutables:
  • Nombre único en toda la instancia MinIO
  • No pueden anidarse (no hay buckets dentro de buckets)
  • Todos los objetos viven en un bucket

2. Ruta / Key / Prefix

Es la ruta del objeto dentro del bucket:

agua/reportes/2025/febrero/reporte_20250408.csv
│     │         │    │       │
│     │         │    │       └─ Nombre del objeto
│     │         │    └─ Prefijo (subcarpeta virtual)
│     │         └─ Prefijo
│     └─ Prefijo
└─ Bucket

3. Artefacto = Objeto + Metadata

Un artefacto es:

Artefacto = Datos binarios + Metadata
Ejemplo en tu contexto:
  • Content-Type: text/csv
  • Size: 1,234,567 bytes
  • Created: 2025-04-08T10:30:00Z
  • ETag: "abc123def456" (detección de cambios)
  • Tags: estatus=confirmado, parroquia=pueblo-nuevo

Definición de rutas y artefactos

Estructura lógica recomendada

Para tu Monitor Situacional Cumaná:

monitor-cumaná/
├── agua/
│   ├── reportes/
│   │   ├── ciudadanos/
│   │   │   └── 2025/04/08/
│   │   │       ├── reporte_20250408_120000_cedula_12345678.csv
│   │   ├── institucional/
│   │   └── análisis/
│   ├── ciudadanos/
│   ├── fotos/
│   │   ├── daños/
│   │   └── reparaciones/
│   └── mapas/
├── electricidad/
├── salud/
└── auditoría/

Naming convention recomendada

Patrón general:

{categoria}/{subcategoría}/{tipo}_{timestamp}_{identificador}.{ext}

Ejemplos reales:

agua/reportes/ciudadanos/reporte_20250408_120530_cedula_12345678.csv
agua/reportes/institucional/resumen_20250408_mensual_aghes.xlsx
agua/mapas/pueblo_nuevo_20250101_v1.geojson
agua/fotos/daños/foto_20250408_153045_calle_mariño_sector1.jpg

Generación de rutas en código

Python (Flask)

from datetime import datetime

def generar_ruta_reporte(cedula, parroquia, estatus):
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    bucket = "agua"
    prefix = f"reportes/ciudadanos/{parroquia}/{estatus}"
    key = f"{prefix}/reporte_{timestamp}_{cedula}.csv"
    return bucket, key

# Uso:
bucket, ruta = generar_ruta_reporte("12345678", "pueblo_nuevo", "sin_agua")
# Resultado: ("agua", "reportes/ciudadanos/pueblo_nuevo/sin_agua/reporte_20250408_120530_12345678.csv")

Node.js

function generarRutaReporte(cedula, parroquia, estatus) {
  const ahora = new Date();
  const timestamp = ahora.toISOString().replace(/[:\-T.]/g, '').slice(0, 15);
  const año = ahora.getFullYear();
  const mes = String(ahora.getMonth() + 1).padStart(2, '0');
  const dia = String(ahora.getDate()).padStart(2, '0');
  
  const prefix = `reportes/ciudadanos/${parroquia}/${estatus}/${año}/${mes}/${dia}`;
  return {
    bucket: 'agua',
    key: `${prefix}/reporte_${timestamp}_${cedula}.csv`
  };
}

Comparativa: MinIO vs Otros sistemas

Matriz comparativa: Potencialidades reales

Potencial MinIO AWS S3 Google Cloud Azure Blob Filesystem PostgreSQL MongoDB
Escalabilidad horizontal ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐
Costo a escala ⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐
Control total (on-prem) ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Compatibilidad S3 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐
Consultas/indexación ⭐⭐ ⭐⭐ ⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Transacciones ACID ⭐⭐⭐⭐⭐ ⭐⭐⭐
Versionado nativo ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐

Potencialidades reales

1. Compatibilidad S3 = Portabilidad máxima ⭐ CRÍTICA

MinIO habla S3 nativamente. El mismo código funciona en MinIO, AWS S3, Google Cloud:

MinIO (local):

from minio import Minio
client = Minio('localhost:9000', access_key='minioadmin', secret_key='minioadmin')
client.put_object('agua', 'reporte.csv', stream, length)

AWS S3 (sin cambiar código):

from minio import Minio
client = Minio('s3.amazonaws.com', access_key='AWS_KEY', secret_key='AWS_SECRET')
client.put_object('agua', 'reporte.csv', stream, length)
Potencial real: Hoy usas MinIO on-prem. Mañana migras a AWS sin reescribir código. O ejecutas híbrido: datos locales + respaldo en cloud.

2. Control total del hardware = Costo predecible ⭐ CRÍTICA para Cumaná

Escenario MinIO AWS S3
5 MB/día × 365 días/año Costo disco fijo $1.38/año
1 TB acumulado (2 años) Costo disco fijo $276/año
10 TB acumulado (5 años) Costo disco fijo $2,760/año
En MinIO: El disco ya existe. El costo adicional es cero.

3. No hay "cold storage" delays

MinIO: todos los datos igual de rápidos, siempre.

AWS S3 tiene tiers:

  • Standard → ms de latencia (caro: $0.023/GB)
  • Infrequent Access → ms de latencia pero penalty por lectura
  • Glacier → horas (muy barato pero lento)
  • Deep Archive → 12 horas (más barato)

MinIO no penaliza archivos viejos. Un reporte de 2024 es igual de rápido que uno de hoy.

4. Edge computing / Replicación local

Cumaná central (cubagua) ↓ (replicación automática) Replica en Margarita ↓ Replica en Cariaco
Potencial:
  • Datos disponibles en múltiples ubicaciones
  • Redundancia automática
  • Sin costos de transferencia inter-región (MinIO) vs ~$0.02 por GB (AWS)

5. Versionado automático para auditoría

MinIO mantiene versiones de objetos:

# Habilitar versionado en bucket
mc version enable minio/agua

# Subir reporte_20250408.csv (versión 1)
# Luego subir reporte_20250408.csv (versión 2)
# Luego subir reporte_20250408.csv (versión 3)

# Listar todas las versiones
mc ls --versions minio/agua/reportes/
Ventajas:
  • Auditoría de cambios (quién cambió qué, cuándo)
  • Recuperación de errores
  • Compliance regulatorio

Matriz de decisión

📊 REPORTES CSV (ciudadanos, agua)
→ PostgreSQL (para consultas) + MinIO (para versionado/backup)
🖼️ IMÁGENES/FOTOS DE DAÑOS
→ MinIO (on-prem) o S3 (si presupuesto permite)
🗺️ GEOJSON/MAPAS VECTORIALES
→ PostgreSQL con PostGIS (para consultas geo) + MinIO (para versiones procesadas)
📝 LOGS DEL SISTEMA
→ Filesystem local (rápido) + MinIO (rotación nightly)
💾 BACKUPS COMPLETOS
→ MinIO (con versionado habilitado)
🔍 AUDITORÍA (quién cambió qué)
→ PostgreSQL (registros transaccionales)

Arquitectura recomendada para Cumaná

Stack full-stack para Monitor Situacional

┌──────────────────────────────────────────────┐ │ FRONTEND (Vercel) │ │ React + Next.js + TypeScript │ │ (Interfaz web, dashboards, reportes) │ └────────────────┬─────────────────────────────┘ │ API calls (HTTPS) │ ┌────────┴──────────────┐ ↓ ↓ ┌──────────────┐ ┌──────────────┐ │ PostgreSQL │ │ MinIO │ │ (Cloud) │ │ (On-prem) │ ├──────────────┤ ├──────────────┤ │ • Ciudadanos │ │ • Fotos │ │ • Reportes │ │ • GeoJSON │ │ • Auditoría │ │ • Backups │ │ • Consultas │ │ • Archivos │ │ • PostGIS │ │ • Versiones │ └──────────────┘ └──────────────┘ ↑ ↑ │ Sincronización bidireccional └───────────────────────┘

Flujo de datos

  1. Ciudadano reporta en Vercel
  2. Backend (Node.js) escribe en PostgreSQL
  3. Foto se almacena en MinIO: agua/fotos/daños/2025/04/08/foto_*.jpg
  4. CSV se sincroniza (cron cada 5 min): PostgreSQL → CSV → MinIO
  5. Dashboard en Vercel consulta estadísticas + fotos + mapas

Ventajas de esta arquitectura

Ventaja Beneficio
PostgreSQL en cloud Escalable, respaldos automáticos, acceso remoto
MinIO on-prem Control de datos, costo fijo, velocidad local
Vercel Deploy automático, CDN global, sin servidores
S3-compatible Portabilidad (mañana migras a AWS si quieres)
Replicable Cambias solo el bucket raíz y funciona en otra ciudad

Conclusión

¿Por qué MinIO para tu caso?

✅ Es PERFECTO porque:
  1. Soberanía de datos (eres gobierno, datos críticos)
  2. Costos predecibles (ya tienes hardware)
  3. Datos no estructurados (fotos, GeoJSON, archivos)
  4. Escalabilidad futura (replicar a otras ciudades)
  5. Portabilidad (si mañana necesitas migrar a S3)
  6. Versionado (auditoría de cambios)
  7. Desarrollo local sin internet (cubagua funciona off-grid)
⚠️ Pero necesitas TAMBIÉN:
  • PostgreSQL para consultas sobre ciudadanos
  • PostGIS para consultas geoespaciales
  • Elasticsearch (futuro) si necesitas búsqueda full-text
❌ NO necesitas:
  • MongoDB (tus datos son estructurados)
  • Elasticsearch (por ahora)
  • AWS/Google (soberanía de datos)

Comandos útiles

Instalar MinIO Client en WSL

$ curl https://dl.min.io/client/mc/release/linux-amd64/mc -o mc
$ chmod +x mc
$ sudo mv mc /usr/local/bin/

Configurar alias

$ mc alias set minio http://localhost:9000 minioadmin minioadmin

Operaciones básicas

$ mc mb minio/agua
$ mc cp reporte.csv minio/agua/reportes/
$ mc ls minio/agua/reportes/ciudadanos/
$ mc rm minio/agua/reportes/viejo.csv
$ mc rm --recursive minio/agua/2024/
$ mc mirror ./datos-locales minio/agua/respaldos/

Páginas

Entrada destacada

La Memoria Semántica de las IA (RAG)

Logos & Contexto · Inteligencia Artificial Aplicada RAG: la memoria semántica de las máquinas Cómo...

Entradas populares

Visitas: