A IA dentro da tua biblioteca de fotos, e por que a mudámos para as nossas próprias GPUs

Quando pesquisas «cão na neve» na tua biblioteca de fotos e a imagem certa aparece, algo já leu essa foto por ti. Ninguém a etiquetou. Um modelo de machine learning olhou para os pixels, decidiu o que estava no enquadramento e guardou essa compreensão para que a pudesses encontrar mais tarde. Recentemente mudámos esse trabalho das CPUs para as nossas próprias GPUs (graphics processing units, unidades de processamento gráfico). Este artigo explica o que a IA realmente faz e por que o hardware que a sustenta é importante.
Os modelos que tornam isto possível não são nossos. Vêm do projeto de código aberto Immich sobre o qual o PixelUnion está construído. O que é nosso é o local onde são executados: em hardware que possuímos e operamos nós próprios, em solo europeu, não numa nuvem de IA de terceiros. Os modelos leem as tuas fotos, e para nós importa que o façam nos nossos próprios racks e em nenhum outro lugar.
Há uma distinção que vale a pena fazer antes de continuar, porque é a que mais conta para a tua privacidade. Usar um modelo não é o mesmo que treiná-lo. O treino é o processo caro e único em que um modelo aprende a partir de milhões de imagens de exemplo, e é feito pelos autores do modelo muito antes de chegar até nós. O que nós fazemos é inferência: pegamos num modelo acabado, já treinado, e passamos a tua foto por ele uma única vez para obter um resultado, tal como passas um documento por um scanner. As tuas fotos nunca são usadas para ensinar seja o que for aos modelos. Não são adicionadas a um conjunto de treino, não melhoram um modelo partilhado e nada delas sai para tornar uma versão futura mais inteligente. O modelo olha para a tua foto, dá a sua resposta e esquece-a.
Três tarefas, um truque partilhado: tornar os pixels pesquisáveis
O Immich executa a sua IA num serviço separado, o contentor immich-machine-learning, documentado no README de machine learning do projeto. Realiza três tarefas, e cada uma resolve um problema diferente:
- A pesquisa inteligente transforma uma foto em algo que podes procurar com linguagem comum, usando um modelo CLIP.
- O reconhecimento facial encontra rostos e determina quais pertencem à mesma pessoa, usando um pacote de modelos como o
buffalo_l. - O OCR lê o texto que aparece nas tuas fotos, usando um modelo
PP-OCRv5.
Vale a pena ser preciso aqui, porque «três modelos» é uma simplificação. Duas destas tarefas são, na verdade, um par de modelos que trabalham em sequência, e cada tarefa pode ser substituída por um modelo diferente. O reconhecimento facial executa um modelo de deteção seguido de um modelo de reconhecimento, e o buffalo_l é um pacote que contém ambos. O Immich também oferece alternativas como antelopev2, buffalo_m e buffalo_s. O OCR funciona da mesma forma, um modelo para encontrar o texto e outro para o ler. E o próprio CLIP é um par de codificadores, um para imagens e um para texto, com muitas variantes intercambiáveis. Não existe qualquer modelo de deteção de objetos separado: reconhecer que uma foto contém um cão ou uma praia é tratado pelo CLIP, não por um modelo de etiquetagem dedicado.
O que importa para os compreender é que as três tarefas partilham um mesmo truque subjacente. Por isso, compreendamos primeiro esse truque. Depois, as diferenças fazem sentido.

CLIP: procurar por significado, não por etiquetas
A antiga pesquisa de fotos funcionava com nomes de ficheiro e etiquetas manuais. Se não tivesses escrito «praia» numa legenda, procurar «praia» não encontrava nada. O CLIP, um modelo publicado originalmente pela OpenAI (artigo aqui), remove essa limitação. Olha para o conteúdo real de uma imagem.
Aqui está a parte em que as pessoas tropeçam, explicada de forma simples. O CLIP não guarda uma lista de palavras para cada foto. Converte cada foto num vetor: uma longa lista de números, umas centenas, que em conjunto descrevem o significado da imagem. Uma foto de um husky na neve fresca e uma foto de outro cão na neve acabam com listas de números semelhantes, porque significam coisas semelhantes. Essa lista chama-se embedding.
O que é realmente a pesquisa vetorial
Assim que cada foto na tua biblioteca é um vetor, guardamos todos esses vetores numa base de dados. A pesquisa funciona assim:
- Escreves «cão na neve».
- O mesmo modelo transforma as tuas palavras num vetor, com o mesmo sistema de números das fotos.
- A base de dados compara o teu vetor de pesquisa com os vetores das fotos guardados e mede quão perto está cada um.
- As correspondências mais próximas voltam primeiro.
«Perto» aqui é matemática. Cada vetor é um ponto no espaço, e o sistema mede a distância entre a tua consulta e cada foto. Na forma mais simples, isto é força bruta: verificar a distância a cada foto, uma a uma, ordenar pela mais próxima. Nesse processo não há em momento algum correspondência de etiquetas nem pesquisa por palavra-chave. Uma foto sem legenda, sem nome de ficheiro e sem descrição aparece na mesma, porque o seu significado vive nos números.

Essa comparação por força bruta é a versão honesta, e para uma biblioteca normal funciona bem. Também nomeia o custo. Comparar uma consulta com milhões de vetores, um a um, torna-se lento. Em grande escala, passas para índices mais inteligentes, a pesquisa aproximada dos vizinhos mais próximos, que salta a maioria das comparações e mesmo assim encontra os resultados certos. Qual abordagem precisas depende do tamanho da biblioteca, mas o princípio mantém-se: transformar tudo em vetores e depois encontrar os mais próximos.
Mais uma coisa que importa na Europa. O modelo CLIP predefinido lida bem com o inglês e mal com outras línguas. Existem variantes multilingues, e o Immich permite-te substituí-las, como descreve o seu guia de seleção de modelo. O compromisso é real: os melhores modelos multilingues são maiores e precisam de mais memória para funcionar. Essa pressão sobre a memória é uma das razões pelas quais a escolha do hardware começa a contar, e já lá chegamos.
buffalo_l: encontrar a mesma pessoa ao longo das tuas fotos
O reconhecimento facial no Immich usa o buffalo_l, um pacote de modelos do projeto InsightFace, alojado para o Immich no Hugging Face. Funciona em duas fases, e ambas vale a pena compreender, porque muitas vezes se assume que faz algo que não faz.
A primeira fase é a deteção. O modelo analisa a imagem e determina onde estão os rostos. Pensa no quadrado de focagem que uma câmara desenha à volta de um rosto, só que o modelo fá-lo à posteriori, em cada foto. O resultado é um conjunto de caixas: aqui está um rosto, aqui está outro.
A segunda fase é o reconhecimento. Para cada rosto encontrado, o modelo produz um vetor, a mesma ideia do CLIP mas afinada para rostos. Podes vê-lo como uma impressão digital numérica desse rosto. Duas fotos da mesma pessoa, com luz diferente e de ângulos diferentes, produzem vetores que ficam perto um do outro. Duas pessoas diferentes ficam longe.
Este é todo o mecanismo por trás de «pessoas» na tua biblioteca. Não procuramos o teu rosto em nenhuma base de dados externa, e nada leva um nome até escolheres etiquetar uma pessoa tu próprio. O modelo mede a geometria de um rosto e transforma-a em números, e depois agrupa os números que estão perto. O próprio guia sobre clusters de rostos do Immich descreve como esse agrupamento pode ser ajustado. As impressões digitais permanecem no nosso sistema, no nosso hardware. Nunca são o produto.
PP-OCRv5: ler o texto dentro das tuas imagens
O mais recente dos três é o OCR, reconhecimento ótico de caracteres, adicionado no Immich versão 2.2. Usa o PP-OCRv5, um modelo do projeto PaddleOCR da Baidu. O OCR é o que te permite procurar palavras que aparecem dentro de uma foto: uma placa de rua, uma montra de loja, um quadro branco, o rótulo de uma garrafa.
Também funciona em duas fases, e a divisão espelha o reconhecimento facial.
Primeiro deteta o texto. O modelo encontra as regiões da imagem que contêm escrita e desenha caixas à volta delas, da mesma forma que o modelo de rostos enquadra os rostos. Uma foto de uma rua pode ter texto em cinco sítios: uma placa, uma matrícula, um cartaz, uma ementa, um autocarro. Cada um torna-se uma caixa.
Depois lê. Para cada caixa, um segundo modelo determina que caracteres estão realmente lá e transforma-os em texto real, legível por máquina. Esse texto vai para o índice de pesquisa, para que mais tarde possas procurar «pizzaria» e encontrar a foto da fachada do restaurante, mesmo que nunca tenhas escrito uma legenda.
O compromisso é um daqueles detalhes típicos do Marc que vale a pena assinalar: o OCR é bom com texto impresso nítido em escritas suportadas, e muito mais fraco com escrita à mão ou tipos de letra muito estilizados. O Immich suporta oficialmente inglês, chinês e japonês, com as línguas de escrita latina a funcionarem em geral com uma precisão algo inferior, como discutido no tópico sobre línguas de OCR do projeto. É uma funcionalidade verdadeiramente útil, não mágica.
Por que tudo isto corre muito melhor numa GPU
Cada modelo acima faz, por baixo, o mesmo tipo de aritmética: quantidades enormes de pequenas multiplicações e adições, organizadas como cálculo matricial. Transformar uma foto num vetor são milhões dessas operações. Esse único facto explica toda a história do hardware.
Uma CPU tem um pequeno número de núcleos muito capazes, de um punhado a algumas dezenas. Cada núcleo é flexível e rápido, e processa as tarefas em grande parte em sequência. Esse design é excelente para o trabalho variado e ramificado que um servidor faz o dia todo. Encaixa mal em fazer a mesma multiplicação simples uns milhões de vezes seguidas.
Uma GPU é o oposto. Tem milhares de núcleos mais simples, construídos para executar a mesma operação ao mesmo tempo sobre enormes lotes de números, em paralelo. As placas gráficas foram concebidas para sombrear milhões de pixels em simultâneo, e acontece que a inferência de machine learning é o mesmo tipo de problema: a mesma matemática, repetida sobre muitos dados. Assim, em vez de os milhões de operações de uma foto escorrerem onda após onda por uns poucos núcleos de CPU, distribuem-se em conjunto por milhares de núcleos de GPU.

O resultado não é uma pequena melhoria, é uma ordem de grandeza de velocidade diferente para esta carga de trabalho específica. O Immich oferece exatamente isto na sua documentação sobre aceleração por hardware, que permite ao serviço de machine learning correr em CUDA, ROCm ou OpenVINO em vez de na CPU. Os relatos da comunidade dão uma ideia da escala. Na CPU, a pesquisa inteligente é sistematicamente a mais lenta das tarefas de machine learning, com os utilizadores a descrevê-la como o estrangulamento ao indexar uma biblioteca grande. Em hardware de GPU modesto, um relato documenta o embedding de cerca de 300 000 fotos em menos de uma noite. São números externos, de instalações de outras pessoas, não os nossos, mas a direção é coerente em todo o lado: a GPU limpa o atraso numa fração do tempo.
As placas que escolhemos para isto são placas gráficas de consumo antigas, não novos aceleradores de centro de dados. É uma escolha deliberada, e traz compromissos que vale a pena nomear. Uma placa dessas ainda tem milhares de núcleos paralelos e memória integrada suficiente para conter estes modelos com folga, e é tudo o que esta carga de trabalho precisa. Os modelos não são grandes segundo os padrões atuais. O CLIP é o mais pesado dos três, enquanto os modelos de rosto e de OCR são comparativamente leves. Reutilizar hardware antigo mas capaz mantém bom silício em serviço em vez de o pôr numa prateleira, e mantém toda a cadeia em equipamento que nos pertence por inteiro.
Há um custo real do outro lado da balança, e fingir o contrário seria desonesto. Uma GPU consome mais energia sob carga do que uma CPU inativa, e operar o próprio hardware significa que nós carregamos com a manutenção, os controladores e a eletricidade. Achamos que é o compromisso certo. Por foto processada, a GPU faz o trabalho com uma eficiência muito melhor, e significa que a IA que lê as tuas memórias corre em máquinas que controlamos, sob direito europeu, em vez de ser enviada para a nuvem de outra pessoa para processamento.
Por agora executamos os modelos predefinidos do Immich, os mesmos que qualquer utilizador do Immich obtém de origem. A razão pela qual este passo de hardware vai além da velocidade é a margem. Os modelos maiores geralmente precisam de mais poder de cálculo e mais memória para correr a um ritmo utilizável, precisamente o que uma CPU não conseguia fornecer. Com as nossas próprias GPUs no lugar, correr uma variante de CLIP maior para uma pesquisa mais afinada, ou um modelo de rosto mais pesado para um melhor agrupamento, torna-se uma opção prática em vez de uma impossibilidade. Não fazemos aqui promessas sobre modelos específicos. A questão é que este passo abre a porta, e melhores resultados para os nossos clientes são a razão para a atravessar.
Há uma armadilha na mudança para um modelo maior, e é melhor sermos francos sobre ela. Um modelo diferente produz vetores diferentes. Os números que um modelo CLIP atribui a uma foto não significam nada para outro modelo CLIP, por isso não podes misturar o antigo e o novo. Se algum dia passarmos para um modelo maior, teríamos de recalcular os embeddings de cada foto na biblioteca de cada utilizador do zero, nas nossas próprias GPUs. Para uma base de utilizadores grande, isso é uma quantidade enorme de cálculo, e é exatamente o tipo de tarefa que em CPUs é sem esperança e em GPUs é apenas grande. Este passo aproxima-nos de estarmos prontos para isso, mas ainda não lá chegámos. Quando chegarmos, isso merecerá um artigo próprio.
Por que o fazemos nós próprios
Nenhum destes modelos é exótico, e nenhum é secreto. É a natureza de construir sobre código aberto: podes ler exatamente o que o CLIP, o buffalo_l e o PP-OCRv5 fazem, e nós também. A decisão que realmente molda a tua privacidade não é qual modelo é executado, mas onde é executado e quem o opera.
Executamo-los nas nossas próprias GPUs, no nosso próprio ambiente, em solo europeu. As tuas fotos são lidas por máquinas pelas quais somos responsáveis, e os vetores e impressões digitais que saem desse processo ficam connosco e nunca são vendidos. É a parte que as Big Tech não te oferecerão, porque para elas ler as tuas fotos é o modelo de negócio, não uma funcionalidade.
Para sermos claros sobre onde estamos: este é um primeiro passo, não o quadro terminado. Os modelos de machine learning agora correm nas nossas próprias GPUs, mas ainda não toda a nossa plataforma corre em hardware que possuímos. Construímos infraestrutura operada por nós próprios peça a peça, e a IA que lê as tuas fotos foi um ponto de partida deliberado, porque é a parte mais sensível. Preferimos dizer-te exatamente o que corre e onde hoje, em vez de dar a entender que estamos mais avançados do que estamos. Conta com que aprofundaremos isto em artigos futuros, à medida que mais partes do sistema se mudam para o nosso próprio hardware.
Se queres uma biblioteca de fotos com uma pesquisa tão capaz, sem entregar os dados subjacentes a uma empresa que os monetiza, é exatamente isso que estamos a construir.
Uma nota sobre as imagens: as infografias deste artigo foram geradas com IA. Achamos que merecem o seu lugar, por tornarem estas ideias mais fáceis de visualizar.