Blog

So automatisieren Sie Synonyme und laden diese mithilfe unserer Synonym-API hoch.

Erfahren Sie, wie LLMs verwendet werden können, um Synonyme automatisch zu identifizieren und zu generieren, sodass Begriffe programmatisch in die Elasticsearch-Synonym-API geladen werden können.

Die Verbesserung der Qualität der Suchergebnisse ist unerlässlich für ein effizientes Nutzererlebnis. Eine Möglichkeit zur Optimierung von Suchanfragen besteht darin, die abgefragten Begriffe automatisch durch Synonyme zu erweitern. Dies ermöglicht eine breitere Interpretation von Anfragen, berücksichtigt sprachliche Variationen und verbessert so die Ergebnisübereinstimmung.

Dieser Blogbeitrag untersucht, wie große Sprachmodelle (LLMs) verwendet werden können, um Synonyme automatisch zu identifizieren und zu generieren, sodass diese Begriffe programmatisch in die Synonym-API von Elasticsearch geladen werden können.

Wann verwendet man Synonyme?

Die Verwendung von Synonymen kann im Vergleich zur Vektorsuche eine schnellere und kostengünstigere Lösung sein. Die Implementierung ist einfacher, da sie keine tiefgreifenden Kenntnisse über Einbettungen oder einen komplexen Vektor-Ingestionsprozess erfordert.

Darüber hinaus ist der Ressourcenverbrauch geringer, da die Vektorsuche für die Einbettungsindizierung und den Abruf eine größere Speicherkapazität und einen größeren Arbeitsspeicher benötigt.

Ein weiterer wichtiger Aspekt ist die Regionalisierung der Suche. Mithilfe von Synonymen ist es möglich, Begriffe an die jeweilige Sprache und die lokalen Gepflogenheiten anzupassen. Dies ist in Situationen nützlich, in denen Einbettungen möglicherweise nicht mit regionalen Ausdrücken oder länderspezifischen Begriffen übereinstimmen. Beispielsweise können manche Wörter oder Akronyme je nach Region unterschiedliche Bedeutungen haben, werden aber von den lokalen Nutzern selbstverständlich als Synonyme behandelt. In Brasilien ist das recht üblich. „Abacaxi“ und „ananás“ bezeichnen die gleiche Frucht (Ananas), wobei der zweite Begriff in einigen Regionen des Nordostens gebräuchlicher ist. Ähnlich verhält es sich mit dem im Südosten bekannten „pão francês“, das im Nordosten als „pão careca“ bekannt ist.

Wie kann man LLMs verwenden, um Synonyme zu generieren?

Um Synonyme automatisch zu erhalten, können wir LLMs verwenden, die den Kontext eines Begriffs analysieren und passende Variationen vorschlagen. Dieser Ansatz ermöglicht die dynamische Erweiterung von Synonymen und gewährleistet so eine umfassendere und genauere Suche, ohne auf ein festes Wörterbuch angewiesen zu sein.

In dieser Demonstration verwenden wir ein LLM, um Synonyme für E-Commerce-Produkte zu generieren. Viele Suchanfragen liefern aufgrund von Variationen in den Suchbegriffen nur wenige oder gar keine Ergebnisse. Mit Synonymen können wir dieses Problem lösen. Eine Suche nach „Smartphone“ kann beispielsweise verschiedene Modelle von Mobiltelefonen umfassen, um sicherzustellen, dass die Nutzer die Produkte finden, die sie suchen.

Voraussetzungen

Bevor wir beginnen, müssen wir die Umgebung einrichten und die erforderlichen Abhängigkeiten definieren. Wir werden die von Elastic bereitgestellte Lösung nutzen, um Elasticsearch und Kibana lokal in Docker auszuführen. Der Code wird in Python, Version 3.9.6, mit folgenden Abhängigkeiten geschrieben:

pip install openai==1.59.8 elasticsearch==8.15.1

Erstellung des Produktindex

Zunächst erstellen wir einen Index der Produkte ohne Synonymunterstützung. Dies ermöglicht es uns, Abfragen zu validieren und sie dann mit einem Index zu vergleichen, der Synonyme enthält.

Um den Index zu erstellen, laden wir einen Produktdatensatz per Massenimport mit folgendem Befehl in den 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)"}

Synonyme mit LLM generieren

In diesem Schritt verwenden wir ein LLM, um dynamisch Synonyme zu generieren. Um dies zu erreichen, werden wir die OpenAI-API integrieren und ein geeignetes Modell sowie eine entsprechende Eingabeaufforderung definieren. Der LLM erhält die Produktkategorie und den Produktnamen, wobei darauf geachtet wird, dass die Synonyme kontextuell relevant sind.

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

Aus dem erstellten Produktindex rufen wir alle Artikel der Kategorie „Elektronik“ ab und senden deren Namen an das LLM. Die erwartete Ausgabe sieht in etwa so aus:

{
  "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"]
}

Mit den generierten Synonymen können wir diese mithilfe der Synonyms API in Elasticsearch registrieren.

Synonyme mit der Synonyms-API verwalten

Die Synonyms-API bietet eine effiziente Möglichkeit, Synonymgruppen direkt im System zu verwalten. Jedes Synonymset besteht aus Synonymregeln, nach denen eine Gruppe von Wörtern bei Suchanfragen als gleichwertig behandelt wird.

Beispiel für die Erstellung eines Synonymsets

PUT _synonyms/my-synonyms-set
{
  "synonyms_set": [
    {
      "id": "rule-1",
      "synonyms": "hello, hi"
    },
    {
      "synonyms": "bye, goodbye"
    }
  ]
}

Dadurch entsteht eine Menge namens „meine-Synonyme-Menge“, in der „hello“ und „hi“ sowie „bye“ und „goodbye“ als gleichwertig behandelt werden.

Implementierung der Synonymerstellung für den Produktkatalog

Nachfolgend ist die Methode aufgeführt, die für den Aufbau eines Synonymsets und dessen Einfügen in Elasticsearch zuständig ist. Die Synonymregeln werden auf der Grundlage der vom LLM vorgeschlagenen Synonymzuordnung generiert. Jede Regel hat eine ID, die dem Produktnamen im Slug-Format entspricht, und die vom LLM berechnete Liste der Synonyme.

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 None

Nachfolgend die Anfragenutzlast zum Erstellen des Synonymsets:

{
   "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"
      }
   ]
}

Nachdem im Cluster ein Synonymset erstellt wurde, können wir zum nächsten Schritt übergehen, nämlich der Erstellung eines neuen Index mit Synonymunterstützung unter Verwendung des definierten Sets.

Der vollständige Python-Code mit den von LLM generierten Synonymen und der durch die Synonyms-API definierten Erstellung von Synonymsätzen ist unten aufgeführt:

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)

Erstellen eines Index mit Synonymunterstützung

Es wird ein neuer Index erstellt, in dem alle Daten aus dem Index products neu indiziert werden. Dieser Index verwendet synonyms_filter, der den zuvor erstellten products-synonyms-set anwendet.

Nachfolgend die Indexzuordnung, die für die Verwendung von Synonymen konfiguriert ist:

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"
      }
    }
  }
}

Neuindizierung des Index products

Nun werden wir die Reindex-API verwenden, um die Daten vom Index products in den neuen Index products_02 zu migrieren, der auch Synonymunterstützung beinhaltet. Der folgende Code wurde in den Kibana DevTools ausgeführt:

POST _reindex
{
  "source": {
    "index": "products"
  },
  "dest": {
    "index": "products_02"
  }
}

Nach der Migration wird der Index products_02 gefüllt sein und kann Suchanfragen mithilfe des konfigurierten Synonymsets validieren.

Suche mit Synonymen validieren

Lassen Sie uns die Suchergebnisse der beiden Indizes vergleichen. Wir werden die gleiche Abfrage auf beiden Indizes ausführen und überprüfen, ob die Synonyme verwendet werden, um Ergebnisse abzurufen.

Suche im Index products (ohne Synonyme)

Wir werden Kibana verwenden, um Suchvorgänge durchzuführen und die Ergebnisse zu analysieren. Im Menü „Analytics > Discovery“ erstellen wir eine Datenansicht, um die Daten aus den von uns erstellten Indizes zu visualisieren.

Klicken Sie innerhalb von Discovery auf Datenansicht und definieren Sie einen Namen und ein Indexmuster. Für den Index "Produkte" verwenden wir das Muster "Produkte ". Anschließend wiederholen wir den Vorgang, um eine neue Datenansicht für den Index "products_02" zu erstellen, wobei wir das Muster "products_02 " verwenden.

Nachdem die Datenansichten konfiguriert sind, können wir zu Analytics > Discovery zurückkehren und die Validierungen starten.

Hier erhalten wir nach Auswahl der DataView-Produkte und einer Suche nach dem Begriff „Tablet“ keine Ergebnisse, obwohl wir wissen, dass es Produkte wie „Kindle Paperwhite“ und „Apple iPad Air“ gibt.

Suche im Index products_02 (unterstützt Synonyme)

Bei der Durchführung derselben Abfrage in der Datenansicht "products_synonyms", die Synonyme unterstützt, wurden die Produkte erfolgreich abgerufen. Dies beweist, dass die konfigurierte Synonymgruppe korrekt funktioniert und sicherstellt, dass verschiedene Variationen der Suchbegriffe die erwarteten Ergebnisse liefern.

Das gleiche Ergebnis lässt sich erzielen, indem man dieselbe Abfrage direkt in den Kibana DevTools ausführt. Suchen Sie einfach im Index products_02 mithilfe der Elasticsearch Search API:

Fazit

Die Implementierung von Synonymen in Elasticsearch verbesserte die Genauigkeit und Abdeckung der Produktkatalogsuche. Der entscheidende Unterschied bestand in der Verwendung eines LLM, das Synonyme automatisch und kontextbezogen generierte, wodurch die Notwendigkeit vordefinierter Listen entfiel. Das Modell analysierte Produktnamen und Kategorien und stellte dabei relevante Synonyme für den E-Commerce sicher.

Darüber hinaus vereinfachte die Synonyms-API die Wörterbuchverwaltung, sodass Synonymsätze dynamisch geändert werden können. Mit diesem Ansatz wurde die Suche flexibler und besser an unterschiedliche Suchanfragen der Nutzer anpassbar.

Dieser Prozess kann durch neue Daten und Modellanpassungen kontinuierlich verbessert werden, wodurch ein immer effizienteres Forschungserlebnis gewährleistet wird.

Referenzen

Elasticsearch lokal ausführen

https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html

Synonyms API

https://www.elastic.co/guide/en/elasticsearch/reference/current/synonyms-apis.html

Zugehörige Inhalte

Bewertung der Relevanz von Suchanfragen mit Bewertungslisten

Jhon Guzmán

Generierung von Filtern und Facetten mithilfe von maschinellem Lernen

Andre Luiz

Sie wissen schon, Kontext – Teil I: Die Entwicklung von hybrider Suche und Kontextgestaltung

Woody Walton

Skalierung von späten Interaktionsmodellen in Elasticsearch – Teil 2

Peter Straßer

Hybride Suche ohne Probleme: Vereinfachte hybride Suche mit Retrievern

Mike Pellegrini

Sind Sie bereit, hochmoderne Sucherlebnisse zu schaffen?

Eine ausreichend fortgeschrittene Suche kann nicht durch die Bemühungen einer einzelnen Person erreicht werden. Elasticsearch wird von Datenwissenschaftlern, ML-Ops-Experten, Ingenieuren und vielen anderen unterstützt, die genauso leidenschaftlich an der Suche interessiert sind wie Sie. Lasst uns in Kontakt treten und zusammenarbeiten, um das magische Sucherlebnis zu schaffen, das Ihnen die gewünschten Ergebnisse liefert.

Probieren Sie es selbst aus