AI:n inuti ditt fotobibliotek, och varför vi har flyttat den till våra egna GPU:er

När du söker i ditt fotobibliotek efter “hund i snön” och rätt bild dyker upp har något redan läst det fotot åt dig. Ingen taggade det. En machine learning-modell tittade på pixlarna, avgjorde vad som fanns i bilden och sparade den förståelsen så att du kunde hitta det igen senare. Vi flyttade nyligen det arbetet från CPU:er till våra egna GPU:er (graphics processing units, grafikprocessorer). Det här inlägget förklarar vad AI:n faktiskt gör och varför hårdvaran under den spelar roll.
Modellerna som gör detta möjligt är inte våra egna. De kommer från open source-projektet Immich som PixelUnion är byggt på. Det som är vårt är var de körs: på hårdvara som vi själva äger och driver, på europeisk mark, inte i ett tredjeparts AI-moln. Modellerna läser dina foton, och för oss spelar det roll att de gör det i våra egna rack och ingen annanstans.
Det finns en distinktion värd att göra innan vi går vidare, för det är den som betyder mest för din integritet. Att använda en modell är inte samma sak som att träna en. Träning är den dyra engångsprocessen där en modell lär sig av miljontals exempelbilder, och den utförs av modellens upphovspersoner långt innan den når oss. Det vi gör är inferens: vi tar en färdig, redan tränad modell och skickar ditt foto genom den en gång för att få ett resultat, på samma sätt som du skickar ett dokument genom en skanner. Dina foton används aldrig för att lära modellerna något. De läggs inte till i en träningsmängd, de förbättrar inte en delad modell, och inget av dem lämnar oss för att göra en framtida version smartare. Modellen tittar på ditt foto, ger sitt svar och glömmer det igen.
Tre uppgifter, ett gemensamt knep: att göra pixlar sökbara
Immich kör sin AI i en separat tjänst, containern immich-machine-learning, dokumenterad i projektets machine learning-README. Den utför tre uppgifter, och var och en löser ett olika problem:
- Smart sökning förvandlar ett foto till något du kan söka i med vanligt språk, med hjälp av en CLIP-modell.
- Ansiktsigenkänning hittar ansikten och räknar ut vilka som tillhör samma person, med hjälp av ett modellpaket som
buffalo_l. - OCR läser text som förekommer i dina foton, med hjälp av en
PP-OCRv5-modell.
Det är värt att vara precis här, för “tre modeller” är en förenkling. Två av dessa uppgifter är faktiskt ett par modeller som arbetar i följd, och varje uppgift kan bytas ut mot en annan modell. Ansiktsigenkänning kör en detektionsmodell följd av en igenkänningsmodell, och buffalo_l är ett paket som innehåller båda. Immich levererar även alternativ som antelopev2, buffalo_m och buffalo_s. OCR fungerar på samma sätt, en modell för att hitta text och en annan för att läsa den. Och CLIP i sig är ett par encoders, en för bilder och en för text, med många utbytbara varianter. Det finns ingen separat objektdetektionsmodell alls: att känna igen att ett foto innehåller en hund eller en strand hanteras av CLIP, inte av en dedikerad taggningsmodell.
Det som spelar roll för att förstå dem är att alla tre uppgifter delar ett underliggande knep. Så låt oss förstå det knepet först. Sedan blir skillnaderna begripliga.

CLIP: att söka på betydelse, inte på taggar
Gammal fotosökning byggde på filnamn och manuella taggar. Om du inte hade skrivit “strand” i en bildtext hittade en sökning på “strand” ingenting. CLIP, en modell som ursprungligen publicerades av OpenAI (artikel här), tar bort den begränsningen. Den tittar på det faktiska innehållet i en bild.
Här är den del folk snubblar på, förklarad enkelt. CLIP lagrar inte en lista med ord för varje foto. Den omvandlar varje foto till en vektor: en lång lista med tal, ett par hundra av dem, som tillsammans beskriver bildens betydelse. En bild på en husky i nyfallen snö och en bild på en annan hund i snö slutar med liknande listor av tal, eftersom de betyder något liknande. Den listan kallas en embedding.
Vad vektorsökning faktiskt är
Så snart varje foto i ditt bibliotek är en vektor lagrar vi alla dessa vektorer i en databas. Sökningen fungerar så här:
- Du skriver “hund i snön”.
- Samma modell förvandlar dina ord till en vektor, i samma talsystem som fotona.
- Databasen jämför din sökvektor med de lagrade fotovektorerna och mäter hur nära var och en ligger.
- De närmaste träffarna kommer tillbaka först.
“Nära” är här matematik. Varje vektor är en punkt i rummet, och systemet mäter avståndet mellan din sökfråga och varje foto. I sin enklaste form är detta brute force: kontrollera avståndet till varje enskilt foto, sortera efter det närmaste. Det finns ingen taggmatchning och ingen nyckelordssökning någonstans i den processen. Ett foto utan bildtext, utan filnamn och utan beskrivning dyker ändå upp, eftersom dess betydelse bor i talen.

Den brute force-jämförelsen är den ärliga versionen, och för ett normalt bibliotek fungerar den bra. Den namnger också kostnaden. Att jämföra en sökfråga med miljontals vektorer, en i taget, blir långsamt. I stor skala byter man till smartare index, approximate nearest neighbor-sökning, som hoppar över de flesta jämförelserna och ändå hittar rätt träffar. Vilken metod du behöver beror på bibliotekets storlek, men principen är densamma: gör om allt till vektorer, hitta sedan de närmaste.
En sak till som spelar roll i Europa. Standard-CLIP-modellen hanterar engelska bra och andra språk dåligt. Det finns flerspråkiga varianter, och Immich låter dig byta in dem, som projektets guide för modellval beskriver. Avvägningen är verklig: de bättre flerspråkiga modellerna är större och behöver mer minne för att köra. Det minnestrycket är ett av skälen till att valet av hårdvara börjar spela roll, och dit kommer vi.
buffalo_l: att hitta samma person genom alla dina foton
Ansiktsigenkänning i Immich använder buffalo_l, ett modellpaket från InsightFace-projektet, hostat för Immich på Hugging Face. Det körs i två steg, och båda är värda att förstå, eftersom man ofta antar att det gör något det inte gör.
Steg ett är detektion. Modellen skannar bilden och räknar ut var ansiktena är. Tänk på fokusrutan som en kamera ritar runt ett ansikte, förutom att modellen gör det i efterhand, på varje foto. Resultatet är en uppsättning rutor: här är ett ansikte, här är ett till.
Steg två är igenkänning. För varje hittat ansikte producerar modellen en vektor, samma idé som CLIP men avstämd för ansikten. Du kan se den som ett numeriskt fingeravtryck av det ansiktet. Två foton av samma person, i olika ljus och från olika vinklar, ger vektorer som ligger nära varandra. Två olika personer ligger långt ifrån varandra.
Det är hela mekanismen bakom “personer” i ditt bibliotek. Vi slår inte upp ditt ansikte mot någon extern databas, och inget bär ett namn förrän du själv väljer att märka en person. Modellen mäter geometrin i ett ansikte och gör om den till tal, och grupperar sedan de tal som ligger nära. Immichs egen guide om ansiktskluster beskriver hur den grupperingen kan finjusteras. Fingeravtrycken stannar i vårt system, på vår hårdvara. De är aldrig produkten.
PP-OCRv5: att läsa texten inuti dina bilder
Den nyaste av de tre är OCR, optisk teckenigenkänning, tillagd i Immich version 2.2. Den använder PP-OCRv5, en modell från Baidus PaddleOCR-projekt. OCR är det som låter dig söka efter ord som förekommer inuti ett foto: en gatuskylt, en butiksfasad, en whiteboard, etiketten på en flaska.
Även detta fungerar i två steg, och uppdelningen speglar ansiktsigenkänning.
Först upptäcker den text. Modellen hittar de områden av bilden som innehåller skrift och ritar rutor runt dem, på samma sätt som ansiktsmodellen ramar in ansikten. Ett foto av en gata kan ha text på fem ställen: en skylt, en registreringsskylt, en affisch, en meny, en buss. Var och en blir en ruta.
Sedan läser den. För varje ruta räknar en andra modell ut vilka tecken som faktiskt finns där och gör om dem till riktig, maskinläsbar text. Den texten går in i sökindexet, så att du senare kan söka efter “pizzeria” och hitta fotot av restaurangfasaden, trots att du aldrig skrev en bildtext.
Avvägningen är en sådan typisk Marc-detalj värd att nämna: OCR är bra på tydlig tryckt text i språk med stöd och mycket svagare på handskrift eller kraftigt stiliserade typsnitt. Immich stöder officiellt engelska, kinesiska och japanska, medan språk med latinsk skrift i allmänhet fungerar med något lägre precision, som diskuteras i projektets tråd om OCR-språk. Det är en verkligt användbar funktion, inte en magisk.
Varför allt detta körs så mycket bättre på en GPU
Varje modell ovan utför under ytan samma sorts aritmetik: enorma mängder små multiplikationer och additioner, ordnade som matrismatematik. Att göra om ett foto till en vektor är miljontals av dessa operationer. Det enda faktumet förklarar hela hårdvaruhistorien.
En CPU har ett litet antal mycket kapabla kärnor, en handfull till ett par dussin. Varje kärna är flexibel och snabb och arbetar sig genom uppgifter till stor del i följd. Den designen är utmärkt för det varierade, förgrenade arbete en server utför hela dagen. Den passar dåligt för att göra samma enkla multiplikation några miljoner gånger i rad.
En GPU är motsatsen. Den har tusentals enklare kärnor, byggda för att köra samma operation över enorma mängder tal på en gång, parallellt. Grafikkort designades för att skugga miljontals pixlar samtidigt, och det visar sig att machine learning-inferens är samma sorts problem: samma matematik, upprepad över mycket data. Så i stället för att ett fotos miljontals operationer sipprar våg efter våg genom några få CPU-kärnor sprids de tillsammans över tusentals GPU-kärnor.

Resultatet är ingen liten förbättring, det är en annan storleksordning av hastighet för just denna arbetsbelastning. Immich erbjuder precis detta i sin dokumentation om hårdvaruacceleration, som låter machine learning-tjänsten köra på CUDA, ROCm eller OpenVINO i stället för på CPU:n. Rapporter från gemenskapen ger en känsla för skalan. På CPU är smart sökning genomgående den långsammaste av machine learning-uppgifterna, och användare beskriver den som flaskhalsen vid indexering av ett stort bibliotek. På blygsam GPU-hårdvara dokumenterar en skildring embedding av ungefär 300 000 foton på mindre än en natt. Det är externa siffror från andras uppsättningar, inte våra egna, men riktningen är konsekvent överallt: GPU:n betar av eftersläpningen på en bråkdel av tiden.
Korten vi valde för detta är äldre konsumentgrafikkort, inte nya datacenteracceleratorer. Det är ett medvetet val, och det kommer med avvägningar värda att nämna. Ett sådant kort har fortfarande tusentals parallella kärnor och tillräckligt med inbyggt minne för att rymma dessa modeller bekvämt, och det är allt denna arbetsbelastning behöver. Modellerna är inte stora enligt dagens mått. CLIP är den tyngsta av de tre, medan ansikts- och OCR-modellerna är förhållandevis lätta. Att återanvända kapabel äldre hårdvara håller bra kisel i drift i stället för att ställa det på en hylla, och det håller hela kedjan på utrustning som är helt vår egen.
Det finns en verklig kostnad på andra sidan av vågskålen, och att låtsas annat vore ohederligt. En GPU drar mer ström under belastning än en overksam CPU, och att driva sin egen hårdvara betyder att vi bär underhållet, drivrutinerna och elen. Vi tycker att det är rätt avvägning. Per behandlat foto utför GPU:n arbetet med långt bättre effektivitet, och det betyder att AI:n som läser dina minnen körs på maskiner vi kontrollerar, under europeisk lag, i stället för att skickas till någon annans moln för att behandlas.
Tills vidare kör vi Immichs standardmodeller, samma som varje Immich-användare får direkt. Skälet till att detta hårdvarusteg sträcker sig bortom hastighet är utrymme. Större modeller behöver i regel mer beräkningskraft och mer minne för att köra i ett användbart tempo, precis det en CPU inte kunde erbjuda. Med våra egna GPU:er på plats blir det att köra en större CLIP-variant för skarpare sökning, eller en tyngre ansiktsmodell för bättre klustring, ett praktiskt alternativ i stället för en omöjlighet. Vi ger inga löften om specifika modeller här. Poängen är att detta steg öppnar dörren, och bättre resultat för våra kunder är skälet att gå igenom den.
Det finns en hake med att byta till en större modell, och det är bäst att vara öppen om den. En annan modell producerar andra vektorer. Talen som en CLIP-modell tilldelar ett foto betyder ingenting för en annan CLIP-modell, så du kan inte blanda gammalt och nytt. Om vi någonsin byter till en större modell skulle vi behöva räkna om embeddings för varje foto i varje användares bibliotek från grunden, på våra egna GPU:er. För en stor användarbas är det en enorm mängd beräkningar, och det är precis den sortens uppgift som är hopplös på CPU:er och bara en stor uppgift på GPU:er. Detta steg för oss närmare att vara redo för det, men vi är inte där än. När vi är det är det värt ett eget blogginlägg.
Varför vi gör det själva
Ingen av dessa modeller är exotisk, och ingen av dem är hemlig. Det är naturen hos att bygga på open source: du kan läsa exakt vad CLIP, buffalo_l och PP-OCRv5 gör, och det kan vi också. Beslutet som verkligen formar din integritet är inte vilken modell som körs, utan var den körs och vem som driver den.
Vi kör dem på våra egna GPU:er, i vår egen miljö, på europeisk mark. Dina foton läses av maskiner som vi ansvarar för, och vektorerna och fingeravtrycken som kommer ut ur den processen stannar hos oss och säljs aldrig. Det är den del Big Tech inte kommer att erbjuda dig, för för dem är läsningen av dina foton affärsmodellen, inte en funktion.
För att vara tydliga med var vi står: detta är ett första steg, inte den färdiga bilden. Machine learning-modellerna körs nu på våra egna GPU:er, men ännu körs inte hela vår plattform på hårdvara vi äger. Vi bygger upp självdriven infrastruktur bit för bit, och AI:n som läser dina foton var en medveten startpunkt, eftersom den är den känsligaste delen. Vi berättar hellre exakt vad som körs var i dag än antyder att vi är längre fram än vi är. Räkna med att vi fördjupar detta i framtida inlägg när mer av stacken flyttar över till vår egen hårdvara.
Om du vill ha ett fotobibliotek med en sökning som är så kapabel, utan att lämna över underliggande data till ett företag som tjänar pengar på dem, är det precis det vi bygger.
En notis om bilderna: infografiken i det här inlägget genererades med AI. Vi tycker att den förtjänar sin plats genom att göra dessa idéer lättare att föreställa sig.