Leçon 4 — Construire le moteur

Chercher par le sens, dans toutes les langues

5 min de lecture

Chercher par le sens, dans toutes les langues

Le chemin d'une requête

sequenceDiagram
  participant U as Utilisateur
  participant M as moteur.py
  participant G as gemini-embedding-2
  participant I as index (npy + sqlite)
  U->>M: "something to keep my baby warm at night"
  M->>G: "task: search result | query: something to ..."
  G-->>M: vecteur (768)
  M->>I: vecteurs @ requête (60 produits scalaires)
  I-->>M: 5 meilleures lignes + fiches
  M-->>U: Gigoteuse, Babyphone, Sac de couchage...

Une seule requête au modèle par recherche : les 60 fiches sont déjà vectorisées.

files/moteur.py (extrait)
def chercher(vecteurs, produits, embed, requete, k=5):
    q = embed([texte_requete(requete)])[0]
    return [(produits[i], s) for i, s in top_k(vecteurs, q, k)]
terminal
python moteur.py chercher "chaussure pour courir dans la boue"
python moteur.py chercher "something to keep my baby warm at night"

Pourquoi les mots-clés échouent

Une recherche par mots-clés compare les mots écrits. Le standard du domaine s'appelle BM25 : il donne un score à chaque document selon les mots de la requête qu'il contient, en favorisant les mots rares. Il est rapide, explicable, et ne demande aucun modèle. Mais :

RequêteCe que fait BM25Ce que font les embeddings
« faire le ménage sans y penser »aucun mot commun avec « Robot aspirateur laveur »trouve l'aspirateur robot
« Rasen mähen mit Akku » (allemand)aucun mot français en communtrouve la tondeuse à batterie
« noise cancelling headphones »« noise », « headphones » absents du cataloguetrouve le casque à réduction de bruit
« P043 » ou une référence exactetrouve tout de suitepeut se tromper : un code n'a pas de « sens »

Multilingue sans traduction

gemini-embedding-2 place les textes de plus de 100 langues dans le même espace. Le catalogue est en français, les requêtes peuvent être dans n'importe quelle langue couverte : aucune étape de traduction, aucun index par langue.

Un client tape la référence exacte « P043 ». Quelle approche est la plus fiable ?

Combien d'appels au modèle d'embeddings coûte une recherche dans l'index de 60 fiches ?

Exercice : une recherche hybride minimale

Combinez les classements BM25 et sémantique avec la fusion RRF : score(d) = Σ 1 / (60 + rang(d)) sur les deux classements. Écrivez la fonction à partir de deux listes d'identifiants ordonnées.

Voir la solution
def fusion_rrf(*classements, k=60, n=5):
    scores = {}
    for classement in classements:
        for rang, doc in enumerate(classement, 1):
            scores[doc] = scores.get(doc, 0) + 1 / (k + rang)
    return sorted(scores, key=scores.get, reverse=True)[:n]

# fusion_rrf(ids_semantiques_top20, ids_bm25_top20)

La constante 60 est la valeur proposée par les auteurs de la méthode : elle atténue l'écart entre la 1re et la 2e place. Pas besoin de rendre les scores comparables entre eux, seuls les rangs comptent.

Résultat obtenu

Recherches réelles le 2026-10-15 (gemini-embedding-2, 768 dimensions) :

$ python moteur.py chercher "chaussure pour courir dans la boue"
0.780  P058  Trail Gecko (coloris forêt)  (Chaussures)
0.774  P001  Trailrun Gecko  (Chaussures)
0.716  P002  Asphalte Flow  (Chaussures)
0.693  P003  Randonnée Cimes Mid  (Chaussures)
0.672  P004  Sandale Rivière  (Chaussures)
$ python moteur.py chercher "something to keep my baby warm at night"
0.714  P036  Gigoteuse Douillette TOG 2.5  (Bébé)
0.689  P032  Babyphone Vidéo Veille  (Bébé)
0.665  P038  Sac de couchage Grand Froid  (Camping)
0.643  P006  Pantoufle Nuage  (Chaussures)
0.642  P035  Tapis d'éveil Jungle  (Bébé)

La requête anglaise trouve en premier la gigoteuse (« turbulette pour dormir au chaud sans couverture ») alors qu'elle ne partage aucun mot avec la fiche. Notez le sac de couchage en 3e position : « au chaud la nuit » est aussi son sens.

Je sais faire

  • Lancer une recherche sémantique sur l'index local
  • Expliquer ce que fait BM25 et quand il bat les embeddings
  • Interroger un catalogue français dans une autre langue sans traduction
  • Combiner deux classements avec une fusion RRF
Suivant