Freedam
IngénieriePartie 1 sur 7 · 29 min de lectureMis à jour le

Ce qu’il faut vraiment pour construire une bonne recherche d’images

En février 2000, Jennifer Lopez a porté une robe Versace verte aux Grammys, et pendant quelques semaines, ce fut ce qu’on cherchait le plus sur Google. Google ne pouvait renvoyer que dix liens bleus, dont certains menaient à des pages susceptibles de contenir une photographie. Eric Schmidt a écrit plus tard que c’était la requête la plus populaire qu’ils aient jamais vue, et la raison pour laquelle ils avaient construit une recherche d’images. Google Images a été lancé en juillet 2001 et indexait environ 250 millions d’images.

La robe, le soir même : Jennifer Lopez remet le Grammy du meilleur album R&B lors de la 42e cérémonie des Grammy Awards, le 23 février 2000. Vidéo issue de la série GRAMMY Rewind de la Recording Academy.

J’aime cette histoire à cause de ce que les gens oublient de raconter : Google Images ne cherchait pas dans les pixels. Il indexait le nom de fichier, le texte alternatif, la légende et les mots proches d’une balise <img>, puis comparait la requête à ce texte. La robe était trouvable parce que des milliers de pages avaient écrit « Jennifer Lopez », « Versace » et « Grammys » à côté d’elle.

Maquette d’une page de résultats de recherche début 2000 : dix liens bleus et aucune image RECHERCHE WEB, FÉVRIER 2000 jennifer lopez green dress Rechercher Grammy Awards 2000: red carpet arrivals Versace - Spring 2000 collection J.Lo fan page (under construction) E! Online: who wore what alt.fan.jennifer-lopez archive Green dress - GeoCities … 4 autres liens pas une seule image sur cette page requête la plus populaire vue par Google
Ce à quoi ressemblait une recherche web de la robe début 2000, reconstituée. La recherche textuelle avait les mots et ne pouvait pas montrer l’image.

Vingt-cinq ans et plusieurs générations de vision par ordinateur plus tard, la recherche d’images commence toujours par créer quelque chose de cherchable à partir de l’image ou autour d’elle, ce qui explique bon nombre des problèmes pratiques qui suivent.

Je dirige freedam, un gestionnaire de médias numériques (digital asset manager) pour les photographies, les vidéos et les documents qu’une entreprise a besoin de retrouver. Nous avons passé plus de temps d’ingénierie sur la recherche que sur toute autre partie du produit : cet article rassemble donc ce que nous avons appris, pour ceux qui en construisent une ou qui veulent comprendre pourquoi la leur rate des résultats. Il existe aussi une version plus technique avec le SQL et les paramètres ; celle-ci s’en tient à la forme du problème.

Une image ne contient aucun mot

Une ligne d’une table de commandes contient un nom de client, un ticket de support contient un corps de message, et un PDF peut avoir une couche de texte. Un JPEG a trois canaux de couleur et quelques données EXIF, mais aucun terme qu’une requête texte puisse faire correspondre directement.

Une recherche d’images a donc besoin d’un substitut cherchable pour l’image. En pratique, ces substituts se répartissent en quatre grands groupes, et chacun couvre des requêtes que les autres ne couvrent pas.

Quatre ponts entre une requête texte et les pixels d’une image requête « robe verte » les pixels aucun terme à l’intérieur Des mots saisis par quelqu’unnom de fichier, légende, texte autour de l’image. Google Images, 2001 Des mots issus d’un vocabulairetags, catégories, taxonomie. Précis, filtrable, coûteux, jamais terminé Des mots écrits par une machineOCR, légendes, transcriptions. Abondant, bruité, aveugle à votre métier Aucun motl’image en 768 nombres. Du sens sans mots ; ne sait pas épeler un SKU
Toute recherche d’images franchit l’un de quatre ponts. Les systèmes qui choisissent un pont favori échouent sur les requêtes qui demandent les trois autres.

Des mots saisis par quelqu’un. Un nom de fichier, un titre, une légende ou le texte autour d’une image. C’est sur cela que Google Images a démarré, et sur cela qu’AltaVista Photo Finder avait démarré trois ans plus tôt. C’est peu coûteux et souvent efficace, parce que les gens sont doués pour nommer les choses, mais cela n’aide en rien quand un dossier ne contient que des fichiers nommés DSC_0001 à DSC_4817.

Des mots issus d’un vocabulaire. Les tags, les catégories et les taxonomies sont précis et filtrables, ce qui explique que les agences de photos et les photothèques d’entreprise s’appuient dessus. Ils sont aussi coûteux à maintenir, et le vocabulaire tend à s’éloigner du langage que les gens emploient pour chercher.

Des mots écrits par une machine. Cela comprend l’OCR de l’image, les légendes produites par un modèle de vision et les transcriptions de vidéos. L’ESP Game de Luis von Ahn utilisait une version humaine en 2004 : deux inconnus voyaient la même image, marquaient des points lorsqu’ils saisissaient le même mot, et leur accord devenait une étiquette. Google l’a sous licence sous le nom de Google Image Labeler en 2006 et l’a exploité pendant cinq ans. Les modèles peuvent aujourd’hui produire ces étiquettes à grande échelle, même si le résultat est bruité et dépourvu de contexte métier : un modèle peut reconnaître une basket sans savoir que c’est le SKU 4471-RD.

Aucun mot. Une image peut être représentée par des nombres et comparée à d’autres représentations numériques. QBIC d’IBM le faisait en 1995 en laissant les gens esquisser une disposition de couleurs. TinEye en 2008 et la recherche par image de Google en 2011 ont rendu familière la forme inverse : fournir une image et retrouver ses copies. CLIP a ensuite placé le texte et les images dans le même espace numérique : une requête comme a dog on a skateboard pouvait ainsi trouver une image que personne n’avait taguée avec ces mots. C’est la base de la plupart des récentes démonstrations de « recherche IA ».

Rien dans cette liste n’a remplacé ce qui précédait. Google Images utilise toujours le texte environnant et les agences de photos paient toujours des gens pour taguer les images, parce que chaque représentation répond à des questions que les autres ne savent pas traiter. Notre première erreur a été de traiter l’une d’elles comme la réponse principale au lieu de les combiner.

Ce que la recherche poursuivait pendant ce temps

La recherche menée parallèlement à ces produits a consacré une trentaine d’années à une question : comment réduire l’écart entre les caractéristiques visuelles et le sens exprimé par une requête. Les modèles récents ont réalisé des progrès substantiels, même si le résultat est plus étroit que ne le laissent croire de nombreuses démonstrations.

Trente ans de recherche d’images : produits, recherche en vision par ordinateur et infrastructure de recherche 1992200020102020 PRODUITS RECHERCHE EN VISION INFRASTRUCTURE AltaVista Photo Finder1998 Google Images2001 Tags Flickr2004 Image Labeler2006 TinEye2008 Recherche par image Google2011 terme « CBIR »1992 IBM QBIC1995 le fossé sémantique2000 Video Google2003 ImageNet2009 AlexNet2012 DeViSE2013 CLIP2021 BM251994 fusion de rangs réciproques2009 hachage multi-index2012 HNSW2016
Les produits sont d’abord sortis sur du texte, pendant que la recherche en vision travaillait sur le fossé sémantique. Les méthodes de recherche nécessaires pour exploiter les deux à grande échelle se sont développées en parallèle.

L’expression « content-based image retrieval » (recherche d’images par le contenu) a été forgée en 1992 par Toshikazu Kato, au Electrotechnical Laboratory japonais, pour désigner l’idée qu’on pourrait chercher des images d’après ce qu’elles contiennent plutôt que d’après ce que quelqu’un a écrit à leur sujet. QBIC d’IBM a été le premier système sérieux à l’essayer. Il savait comparer des histogrammes de couleurs, des textures et des formes, et on l’interrogeait par une esquisse. Le Photo Finder d’AltaVista, en 1998, construit avec une société nommée Virage, a bel et bien proposé au public un bouton « visuellement similaire », et le public, dans son immense majorité, a continué de saisir des mots.

La raison en a été nommée en 2000, dans un article de synthèse de Smeulders et ses collègues que tous les chercheurs du domaine citent depuis : le fossé sémantique (semantic gap). L’écart entre ce qu’un ordinateur peut extraire des pixels (cette région est verdâtre, ce bord est vertical) et ce qu’une personne veut dire par une requête (une robe, une célébrité, une cérémonie de remise de prix). Les histogrammes de couleurs se trouvent d’un côté de cet écart. Toutes les requêtes que quelqu’un saisit réellement se trouvent de l’autre. Pendant les vingt années suivantes, le programme de recherche a été, pour l’essentiel : « combler l’écart ».

Il s’est comblé par étapes, et chaque étape a fini dans un produit. Les caractéristiques locales (SIFT, 1999) et l’astuce « Video Google » de 2003, qui traitait des fragments visuels comme des mots et les indexait comme du texte, sont les ancêtres directs de TinEye et de la recherche inversée d’images de Google : une correspondance d’images identiques à l’échelle du web, ce qui est un problème différent et plus simple que celui du sens. ImageNet, en 2009, a rendu disponible un million d’images étiquetées, et AlexNet, en 2012, a montré qu’un réseau de neurones entraîné dessus produisait des caractéristiques qui battaient tous les descripteurs conçus à la main. Puis, en 2013, un article de Google appelé DeViSE a fait quelque chose qui paraît évident aujourd’hui et qui paraissait étrange alors : il a entraîné les caractéristiques des images à atterrir près des vecteurs de mots de leurs étiquettes, de sorte qu’une image d’une chose et le nom de cette chose se trouvaient proches dans un même espace, et qu’un modèle pouvait reconnaître des catégories sur lesquelles il n’avait jamais été entraîné. CLIP, en 2021, a été cette idée portée à 400 millions de paires image-texte collectées sur le web. L’écart qui avait été le problème central du domaine depuis 1992 était, pour les requêtes descriptives, en grande partie comblé.

Le qualificatif important est descriptives. CLIP peut trouver a dog on a skateboard, mais il ne sait pas trouver de façon fiable SS26-HERO-03, comprendre que la recherche en cours est limitée à une collection, ni signaler qu’une limite de candidats a exclu 953 résultats. Ce sont des problèmes de produit et de recherche, traités par un autre ensemble d’outils : BM25 pour le classement par mots-clés, la fusion de rangs réciproques (reciprocal rank fusion) pour combiner des listes de résultats, et HNSW pour la recherche rapide de plus proches voisins sur des vecteurs. La recherche sémantique est utile, mais elle reste un composant du moteur de recherche.

Ce que les gens attendent vraiment

Avant l’architecture, je veux consacrer un moment aux utilisateurs, parce que leurs attentes sont à l’origine de la plupart des contraintes de conception, et qu’elles ne sont pas ce qu’un ingénieur de recherche choisirait.

La plupart des gens ont appris l’interaction avec Google Images, où les résultats arrivent vite, où la grille se termine rarement et où il n’existe pas de bonne réponse unique à sunset. Si l’une des premières images est utile, la recherche a fait son travail.

La photothèque d’une entreprise est un animal différent, et le modèle mental de Google y est activement nuisible, de façons que j’ai mis des années à voir.

Ce que Google Images a appris aux utilisateurs, face à ce dont une photothèque d’entreprise a besoin CE QUE GOOGLE IMAGES VOUS A APPRIS CE DONT UNE PHOTOTHÈQUE A BESOIN Vous parcourezn’importe quel beau coucher de soleil convient Vous cherchez une chose précisele coucher de soleil de Lisbonne, avec le pont, du rapport annuel Les requêtes sont des descriptions« robe rouge », « plage la nuit » Les requêtes sont souvent des identifiants4471-RD · SS26-HERO-03 · coque galaxy a52 Le périmètre est le web entieril n’y a pas de « dedans » On cherche à l’intérieur d’un ensemblece dossier, ce shooting, cette campagne Jamais videla grille se remplit toujours et défile sans fin « Non » est une réponse précieusepersonne n’a encore photographié Madrid : à commander Vous regardez les trois premiers Vous agissez sur les 1 240
Chaque utilisateur arrive avec la colonne de gauche en tête. Le produit doit satisfaire la colonne de droite, sans être sensiblement différent à utiliser.

Dans une photothèque d’entreprise, la réponse est généralement plus précise : le coucher de soleil du shooting de Lisbonne, avec le pont, utilisé dans le rapport annuel de l’an dernier. Il peut y avoir un seul résultat correct ou douze : une grille de 400 couchers de soleil plausibles n’est donc pas particulièrement utile.

De nombreuses requêtes de photothèque ne sont pas du tout des descriptions. Les logs contiennent 4471-RD, SS26-HERO-03, des numéros de facture et des noms de modèles, courants dans un DAM et mal adaptés à la recherche sémantique, parce que les plus proches voisins d’un SKU sont généralement d’autres SKU.

Les gens cherchent aussi à l’intérieur d’un dossier, d’une collection ou d’une campagne. « Trouve les images principales de ce shooting » est une demande courante, et les limites de candidats peuvent rendre ce type de recherche incomplet sans que la page de résultats paraisse défaillante.

« Aucun résultat » peut aussi être utile. Si personne n’a photographié le nouveau magasin de Madrid, l’utilisateur doit peut-être commander ce travail, alors que remplir la grille de photographies de Barcelone et de Séville ne fait que masquer cette information.

Enfin, les gens agissent sur des ensembles de résultats entiers : « Sélectionne les 1 240 résultats et applique cette date d’expiration de licence. » Ce n’est sûr que si 1 240 est vraiment l’ensemble complet.

On juge généralement une recherche à ses premiers résultats : les correspondances manquantes sont donc difficiles à remarquer. Une requête peut perdre les deux tiers de ses médias pertinents et renvoyer tout de même une page plausible en quatre-vingt-dix millisecondes. Dans une photothèque que tout le monde, nous compris, jugeait raisonnablement bonne, la mesure a révélé des échecs nets sur quinze requêtes réalistes sur soixante, dont aucun n’avait été signalé.

Pour une photothèque d’entreprise, une bonne recherche d’images doit donc trouver des médias précis, gérer les identifiants autant que les descriptions, fonctionner à l’intérieur d’un périmètre, renvoyer un résultat vide honnête et signaler si des limites de candidats ont pu exclure des correspondances. Le reste de cet article explique comment nous avons abordé ces exigences.

L’indexation fixe la limite

Nous avons d’abord passé trop de temps sur le classement, parce que c’est la partie visible de la recherche, mais beaucoup de nos problèmes de rappel (recall) commençaient à l’indexation. Une requête ne peut pas récupérer un terme qui n’a jamais été placé dans la représentation cherchable du média.

Nous compilons donc un document de recherche stocké pour chaque média et chaque langue, reconstruit quand le média change. Il inclut le titre, le nom de fichier, la description, le créateur, le copyright, le lieu, les mots-clés, les tags et légendes générés, l’OCR, les métadonnées personnalisées, les noms de collections, les noms de personnes confirmées et les sous-titres de vidéos. Les termes de vocabulaire contrôlé incluent aussi leurs ancêtres : un média tagué espresso machine peut ainsi être trouvé via small appliances ou kitchen sans que l’utilisateur connaisse la taxonomie.

Comment le document de recherche et l’embedding d’un média sont compilés SOURCES COMPILÉ, PAR MÉDIA INDEXÉ, DE DEUX FAÇONS titre, nom de fichier, description créateur, copyright, lieu mots-clés + tags IA, légende texte OCR, texte extrait valeurs de métadonnées personnalisées terme de vocabulaire + ancêtres noms de collections personnes confirmées (visages) libellés de points focaux sous-titres / transcription document de recherche tout, pondéré poids = répétition littérale ancêtre 3 / parent 2 / feuille 1 une ligne par langue texte d’embedding un sous-ensemble budgété : titre 300 / desc. 1 500 méta 2 000 / OCR 2 000 8 000 caractères au total index de mots-clés (BM25) le document contient-il ces mots ? un index par langue, dans PostgreSQL 20 stemmers, tolérance aux fautes via trigrammes exact. Trouve 4471-RD. Rate « fall » si le photographe a écrit « autumn » sémantique (vecteurs) texte et image partagent un espace de 768 dim. modèles nomic texte + vision, auto-hébergés index HNSW dans pgvector, distance cosinus trouve ce que personne n’a tagué. Renvoie toujours k voisins, même si rien ne correspond Chaque source alimente le document de recherche ; le texte d’embedding en prend une sélection limitée en caractères.
Le même média est compilé deux fois, en deux géométries de recherche différentes. Les deux vivent dans la même ligne PostgreSQL : elles voient donc la même transaction.

Deux aspects de ce document se sont révélés bien plus importants que je ne le pensais.

Le premier est la pondération. Un titre doit compter plus qu’une ligne d’OCR, et comme un index de mots-clés n’a aucune notion de champs, nous représentons ce poids en répétant le texte important dans le document. Cela fonctionne, mais modifie aussi la longueur du document. Comme le score par mots-clés se normalise selon la longueur, la répétition peut favoriser les documents plus courts en cas d’égalité. Dans une requête sur un nom de lieu, onze vidéos de produits ont devancé les photographies de produits : les documents des vidéos faisaient de 155 à 493 caractères, alors que les documents plus riches des images en faisaient de 746 à 1 280.

Le second est la tokenisation, qui décide où un terme se termine et où le suivant commence. Nous avons trouvé un petit exemple utile avec des libellés de compatibilité comme Galaxy A52/A52S : PostgreSQL traitait la valeur comme un seul token en forme de chemin, de sorte qu’une requête contenant a52 manquait des médias qui portaient visiblement ce libellé. Normaliser les séparateurs avant l’indexation a réglé le cas. La leçon plus générale est simplement d’inspecter les termes produits par l’analyseur quand le texte est présent mais que le rappel est étonnamment faible, car reconstruire les mêmes tokens ne changera pas le résultat.

Deux façons de chercher, une base de données

Une fois le document constitué, il existe deux façons utiles de le chercher, et elles excellent dans des domaines opposés.

La première est la recherche par mots-clés avec BM25. Le nom n’est pas très parlant (il signifie « Best Match », et 25 est le numéro de version qui s’est imposé), mais l’idée est simple : un document obtient un meilleur score quand un terme de la requête y apparaît plus souvent, quand le terme est rare dans la photothèque et quand le document est court. La formule date de 1994 et reste efficace pour des termes exacts comme 4471-RD. Sa faiblesse est le vocabulaire : quand le photographe a écrit autumn et que le marketeur cherche fall, il peut n’y avoir aucun terme commun à classer.

La seconde est l’approche de type CLIP : transformer le document et l’image en points dans un espace de 768 dimensions, placer la requête dans le même espace et renvoyer les points proches. Cela peut trouver team celebrating outdoors quand personne n’a employé ces mots, mais un index vectoriel renvoie toujours k voisins, y compris quand aucun n’est une bonne correspondance. Un seuil de distance fait donc partie de la conception de la recherche, et n’est pas un simple réglage facultatif du classement.

Nous exécutons les deux dans PostgreSQL, sur la même instance que les médias : BM25 via pg_textsearch, et les vecteurs via pgvector avec un index HNSW. Cela évite un service de recherche séparé et son pipeline de synchronisation.

Le compromis est simple. Un nouveau média peut devenir cherchable dans la transaction qui l’insère, tandis que les permissions, les embargos et les droits d’usage restent de simples clauses WHERE au lieu d’un second modèle d’autorisation. Les installations auto-hébergées ont aussi un service avec état de moins à exploiter. En contrepartie, la forme de la requête compte énormément : dans un cas, référencer deux fois la même sous-requête a transformé une requête de 6 ms en une requête de 7,3 secondes, parce que le planificateur avait perdu la borne de lignes nécessaire à un parcours d’index top-k. Une grande partie du travail consiste donc à vérifier les plans et à garder visibles pour PostgreSQL les bornes voulues.

Les embeddings viennent de modèles nomic de texte et de vision entraînés à partager un espace, exécutés dans un sidecar auto-hébergé pour que les images des clients ne quittent pas l’installation. Deux détails opérationnels ont compté. D’abord, les modèles utilisent des préfixes de tâche : les documents sont encodés avec search_document et les requêtes avec search_query, ces entrées doivent donc être couvertes par des tests, car un préfixe incorrect dégrade la qualité sans produire d’erreur. Ensuite, nous mettons brièvement en cache les échecs d’encodage des requêtes, ce qui permet à la recherche de se rabattre sur la recherche lexicale au lieu de contacter à chaque frappe un sidecar indisponible.

À partir de quelle distance est-ce assez proche ?

La voie vectorielle a besoin d’un seuil au-delà duquel un voisin n’est plus considéré comme une correspondance. Nous attendions un seul seuil, mais la valeur utile variait avec la longueur de la requête et n’était pas monotone.

Requête Distance cosinus max
1 mot 0,35
2 mots 0,42
3 à 5 mots 0,45
6 à 10 mots 0,48
plus de 10 mots 0,40

Les deux extrémités sont strictes, pour des raisons opposées. Un mot isolé comme chair a un voisinage sémantique gigantesque : avec un seuil lâche, il correspond à toutes les photographies d’intérieur de la photothèque, remplit la page et a l’air fiable tout en étant inutile. Une requête très longue, qui en pratique est quelqu’un qui colle un titre de produit entier, produit un embedding vague, moyenné, qui se situe faiblement près de tout ; relâchez le seuil à cet endroit et vous récupérez tout le corpus, par ordre de confiance. La bande médiane, où la requête est assez précise pour signifier quelque chose et assez courte pour continuer à le signifier, est celle où la recherche sémantique justifie sa place.

Les requêtes d’un seul mot reçoivent une règle supplémentaire : un résultat doit aussi avoir une correspondance lexicale. Sans elle, les termes de niche tendent à remplir la page d’images sémantiquement voisines, ce qui fait paraître un résultat vide comme un résultat abondant. Avec cette règle, madrid peut ne renvoyer aucun résultat quand la photothèque ne contient aucun texte correspondant.

Combiner deux classements qui ne parlent pas la même langue

Un score BM25 et une distance cosinus ne sont pas directement comparables. Les normaliser sur une échelle commune fait dépendre la combinaison du corpus, de la langue et des seuils utilisés pour produire cet ensemble de résultats.

Nous combinons donc des rangs. Chaque voie produit une liste ordonnée ; un document à la position r contribue 1 / (60 + r), tandis qu’un document absent d’une liste ne contribue rien de cette voie. La Reciprocal Rank Fusion est simple, ne demande aucune calibration des scores, et permet à un document bien classé dans les deux listes de devancer un document soutenu par une seule méthode de recherche.

Fusion de rangs réciproques d’une liste BM25 et d’une liste vectorielle RANGS BM25 1 000 premiers conservés (scan brut 3 000) 1 média 4471 2 média 9310 8 média 1180 40 média 7702 … pas de correspondance vectorielle RANGS VECTORIELS 200 premiers, filtrés par distance 1 média 6025 3 média 7702 11 média 4471 62 média 1180 … pas de correspondance lexicale FULL OUTER JOIN une ligne peut être dans l’une des listes, ou dans les deux 1/(60+r₁) + 1/(60+r₂) rang absent ⇒ 0,0, jamais une pénalité FUSIONNÉ 4471 0,0305 7702 0,0259 1180 0,0229 6025 0,0164 9310 0,0161 7702 : rang 40 en lexical, rang 3 en sémantique. Il gagne. puis, dans l’ordre : bonus de phrase (titre contenant la requête littérale = 2, document la contenant = 1) ▸ rrf_score ▸ id média seuil adaptatif au nombre de mots ▸ une ligne à un mot doit avoir un rang lexical ▸ bandes garanties toujours admises
La RRF n’a besoin d’aucune calibration des scores : un document absent d’une liste y contribue simplement zéro. La jointure externe complète est ce qui permet à une correspondance purement sémantique de concourir.

Les limites de candidats peuvent masquer des correspondances

Tout ce qui précède concerne la pertinence, mais les limites de candidats déterminent si les médias pertinents sont atteignables.

Tout système de recherche a besoin d’une borne. Plutôt que de scorer 200 000 documents à chaque frappe, il peut retenir les 1 000 premiers candidats lexicaux et les 200 premiers candidats vectoriels, puis classer cet ensemble réduit. Si la réponse n’indique pas la borne, la page et le paginateur peuvent paraître normaux alors que des médias situés au-delà de la coupe sont absents.

Par exemple, une collection contient 400 médias et 30 portent le terme recherché, mais la recherche en renvoie quatre. Les 1 000 premiers candidats ont été sélectionnés sur toute la photothèque avant l’application du filtre de collection : les 26 autres se sont donc retrouvés hors de l’ensemble de candidats. Les médias renvoyés sont pertinents ; le problème est que la plupart des correspondances éligibles n’ont jamais été disponibles pour le classement.

Le cas plus général est la saturation du plafond (cap crowding) : si 1 953 documents contiennent tous les termes et que seuls 1 000 candidats sont conservés, des lignes tout aussi pertinentes peuvent être exclues par un départage.

Notre correctif est une seconde récupération garantie pour les lignes qui doivent rester atteignables, comme les membres de la collection dans laquelle on cherche et les médias dont le titre contient littéralement le terme. Ces lignes entrent après les positions du scan classé normalement, et chaque limite en aval les admet explicitement. La première page garde le même ordre, tandis que les lignes supplémentaires restent disponibles dans les pages suivantes et dans le total.

Les bandes garanties survivent au plafond de candidats CANDIDATS CLASSÉS pos. 1 … 998 pos. 999 pos. 1000 plafond pos. 1001, écarté pos. 1002, écarté … 953 autres, en silence BANDE GARANTIE Lignes qui doivent être trouvables quel que soit leur rang : • membres de la collection dans laquelle vous avez cherché • (en option) tout média dont le titre contient le terme Elles entrent aux positions rawLimit + n, au-delà de toutes les positions réelles du scan, et MIN(best_pos) conserve le vrai rang de tout ce qui est déjà dans la coupe. Pourquoi l’ordre n’est pas modifié Les lignes de bande viennent après toutes les lignes classées : la première page est identique octet pour octet à celle sans bande. Chaque porte en aval, le seuil RRF et le LIMIT final, porte une clause explicite « …OU cette ligne est dans une bande ». L’indicateur remonte dans l’union avec BOOL_OR plutôt que par une seconde jointure, pour que le scan garde sa borne de lignes.
Une bande change ce qui est atteignable, pas ce qui est classé premier. Cette séparation est ce qui rend une garantie de rappel sûre à livrer.

La récupération garantie varie avec la taille du périmètre. Pour une collection de quarante médias, nous scorons les quarante directement, ce qui est complet par construction et coûte environ une demi-milliseconde par membre. Jusqu’à quelques milliers de membres, nous ajoutons une comparaison vectorielle exacte sur le périmètre au lieu d’utiliser l’index approximatif. Jusqu’à cinquante mille, nous parcourons la liste classée plus en profondeur, tandis que les périmètres plus grands recoupent assez le pool de candidats normal pour que le travail supplémentaire soit moins utile.

Stratégie de bande selon la taille du périmètre 1 32 2 000 50 000 ∞ TAILLE DU PÉRIMÈTRE : MEMBRES DE LA COLLECTION DANS LAQUELLE VOUS CHERCHEZ scorer chaque membre aucun scan : classer directement le document de chaque membre complet par construction ≈ 0,6 ms par membre + scan vectoriel exact cosinus en force brute sur les membres, aucune perte de rappel ANN dans le périmètre < 40 ms à 2 000 scan profond du classement lire la liste classée jusqu’à couvrir le périmètre, dans la limite de 45 000 lignes ≈ 2,7 µs/ligne → ≈ 120 ms aucune bande un périmètre aussi grand recoupe déjà fortement le pool de candidats du tenant le travail en plus ne serait pas rentable
Quatre régimes, choisis selon la taille. Le cas du petit périmètre n’est pas une optimisation : scorer chaque membre est la seule variante prouvablement complète quelle que soit la taille du corpus.

Indiquer si les résultats sont complets

Les limites de candidats conduisent à une question pratique : le système peut-il dire à l’utilisateur s’il a montré toutes les correspondances ?

Cela compte bien au-delà du confort de l’utilisateur. « Sélectionne les 1 240 et applique cette politique de droits » n’est sûr que si 1 240 est démontrablement l’ensemble complet. Une recherche qui tronque silencieusement à 1 000 transforme une opération en masse en incident d’intégrité des données dont personne ne s’aperçoit pendant des mois.

Chaque recherche freedam renvoie donc un verdict avec ses résultats : complete (complet), truncated (tronqué) ou unknown (inconnu). Il est calculé par des colonnes de comptage supplémentaires dans la même requête, qui mesurent combien de lignes chaque source de candidats a réellement produites par rapport au plafond sous lequel cette source fonctionnait. Si une source a atteint sa borne, le résultat est tronqué, l’interface le dit, et les opérations en masse sur ce résultat avertissent. Scorer tous les membres d’une petite collection est complet par construction. Un scan profond n’est complet que s’il s’est terminé avant sa borne de lignes. Une nouvelle source de candidats vaut unknown par défaut tant que personne n’a prouvé le contraire. Et un résultat obtenu par un repli, une correction de faute ou une expansion de préfixe n’hérite jamais du verdict qu’avait obtenu la requête d’origine.

Les trois verdicts d’exhaustivité et ce que chacun permet COMPLETE chaque source de candidats a terminé sous son plafond, ou a été scorée exhaustivement, membre par membre 1 240 résultats « tout sélectionner » signifie les 1 240 TRUNCATED une source a atteint sa borne de lignes ; la sonde a compté plus de lignes que le plafond n’en a laissé passer 1 000 sur plus de 1 000 l’interface le dit ; les actions en masse avertissent UNKNOWN la valeur par défaut de toute nouvelle source tant que personne n’a prouvé sa borne, et de tout chemin de repli correction de faute, expansion de préfixe n’hérite jamais du verdict de l’original Calculé dans la même requête que celle qui a produit les résultats colonnes COUNT supplémentaires par source, comparées au plafond sous lequel la source s’est exécutée. Une sonde écrite à part divergerait de la vraie requête.
Une recherche capable de distinguer ces trois cas peut autoriser sans risque une opération en masse. Une recherche qui annonce toujours un total ne le peut pas.

Cela a aussi changé notre façon de passer en revue la supervision et les tests. Nous avions un monitor qui restait silencieux après la mort de sa tâche, un test de départage qui restait vert après la disparition du départage dans la requête, et une suite de qualité dont les avertissements ne pouvaient pas modifier le code de sortie. Pour chaque contrôle, nous nous demandons désormais ce que serait sa sortie si le comportement était cassé. Si l’échec produit la même sortie que le succès, le contrôle a besoin d’une autre assertion observable.

Les autres façons de demander

Le texte est une entrée. Trois autres comptent spécifiquement pour les images, et je serai bref, car chacune a son propre article.

Vous pouvez chercher avec une image pour savoir si elle a déjà été sous licence, ou pour retrouver le reste d’un shooting. Ce chemin utilise des hashs perceptuels et une recherche multi-index pour générer des candidats, puis un embedding visuel pour les vérifier. L’article sur les quasi-doublons traite des styles de catalogue qui affaiblissent l’algorithme standard.

Vous pouvez chercher une personne. Les visages ont leur propre détecteur et leur propre espace d’embeddings, dans un sidecar qui n’envoie aucune image hors de l’installation. Un visage n’a pas de nom tant qu’une personne ne l’a pas confirmé : le système regroupe donc des candidats et n’écrit que des noms confirmés dans le document de recherche. Les détails se trouvent dans l’article sur la recherche de personnes.

Vous pouvez aussi chercher avec une phrase. Notre assistant ne classe pas les médias ; il compile la phrase en l’arbre de filtres que produit l’interface de recherche avancée, avec un intent explicite tel que replace, refine, add ou remove. Cet arbre passe par le chemin de recherche normal, sous les mêmes permissions et avec le même compte rendu d’exhaustivité : l’utilisateur peut donc examiner et corriger l’interprétation. L’article sur la recherche conversationnelle traite de cette frontière et de ses compromis.

Comment nous savons que tout cela fonctionne

Nous évaluons ces décisions avec soixante requêtes réalistes et une vérité terrain convenue, exécutées via le chemin de recherche de production sur une réplique de la photothèque d’un client d’environ 23 000 médias. L’instrument rapporte la réussite ou l’échec net, le rappel et le rang réciproque, et il n’a qu’un accès en lecture seule : il ne peut donc ni modifier de réglages ni reconstruire un index. L’article sur la mesure explique la méthode et ses limites.

La première exécution sérieuse a révélé quinze échecs nets dans une recherche que tout le monde décrivait comme raisonnablement bonne. Plus tard, nous avons attribué cinq régressions de rappel à un changement de tokenisation, mais la mesure a montré que quatre requêtes avaient un rappel et un rang identiques à quinze décimales près. La vraie cause était la longueur des documents, comme dans le cas vidéos contre photos plus haut. L’instrument a été utile parce qu’il a séparé une explication plausible du changement qui avait réellement affecté le résultat.

Retour à la robe

La robe Versace originale de 2000, en mousseline de soie verte à motif jungle, exposée sur un mannequin dans une vitrine du Museum at FIT, à New York
La robe elle-même, vingt-cinq ans plus tard : la robe Versace de 2000 exposée au Museum at FIT à New York, en novembre 2025. Photo de Rhododendrites, Wikimedia Commons, CC BY-SA 4.0.

Google a trouvé la robe en 2001 en lisant les mots autour de l’image. Aujourd’hui, nous trouvons une photo de produit en cherchant le texte assemblé autour d’elle et une représentation vectorielle produite à partir de l’image et de ses métadonnées. Les modèles sémantiques aident pour les requêtes descriptives, mais le reste du système doit encore gérer les identifiants, les règles d’accès, les périmètres, les limites de candidats et des totaux honnêtes.

Si vous débutez, consacrez du temps à la représentation indexée, car une requête ne peut pas retrouver des termes que le tokenizer n’a jamais émis. Exécutez ensemble la recherche lexicale et la recherche sémantique, et fusionnez leurs rangs plutôt que leurs scores. Réglez les seuils vectoriels selon la forme de la requête, envisagez d’exiger un appui lexical pour les mots isolés, et traitez chaque plafond de candidats comme un problème possible d’exhaustivité. Surtout, signalez quand le système ne peut pas prouver qu’il a renvoyé toutes les correspondances.

Si vous préférez voir plutôt que lire, il existe une démo avec une photothèque préremplie. La chose intéressante à faire est de chercher quelque chose que personne n’aurait tagué, puis de chercher quelque chose à l’intérieur d’un dossier, et de compter.

Pour les développeurs

À lire aussi