Comment automatiser les synonymes et le téléchargement à l'aide de notre API Synonymes ?
Découvrez comment les LLM peuvent être utilisés pour identifier et générer automatiquement des synonymes, permettant ainsi aux termes d'être chargés de manière programmatique dans l'API de synonymes d'Elasticsearch.
L'amélioration de la qualité des résultats de recherche est essentielle pour offrir une expérience efficace aux utilisateurs. L'un des moyens d'optimiser les recherches consiste à étendre automatiquement les termes recherchés au moyen de synonymes. Cela permet d'interpréter les requêtes de manière plus large, de couvrir les variations linguistiques et donc d'améliorer la concordance des résultats.
Ce blog explore la manière dont les grands modèles de langage (LLM) peuvent être utilisés pour identifier et générer automatiquement des synonymes, ce qui permet de charger ces termes de manière programmatique dans l'API de synonymes d'Elasticsearch.
Quand utiliser des synonymes ?
L'utilisation de synonymes peut être une solution plus rapide et plus rentable que la recherche vectorielle. Sa mise en œuvre est plus simple car elle ne nécessite pas de connaissances approfondies en matière d'encastrements ni de processus complexe d'ingestion de vecteurs.
En outre, la consommation de ressources est plus faible, car la recherche vectorielle nécessite une plus grande capacité de stockage et de mémoire pour l'indexation de l'incorporation et la recherche.
Un autre aspect important est la régionalisation de la recherche. Grâce aux synonymes, il est possible d'adapter les termes à la langue et aux coutumes locales. Ceci est utile dans les situations où les embeddings peuvent ne pas correspondre à des expressions régionales ou à des termes spécifiques à un pays. Par exemple, certains mots ou acronymes peuvent avoir des significations différentes selon la région, mais sont naturellement traités comme des synonymes par les utilisateurs locaux. Au Brésil, cette situation est assez courante. "Abacaxi" et "ananás" sont le même fruit (ananas), mais le second terme est plus couramment utilisé dans certaines régions du nord-est. "De même, le pão francês", bien connu dans le Sud-Est, peut être appelé "pão careca" dans le Nord-Est.
Comment utiliser les LLM pour générer des synonymes ?
Pour obtenir automatiquement des synonymes, on peut utiliser des LLM, qui analysent le contexte d'un terme et suggèrent des variations appropriées. Cette approche permet d'étendre dynamiquement les synonymes, ce qui garantit une recherche plus large et plus précise sans dépendre d'un dictionnaire fixe.
Dans cette démonstration, nous utiliserons un LLM pour générer des synonymes pour des produits de commerce électronique. De nombreuses recherches ne donnent que peu ou pas de résultats en raison de variations dans les termes recherchés. Les synonymes permettent de résoudre ce problème. Par exemple, une recherche sur "smartphone" peut englober différents modèles de téléphones mobiles, ce qui permet aux utilisateurs de trouver les produits qu'ils recherchent.
Produits requis
Avant de commencer, nous devons configurer l'environnement et définir les dépendances nécessaires. Nous utiliserons la solution fournie par Elastic pour exécuter Elasticsearch et Kibana localement dans Docker. Le code sera écrit en Python, v3.9.6, avec les dépendances suivantes :
pip install openai==1.59.8 elasticsearch==8.15.1Création de l'index des produits
Dans un premier temps, nous créerons un index des produits sans support de synonymes. Cela nous permettra de valider les requêtes et de les comparer à un index comprenant des synonymes.
Pour créer l'index, nous chargeons en masse un jeu de données de produits à l'aide de la commande suivante dans Kibana DevTools :
POST _bulk
{"index": {"_index": "products", "_id": 10001}}
{"category": "Electronics", "name": "iPhone 14 Pro"}
{"index": {"_index": "products", "_id": 10007}}
{"category": "Electronics", "name": "MacBook Pro 16-inch"}
{"index": {"_index": "products", "_id": 10013}}
{"category": "Electronics", "name": "Samsung Galaxy Tab S8"}
{"index": {"_index": "products", "_id": 10037}}
{"category": "Electronics", "name": "Apple Watch Series 8"}
{"index": {"_index": "products", "_id": 10049}}
{"category": "Electronics", "name": "Kindle Paperwhite"}
{"index": {"_index": "products", "_id": 10067}}
{"category": "Electronics", "name": "Samsung QLED 4K TV"}
{"index": {"_index": "products", "_id": 10073}}
{"category": "Electronics", "name": "HP Spectre x360 Laptop"}
{"index": {"_index": "products", "_id": 10079}}
{"category": "Electronics", "name": "Apple AirPods Pro"}
{"index": {"_index": "products", "_id": 10115}}
{"category": "Electronics", "name": "Amazon Echo Show 10"}
{"index": {"_index": "products", "_id": 10121}}
{"category": "Electronics", "name": "Apple iPad Air"}
{"index": {"_index": "products", "_id": 10127}}
{"category": "Electronics", "name": "Apple AirPods Max"}
{"index": {"_index": "products", "_id": 10151}}
{"category": "Electronics", "name": "Sony WH-1000XM4 Headphones"}
{"index": {"_index": "products", "_id": 10157}}
{"category": "Electronics", "name": "Google Pixel 6 Pro"}
{"index": {"_index": "products", "_id": 10163}}
{"category": "Electronics", "name": "Apple MacBook Air"}
{"index": {"_index": "products", "_id": 10181}}
{"category": "Electronics", "name": "Google Pixelbook Go"}
{"index": {"_index": "products", "_id": 10187}}
{"category": "Electronics", "name": "Sonos Beam Soundbar"}
{"index": {"_index": "products", "_id": 10199}}
{"category": "Electronics", "name": "Apple TV 4K"}
{"index": {"_index": "products", "_id": 10205}}
{"category": "Electronics", "name": "Samsung Galaxy Watch 4"}
{"index": {"_index": "products", "_id": 10211}}
{"category": "Electronics", "name": "Apple MacBook Pro 16-inch"}
{"index": {"_index": "products", "_id": 10223}}
{"category": "Electronics", "name": "Amazon Echo Dot (4th Gen)"}Générer des synonymes avec LLM
Dans cette étape, nous utiliserons un LLM pour générer dynamiquement des synonymes. Pour ce faire, nous intégrerons l'API OpenAI, en définissant un modèle et une invite appropriés. Le LLM recevra la catégorie et le nom du produit, en veillant à ce que les synonymes soient pertinents du point de vue contextuel.
import json
import logging
from openai import OpenAI
def call_gpt(prompt, model):
try:
logging.info("generate synonyms by llm...")
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
temperature=0.7,
max_tokens=1000
)
content = response.choices[0].message.content.strip()
return content
except Exception as e:
logging.error(f"Failed to use model: {e}")
return None
def generate_synonyms(category, products):
synonyms = {}
for product in products:
prompt = f"You are an expert in generating synonyms for products. Based on the category and product name provided, generate synonyms or related terms. Follow these rules:\n"
prompt += "1. **Format**: The first word should be the main item (part of the product name, excluding the brand), followed by up to 3 synonyms separated by commas.\n"
prompt += "2. **Exclude the brand**: Do not include the brand name in the synonyms.\n"
prompt += "3. **Maximum synonyms**: Generate a maximum of 3 synonyms per product.\n\n"
prompt += f"The category is: **{category}**, and the product is: **{product}**. Return only the synonyms in the requested format, without additional explanations."
response = call_gpt(prompt, "gpt-4o")
synonyms[product] = response
return synonymsÀ partir de l'index des produits créé, nous récupérerons tous les articles de la catégorie "Electronics" et enverrons leurs noms au LLM. Le résultat attendu sera quelque chose comme :
{
"iPhone 14 Pro": ["iPhone", "smartphone", "mobile", "handset"],
"MacBook Pro 16-inch": ["MacBook", "Laptop", "Notebook", "Ultrabook"],
"Samsung Galaxy Tab S8": ["Tab", "Tablet", "Slate", "Pad"],
"Bose QuietComfort 35 Headphones": ["Headphones", "earphones", "earbuds", "headset"]
}Avec les synonymes générés, nous pouvons les enregistrer dans Elasticsearch à l'aide de l'API Synonyms.
Gestion des synonymes avec l'API Synonyms
L'API Synonymes offre un moyen efficace de gérer les ensembles de synonymes directement dans le système. Chaque ensemble de synonymes se compose de règles de synonymie, selon lesquelles un groupe de mots est traité comme équivalent dans les recherches.
Exemple de création d'un jeu de synonymes
PUT _synonyms/my-synonyms-set
{
"synonyms_set": [
{
"id": "rule-1",
"synonyms": "hello, hi"
},
{
"synonyms": "bye, goodbye"
}
]
}Cela crée un ensemble appelé "my-synonyms-set," où "hello" et "hi" sont traités comme des équivalents, ainsi que "bye" et "goodbye."
Mise en œuvre de la création de synonymes pour le catalogue de produits
Vous trouverez ci-dessous la méthode permettant de construire un ensemble de synonymes et de l'insérer dans Elasticsearch. Les règles de synonymie sont générées sur la base du mappage des synonymes suggérés par le LLM. Chaque règle possède un identifiant, correspondant au nom du produit au format "slug", et la liste des synonymes calculée par le LLM.
import json
import logging
from elasticsearch import Elasticsearch
from slugify import slugify
es = Elasticsearch(
"http://localhost:9200",
api_key="your_api_key"
)
def mount_synonyms(results):
synonyms_set = [{"id": slugify(product), "synonyms": synonyms} for product, synonyms in
results.items()]
try:
response = es.synonyms.put_synonym(id="products-synonyms-set",
synonyms_set=synonyms_set)
logging.info(json.dumps(response.body, indent=4))
return response.body
except Exception as e:
logging.error(f"Error create synonyms: {str(e)}")
return NoneVous trouverez ci-dessous la demande de création d'un ensemble de synonymes :
{
"synonyms_set":[
{
"id": "iphone-14-pro",
"synonyms": "iPhone, smartphone, mobile, handset"
},
{
"id": "macbook-pro-16-inch",
"synonyms": "MacBook, Laptop, Notebook, Computer"
},
{
"id": "samsung-galaxy-tab-s8",
"synonyms": "Tablet, Slate, Pad, Device"
},
{
"id": "garmin-forerunner-945",
"synonyms": "Forerunner, smartwatch, fitness watch, GPS watch"
},
{
"id": "bose-quietcomfort-35-headphones",
"synonyms": "Headphones, Earphones, Headset, Cans"
}
]
}Une fois l'ensemble de synonymes créé dans le cluster, nous pouvons passer à l'étape suivante, qui consiste à créer un nouvel index avec prise en charge des synonymes à l'aide de l'ensemble défini.
Le code Python complet avec les synonymes générés par LLM et la création d'ensembles de synonymes définie par l'API Synonyms est ci-dessous :
import json
import logging
from elasticsearch import Elasticsearch
from openai import OpenAI
from slugify import slugify
logging.basicConfig(level=logging.INFO)
client = OpenAI(
api_key="your-key",
)
es = Elasticsearch(
"http://localhost:9200",
api_key="your_api_key"
)
def call_gpt(prompt, model):
try:
logging.info("generate synonyms by llm...")
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
temperature=0.7,
max_tokens=1000
)
content = response.choices[0].message.content.strip()
return content
except Exception as e:
logging.error(f"Failed to use model: {e}")
return None
def generate_synonyms(category, products):
synonyms = {}
for product in products:
prompt = f"You are an expert in generating synonyms for products. Based on the category and product name provided, generate synonyms or related terms. Follow these rules:\n"
prompt += "1. **Format**: The first word should be the main item (part of the product name, excluding the brand), followed by up to 3 synonyms separated by commas.\n"
prompt += "2. **Exclude the brand**: Do not include the brand name in the synonyms.\n"
prompt += "3. **Maximum synonyms**: Generate a maximum of 3 synonyms per product.\n\n"
prompt += f"The category is: **{category}**, and the product is: **{product}**. Return only the synonyms in the requested format, without additional explanations."
response = call_gpt(prompt, "gpt-4o")
synonyms[product] = response
return synonyms
def get_products(category):
query = {
"size": 50,
"_source": ["name"],
"query": {
"bool": {
"filter": [
{
"term": {
"category.keyword": category
}
}
]
}
}
}
response = es.search(index="products", body=query)
if response["hits"]["total"]["value"] > 0:
product_names = [hit["_source"]["name"] for hit in response["hits"]["hits"]]
return product_names
else:
return []
def mount_synonyms(results):
synonyms_set = [{"id": slugify(product), "synonyms": synonyms} for product, synonyms in
results.items()]
try:
es_client = get_client_es()
response = es_client.synonyms.put_synonym(id="products-synonyms-set",
synonyms_set=synonyms_set)
logging.info(json.dumps(response.body, indent=4))
return response.body
except Exception as e:
logging.error(f"Erro update synonyms: {str(e)}")
return None
if __name__ == '__main__':
category = "Electronics"
products = get_products("Electronics")
llm_synonyms = generate_synonyms(category, products)
mount_synonyms(llm_synonyms)Création d'un index avec prise en charge des synonymes
Un nouvel index sera créé dans lequel toutes les données de l'index products seront réindexées. Cet index utilisera le synonyms_filter, qui applique le products-synonyms-set créé précédemment.
Vous trouverez ci-dessous le mappage de l'index configuré pour utiliser les synonymes :
PUT products_02
{
"settings": {
"analysis": {
"filter": {
"synonyms_filter": {
"type": "synonym",
"synonyms_set": "products-synonyms-set",
"updateable": true
}
},
"analyzer": {
"synonyms_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"synonyms_filter"
]
}
}
}
},
"mappings": {
"properties": {
"ID": {
"type": "long"
},
"category": {
"type": "keyword"
},
"name": {
"type": "text",
"analyzer": "standard",
"search_analyzer": "synonyms_analyzer"
}
}
}
}Réindexation de l'index products
Nous allons maintenant utiliser l'API Reindex pour migrer les données de l'index products vers le nouvel index products_02, qui prend en charge les synonymes. Le code suivant a été exécuté dans Kibana DevTools :
POST _reindex
{
"source": {
"index": "products"
},
"dest": {
"index": "products_02"
}
}Après la migration, l'index products_02 sera alimenté et prêt à valider les recherches à l'aide du jeu de synonymes configuré.
Valider la recherche avec des synonymes
Comparons les résultats de recherche entre les deux index. Nous allons exécuter la même requête sur les deux index et vérifier si les synonymes sont utilisés pour récupérer les résultats.
Recherche dans l'index products (sans synonymes)
Nous utiliserons Kibana pour effectuer des recherches et analyser les résultats. Dans le menu Analytics > Discovery, nous allons créer une vue de données pour visualiser les données des index que nous avons créés.
Dans Discovery, cliquez sur Data View et définissez un nom et un modèle d'index. Pour l'index "products", nous utiliserons le modèle "products". Ensuite, nous répéterons le processus pour créer une nouvelle vue de données pour l'index "products_02", en utilisant le modèle "products_02".

Une fois les vues de données configurées, nous pouvons retourner sur Analytics > Discovery et commencer les validations.

Ici, après avoir sélectionné les produits DataView et effectué une recherche pour le terme "tablet", nous n'obtenons aucun résultat, même si nous savons qu'il existe des produits tels que "Kindle Paperwhite" et "Apple iPad Air".

Recherche dans l'index products_02 (support des synonymes)
Lors de l'exécution de la même requête sur la vue de données "products_synonyms", qui prend en charge les synonymes, les produits ont été récupérés avec succès. Cela prouve que le jeu de synonymes configuré fonctionne correctement, en garantissant que les différentes variations des termes recherchés renvoient les résultats escomptés.

Nous pouvons obtenir le même résultat en exécutant la même requête directement dans Kibana DevTools. Il suffit d'effectuer une recherche dans l'index products_02 à l'aide de l'API de recherche Elasticsearch :

Conclusion
La mise en œuvre de synonymes dans Elasticsearch a permis d'améliorer la précision et la couverture des recherches dans les catalogues de produits. Le principal facteur de différenciation était l'utilisation d'un LLM, qui générait des synonymes automatiquement et en fonction du contexte, éliminant ainsi le besoin de listes prédéfinies. Le modèle a analysé les noms et les catégories de produits, en veillant à ce que les synonymes soient pertinents pour le commerce électronique.
En outre, l'API Synonymes a simplifié la gestion des dictionnaires, en permettant de modifier dynamiquement les ensembles de synonymes. Grâce à cette approche, la recherche est devenue plus souple et plus adaptable aux différents types de requêtes des utilisateurs.
Ce processus peut être continuellement amélioré grâce à de nouvelles données et à des ajustements de modèles, ce qui garantit une expérience de recherche de plus en plus efficace.
Références
Exécuter Elasticsearch localement
https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html
Synonymes API
https://www.elastic.co/guide/en/elasticsearch/reference/current/synonyms-apis.html
Pour aller plus loin




