Salta el contingut

Pràctica PR5073/03: Dashboard d'IA amb Metabase

Objectius

  • Desplegar Metabase amb Docker Compose i PostgreSQL
  • Dissenyar i crear una base de dades de prediccions d'IA
  • Connectar Metabase a la base de dades del model
  • Construir preguntes amb Query Builder i SQL natiu
  • Crear un dashboard de monitoratge complet
  • Configurar alertes i compartir el dashboard

Prerequisits

Requisit Detall
Temps estimat 8 hores
RAM mínima 4 GB
Docker Desktop v4.25+ instal·lat i funcionant
Coneixements SQL bàsic, conceptes de models d'IA

Introducció

En aquesta pràctica construiràs un sistema complet de monitoratge d'un model d'IA fictici (predicció de churn de clients) utilitzant Metabase com a eina de visualització.

Simularàs les dades que un model en producció real generaria i construiràs el dashboard que un equip de dades i una direcció empresarial necessitaria per prendre decisions.


Fase 1: Preparar l'entorn Docker

1.1 Estructura de directoris

mkdir -p practica-metabase/{data,init-sql}
cd practica-metabase

1.2 Docker Compose

Crea el fitxer docker-compose.yml:

version: '3.8'

services:
  # Base de dades per a les dades del model d'IA
  ia-db:
    image: postgres:16-alpine
    container_name: ia-db-[el-teu-nom]
    environment:
      POSTGRES_DB: ia_produccion
      POSTGRES_USER: ia_admin
      POSTGRES_PASSWORD: ia_password_2025
    volumes:
      - ./init-sql:/docker-entrypoint-initdb.d
      - ia_db_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ia_admin -d ia_produccion"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Base de dades per a la configuració de Metabase
  metabase-db:
    image: postgres:16-alpine
    container_name: metabase-db-[el-teu-nom]
    environment:
      POSTGRES_DB: metabase
      POSTGRES_USER: metabase
      POSTGRES_PASSWORD: metabase_password_2025
    volumes:
      - metabase_db_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U metabase"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Metabase
  metabase:
    image: metabase/metabase:latest
    container_name: metabase-[el-teu-nom]
    ports:
      - "3000:3000"
    environment:
      MB_DB_TYPE: postgres
      MB_DB_DBNAME: metabase
      MB_DB_PORT: 5432
      MB_DB_USER: metabase
      MB_DB_PASS: metabase_password_2025
      MB_DB_HOST: metabase-db
      MB_SITE_URL: http://localhost:3000
    depends_on:
      metabase-db:
        condition: service_healthy
      ia-db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "--fail", "-I", "http://localhost:3000/api/health"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 90s

volumes:
  ia_db_data:
  metabase_db_data:

1.3 Script SQL d'inicialització

Crea el fitxer init-sql/01_schema.sql:

-- Esquema per a les dades del model d'IA

-- Taula de models
CREATE TABLE models (
    id          SERIAL PRIMARY KEY,
    nom         VARCHAR(100) NOT NULL,
    versio      VARCHAR(20) NOT NULL,
    tipus       VARCHAR(50) NOT NULL,  -- classificacio, regressio, nlp...
    actiu       BOOLEAN DEFAULT TRUE,
    created_at  TIMESTAMP DEFAULT NOW()
);

-- Taula de prediccions
CREATE TABLE prediccions (
    id              SERIAL PRIMARY KEY,
    model_id        INTEGER REFERENCES models(id),
    client_id       INTEGER NOT NULL,
    prediccio       VARCHAR(50) NOT NULL,   -- 'churn' o 'no_churn'
    valor_real      VARCHAR(50),            -- NULL fins que es confirma
    confianca       FLOAT NOT NULL,         -- 0.0 a 1.0
    correcta        BOOLEAN,                -- NULL fins que es confirma
    latencia_ms     INTEGER NOT NULL,
    segment_client  VARCHAR(50),            -- premium, standard, basic
    regio           VARCHAR(50),
    created_at      TIMESTAMP NOT NULL
);

-- Índexs per a millor rendiment
CREATE INDEX idx_pred_model ON prediccions(model_id);
CREATE INDEX idx_pred_created ON prediccions(created_at);
CREATE INDEX idx_pred_correcta ON prediccions(correcta);

-- Usuari de només lectura per a Metabase
CREATE USER metabase_ro WITH PASSWORD 'metabase_ro_2025';
GRANT CONNECT ON DATABASE ia_produccion TO metabase_ro;
GRANT USAGE ON SCHEMA public TO metabase_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO metabase_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO metabase_ro;

Crea el fitxer init-sql/02_data.sql per generar dades de prova:

-- Inserir models
INSERT INTO models (nom, versio, tipus) VALUES
    ('Predictor Churn v1', '1.0.0', 'classificacio'),
    ('Predictor Churn v2', '2.1.3', 'classificacio'),
    ('Segmentador Clients', '1.2.0', 'classificacio');

-- Generar 90 dies de prediccions (script PL/pgSQL)
DO $$
DECLARE
    segments VARCHAR[] := ARRAY['premium', 'standard', 'basic'];
    regions  VARCHAR[] := ARRAY['nord', 'sud', 'est', 'oest', 'centre'];
    pred     VARCHAR;
    real_v   VARCHAR;
    conf     FLOAT;
    correcta BOOLEAN;
    lat      INTEGER;
    i        INTEGER;
    dia      TIMESTAMP;
    model_id INTEGER;
BEGIN
    FOR day_offset IN 0..89 LOOP
        dia := NOW() - (day_offset || ' days')::INTERVAL;

        -- Model v2 (actiu, 80 prediccions/dia)
        FOR i IN 1..80 LOOP
            conf := 0.60 + random() * 0.39;
            -- Accuracy decreix lleugerament en els últims 7 dies (drift)
            IF day_offset < 7 THEN
                correcta := random() < 0.88;
            ELSE
                correcta := random() < 0.94;
            END IF;

            IF random() < 0.23 THEN
                pred := 'churn';
            ELSE
                pred := 'no_churn';
            END IF;

            IF correcta THEN
                real_v := pred;
            ELSIF pred = 'churn' THEN
                real_v := 'no_churn';
            ELSE
                real_v := 'churn';
            END IF;

            lat := 80 + (random() * 300)::INTEGER;
            IF day_offset < 3 THEN lat := lat + 150; END IF; -- latència alta recent

            INSERT INTO prediccions (
                model_id, client_id, prediccio, valor_real, confianca,
                correcta, latencia_ms, segment_client, regio, created_at
            ) VALUES (
                2,
                (1000 + (random() * 9000)::INTEGER),
                pred,
                real_v,
                ROUND(conf::NUMERIC, 4),
                correcta,
                lat,
                segments[1 + (random() * 2)::INTEGER],
                regions[1 + (random() * 4)::INTEGER],
                dia + (random() * INTERVAL '23 hours')
            );
        END LOOP;

        -- Model v1 (antic, 30 prediccions/dia, menys accuracy)
        FOR i IN 1..30 LOOP
            conf := 0.55 + random() * 0.35;
            correcta := random() < 0.87;
            IF random() < 0.25 THEN pred := 'churn'; ELSE pred := 'no_churn'; END IF;
            IF correcta THEN real_v := pred;
            ELSIF pred = 'churn' THEN real_v := 'no_churn';
            ELSE real_v := 'churn'; END IF;

            INSERT INTO prediccions (
                model_id, client_id, prediccio, valor_real, confianca,
                correcta, latencia_ms, segment_client, regio, created_at
            ) VALUES (
                1,
                (1000 + (random() * 9000)::INTEGER),
                pred, real_v,
                ROUND(conf::NUMERIC, 4),
                correcta,
                100 + (random() * 500)::INTEGER,
                segments[1 + (random() * 2)::INTEGER],
                regions[1 + (random() * 4)::INTEGER],
                dia + (random() * INTERVAL '23 hours')
            );
        END LOOP;
    END LOOP;
END $$;

Fase 2: Engegar i configurar Metabase

# Engegar tots els serveis
docker compose up -d

# Esperar ~90 segons i comprovar
docker compose logs metabase | tail -20

Obre http://localhost:3000 i configura el compte d'administrador.

2.1 Connectar la base de dades d'IA

  1. AdminDatabasesAdd a database
  2. Selecciona: PostgreSQL
  3. Configuració:
Display name: Prediccions Model Churn
Host: ia-db
Port: 5432
Database name: ia_produccion
Username: metabase_ro
Password: metabase_ro_2025
  1. Fes clic a Save i espera que la connexió es verifiqui.

Fase 3: Crear les preguntes

Crea les següents preguntes a Metabase i guarda-les a una col·lecció PR5073/03 - [el teu nom].

Pregunta 1: Accuracy del model v2 per dia (Query Builder)

  • Font: prediccions
  • Filtra: model_id = 2 i created_at >= últims 30 dies
  • Agrupa per: created_at (per dia)
  • Mètrica: % de correcta = true
  • Visualització: Línia
  • Afegeix una línia de referència a 0.90 (90%)

Pregunta 2: Comparació d'accuracy entre models (SQL)

SELECT
    m.nom AS model,
    DATE_TRUNC('week', p.created_at) AS setmana,
    COUNT(*) AS total,
    ROUND(AVG(CASE WHEN p.correcta THEN 1.0 ELSE 0.0 END)::NUMERIC, 3) AS accuracy,
    ROUND(AVG(p.confianca)::NUMERIC, 3) AS confianca_mitjana
FROM prediccions p
JOIN models m ON p.model_id = m.id
WHERE p.created_at >= NOW() - INTERVAL '60 days'
GROUP BY 1, 2
ORDER BY 2 DESC, 1;

Visualització: Línia amb múltiples sèries (una per model)

Pregunta 3: Distribució de prediccions per segment (Query Builder)

  • Font: prediccions
  • Filtra: model_id = 2 i created_at: últims 7 dies
  • Agrupa per: segment_client
  • Mètrica: COUNT i % correcta
  • Visualització: Barres agrupades

Pregunta 4: Latència P95 per dia (SQL)

SELECT
    DATE_TRUNC('day', created_at) AS dia,
    ROUND(PERCENTILE_CONT(0.50) WITHIN GROUP (ORDER BY latencia_ms)::NUMERIC, 0) AS p50_ms,
    ROUND(PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY latencia_ms)::NUMERIC, 0) AS p95_ms,
    MAX(latencia_ms) AS max_ms
FROM prediccions
WHERE model_id = 2
  AND created_at >= NOW() - INTERVAL '30 days'
GROUP BY 1
ORDER BY 1;

Visualització: Línia. Afegeix línia de referència a 500ms.

Pregunta 5: KPI Accuracy actual (número)

  • Font: prediccions
  • Filtra: model_id = 2 i created_at: avui
  • Mètrica: % correcta = true
  • Visualització: Número (gran, centrat)

Pregunta 6: Taula d'errors recents (SQL)

SELECT
    p.created_at,
    p.client_id,
    p.prediccio,
    p.valor_real,
    ROUND(p.confianca::NUMERIC, 3) AS confianca,
    p.segment_client,
    p.regio
FROM prediccions p
WHERE p.model_id = 2
  AND p.correcta = FALSE
  AND p.created_at >= NOW() - INTERVAL '7 days'
ORDER BY p.created_at DESC
LIMIT 50;

Visualització: Taula


Fase 4: Construir el dashboard

  1. NouDashboard → Nom: Monitor Model Churn - PR5073/03 [nom]
  2. Afegeix totes les preguntes creades
  3. Organitza el layout:
[KPI Accuracy]  [KPI Total pred.]  [KPI Latència P95]  [KPI % Churn]
[─────────────────────────────────────────────────────────────────────]
[Accuracy per dia — últims 30d (línia)   |  Per segment (barres)     ]
[─────────────────────────────────────────────────────────────────────]
[Comparació v1 vs v2 (línia multi-sèrie)                             ]
[─────────────────────────────────────────────────────────────────────]
[Latència P50/P95 (línia)               |  Errors recents (taula)   ]
  1. Afegeix filtres globals:
  2. Data: rang de dates (connectat a totes les preguntes)
  3. Model: selecció de model (connectat a les preguntes que filtren per model_id)

  4. Guarda el dashboard.


Fase 5: Alertes i subscripcions

Alerta d'accuracy baixa

  1. Obre la pregunta "KPI Accuracy actual"
  2. Fes clic a la campaneta (Alerts) → Create an alert
  3. Configura:
  4. Condició: Valor < 0.90
  5. Freqüència: cada hora
  6. Notificació: al teu email

Subscripció setmanal

  1. Obre el dashboard
  2. SubscriptionsEmail it
  3. Configura:
  4. Recipients: el teu email
  5. Freqüència: setmanal, dilluns a les 8:00
  6. Format: PDF

Lliurament

Lliura al campus virtual:

  • Fitxer docker-compose.yml
  • Fitxers SQL d'inicialització (init-sql/)
  • Captura del dashboard complet (tots els cards visibles)
  • Captura de cada una de les 6 preguntes amb les dades i la visualització
  • Captura de la configuració de l'alerta d'accuracy
  • Captura de la configuració de la subscripció setmanal
  • Captura de la URL pública del dashboard (si l'habilites)
  • Document de reflexió (max 1 pàgina):
  • Per quin ús real d'IA seria útil aquest dashboard?
  • Quines mètriques afegiries si fos un projecte real?
  • Quan triaries Power BI en lloc de Metabase?

Rúbrica d'avaluació

Veure Rúbrica PR5073/03