L'IA dentro la tua libreria di foto, e perché l'abbiamo spostata sulle nostre GPU

L'IA dentro la tua libreria di foto, e perché l'abbiamo spostata sulle nostre GPU

Quando cerchi «cane nella neve» nella tua libreria di foto e compare l’immagine giusta, qualcosa ha già letto quella foto per te. Nessuno l’ha etichettata. Un modello di machine learning ha guardato i pixel, ha deciso cosa c’era nell’inquadratura e ha memorizzato quella comprensione perché tu potessi ritrovarla in seguito. Di recente abbiamo spostato questo lavoro dalle CPU alle nostre GPU (graphics processing units, unità di elaborazione grafica). Questo articolo spiega cosa fa davvero l’IA e perché conta l’hardware che la sostiene.

I modelli che rendono possibile tutto questo non sono nostri. Provengono dal progetto open source Immich su cui è costruito PixelUnion. Ciò che è nostro è dove vengono eseguiti: su hardware che possediamo e gestiamo noi stessi, su suolo europeo, non in un cloud IA di terzi. I modelli leggono le tue foto, e per noi conta che lo facciano nei nostri rack e da nessun’altra parte.

C’è una distinzione da fare prima di andare avanti, perché è quella che conta di più per la tua privacy. Usare un modello non è la stessa cosa che addestrarlo. L’addestramento è il processo costoso e una tantum in cui un modello impara da milioni di immagini di esempio, e viene svolto dagli autori del modello molto prima che arrivi a noi. Quello che facciamo noi è inferenza: prendiamo un modello finito, già addestrato, e facciamo passare la tua foto una sola volta per ottenere un risultato, come fai passare un documento in uno scanner. Le tue foto non vengono mai usate per insegnare qualcosa ai modelli. Non vengono aggiunte a un set di addestramento, non migliorano un modello condiviso e nulla di esse esce per rendere più intelligente una versione futura. Il modello guarda la tua foto, dà la sua risposta e la dimentica.


Tre compiti, un trucco condiviso: rendere ricercabili i pixel

Immich esegue la sua IA in un servizio separato, il container immich-machine-learning, documentato nel README di machine learning del progetto. Svolge tre compiti, e ciascuno risolve un problema diverso:

  • La ricerca intelligente trasforma una foto in qualcosa che puoi cercare con il linguaggio comune, tramite un modello CLIP.
  • Il riconoscimento facciale trova i volti e stabilisce quali appartengono alla stessa persona, tramite un pacchetto di modelli come buffalo_l.
  • L’OCR legge il testo che compare nelle tue foto, tramite un modello PP-OCRv5.

Vale la pena essere precisi qui, perché «tre modelli» è una semplificazione. Due di questi compiti sono in realtà una coppia di modelli che lavorano in sequenza, e ogni compito può essere sostituito con un modello diverso. Il riconoscimento facciale esegue un modello di rilevamento seguito da un modello di riconoscimento, e buffalo_l è un pacchetto che li contiene entrambi. Immich offre anche alternative come antelopev2, buffalo_m e buffalo_s. L’OCR funziona allo stesso modo, un modello per trovare il testo e un altro per leggerlo. E CLIP stesso è una coppia di encoder, uno per le immagini e uno per il testo, con molte varianti intercambiabili. Non esiste alcun modello di rilevamento oggetti separato: riconoscere che una foto contiene un cane o una spiaggia è gestito da CLIP, non da un modello di etichettatura dedicato.

Ciò che conta per capirli è che tutti e tre i compiti condividono un unico trucco di fondo. Capiamo quindi prima quel trucco. Dopodiché, le differenze acquistano senso.

Rilevamento e riconoscimento dei volti in due fasi


CLIP: cercare per significato, non per etichette

La vecchia ricerca fotografica si basava sui nomi dei file e sulle etichette manuali. Se non avevi scritto «spiaggia» in una didascalia, cercare «spiaggia» non trovava nulla. CLIP, un modello pubblicato originariamente da OpenAI (articolo qui), rimuove questo limite. Guarda il contenuto effettivo di un’immagine.

Ecco la parte su cui la gente inciampa, spiegata in modo semplice. CLIP non memorizza un elenco di parole per ogni foto. Converte ogni foto in un vettore: un lungo elenco di numeri, qualche centinaio, che insieme descrivono il significato dell’immagine. Una foto di un husky nella neve fresca e una foto di un altro cane nella neve finiscono con elenchi di numeri simili, perché significano cose simili. Quell’elenco si chiama embedding.

Cos’è davvero la ricerca vettoriale

Una volta che ogni foto nella tua libreria è un vettore, memorizziamo tutti questi vettori in un database. La ricerca funziona così:

  1. Scrivi «cane nella neve».
  2. Lo stesso modello trasforma le tue parole in un vettore, con lo stesso sistema di numeri delle foto.
  3. Il database confronta il tuo vettore di ricerca con i vettori delle foto memorizzati e misura quanto è vicino ciascuno.
  4. Le corrispondenze più vicine tornano per prime.

«Vicino» qui è matematica. Ogni vettore è un punto nello spazio, e il sistema misura la distanza tra la tua query e ogni foto. Nella forma più semplice è forza bruta: controllare la distanza da ogni singola foto, ordinare in base alla più vicina. In quel processo non c’è mai corrispondenza di etichette né ricerca per parola chiave. Una foto senza didascalia, senza nome di file e senza descrizione emerge comunque, perché il suo significato vive nei numeri.

Come la ricerca vettoriale trova le foto più vicine alla tua query

Quel confronto a forza bruta è la versione onesta, e per una libreria normale funziona bene. Nomina anche il costo. Confrontare una query con milioni di vettori, uno alla volta, diventa lento. Su larga scala si passa a indici più intelligenti, la ricerca approssimata dei vicini più prossimi, che salta la maggior parte dei confronti e trova comunque i risultati giusti. Quale approccio serve dipende dalle dimensioni della libreria, ma il principio resta lo stesso: trasformare tutto in vettori, poi trovare i più vicini.

Un’altra cosa che conta in Europa. Il modello CLIP predefinito gestisce bene l’inglese e male le altre lingue. Esistono varianti multilingue, e Immich ti permette di sostituirle, come descrive la sua guida alla selezione del modello. Il compromesso è reale: i migliori modelli multilingue sono più grandi e hanno bisogno di più memoria per funzionare. Questa pressione sulla memoria è uno dei motivi per cui la scelta dell’hardware inizia a contare, e ci arriviamo.


buffalo_l: ritrovare la stessa persona in tutte le tue foto

Il riconoscimento facciale in Immich usa buffalo_l, un pacchetto di modelli del progetto InsightFace, ospitato per Immich su Hugging Face. Funziona in due fasi, ed entrambe vale la pena capirle, perché spesso si suppone che faccia qualcosa che non fa.

La prima fase è il rilevamento. Il modello scansiona l’immagine e stabilisce dove sono i volti. Pensa al quadratino di messa a fuoco che una fotocamera disegna attorno a un volto, solo che il modello lo fa a posteriori, su ogni foto. Il risultato è un insieme di riquadri: ecco un volto, eccone un altro.

La seconda fase è il riconoscimento. Per ogni volto trovato, il modello produce un vettore, la stessa idea di CLIP ma calibrata sui volti. Puoi vederlo come un’impronta numerica di quel volto. Due foto della stessa persona, con luce diversa e da angolazioni diverse, producono vettori che stanno vicini. Due persone diverse stanno lontane.

Questo è l’intero meccanismo dietro «persone» nella tua libreria. Non cerchiamo il tuo volto in alcun database esterno, e nulla porta un nome finché non scegli tu stesso di etichettare una persona. Il modello misura la geometria di un volto e la trasforma in numeri, poi raggruppa i numeri vicini. La guida ai cluster di volti di Immich descrive come si può regolare quel raggruppamento. Le impronte restano nel nostro sistema, sul nostro hardware. Non sono mai il prodotto.


PP-OCRv5: leggere il testo dentro le tue immagini

Il più recente dei tre è l’OCR, il riconoscimento ottico dei caratteri, aggiunto in Immich versione 2.2. Usa PP-OCRv5, un modello del progetto PaddleOCR di Baidu. L’OCR è ciò che ti permette di cercare parole che compaiono dentro una foto: un cartello stradale, una vetrina, una lavagna, l’etichetta di una bottiglia.

Anche questo funziona in due fasi, e la suddivisione rispecchia il riconoscimento facciale.

Prima rileva il testo. Il modello trova le regioni dell’immagine che contengono scrittura e vi disegna intorno dei riquadri, allo stesso modo in cui il modello dei volti inquadra i volti. Una foto di una strada può avere testo in cinque punti: un cartello, una targa, un manifesto, un menù, un autobus. Ciascuno diventa un riquadro.

Poi legge. Per ogni riquadro, un secondo modello stabilisce quali caratteri ci sono davvero e li trasforma in testo reale, leggibile dalla macchina. Quel testo va nell’indice di ricerca, così più tardi puoi cercare «pizzeria» e trovare la foto della facciata del ristorante, anche se non hai mai scritto una didascalia.

Il compromesso è uno di quei dettagli tipici di Marc che vale la pena segnalare: l’OCR è bravo con il testo stampato nitido negli alfabeti supportati, e molto più debole con la scrittura a mano o i font molto stilizzati. Immich supporta ufficialmente inglese, cinese e giapponese, mentre le lingue con alfabeto latino in genere funzionano con una precisione un po’ inferiore, come discusso nel thread sulle lingue OCR del progetto. È una funzione davvero utile, non magica.


Perché tutto questo gira molto meglio su una GPU

Ogni modello qui sopra svolge sotto la superficie lo stesso tipo di aritmetica: enormi quantità di piccole moltiplicazioni e addizioni, organizzate come calcolo matriciale. Trasformare una foto in un vettore sono milioni di queste operazioni. Questo solo fatto spiega tutta la storia dell’hardware.

Una CPU ha un piccolo numero di core molto capaci, da una manciata a un paio di dozzine. Ogni core è flessibile e veloce, e affronta i compiti in gran parte in sequenza. Questo design è eccellente per il lavoro vario e ramificato che un server svolge tutto il giorno. Si adatta male a fare la stessa moltiplicazione semplice qualche milione di volte di fila.

Una GPU è l’opposto. Ha migliaia di core più semplici, costruiti per eseguire la stessa operazione contemporaneamente su enormi lotti di numeri, in parallelo. Le schede grafiche sono state progettate per ombreggiare milioni di pixel simultaneamente, e si scopre che l’inferenza di machine learning è lo stesso tipo di problema: la stessa matematica, ripetuta su molti dati. Così, invece che i milioni di operazioni di una foto scorrano onda dopo onda attraverso pochi core di CPU, si distribuiscono insieme su migliaia di core di GPU.

Una CPU con pochi core grandi rispetto a una GPU con molti core piccoli

Il risultato non è un piccolo miglioramento, è un ordine di grandezza di velocità diverso per questo specifico carico di lavoro. Immich offre esattamente questo nella sua documentazione sull’accelerazione hardware, che consente al servizio di machine learning di girare su CUDA, ROCm o OpenVINO invece che sulla CPU. Le segnalazioni della community danno un’idea della scala. Su CPU, la ricerca intelligente è costantemente il più lento dei compiti di machine learning, e gli utenti la descrivono come il collo di bottiglia nell’indicizzazione di una libreria grande. Su hardware GPU modesto, un resoconto documenta l’embedding di circa 300.000 foto in meno di una notte. Sono cifre esterne, tratte dalle configurazioni di altre persone, non nostre, ma la direzione è coerente ovunque: la GPU smaltisce l’arretrato in una frazione del tempo.

Le schede che abbiamo scelto sono vecchie schede grafiche di consumo, non nuovi acceleratori da data center. È una scelta deliberata, e porta con sé compromessi che vale la pena nominare. Una scheda del genere ha ancora migliaia di core paralleli e memoria integrata sufficiente a contenere questi modelli comodamente, ed è tutto ciò di cui questo carico di lavoro ha bisogno. I modelli non sono grandi per gli standard odierni. CLIP è il più pesante dei tre, mentre i modelli di volto e OCR sono relativamente leggeri. Riutilizzare hardware vecchio ma capace tiene in servizio del buon silicio invece di metterlo su uno scaffale, e mantiene l’intera pipeline su apparecchiature che ci appartengono del tutto.

C’è un costo reale dall’altra parte della bilancia, e sostenere il contrario sarebbe disonesto. Una GPU assorbe più energia sotto carico di una CPU inattiva, e gestire il proprio hardware significa che ci facciamo carico noi della manutenzione, dei driver e dell’elettricità. Riteniamo sia il compromesso giusto. Per foto elaborata, la GPU fa il lavoro con un’efficienza molto migliore, e significa che l’IA che legge i tuoi ricordi gira su macchine che controlliamo, secondo il diritto europeo, invece di essere spedita nel cloud di qualcun altro per l’elaborazione.

Per ora eseguiamo i modelli predefiniti di Immich, gli stessi che qualsiasi utente di Immich ottiene di serie. Il motivo per cui questo passo hardware va oltre la velocità è il margine. I modelli più grandi in genere hanno bisogno di più potenza di calcolo e più memoria per girare a un ritmo utilizzabile, esattamente ciò che una CPU non poteva fornire. Con le nostre GPU al loro posto, eseguire una variante di CLIP più grande per una ricerca più precisa, o un modello di volto più pesante per un raggruppamento migliore, diventa un’opzione pratica invece che un’impossibilità. Qui non facciamo promesse su modelli specifici. Il punto è che questo passo apre la porta, e risultati migliori per i nostri clienti sono il motivo per attraversarla.

C’è un tranello nel passaggio a un modello più grande, ed è meglio essere schietti al riguardo. Un modello diverso produce vettori diversi. I numeri che un modello CLIP assegna a una foto non significano nulla per un altro modello CLIP, quindi non puoi mescolare il vecchio e il nuovo. Se un giorno passassimo a un modello più grande, dovremmo ricalcolare gli embedding di ogni foto nella libreria di ogni utente da zero, sulle nostre GPU. Per una grande base di utenti è una quantità enorme di calcolo, ed è esattamente il tipo di lavoro che su CPU è senza speranza e su GPU è solo grande. Questo passo ci avvicina all’essere pronti per questo, ma non ci siamo ancora. Quando lo saremo, meriterà un articolo a sé.


Perché lo facciamo noi stessi

Nessuno di questi modelli è esotico, e nessuno è segreto. È la natura del costruire su open source: puoi leggere esattamente cosa fanno CLIP, buffalo_l e PP-OCRv5, e possiamo farlo anche noi. La decisione che davvero plasma la tua privacy non è quale modello viene eseguito, ma dove viene eseguito e chi lo gestisce.

Li eseguiamo sulle nostre GPU, nel nostro ambiente, su suolo europeo. Le tue foto vengono lette da macchine di cui siamo responsabili, e i vettori e le impronte che escono da quel processo restano con noi e non vengono mai venduti. È la parte che Big Tech non ti offrirà, perché per loro leggere le tue foto è il modello di business, non una funzione.

Per essere chiari su dove siamo: questo è un primo passo, non il quadro finito. I modelli di machine learning ora girano sulle nostre GPU, ma non tutta la nostra piattaforma gira ancora su hardware che possediamo. Costruiamo un’infrastruttura gestita da noi pezzo per pezzo, e l’IA che legge le tue foto è stata un punto di partenza deliberato, perché è la parte più sensibile. Preferiamo dirti esattamente cosa gira e dove oggi, invece di lasciar intendere di essere più avanti di quanto siamo. Aspettati che approfondiremo questo tema in articoli futuri, man mano che una parte maggiore dello stack si sposta sul nostro hardware.

Se vuoi una libreria di foto con una ricerca così capace, senza consegnare i dati sottostanti a un’azienda che li monetizza, è esattamente ciò che stiamo costruendo.

Scopri cosa offriamo →


Una nota sulle immagini: le infografiche di questo articolo sono state generate con l’IA. Pensiamo che si guadagnino il loro posto, rendendo queste idee più facili da immaginare.