Cahier des charges et données du moteur produits
Le besoin
Une boutique en ligne fictive vend 60 produits dans 10 rayons. Elle veut :
- une barre de recherche qui comprend les reformulations (« faire le ménage sans y penser ») et les visiteurs étrangers ;
- un bloc « produits similaires » sur chaque fiche ;
- un rapport des doublons du catalogue, à faire valider par l'équipe produit ;
- une exploration des regroupements naturels du catalogue ;
- une mesure de qualité rejouable à chaque changement.
flowchart TB
subgraph Donnees["Données (fictives)"]
G["generer_produits.py"] --> P["produits.json : 60 fiches dont 3 quasi-doublons"]
R["requetes_eval.json : 31 requêtes, 4 langues"]
end
subgraph Moteur["moteur.py"]
I["indexer"] --> C["chercher"]
I --> S["similaires"]
I --> D["doublons"]
I --> K["clusters"]
end
P --> I
R --> E["evaluer.py : rappel@5"]
C --> E
Les données
Les fiches sont inventées : noms de produits et de marques fictifs, prix d'exemple. generer_produits.py les écrit dans produits.json à partir d'une liste en dur, pour que tout le monde ait exactement le même catalogue.
FICHES = [
# (catégorie, nom, description, prix en euros)
("Chaussures", "Trailrun Gecko", "Chaussure de trail à crampons de 5 mm pour terrains boueux et rocailleux, membrane respirante.", 129),
...
# Quasi-doublons volontaires (même produit, rédaction différente)
("Chaussures", "Trail Gecko (coloris forêt)", "Chaussure de trail running avec crampons de 5 mm, pensée pour la boue et les rochers, tige respirante.", 129),
]| Fichier | Contenu | Rôle |
|---|---|---|
produits.json | 60 fiches : id, categorie, nom, description, prix | le catalogue à indexer |
requetes_eval.json | 31 requêtes, langue, produits pertinents | le jeu de référence |
index/vecteurs.npy | matrice (60, 768) | généré par moteur.py indexer |
index/produits.sqlite | fiches + empreintes | généré par moteur.py indexer |
Les critères d'acceptation
| Critère | Seuil | Mesuré par |
|---|---|---|
| Rappel@5 global | au moins 0,90 | evaluer.py |
| Rappel@5 en anglais, espagnol, allemand | au moins 0,90 chacun | evaluer.py (par langue) |
| Meilleur que la recherche par mots-clés | oui, sur chaque langue | colonne BM25 |
| Doublons connus retrouvés | 3 sur 3, aucun faux positif | moteur.py doublons |
| Coût de réindexation sans changement | 0 appel | moteur.py indexer deux fois |
| Tests sans clé | tous verts | pytest -q |
Pourquoi générer le catalogue à partir d'une liste en dur plutôt que de demander à un LLM à chaque exécution ?
Une évaluation n'a de sens que si les données sont fixes. Un catalogue régénéré différemment à chaque fois rendrait les rappels@5 incomparables.
Quels fichiers peut-on supprimer sans perte, car ils se régénèrent ?
produits.json se régénère avec generer_produits.py, et l'index avec moteur.py indexer (au prix de quelques appels). requetes_eval.json est un travail humain de jugement : il se versionne et ne se régénère pas.
Exercice : 5 requêtes de plus
Ajoutez 5 requêtes à requetes_eval.json qui mettent le moteur en difficulté : au moins une avec négation, une très courte, une avec une faute de frappe. Notez vos prédictions avant de lancer evaluer.py.
Voir la solution
Exemples possibles :
{"requete": "casque mais pas pour l'avion, pour courir", "langue": "fr", "pertinents": ["P020"]},
{"requete": "thé", "langue": "fr", "pertinents": ["P007"]},
{"requete": "aspirateur robo", "langue": "fr", "pertinents": ["P055"]},
{"requete": "cadeau pour quelqu'un qui télétravaille", "langue": "fr", "pertinents": ["P013", "P014", "P016", "P017", "P051", "P054"]},
{"requete": "regalo para un aficionado a los discos", "langue": "es", "pertinents": ["P023"]}Les négations sont un point faible connu des embeddings : « pas pour l'avion » contient « avion » et peut remonter le casque de voyage. Les requêtes très courtes donnent peu de contexte. Les fautes de frappe légères passent souvent bien. Mesurez pour savoir.
Résultat obtenu
Génération du catalogue le 2026-10-15 :
$ python generer_produits.py
60 fiches écrites dans produits.jsonEt un aperçu des identifiants (les 3 dernières fiches sont les quasi-doublons de P001, P019 et P037) :
P001 Trailrun Gecko P002 Asphalte Flow P003 Randonnée Cimes Mid
P019 Casque Silence Pro P020 Écouteurs Sport Fil-Libre P021 Enceinte Galet
P037 Tente Dôme 3 places P038 Sac de couchage Grand Froid P039 Réchaud gaz Mini-Flamme
P058 Trail Gecko (coloris forêt) P059 Casque Silence Pro - édition noire P060 Tente Dôme 3 personnesJe sais faire
- Traduire un besoin métier en fonctions du moteur (recherche, similaires, doublons, clusters)
- Préparer des données fictives reproductibles avec une vérité terrain
- Écrire des critères d'acceptation mesurables
- Enrichir un jeu de requêtes avec des cas difficiles