Saltar a contenido

← Volver al índice | Arquitectura del Sistema | Arquitectura IA

Modelo de Datos

Tipo: Documentación Técnica — Modelo de Datos
Audiencia: Equipo de desarrollo backend, DBA, arquitectos
Fecha: 20 de marzo de 2026
Relacionado con: Arquitectura del Sistema | MLOps y Workflows Agénticos | Docker Compose


1. Visión General

El modelo de datos se compone de dos sistemas complementarios:

  • PostgreSQL + pgvector: Datos relacionales y vectores de embedding
  • ChromaDB: Almacenamiento vectorial dedicado para búsqueda por similitud
flowchart LR
    subgraph PG ["PostgreSQL + pgvector"]
        REL["Datos relacionales"]
        VEC["Vectores - pgvector"]
    end

    subgraph CHR ["ChromaDB"]
        COL["Colecciones vectoriales"]
        META["Metadatos de documentos"]
    end

    subgraph MIN ["MinIO"]
        IMG["Imágenes originales"]
        ARCH["Archivos adjuntos"]
    end

    REL <-->|"FK / joins"| VEC
    VEC <-->|"sincronización"| COL
    REL -->|"ruta S3"| IMG

    style PG fill:#3498db,color:#fff
    style CHR fill:#f39c12,color:#fff
    style MIN fill:#2ecc71,color:#fff

2. Schema PostgreSQL — Diagrama ER Completo

erDiagram
    DEPARTAMENTO ||--o{ INVESTIGADOR : pertenece
    DEPARTAMENTO ||--o{ COLECCION : gestiona
    DEPARTAMENTO ||--o{ FUENTE_DATOS : monitoriza
    COLECCION ||--o{ MUESTRA : contiene
    MUESTRA ||--o{ IMAGEN_MUESTRA : tiene
    MUESTRA ||--o{ PARAMETRO_BIOLOGICO : mide
    MUESTRA }o--|| ESPECIE : identifica
    ESPECIE ||--o{ TAXONOMIA : clasifica
    MUESTRA }o--|| CAMPANA : proviene
    CAMPANA }o--|| ZONA_GEOGRAFICA : realizada_en
    IMAGEN_MUESTRA ||--|| EMBEDDING_VECTOR : genera
    INVESTIGADOR ||--o{ IDENTIFICACION_IA : realiza
    INVESTIGADOR ||--o{ FUENTE_DATOS : crea
    IDENTIFICACION_IA }o--|| MUESTRA : sobre
    IDENTIFICACION_IA }o--|| ESPECIE : sugiere
    IDENTIFICACION_IA }o--|| MODELO_REGISTRO : usa
    MODELO_REGISTRO }o--|| DEPARTAMENTO : sirve

    DEPARTAMENTO {
        uuid id PK
        string nombre
        string descripcion
        string responsable
        timestamp created_at
    }

    INVESTIGADOR {
        uuid id PK
        uuid departamento_id FK
        string nombre_completo
        string email
        string entra_id
        string rol
        boolean activo
        timestamp created_at
    }

    COLECCION {
        uuid id PK
        uuid departamento_id FK
        string nombre
        string tipo_preservacion
        int total_especimenes
        date fecha_inicio
        string descripcion
        timestamp created_at
    }

    MUESTRA {
        uuid id PK
        uuid coleccion_id FK
        uuid especie_id FK
        uuid campana_id FK
        string codigo_interno
        date fecha_captura
        string metodo_captura
        float latitud
        float longitud
        string estado_conservacion
        jsonb metadatos_extra
        timestamp created_at
        timestamp updated_at
    }

    ESPECIE {
        uuid id PK
        string nombre_cientifico
        string nombre_comun
        string familia
        string orden
        string clase
        string phylum
        string reino
    }

    TAXONOMIA {
        uuid id PK
        uuid especie_id FK
        string nivel
        string valor
        string fuente
    }

    PARAMETRO_BIOLOGICO {
        uuid id PK
        uuid muestra_id FK
        float talla_cm
        float peso_g
        string sexo
        string madurez_gonadal
        int edad_estimada
        string metodo_edad
        float indice_gonadosomatico
        jsonb datos_adicionales
    }

    CAMPANA {
        uuid id PK
        uuid zona_id FK
        string nombre
        string buque
        date fecha_inicio
        date fecha_fin
        string tipo
        int muestras_totales
    }

    ZONA_GEOGRAFICA {
        uuid id PK
        string nombre
        string mar
        float lat_centro
        float lon_centro
        string geometria_wkt
    }

    IMAGEN_MUESTRA {
        uuid id PK
        uuid muestra_id FK
        string ruta_s3
        string tipo_imagen
        int ancho_px
        int alto_px
        jsonb metadatos_exif
        timestamp fecha_captura
    }

    EMBEDDING_VECTOR {
        uuid id PK
        uuid imagen_id FK
        string modelo_embedding
        vector embedding_768d
        float confidence_score
        timestamp generado_at
    }

    IDENTIFICACION_IA {
        uuid id PK
        uuid muestra_id FK
        uuid especie_sugerida_id FK
        uuid investigador_id FK
        string modelo_utilizado
        float confianza
        string edad_estimada
        string sexo_estimado
        jsonb top_k_similares
        boolean confirmada
        timestamp created_at
    }

    FUENTE_DATOS {
        uuid id PK
        uuid departamento_id FK
        uuid responsable_id FK
        string nombre
        string tipo
        jsonb configuracion
        string periodicidad
        string esquema_esperado
        boolean activa
        timestamp ultima_ejecucion
        timestamp created_at
    }

    MODELO_REGISTRO {
        uuid id PK
        uuid departamento_id FK
        string nombre
        string version
        string stage
        string dataset_entrenamiento
        float precision_val
        float vram_gb
        string ruta_pesos
        string mlflow_run_id
        timestamp desplegado_at
        timestamp created_at
    }

3. Detalle de Tablas Principales

3.1 muestra

Tabla central del sistema. Cada muestra biológica se registra aquí.

Columna Tipo Descripción
id UUID PK Identificador único
coleccion_id UUID FK Colección a la que pertenece
especie_id UUID FK Especie identificada (puede ser NULL si pendiente)
campana_id UUID FK Campaña de origen (puede ser NULL)
codigo_interno VARCHAR(50) Código del IEO (ej: IEOMA-CFM-0001)
fecha_captura DATE Fecha de recolección
metodo_captura VARCHAR(100) Arrastre, palangre, nasas, etc.
latitud / longitud FLOAT Coordenadas GPS de captura
estado_conservacion VARCHAR(50) Líquido, seco, fresco
metadatos_extra JSONB Datos adicionales flexibles

3.2 embedding_vector

Almacena los vectores de embedding generados por el modelo de visión.

Columna Tipo Descripción
id UUID PK Identificador único
imagen_id UUID FK Imagen de origen
modelo_embedding VARCHAR(100) Nombre del modelo (ej: clip-vit-l-14)
embedding_768d VECTOR(768) Vector de embedding (pgvector)
confidence_score FLOAT Confianza del embedding

3.3 identificacion_ia

Registro de cada identificación realizada por el motor de IA.

Columna Tipo Descripción
id UUID PK Identificador único
muestra_id UUID FK Muestra analizada
especie_sugerida_id UUID FK Especie propuesta por la IA
investigador_id UUID FK Quién solicitó la identificación
modelo_utilizado VARCHAR(100) Modelo (ej: qwen25-vl-7b)
confianza FLOAT Score de confianza (0.0 - 1.0)
top_k_similares JSONB Array de {muestra_id, score} similares
confirmada BOOLEAN Si el investigador validó el resultado

3.4 fuente_datos

Fuentes de datos externas monitorizadas dinámicamente. Configuradas desde la UI por Responsables de Departamento sin necesidad de despliegues. Ver MLOps y Workflows Agénticos para la arquitectura de dos niveles (YAML infra vs BBDD dinámica).

Columna Tipo Descripción
id UUID PK Identificador único
departamento_id UUID FK Departamento propietario
responsable_id UUID FK Investigador que creó/gestiona la fuente
nombre VARCHAR(200) Nombre descriptivo (ej: «Biometrías ECOMED 2025»)
tipo VARCHAR(50) sharepoint, gsheet, mqtt, oracle_cdc, copernicus
configuracion JSONB Datos de conexión: ruta, sheetId, topic, etc.
periodicidad VARCHAR(20) 15min, 1h, diario, tiempo_real
esquema_esperado JSONB JSON Schema para validación de entrada
activa BOOLEAN Pausar/activar sin reiniciar el sistema
ultima_ejecucion TIMESTAMP Última comprobación exitosa

3.5 modelo_registro

Registro de modelos de IA gestionados por MLflow. Cada fila representa una versión de un modelo desplegada o en staging.

Columna Tipo Descripción
id UUID PK Identificador único
departamento_id UUID FK Departamento al que sirve el modelo
nombre VARCHAR(100) Nombre del modelo (ej: YOLOv11-FathomNet)
version VARCHAR(20) Versión semántica (ej: v2.1)
stage VARCHAR(20) Staging, Production, Archived
dataset_entrenamiento VARCHAR(200) Dataset usado (ej: «ICES SmartDots + IEO»)
precision_val FLOAT Métrica de precisión en validación
vram_gb FLOAT VRAM requerida en GB
ruta_pesos VARCHAR(500) Ruta en MinIO a los pesos del modelo
mlflow_run_id VARCHAR(100) ID del run en MLflow para trazabilidad
desplegado_at TIMESTAMP Fecha de último despliegue a producción

4. Índices y Rendimiento

4.1 Índices PostgreSQL

-- Búsqueda por código interno del IEO
CREATE UNIQUE INDEX idx_muestra_codigo ON muestra(codigo_interno);

-- Búsqueda geográfica
CREATE INDEX idx_muestra_geo ON muestra(latitud, longitud);

-- Búsqueda temporal
CREATE INDEX idx_muestra_fecha ON muestra(fecha_captura);

-- Búsqueda por especie
CREATE INDEX idx_muestra_especie ON muestra(especie_id);

-- Búsqueda por colección
CREATE INDEX idx_muestra_colección ON muestra(coleccion_id);

-- Índice vectorial para búsqueda por similitud (pgvector)
CREATE INDEX idx_embedding_ivfflat ON embedding_vector
  USING ivfflat (embedding_768d vector_cosine_ops)
  WITH (lists = 100);

-- Búsqueda de identificaciones pendientes de confirmar
CREATE INDEX idx_identificacion_pendiente ON identificacion_ia(confirmada)
  WHERE confirmada = false;

-- Fuentes de datos activas por departamento
CREATE INDEX idx_fuente_activa ON fuente_datos(departamento_id, activa)
  WHERE activa = true;

-- Modelos en producción
CREATE INDEX idx_modelo_produccion ON modelo_registro(stage)
  WHERE stage = 'Production';

4.2 Rendimiento Esperado

Operación Objetivo Índice Utilizado
Búsqueda por código IEO < 1ms idx_muestra_codigo
Búsqueda por similitud vectorial (top-10) < 50ms idx_embedding_ivfflat
Listado por campaña + especie < 10ms idx_muestra_especie + idx_muestra_fecha
Identificaciones pendientes de confirmar < 5ms idx_identificacion_pendiente

5. Colecciones ChromaDB

ChromaDB almacena colecciones vectoriales optimizadas para búsqueda por similitud de imágenes.

5.1 Colecciones del MVP

Colección Contenido Metadata
ieo_specimens Embeddings de imágenes de especímenes especie, coleccion, fecha
ieo_otoliths Embeddings de microfotografías de otolitos especie, edad, zona
ieo_documents Embeddings de chunks de documentos tipo, departamento, fecha

5.2 Ejemplo de Inserción

collection = client.get_or_create_collection(
    name="ieo_specimens",
    metadata={"hnsw:space": "cosine"}
)

collection.add(
    ids=["specimen-001"],
    embeddings=[[0.12, -0.34, 0.56, ...]],  # 768d
    metadatas=[{
        "especie": "Mullus surmuletus",
        "coleccion": "CFM-HISTORICA-IEOMA",
        "fecha": "1907-01-01",
        "muestra_pg_id": "uuid-en-postgresql"
    }],
    documents=["Salmonete de roca, Mediterráneo occidental"]
)

6. Estrategia de Migraciones

6.1 Herramienta

  • Liquibase integrado con Quarkus (quarkus-liquibase)
  • Changesets en formato YAML/XML en /backend/src/main/resources/db/changelog/
  • Changelog master: db.changelog-master.yaml

6.2 Changesets Planificados

Changeset Descripción
001-create-schema.yaml Tablas base: departamento, investigador, colección, muestra, especie
002-create-ia-tables.yaml Tablas de IA: imagen_muestra, embedding_vector, identificacion_ia
003-create-indexes.yaml Índices de rendimiento y vectoriales
004-seed-taxonomia.yaml Datos iniciales: taxonomías del proyecto TAXON
005-seed-colecciones.yaml Datos iniciales: colecciones históricas CFM
006-create-fuente-datos.yaml Tabla de fuentes de datos dinámicas
007-create-modelo-registro.yaml Tabla de registro de modelos MLOps

7. Sincronización PostgreSQL — ChromaDB

sequenceDiagram
    participant API4 as Quarkus API
    participant PG2 as PostgreSQL
    participant EMB4 as Modelo Embeddings
    participant CHR3 as ChromaDB

    Note over API4: Al registrar nueva imagen
    API4->>PG2: INSERT imagen_muestra
    API4->>EMB4: Genera embedding
    EMB4-->>API4: Vector 768d
    API4->>PG2: INSERT embedding_vector
    API4->>CHR3: Upsert en colección
    Note over PG2,CHR3: PostgreSQL es fuente de verdad

[!IMPORTANT] PostgreSQL es la fuente de verdad. ChromaDB es un índice secundario optimizado para búsqueda vectorial. En caso de inconsistencia, se regenera la colección ChromaDB desde PostgreSQL.


Documentos Relacionados

Nivel Documento Descripción
Arquitectura Arquitectura del Sistema Visión general, stack, flujos
Arquitectura Arquitectura IA Pipeline IA, embeddings, modelos
Arquitectura MLOps y Workflows Agénticos FuenteDatos, ModeloRegistro, sistema agéntico
Investigación Gobernanza de Datasets Fuentes de datos, carga incremental
Investigación Bancos de Datos Animales Fuentes intl., APIs, datasets de imágenes, almacenamiento
Especificación API REST Endpoints que operan sobre estos datos
Infraestructura Docker Compose Servicios PostgreSQL, ChromaDB