Appariement de produits : Similarité sémantique avec score de découverte

Cet article explique comment nous appairons des clusters de requêtes de recherche à des produits, pièces et articles en utilisant la similarité sémantique avec un modèle de score de découverte optionnel qui équilibre la pertinence, le trafic et le classement de page.

Le problème : Trouver la meilleure correspondance

Lorsque les utilisateurs recherchent "mini pc", nous devons déterminer quelle page produit représente le mieux cette requête. Nous avons des milliers de produits, pièces et articles—lequel devrions-nous afficher ?

Le défi est d'équilibrer plusieurs facteurs :

  • Pertinence sémantique : Dans quelle mesure la page correspond-elle au sens de la requête ?

  • Trafic de la requête : Combien de trafic de recherche cette requête génère-t-elle ?

  • Popularité de la page : Combien de trafic la page reçoit-elle déjà ?

Une approche naïve (similarité sémantique pure) pourrait associer "mini pc" à un produit obscur avec une similarité parfaite mais un trafic nul. Une meilleure approche prend en compte les trois facteurs.

Deux modes d'appariement

Nous prenons en charge deux modes d'appariement :

1. Appariement en masse (Original)

Chaque cluster trouve sa meilleure correspondance indépendamment. Plusieurs clusters peuvent correspondre à la même page :

  • Cluster A : "mini pc" → Produit X (similarité 0,95)

  • Cluster B : "petit ordinateur" → Produit X (similarité 0,93)

  • Cluster C : "bureau compact" → Produit X (similarité 0,91)

Cela crée de la redondance mais garantit que chaque cluster obtient sa meilleure correspondance.

2. Routage exclusif itératif (Cartographie 1:1)

Les clusters sont traités par score de trafic (le plus élevé d'abord). Une fois qu'une page est attribuée, elle est retirée du pool :

  • Cluster A (10K trafic) : "mini pc" → Produit X (attribué)

  • Cluster B (5K trafic) : "petit ordinateur" → Produit Y (X indisponible)

  • Cluster C (2K trafic) : "bureau compact" → Produit Z (X, Y indisponibles)

Cela crée des pages de requête uniques avec un repli automatique sur les correspondances suivantes les meilleures.

L'algorithme : Similarité sémantique

Étape 1 : Charger les embeddings

Nous chargeons les embeddings pré-calculés pour :

  1. Clusters de requêtes : Requête centrale de chaque cluster
  2. Pages sources : Produits, pièces, articles (depuis l'Étape 0)

Les deux utilisent le même modèle all-mpnet-base-v2, garantissant des embeddings comparables.

Étape 2 : Calculer la similarité

Pour chaque cluster, nous calculons la similarité cosinus avec toutes les pages sources :

similarities = util.cos_sim(cluster_embedding, source_embeddings)[0]

Cela produit un score de similarité (0,0 à 1,0) pour chaque page source.

Étape 3 : Appliquer le score de découverte (Optionnel)

Si le score de découverte est activé, nous combinons trois facteurs :

Modèle de score de découverte 50:30:20 :

discovery_score = (similarity * 0.5) + (query_score * 0.3) + (page_rank * 0.2)

Où :

  • Similarité (50%) : Pertinence sémantique (similarité cosinus)

  • Score de requête (30%) : Trafic de requête normalisé (impressions + clics)

  • Classement de page (20%) : Trafic de page normalisé (échelle logarithmique)

Cela équilibre la pertinence avec le potentiel de trafic.

Étape 4 : Normaliser les scores

Avant de combiner, nous normalisons chaque composante à [0, 1] :

Normalisation du score de requête :

max_query_score = max(cluster.total_score for cluster in clusters)
norm_query_score = query_score / max_query_score

Normalisation du classement de page (logarithmique pour empêcher les pages à fort trafic de dominer) :

max_page_rank = max(traffic_index.values())
norm_page_rank = log1p(page_rank) / log1p(max_page_rank)

La mise à l'échelle logarithmique empêche la page d'accueil (trafic le plus élevé) de dominer tous les appariements.

Étape 5 : Appliquer le bonus châssis (Produits uniquement)

Pour les appariements de produits, nous boostons les scores en fonction du type de châssis :

  • Châssis Treo : +10% (le plus récent, le plus populaire)

  • Châssis S : +5% (format compact, forte demande)

  • Châssis H : Pas de bonus (plus ancien, moins populaire)

if matched_type == "product":
    sku = matched_key.replace("/p/", "")
    chassis_prefix = sku.split("-")[0]
    if chassis_prefix.startswith("Treo"):
        similarity *= 1.10
    elif chassis_prefix.startswith("S"):
        similarity *= 1.05

Cela garantit que les produits plus récents sont priorisés lorsque la similarité est proche.

Étape 6 : Sélectionner la meilleure correspondance

Appariement en masse :

best_idx = similarities.argmax()
if similarities[best_idx] >= threshold:
    matches.append(cluster → source_pages[best_idx])

Routage exclusif :

# Trier les clusters par trafic (le plus élevé d'abord)
sorted_clusters = sorted(clusters, key=lambda c: c.total_score, reverse=True)

# ... (détails d'implémentation omis)

Seuil configurable

Le seuil d'appariement détermine la rigueur de l'appariement :

  • 0,80 (par défaut) : Rigueur modérée, la plupart des clusters correspondent

  • 0,85 : Plus strict, moins de correspondances mais de meilleure qualité

  • 0,75 : Plus indulgent, plus de clusters correspondent

Le seuil peut être ajusté sans changement de code via le fichier de configuration.

Mode d'analyse de seuil

Avant d'exécuter le pipeline complet, nous pouvons analyser l'impact du seuil :

python 6_match_source_data.py --analyze-threshold

Cela génère des échantillons à travers des plages de similarité :

  • 0,90-1,00 : Correspondances parfaites

  • 0,80-0,90 : Correspondances fortes

  • 0,70-0,80 : Correspondances modérées

  • 0,60-0,70 : Correspondances faibles

  • 0,50-0,60 : Correspondances très faibles

  • 0,40-0,50 : Mauvaises correspondances

Une interface web affiche ces échantillons pour une revue manuelle. Après avoir sélectionné un seuil, reprenez le pipeline :

python 6_match_source_data.py --resume-after-threshold

Cela charge le seuil depuis la décision de l'interface et complète l'appariement.

Embedding incrémental

Nous mettons en cache les embeddings pour les requêtes et les pages sources. Lorsque de nouvelles données arrivent :

  1. Charger les embeddings existants
  2. Embedder uniquement les nouveaux éléments
  3. Les ajouter au cache

Cela évite de ré-embeder des données inchangées. Voir Stratégie d'embedding pour plus de détails.

Format de sortie

L'appariement produit un fichier JSON avec des statistiques et des correspondances :

{
  "stats": {
    "threshold": 0.80,
# ... (détails d'implémentation omis)

Les correspondances sont triées par similarité (la plus élevée d'abord).

Pourquoi un score de découverte ?

La similarité sémantique pure a des limites :

Problème 1 : Produits obscurs

  • Requête : "mini pc" (10K trafic)

  • Meilleure correspondance : Produit obscur (similarité 0,98, 0 trafic)

  • Meilleure correspondance alternative : Produit populaire (similarité 0,95, 5K trafic)

Problème 2 : Inadéquation du trafic

  • Requête à fort trafic → Page à faible trafic (opportunité gaspillée)

  • Requête à faible trafic → Page à fort trafic (inutile)

Solution du score de découverte :

  • Équilibre la pertinence (50%) avec le potentiel de trafic (30% + 20%)

  • Les requêtes à fort trafic correspondent aux pages à fort trafic

  • Les requêtes à faible trafic correspondent aux pages de niche

  • Maximise la distribution globale du trafic

Caractéristiques de performance

Sur un serveur typique :

  • Temps de traitement : ~20 minutes pour 12,5K clusters × 5K pages sources

  • Utilisation mémoire : ~1 Go (embeddings + matrice de similarité)

  • Utilisation CPU : Élevée pendant le calcul de similarité

Le processus est limité par le CPU. L'utilisation de NumPy avec l'accélération BLAS accélère significativement les opérations matricielles.

Intégration avec le pipeline SEO

L'appariement de produits est l'Étape 6 du pipeline SEO :

  1. Étape 0 : Embed Source Data - Produits, pièces, articles
  2. Étape 1 : Fetch Queries - GSC, Google Ads, live, Algolia
  3. Étape 2 : Combine Queries - Fusionner toutes les sources
  4. Étape 3a : Generate Base Phrase Mappings - Filtres initiaux
  5. Étape 3b : Embed Queries - Convertir en vecteurs
  6. Étape 4 : Expand Phrase Mappings - Trouver des phrases similaires
  7. Étape 5 : Cluster Queries - Grouper en pages
  8. Étape 6 : Match Products ← Vous êtes ici
  9. Étape 7 : Build Query Pages - Générer du HTML
  10. Étape 8 : Generate Related Searches - Trouver des requêtes connexes
  11. Étape 11 : Migrate to Valkey - Charger dans le service de recherche

Voir SEO Pipeline Overview pour le flux complet.

En masse vs Exclusif : Lequel utiliser ?

Appariement en masse (original) :

  • ✅ Chaque cluster obtient sa meilleure correspondance

  • ✅ Simple, prévisible

  • ❌ Pages de requête redondantes (plusieurs clusters → même produit)

  • ❌ Potentiel de trafic gaspillé

Routage exclusif (1:1) :

  • ✅ Pages de requête uniques (pas de redondance)

  • ✅ Repli automatique sur les correspondances suivantes

  • ✅ Meilleure distribution du trafic

  • ❌ Les clusters à faible trafic peuvent obtenir des correspondances sous-optimales

  • ❌ Logique plus complexe

Recommandation : Utiliser le Routage exclusif pour la production. Cela crée des pages de requête uniques et de haute qualité avec une meilleure distribution du trafic.

Index de trafic et mise à l'échelle logarithmique

L'index de trafic suit les pages vues pour toutes les pages sources :

{
  "/p/Treo-N100-8-256-2H-W6-11P": 5000,
  "/p/S-i5-16-512-2H-W6-11P": 3000,
  "/": 50000
}

Nous utilisons la mise à l'échelle logarithmique pour empêcher les pages à fort trafic de dominer :

norm_page_rank = log1p(page_rank) / log1p(max_page_rank)

Sans cela, la page d'accueil (50K trafic) correspondrait à chaque requête. La mise à l'échelle logarithmique compresse la plage, donnant à toutes les pages une chance équitable.

Raisonnement du bonus châssis

Nous boostons les produits des châssis Treo et S car :

  • Treo : Châssis le plus récent, meilleures fonctionnalités, demande la plus élevée

  • Châssis S : Facteur de forme compact, populaire pour les mini PC

  • Châssis H : Plus ancien, en cours de retrait

Lorsque la similarité est proche (par exemple, 0,90 vs 0,89), le bonus garantit que les produits plus récents l'emportent. Cela correspond aux priorités commerciales.

Références

Concepts techniques

Documentation du modèle

Articles connexes

Résumé

Nous appairons des clusters de requêtes à des produits en utilisant la similarité sémantique avec un score de découverte optionnel :

Similarité sémantique :

  • Calculer la similarité cosinus entre les embeddings de requête et de source

  • Appariement basé sur un seuil (par défaut 0,80)

  • Bonus châssis pour Treo (+10%) et S-châssis (+5%)

Score de découverte (50:30:20) :

  • 50% pertinence sémantique (similarité cosinus)

  • 30% trafic de requête (impressions + clics normalisés)

  • 20% classement de page (mise à l'échelle logarithmique)

Deux modes :

  • En masse : Chaque cluster obtient la meilleure correspondance (redondance autorisée)

  • Exclusif : Cartographie 1:1, clusters à fort trafic d'abord (pas de redondance)

Analyse de seuil :

  • Générer des échantillons à travers des plages de similarité

  • Revue manuelle via interface web

  • Reprendre le pipeline avec le seuil sélectionné

Le résultat est un appariement de haute qualité entre requêtes et produits qui équilibre la pertinence sémantique avec le potentiel de trafic, créant des pages de requête optimisées pour le SEO.


← Retour à l'index de documentation