learn.chetana.fr

Garantir la qualité du matching

16 min de lectureAvancé

Le principe : la confiance est graduée, jamais binaire

La recherche hybride (leçon prĂ©cĂ©dente) produit des candidats scorĂ©s — mais que fait-on du score ? Le pipeline le transforme en dĂ©cision Ă  trois issues via deux seuils :

fast match  : score ≄ 0.85  → matched (voie rapide, SQL pur)
              sinon         → deep match (réécritures Haiku + rerank Cohere)
deep match  : score ≄ 0.6   → matched
              candidat < 0.6 → needs_review   (l'humain tranchera)
              aucun candidat → not_found

Le point de design essentiel : le systĂšme ne force jamais un match douteux. Une ligne needs_review conserve son best_match ET ses alternatives (top-4) — l'UI prĂ©sente le doute au lieu de le cacher. Chaque ligne persiste aussi match_confidence et matched_by (history|fast|deep|direct) : la provenance de chaque dĂ©cision est auditable.

À noter (honnĂȘtetĂ© du rĂ©tro-engineering) : ces seuils sont aujourd'hui globaux et codĂ©s en dur — le ScoringConfig porte un commentaire « later read from tenant config ». Un grossiste en visserie et un distributeur pharma n'ont sans doute pas la mĂȘme tolĂ©rance au faux positif.

Le cache d'apprentissage : product_match_history

La source la plus prioritaire du pipeline n'est ni le SQL ni le LLM — c'est la mĂ©moire :

  • Ă  la fin de chaque pipeline, le node match_history upsert chaque ligne rĂ©solue : clĂ© = nom produit normalisĂ© (accents retirĂ©s, minuscules, espaces rĂ©duits — « CĂąble RJ45 Cat6 » ≡ « cable rj45 cat6 »), valeur = variant matchĂ© + usage_count incrĂ©mentĂ© ;
  • au pipeline suivant, une phase 0 consulte ce cache en batch AVANT tout matching : hit → matched_by="history", statut matched, fast et deep entiĂšrement court-circuitĂ©s (zĂ©ro LLM, zĂ©ro rerank) ;
  • le tout scoppĂ© par tenant automatiquement — c'est une table sous RLS comme les autres (leçon 2 !). SubtilitĂ© : le prix n'est PAS cachĂ© — il est rechargĂ© du catalogue courant Ă  chaque hit (un prix figĂ© dans un cache serait un bug mĂ©tier).

Un client B2B recommande souvent les mĂȘmes produits avec les mĂȘmes libellĂ©s : ce cache transforme le 2ᔉ import en opĂ©ration quasi gratuite et dĂ©terministe.

Le feedback utilisateur : product_match_feedback

Quand l'utilisateur corrige un match dans l'UI (PATCH .../lines/{id}), le systĂšme capture le signal : le candidat choisi est flaggĂ© was_overridden_by_user, son rang d'origine enregistrĂ©. Et Ă  chaque deep match, un snapshot du top-K (avec les 5 sous-scores de chaque candidat) est persistĂ© avec was_selected. Cette table est un dataset d'entraĂźnement en construction : elle contient exactement ce qu'il faut pour, un jour, entraĂźner un reranker maison — features (sous-scores) + label (le choix humain).

Nuance dĂ©couverte au rĂ©tro-engineering : les corrections humaines vont dans PMF mais ne sont pas rĂ©injectĂ©es dans le cache history — corriger un match ne « rĂ©pare » pas encore la mĂ©moire. La boucle d'apprentissage temps rĂ©el n'est fermĂ©e qu'Ă  moitiĂ©.

Les garde-fous en amont : ne pas matcher du faux

La qualitĂ© du matching commence avant le matching — si le structurer hallucine une ligne, tout l'aval travaille sur du vent :

  1. grounding par contrat : le prompt d'extraction interdit d'inventer un SKU, impose raw_text (le texte source exact) sur chaque ligne — chaque sortie est traçable vers sa source ;
  2. validator : lignes sans nom, quantitĂ© ≀ 0 ou non numĂ©rique → Ă©liminĂ©es ; un validation_score global dĂ©clenche l'erreur bloquante si tout est invalide ;
  3. critique LLM : les lignes suspectes (score faible, nom trop court/long) passent devant Haiku qui dĂ©tecte les artefacts classiques (un sous-total pris pour un produit, un doublon) — aujourd'hui en tĂ©lĂ©mĂ©trie seule, la boucle de re-extraction n'est pas cĂąblĂ©e ;
  4. brand veto & golden match : les deux rùgles dures du scoring — jamais de faux positif inter-marques, jamais de doute sur un SKU exact ;
  5. anti-pollution : le pipeline live ne crĂ©e jamais de produit au catalogue (allow_auto_create=False) — un email mal lu ne peut pas inventer un variant.

Les chantiers ouverts (et comment l'histoire s'est écrite)

Au moment du rĂ©tro-engineering initial, trois manques Ă©taient visibles — tu as les concepts pour les nommer :

  • l'Ă©val offline : des golden sets dormaient dans samples/ sans harness pour les rejouer
 ce manque a depuis Ă©tĂ© comblĂ© — un harness d'Ă©val complet a Ă©tĂ© construit (corpus de cas durs, scorecard, runs Langfuse), et il a immĂ©diatement fait progresser le matcher. C'est toute la leçon suivante, la plus instructive du module ;
  • pas de mĂ©triques agrĂ©gĂ©es en prod : le taux de correction utilisateur (LE capteur de qualitĂ©) est calculable en SQL dans PMF, mais aucun compteur/dashboard ne le suit en continu — le « monitoring Ă©tage 4 » du cours ML, toujours Ă  construire ;
  • seuils non tenant-isĂ©s et boucle history↔feedback ouverte : l'Ă©val a d'ailleurs prouvĂ© le danger de cette boucle (le cache apprend les erreurs d'un premier import ratĂ© et les re-sert). Premier correctif mergĂ© depuis : un trust gate — le cache ne mĂ©morise et ne re-sert que les matchs confiants. La rĂ©forme complĂšte (write-on-validation + invalidation) reste au backlog.

La morale d'étape : la mécanique de qualité au fil de l'eau (seuils, revue, mémoire, garde-fous) était solide ; dÚs que la mesure systématique est arrivée, elle a trouvé en quelques jours ce que des mois d'usage n'avaient pas prouvé.

đŸ§© Quiz1/5

Une ligne dont le meilleur candidat score 0.55 au deep match devient


🃏 Flashcards1/6