Aller au contenu principal

Recherche lexicale BM25

Mis à jour le 30 juillet 2026

Notre pipeline RAG fonctionne, mais la recherche sémantique seule ne renvoie pas toujours les meilleurs résultats. Parfois, vous avez besoin de correspondances exactes de mots-clés — précisément ce que la recherche sémantique peut manquer. La solution n’est pas de la remplacer, mais de la compléter : combiner la recherche sémantique avec la recherche lexicale via BM25, l’algorithme classique des moteurs de recherche textuels.

Le problème de la recherche sémantique seule

Un exemple concret le montre mieux qu’une théorie. Si vous cherchez un identifiant d’incident spécifique comme « INC-2023-Q4-011 », la recherche sémantique pourrait renvoyer des sections non pertinentes — qui semblent sémantiquement similaires parce qu’elles parlent d’incidents en général — mais ne contiennent pas l’information recherchée. La cause est structurelle : la recherche sémantique se concentre sur le sens, et un identifiant technique n’en a pas — c’est une chaîne arbitraire, invisible dans l’espace des embeddings. Le même angle mort frappe les références produits, numéros de tickets et noms de code : tout le vocabulaire exact des documents d’entreprise.

Stratégie de recherche hybride

La solution : exécuter les deux recherches en parallèle puis fusionner les résultats.

  • Recherche sémantique : trouve du contenu conceptuellement relié via les embeddings
  • Recherche lexicale : trouve des correspondances exactes de mots-clés
  • Résultats fusionnés : combine les deux pour une meilleure pertinence globale

Chaque moteur couvre l’angle mort de l’autre : le sémantique comprend « quels problèmes avons-nous eus ? » sans correspondance de mots, le lexical retrouve « INC-2023-Q4-011 » au caractère près. La fusion — comment classer des résultats issus de deux systèmes de scores incomparables — est un vrai sujet, traité dans la prochaine leçon.

Comment fonctionne BM25

BM25 (Best Match 25) est un algorithme populaire de recherche lexicale — il ne comprend rien au sens, il compte, et il compte intelligemment. Les étapes clés :

  1. Tokeniser la requête : décomposer la question en termes individuels
  2. Compter la fréquence des termes : voir combien de fois chaque terme apparaît dans tous les documents
  3. Pondérer par rareté : les termes moins fréquents reçoivent des scores d’importance plus élevés
  4. Noter les documents : trouver les chunks contenant plus d’instances des termes les plus pondérés

La pondération par rareté est le génie de l’algorithme. Un terme présent partout — « le », « de » — ne discrimine rien ; un terme presque unique désigne son document. Insight clé : les termes rares comme « INC-2023-Q4-011 » pèsent beaucoup plus lourd que les mots courants — le chunk qui contient l’identifiant remonte mécaniquement en tête, exactement le comportement qui manquait au sémantique.

Implémentation

# Créer un store BM25
store = BM25Index()

# Ajouter les documents
for chunk in chunks:
    store.add_document({"content": chunk})

# Rechercher
results = store.search("Que s'est-il passe avec INC-2023-Q4-011 ?", 3)

L’API BM25 est délibérément similaire à celle du store vectoriel — add_document() et search() — ce qui facilite l’utilisation conjointe des deux systèmes : dès la prochaine leçon, cette interface commune permettra de les traiter comme des index interchangeables derrière une façade unique. Notez aussi ce que BM25 ne demande pas : aucun embedding, aucun appel API — l’indexation est locale, instantanée et gratuite.

Meilleurs résultats

Le test confirme : avec BM25, les sections contenant l’identifiant exact de l’incident sont correctement priorisées, au lieu de renvoyer du contenu vaguement apparenté. Chaque moteur brille désormais sur son terrain — reste à les faire travailler ensemble. L’étape suivante est de fusionner les résultats des deux systèmes de recherche en un classement unique.

Points clés à retenir

  • La recherche sémantique rate le vocabulaire exact : identifiants et références n’ont pas de « sens » vectorisable
  • Stratégie hybride : sémantique (le sens) + BM25 (les termes exacts), exécutés en parallèle puis fusionnés
  • BM25 pondère par rareté — un terme rare désigne son document, un mot courant ne compte pas
  • Même API que l’index vectoriel : add_document/search, prête pour la fusion à venir
  • Indexation BM25 locale et gratuite : aucun embedding, aucun appel réseau