Sto cercando di capire come funzioni una IA. Non mi riferisco alla matematica o agli algoritmi che ci sono dietro, ma alla composizione di un qualcosa da interrogare, possibilmente open source e possibilmente che sfrutti la scheda grafica Intel B580 del server in cantina.
Un po’ di terminologia
- ollama, è una specie di frontend che espone in maniera semplificata (ma non ancora semplice) le potenzialità di una IA, in particolare di quella che si chiama llama.cpp. ollama offre funzionalità per scaricare e gestire i vari modelli, offre una interfaccia REST per l’accesso alla IA, e cose simii;
- llama.cpp, è un motore di inferenza scritto in C++ che utilizza i modelli GGUF e che ha la possibilità di accelerare grazie all’hardware delle schede video. Una caratteristica di llama.cpp è che se il modello in uso utilizza più RAM di quanta ne abbia la scheda video, allora viene usata anche la memoria RAM del computer;
- Open-WebUI, è una interfaccia web che permette l’interazione con un motore di inferenza tramite i protocolli di ollama oppure di OpenAI;
- quantizzazione, indicata con sigle tipo Q4_K_M, Q5_K_M, è una modalità di memorizzazione del modello in formato ridotto: anziché contenere i pesi interi da 16 e 32 bit in virgola mobile, si memorizzano valori approssimati usando meno bit. Il metodo per approssimare prevede di usare fattori di scala e altri stratagemmi, che valgono spesso per più quanti successivi, da cui l’opzione del raggruppamento. La lettera Q indica appunto che parliamo di quantizzazione, il numero successivo indica il numero di bit occupati da ogni quanto, la lettera K indica che la quantizzazione è fatta a gruppi ed è contrapposta al numero 0 che indica una quantizzazione non raggruppata, la lettera M indica una precisione media contrapposta alle lettere S (precisione piccola, maggiore velocità) e L (grande precisione, maggiore lentezza);
- perplexity, se si utilizza la quantizzazione si va incontro ad una approssimazione, quindi ad un errore. Per misurare questo errore si fa riferimento ad un valore chiamato perplexity: minore è il valore, migliore è l’approssimazione;
- GGUF, è un formato di file binari che descrivono un modello. Si tratta di una sigla inglese che vuol dire «Formato unificato generato da GPT». Questo formato è l’evoluzione del precedente, chiamato GGML «Linguaggio modello generato da GPT». Il formato GGUF è adottato da vari motori di inferenza;
- SYCL: è uno dei backend che permettono di sfruttare la scheda video, in particolare è quello utilizzato fino a gennaio 2026 da pkix-llm per utilizzare le schede Intel;
- vulkan, è un backend per utilizzare le schede video, ma più generico del SYCL, difatti gestisce schede video Intel, AMD e nVidia e funziona su Linux, MacOS e Windows,
- ROCm, è un backend per utilizzare le schede video AMD.
Proviamo!
Partiamo dal compilare llama.cpp per farne una immagine da usare con docker. Il progetto llama.cpp ha già un dockerfile che prepara un immagine con il compilatore (attualmente basata su Ubuntu 26.04) e che viene lanciata per compilare il tutto e creare una immagine docker finale. La compilazione dura pochi minuti e genera l’immagine llama-cpp-vulkan già pronta tra quelle di docker.
# git clone https://github.com/ggml-org/llama.cpp.git
# cd llama.cpp.git
# docker build -t llama-cpp-vulkan -f .devops/vulkan.Dockerfile .
[...]
# docker image ls llama-cpp-vulkan
REPOSITORY TAG IMAGE ID CREATED SIZE
llama-cpp-vulkan latest 83854865d087 5 minutes ago 501MB
Facciamo un primo test, che attiva il container, controlla e riconosce l’hardware e scarica un piccolo modello. Per dare dello spazio disco nel quale scaricare il modello, uso la mia directory /srv/nfs/docker/modelli_ollama/models:
# docker run -it --rm -v "/srv/nfs/docker/modelli_ollama/models:/root/.cache/llama.cpp:Z" --device /dev/dri/renderD128:/dev/dri/renderD128 --device /dev/dri/card0:/dev/dri/card0 llama-cpp-vulkan -hf ggml-org/gemma-3-1b-it-GGUF
[...]
ggml_vulkan: 0 = Intel(R) Arc(tm) B580 Graphics (BMG G21) (Intel open-source Mesa driver) | uma: 0 | fp16: 1 | bf16: 1 | warp size: 32 | shared memory: 49152 | int dot: 1 | matrix cores: KHR_coopmat
load_backend: loaded Vulkan backend from /app/libggml-vulkan.so
load_backend: loaded CPU backend from /app/libggml-cpu-haswell.so
common_download_file_single_online: no previous model file found /root/.cache/llama.cpp/ggml-org_gemma-3-1b-it-GGUF_preset.ini
[...]
llama_model_load_from_file_impl: using device Vulkan0 (Intel(R) Arc(tm) B580 Graphics (BMG G21)) (0000:0a:00.0) - 3366 MiB free
[...]
Usiamo le immagini già pronte
Al di là di compilare la propria immagine e poi creare l’immagine docker, è anche possibile utilizzare l’immagine standard, quella fatta e tenuta aggiornata direttamente dagli sviluppatori di ollama, la quale all’interno ha i vari backend. Per farlo io ho utilizzato questo file docker che definisce due container, uno per ollama e uno per l’interfaccia web:
services:
ollama-vk:
image: ollama/ollama
container_name: ollama-vk
restart: always
networks: [ ml_shared ]
ports:
- "11434:11434"
devices:
- /dev/dri:/dev/dri
environment:
OLLAMA_HOST: "0.0.0.0"
OLLAMA_VULKAN: 1
volumes:
- /srv/nfs/docker/modelli_ollama:/root/.ollama
openwebui:
image: ghcr.io/open-webui/open-webui:main
container_name: openwebui
restart: always
networks: [ ml_shared ]
depends_on:
- ollama-vk
ports:
- "3000:8080"
environment:
OLLAMA_BASE_URL: "http://ollama-vk:11434"
networks:
ml_shared:
volumes:
ollama_models:
Questo testo, se copiato in un file chiamato docker-compose.yml, permette di attivare tutto ciò che serve. Notare che nella sezione «devices» ho fatto in modo da far vedere nel container il device /dev/dri che da accesso alla scheda video, mentre nella sezione «volumes» ho fatto sì che i modelli non finiscano dentro l’immagine del container, ma su un file system esterno, persistente. In questo modo quando l’immagine verrà aggiornata, non perderò i modelli scaricati.
Una volta attivato questi container di docker, posso controllare se siano veramente attivi in questo modo:
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9382e06bb799 ghcr.io/open-webui/open-webui:main "bash start.sh" 27 minutes ago Up 27 minutes (healthy) 0.0.0.0:3000->8080/tcp, :::3000->8080/tcp openwebui
66487bef49b8 ollama/ollama "/bin/ollama serve" 27 minutes ago Up 27 minutes 0.0.0.0:11434->11434/tcp, :::11434->11434/tcp ollama-vk
e poi collegarmi al Open-WebUi con un browser all’indirizzo http://localhost:3000/ , ma posso collegarmici anche da altri computer sostituendo «localhost» con il nome o l’indirizzo IP del server.
Alla prima connessione sarà necessario creare un account amministratore indicando un nome utente, un indirizzo email e una password. Non ho ancora capito dove queste informazioni vadano a finire, ma se lo scoprissi sarebbe utile impostare, anche per il container dell’interfaccia web, un volume esterno all’immagine, in modo che questi account siano persistenti.
