Come funziona una query RAG

Con l’articolo di oggi chiudiamo il cerchio vedendo cosa accade quando l’utente pone una domanda:

Qual è il colore segreto del laboratorio AI?

il sistema esegue queste operazioni:

1️⃣ la domanda viene convertita in embedding
2️⃣ Qdrant cerca i vettori più simili
3️⃣ vengono recuperati i documenti rilevanti
4️⃣ il contesto viene inviato all’LLM
5️⃣ il modello genera la risposta

Flusso:

Domanda utente
|||

Embedding
|||

Qdrant search
|||

Documenti rilevanti
|||

LLM (Ollama)
|||

Risposta finale

Questo modello permette di ottenere risposte basate sui propri dati, non solo sulle conoscenze del modello.

Conclusioni

Con l’introduzione di Qdrant il laboratorio AI su Kubernetes diventa una vera piattaforma RAG completa.

L’architettura ora è composta da:

  • Ollama → esecuzione dei modelli LLM
  • Qdrant → database vettoriale
  • Open WebUI → gestione knowledge base e interfaccia utente

Questo stack consente di costruire rapidamente assistenti AI che rispondono utilizzando documentazione aziendale, manuali tecnici o dati proprietari.

Nel prossimo articolo vedremo come:

  • creare dataset strutturati
  • migliorare il chunking dei documenti
  • ottimizzare la qualità delle risposte del modello.

Nell’immagine in calce il riassunto di quello che è stato messo in esercizio nel laboratorio

Modello AI

Configurare OpenWebUI per generare allenamenti con RAG

Nei precedenti articoli abbiamo visto come funziona il Retrieval Augmented Generation (RAG) nel nostro laboratorio AI basato su Kubernetes.

In questo articolo vedremo come configurare OpenWebUI per permettere al modello di generare allenamenti di nuoto realistici utilizzando una knowledge base costruita con allenamenti reali.

Obiettivo: trasformare OpenWebUI in un assistente di coaching basato su AI.

Architettura del sistema

Il flusso di lavoro creato è il seguente:

Utente

OpenWebUI

RAG Engine

Qdrant (knowledge base)

Ollama (LLM locale)

Quando l’utente chiede di generare un allenamento:

  1. OpenWebUI interroga la knowledge base
  2. Qdrant restituisce i documenti più simili
  3. Il modello LLM utilizza quei documenti come contesto
  4. Viene generata una nuova seduta di allenamento

Preparazione della Knowledge Base

Il primo passo consiste nel caricare nella piattaforma gli allenamenti reali; nel nostro caso la libreria contiene diverse sedute organizzate per settimana:

week21_sessionA, week22_sessionB, week23_sessionC, week24_sessionA, week25_sessionB, week26_sessionA, week27_sessionA

Ogni documento contiene una seduta completa con la seguente struttura:

  • WARMUP
  • SENSITIVITY
  • TECHNIQUE
  • ACTIVATION
  • MAIN SET
  • COOLDOWN

Questi documenti costituiscono il corpus di conoscenza che il sistema utilizzerà per generare nuovi allenamenti.

Caricare i documenti nella sezione Knowledge

Dall’interfaccia di OpenWebUI:

  1. Aprire il menu laterale
  2. Selezionare Workspace
  3. Entrare nella sezione Knowledge
  4. Creare una nuova knowledge base

Nel mio lab dove le sessioni di allenamento sono specifiche per il nuoto la libreria è stata nominata swim_training_library.

Una volta creata la knowledge base è possibile caricare i documenti:

  • coach_training_rules.txt
  • week21_sessionA.txt
  • week22_sessionB.txt
  • week23_sessionC.txt

Durante l’upload OpenWebUI esegue automaticamente:

  • creazione degli embeddings
  • indicizzazione nel vector database Qdrant

In questo modo i documenti diventano interrogabili tramite ricerca semantica.

Creare un Prompt Skill

Una volta caricata la libreria è utile creare uno skill dedicato alla generazione degli allenamenti.

Gli Skills permettono di definire prompt riutilizzabili che guidano il comportamento del modello.

Nel nostro caso creiamo uno skill chiamato:

swim_workout_generator

All’interno dello skill possiamo inserire un prompt come il seguente.

“Generate a swim workout using the CSS methodology.

Rules:
– use only patterns from the knowledge base
– use zones A1 A2 B1 B2 C1 C2
– include sections:
WARMUP
SENSITIVITY
TECHNIQUE
ACTIVATION
MAIN SET
COOLDOWN
– total distance between 2000m and 2800m
– rest intervals between 10 and 30 seconds
– avoid generic descriptions”

Questo prompt permette di stabilizzare il comportamento del modello.

Collegare la Knowledge allo Skill

Durante la configurazione dello skill è possibile specificare la knowledge base da utilizzare.

Nel nostro caso selezioniamo:

swim_training_library

In questo modo ogni volta che lo skill viene utilizzato:

  • OpenWebUI esegue una ricerca nella knowledge base
  • i documenti più rilevanti vengono passati al modello

Questo è il cuore del RAG workflow.

Utilizzo dei Tools

OpenWebUI permette anche di aggiungere Tools.

I tools sono funzioni che il modello può richiamare per eseguire operazioni esterne.

Nel laboratorio verranno utilizzati per:

  • generare allenamenti
  • convertire gli allenamenti in formato Garmin
  • esportare i workout

Ad esempio nel prossimo step verrà aggiunto un tool Python per generare file di tipo .tcx compatibili con Garmin Connect.

Creare una Workspace dedicata

Per organizzare il lavoro è utile creare un workspac dedicato.

Ad esempio: AI Swim Coach

All’interno della workspace possiamo raccogliere:

  • la knowledge base degli allenamenti
  • gli skills di generazione
  • i tools di esportazione

Così facendo possiamo trasformare OpenWebUI in un vero ambiente di coaching AI.

Test del sistema

Una volta completata la configurazione possiamo testare il sistema.

Ad esempio con una richiesta come:

“Generate a 2500m swim workout using the CSS training methodology”.

Il sistema recupererà i documenti più rilevanti dalla libreria e produrrà un nuovo allenamento coerente con gli esempi reali.

NB: Il file coach_training_rules.txt è quello che spiega al modello come ragiona l’allenatore. Non contiene allenamenti, ma le regole del metodo

  • come sono strutturate le sedute
  • cosa significano le zone
  • quali esercizi sono ammessi
  • che stile deve avere l’allenamento

VEEAM ONE – Automatizzare l’avvio di una VM spenta

Monitorare lo stato delle macchine virtuali (VM) è fondamentale per garantire la continuità operativa dell’infrastruttura virtuale. Con Veeam ONE, puoi creare un allarme personalizzato per notificarti quando una macchina virtuale è spenta automatizzandone la ripartenza.


1. Accedi a Veeam ONE Monitor

  1. Apri Veeam ONE Monitor e accedi con le tue credenziali.
  2. Dal pannello di navigazione sulla sinistra, vai alla sezione Alarms (Allarmi).

2. Scegli l’ambito dell’allarme

Per configurare un allarme che monitora lo stato delle VM:

  1. Naviga nella gerarchia delle entità virtuali (come vCenter Server o cluster).
  2. Seleziona il livello di interesse. Per monitorare tutte le VM, scegli un livello superiore (es. l’intera infrastruttura). Se vuoi monitorare solo specifiche VM, selezionale manualmente.

3. Crea un Nuovo Allarme

  1. Fai clic su Create Alarm (Crea Allarme) nella barra degli strumenti.
  2. Assegna un nome all’allarme, ad esempio “VM Spenta”.
  3. Fornisci una descrizione chiara, come: “Questo allarme si attiva quando una VM è spenta per prevenire interruzioni di servizio non pianificate.”

4. Configura i Trigger dell’Allarme

I trigger definiscono le condizioni per l’attivazione dell’allarme. Per configurare il trigger:

  1. Vai alla scheda Rules (Regole).
  2. Fai clic su Add (Aggiungi) per creare una nuova regola.
  3. Seleziona il parametro VM state (Stato della VM) come criterio di monitoraggio.
  4. Sotto Condition (Condizione), scegli Equals (Uguale) e imposta il valore su Powered Off (Spenta).
  5. Puoi anche aggiungere un timer per evitare falsi positivi, ad esempio impostando il trigger affinché si attivi solo se la VM rimane spenta per più di 5 minuti.

5. Configura le Notifiche

Per ricevere notifiche quando l’allarme si attiva:

  1. Vai alla scheda Notifications (Notifiche).
  2. Seleziona il metodo di notifica preferito:
    • Email Notification: Configura gli indirizzi email dove inviare l’allarme.
    • Run Script: Puoi configurare uno script personalizzato per eseguire azioni specifiche.
  3. Specifica il contenuto della notifica, includendo dettagli come il nome della VM e l’ora in cui è stata spenta.

6. Salva e Attiva l’Allarme

  1. Fai clic su Finish (Fine) per salvare l’allarme.
  2. L’allarme sarà attivo e inizierà immediatamente a monitorare lo stato delle VM.

7. Testa il Funzionamento dell’Allarme

Per verificare che l’allarme funzioni correttamente:

  1. Spegni manualmente una macchina virtuale per simulare la condizione.
  2. Controlla se l’allarme appare nella sezione Triggered Alarms (Allarmi Attivati) del Veeam ONE Monitor.
  3. Verifica di aver ricevuto la notifica configurata.

Suggerimenti per l’Ottimizzazione

  • Filtri Specifici: Se non vuoi monitorare tutte le VM, applica filtri per escludere quelle che possono essere spente intenzionalmente, come macchine di test.
  • Azioni Proattive: Associa lo stato dell’allarme con l’esecuzione di uno script che accenda automaticamente la VM o avvisi un amministratore specifico.

Conclusione

Creare un allarme su Veeam ONE per monitorare lo stato di una VM spenta è semplice e ti permette di agire rapidamente in caso di problemi. Con questa configurazione, puoi migliorare la disponibilità del sistema e ridurre i tempi di inattività non pianificati.

Ricorda di rivedere e aggiornare periodicamente i criteri di allarme per garantire che rimangano pertinenti alle esigenze della tua infrastruttura.

VRO: Orchestrazione di un Servizio – Parte 1

Creazione delle 3 VM Ubuntu e installazione dei servizi Backend, Frontend e DB

Obiettivo

In questa prima parte della guida descriviamo come creare tre macchine virtuali Ubuntu e configurare ciascuna con i servizi necessari:

  • Frontend: server web statico con HTML
  • Backend: applicazione Node.js con API REST
  • DB01: server PostgreSQL

1. Creazione delle VM Ubuntu

Requisiti minimi per ciascuna VM

Sistema operativo: Ubuntu Server 22.04 LTS

CPU: 1 vCPU

RAM: 1-2 GB

Disco: 10 GB

Scheda di rete: Bridged o NAT (consigliato Bridged)

Nomi e indirizzi IP

VM Nome Host IP
Frontend frontend 192.168.16.151
Backend backend 192.168.16.152
DB01 db01 192.168.16.153

Configurare ogni VM con IP statico via Netplan.

2. Installazione e configurazione del Database (DB01)

Installazione di PostgreSQL

sudo apt update && sudo apt install postgresql -y

Creazione utente e database

sudo -u postgres psql
CREATE DATABASE myapp;
CREATE USER backend_user WITH ENCRYPTED PASSWORD ‘backend_pass’;
GRANT ALL PRIVILEGES ON DATABASE myapp TO backend_user;
\q

3. Installazione del Backend (backend)

sudo apt install nodejs npm -y

Struttura base del progetto

mio-backend/
├── server.js
├── db.js
├── routes/
│ └── users.js
├── package.json

Esempio di server.js

const express = require(‘express’);
const cors = require(‘cors’);
const app = express();

app.use(cors());
app.use(express.json());
const usersRoute = require(‘./routes/users’);
app.use(‘/api/users’, usersRoute);

app.listen(3000, () => {
console.log(‘Server backend in ascolto sulla porta 3000’);
});

Connessione al DB (db.js)

onst { Pool } = require(‘pg’);
const pool = new Pool({
user: ‘backend_user’,
host: ‘192.168.16.153’,
database: ‘myapp’,
password: ‘backend_pass’,
port: 5432,
});

module.exports = pool;

Installazione dipendenze

npm init -y
npm install express cors pg

4. Installazione del Frontend (frontend)

Creazione file index.html

<!DOCTYPE html>
<html>
<head>
<title>Gestione Utenti</title>
<script>
const backendURL = “http://192.168.16.152:3000/api/users”;
async function getUsers() {
const res = await fetch(backendURL);
const users = await res.json();
document.body.innerHTML += JSON.stringify(users);
}
window.onload = getUsers;
</script>
</head>
<body>
<h1>Lista Utenti</h1>
</body>
</html>

Installazione di un web server (es. Apache)

sudo apt install apache2 -y
sudo cp index.html /var/www/html/index.html

Nella prossima parte vedremo come configurare lo switch automatico di rete e IP per scenari di Disaster Recovery (DR) utilizzando Netplan e systemd.

Kasten K10 – Repository NFS e Policy di Backup

Dopo aver completato l’installazione di Kasten K10 sul cluster Kubernetes, il passo successivo è configurare una destinazione dove salvare i backup e creare la prima policy di protezione.

In questo articolo vedremo una configurazione minimale ma funzionante, utilizzando una share NFS come repository di backup.

Prerequisiti

  • Cluster Kubernetes funzionante
  • K10 installato
  • accesso alla console K10
  • una share NFS accessibile dal cluster

Nel laboratorio utilizzo una share NFS Western Digiatal che espone le proprie risorse al seguente indirizzo: 192.168.16.92:/mnt/HD/HD_a2/kasten-nfs.

Al fine di verificarne  i mount point esposti è necessario lanciare il comando  showmount -e 192.168.16.92  da qualsiasi nodo del cluster.
Per verificare successivamente che tale share sia disponibile seguite la seguente procedura sul nodo che preferite:

sudo mkdir -p /mnt/k10-nfs-test

sudo mount -t nfs -o vers=3 \
192.168.16.92:/mnt/HD/HD_a2/kasten-nfs \
/mnt/k10-nfs-test

Test:

Touch /mnt/k10-nfs-test/file-test.txt

Il repository è ora utilizzabile.

Ora passiamo alla console di K10 e aggiungiamo una Location Profile:

Aprire la dashboard di K10 e nel seguente percorso:

Settings
→ Location Profiles
→ Create New

Selezionate come provider NFS/SMB e configurate i parametri come indicato nella tabella sottostante:

parametro valore
Name nfs-wd
Server 192.168.16.92
Path /mnt/HD/HD_a2/kasten-nfs

Salvate la configurazione.

La Location Profile rappresenta la destinazione dove K10 esporterà le snapshot dei backup appena effettuati.

Nota: nel laboratorio per una pura necessità didattica ho utilizzato una configurazione kubernetes approach. Ho cioè creato una Storage Class NFS che permettesse la creazione di PV e PVC da utilizzare per l’export dei backup.

Creazione policy di Backup

Policies
→ Create Policy

Configurazione minimale:

parametro valore
Policy Type Backup
Namespace default (o quello desiderato)
Frequency Manual o Daily
Snapshot Enabled
Export Enabled

Nel campo Export Location selezionare il location profile appena creata:

Avvio del primo backup

Dopo aver salvato la policy è possibile avviarla manualmente selezionando Run Once

K10 eseguirà:

  • Snapshot dei volumi
  • Esportazione dei dati sul repository NFS

Lo stato può essere monitorato nella Dashboard

Conclusione

Con pochi passaggi è possibile configurare una protezione di base per il cluster Kubernetes.

La combinazione di:

  • snapshot storage
  • export su repository NFS
  • policy schedulate

permette di implementare rapidamente una strategia di backup e recovery per le applicazioni containerizzate.

Integrazione tra Open WebUI, Ollama e Qdrant

Nel deployment Kubernetes, Open WebUI deve conoscere:

  • endpoint Ollama
  • endpoint Qdrant
  • modello di embeddings

Nel nostro laboratorio la configurazione è definita tramite variabili d’ambiente:

  • OLLAMA_BASE_URL=http://ollama:11434
  • VECTOR_DB=qdrant
  • QDRANT_URI=http://qdrant:6333
  • RAG_EMBEDDING_ENGINE=ollama
  • RAG_EMBEDDING_MODEL=nomic-embed-text:latest

Possiamo verificarle direttamente nel deployment:

  • kubectl -n ai exec deploy/open-webui printenv | grep QDRANT

Output:

  • QDRANT_URI=http://qdrant:6333

In questo modo Open WebUI utilizza automaticamente Qdrant come database vettoriale.