Pendant des années, la recherche de notre plateforme e-commerce de formation professionnelle tournait sur un moteur SaaS externe. L’exemple le plus parlant de notre frustration : un internaute tapait « Excel », et le moteur lui ressortait un article de blog qui n’avait strictement rien à voir. Fin 2025, j’ai proposé de remplacer tout ça par un moteur RAG maison. Il est en production depuis la fin de l’été : environ 47 tickets, une équipe de quatre personnes, et une manière de travailler que l’IA a profondément changée. Voici le retour d’expérience, sans filtre.

Pourquoi partir

Les symptômes étaient anciens. Sur des contenus courts, les résultats étaient parfois incompréhensibles : « Excel » renvoyait de vieux articles, pour des raisons que personne ne pouvait expliquer. Dès qu’une requête dépassait trois mots, tout se noyait — il fallait taper exactement le bon champ sémantique pour avoir quelque chose de pertinent. Et surtout, le classement était opaque : impossible de justifier pourquoi tel résultat sortait devant tel autre. Chaque évolution — un poids sur une promotion, une règle temporaire — passait par le fournisseur.

La facture annuelle restait raisonnable (moins de 10 k€, indexée sur notre trafic). Ce n’était donc pas une histoire de coût, mais de maîtrise : nous étions responsables d’un outil que nous ne pouvions ni expliquer, ni faire évoluer.

Une stack qui était déjà là

Le déclic n’est pas venu d’un outil, mais d’un contexte. L’IA avait fait grimper notre productivité de développement d’un ordre de grandeur, et nos briques étaient déjà en place :

  • Valkey avait remplacé Memcached comme serveur de cache. Valkey Search y ajoute un mode vectoriel avec l’API de RediSearch (FT.CREATE / FT.SEARCH, HNSW, distance COSINE) — la référence du domaine, sur une machine que nous opérions déjà.
  • OpenAI était déjà branché : text-embedding-3-small (1536 dimensions), quelques millisecondes par requête, un coût marginal.
  • LLPhant, une bibliothèque PHP d’orchestration RAG, s’intégrait à Laravel 12 sans friction — avec une documentation qui nous a permis de prendre la main vite.

Nous n’avons pas sérieusement évalué d’alternative : le puzzle se montait de lui-même. Restait le risque du produit jeune (Valkey Search 1.0). Une preuve de concept a suffi à nous convaincre : les résultats étaient immédiatement excellents. PoC, recette, production. Nos notices de formation, assez courtes, se vectorisent d’ailleurs sans découpage élaboré.

Le pipeline, cinq étapes

Chaque recherche traverse cinq étapes, visibles sur notre page de debug interne :

Requête (+ facettes métier : année catalogue, domaine, ville, certifiant…)


[1] Embedding   requête → vecteur 1536 dims                   ~4 ms

[2] Meaning     kNN HNSW sur l'index du pays (COSINE)
      │         seuil de similarité ≥ 0,3, dédup par code

[3] Final       épingles exactes (code produit, titre quasi-exact)
      │         puis tri par distance vectorielle
      │         micro-tiebreak best-seller si écart < 0,005

[4] Pages       pages WordPress vectorisées (re-tri lexical en PHP)

[5] Contexte    assemblage du contexte pour le LLM (chatbot)

Le classement final tient en peu de choses : si l’utilisateur tape un code produit exact ou un titre quasi exact, la formation concernée est épinglée en tête. Sinon, c’est la distance vectorielle qui décide. En cas de quasi-égalité (écart de distance inférieur à 0,005), le best-seller passe devant. Les facettes — année de catalogue, domaine, ville, formation certifiante ou non — préexistent au moteur et filtrent avant la recherche.

Deux pièges valent le détour. D’abord, Valkey Search 1.0 n’indexe pas de texte sans vecteur : impossible de faire du fulltext, nous sommes donc passés à 100 % vectoriel (le code conserve un mode hybride avec fusion RRF, prêt pour le jour où Valkey le permettra). Ensuite, le multi-sites : un même produit de formation se vend sur cegos.fr et sur le site de notre partenaire ib-formation.fr, avec une redirection et une ouverture en nouvel onglet. Avec les deux bases vectorielles en interne, ce croisement d’offres — déjà pénible avec l’ancien moteur, où nous récupérions des classements à re-personnaliser et des listes de stop words à maintenir — se gère désormais directement. Même chose pour le double catalogue 2026/2027 : déduplication par code, prix par année.

La leçon : on a d’abord reconstruit la complexité

Notre première version reproduisait l’ancien monde : une page « Weights » dans notre back-office permettait de régler des poids éditoriaux pour influencer le classement. Résultat : des classements imprévisibles, que nous étions toujours incapables de justifier, et une dette de configuration qui s’accumulait. Nous avons tout supprimé.

Ce qui reste tient sur un coin de table : des épingles, une distance, un micro-tiebreak. Des poids légers pourront revenir un jour — une promotion, des sessions à remplir — mais à petite dose et parce que nous aurons la main dessus. Le critère qui a tranché : quand le métier nous demande « pourquoi mon article ne sort pas ? », il faut pouvoir répondre. Un moteur simple s’explique ; une configuration de poids, non.

Pour évaluer tout ça, notre spécialiste SEO a construit avec le métier un golden dataset d’environ 150 requêtes réelles. Les critères de réussite : top 1 quand on tape un titre ou une référence exacts ; sinon, au moins deux ou trois formations attendues dans les cinq premiers résultats, et les autres cohérentes avec la demande.

Ce que l’IA a changé dans notre façon de travailler

C’est peut-être le point le plus important du REX. Nous travaillons en TDD, avec ce qu’on appelle le harness engineering : contraindre l’IA, lui donner un objectif précis, la laisser itérer jusqu’à l’atteindre — encadrée par les tests. Sur le seul moteur de recherche, ce sont environ 254 méthodes de tests unitaires, 14 scénarios de tests navigateur (Dusk) et des tests de « contrat source » qui verrouillent des invariants du code. Une grande partie de ces tests a été écrite par l’IA, relue par nous. Le golden dataset est rejoué à chaque évolution pour comparer les classements.

L’équipe : Damien (direction technique), Vladimir (SEO, créateur du dataset), Marie (UX/UI, qui refait le front du moteur — en ligne fin d’année) et moi-même. Une petite équipe, un chantier d’envergure.

L’exploitation, au quotidien

Une tâche planifiée nocturne re-vectorise les formations et les pages modifiées (détection par content-hash, ~1 minute pour 500 documents) ; un webhook WordPress fait les ajouts et suppressions en quasi temps réel. Better Stack reçoit des résumés d’indexation et des alertes. En interne, un dashboard « Vector Store » permet de vérifier les bases et de relancer une vectorisation, et la page « RAG Query » déroule les cinq étapes d’une requête pour déboguer sans marteler la front publique.

Les chiffres : environ 10 000 documents indexés (4 000 formations, 6 000 articles), ~47 ms par recherche dont ~4 ms d’embedding. Aucun incident notable en production depuis la bascule.

Les limites, honnêtement

Nous n’avons pas encore de chiffres d’usage : le suivi « recherche → page formation » vient d’être posé, les résultats arriveront dans les prochains mois. Le coût de l’API OpenAI est modeste mais son suivi précis reste à affiner. Le mode hybride attend une version de Valkey Search qui indexe le texte. L’observabilité est un chantier ouvert. Et nous n’avons pas de baseline chiffrée sur l’ancien moteur : nos comparaisons avant/après sont qualitatives, à l’œil.

Et si c’était à refaire ?

Pareil : le golden dataset avec le métier dès le départ, l’outillage interne dès la V1, partir de la stack existante, et un moteur volontairement simple — du simple vers le complexe, jamais l’inverse. Autrement : la page Weights ne serait jamais née, et nous aurions mesuré une baseline chiffrée sur l’ancien moteur avant de basculer. À une équipe qui hésite entre un SaaS et un moteur maison, je dirais : faites une PoC sur un golden dataset, et regardez les résultats.

L’IA nous a fait gagner un facteur dix. Mais c’est précisément parce qu’elle produit vite qu’il faut maîtriser ce qu’on construit : des outils simples, explicables, et testés.