Exemple d'application destinée à illustrer comment le traitement du langage naturel (NLP) , spécifiquement nommé la reconnaissance d'entité (NER) peut être utilisé pour améliorer la précision des requêtes Elasticsearch et l'expérience utilisateur globale. Il y a deux avantages clés à utiliser la PNL aux côtés d'Elasticsearch (ou tout autre moteur de recherche de texte intégral):
Compte tenu de la requête «la veste noire coûte moins de 200 $» , nous pouvons déduire le prix de la couleur et maximum, et appliquer ces filtres de recherche pour l'utilisateur. Ce concept peut être étendu à d'autres domaines (par exemple la marque) et également soutenir les conjugaisons, par exemple «veste de barbour noir ou vert foncé»
Imaginez que vous travaillez pour un magasin de vêtements et d'équipements en plein air. Vous construisez une fonction de recherche de catalogue. Compte tenu de la requête «veste embalable», comment la base de données devrait choisir entre un «filet de moustique embalable» et une «veste légère». Les deux produits correspondent partiellement. TF- IDF sélectionnera très probablement le filet de moustique car il y aura moins de cas de «embalable» que «veste» dans le corpus. Cependant, lorsque vous regardez la requête, il est clair que la veste légère serait la meilleure correspondance.
Nous résolvons généralement ce problème en augmentant certains champs de documents, par exemple en attachant plus de poids aux champs de titre ou de type de produit que la description. Ce genre de fonctionnement, mais la logique est erronée. Nous disons essentiellement à l'acheteur "en fonction de ce que nous vendons, c'est ce que nous pensons être important pour vous".
Les humains comprennent que, compte tenu de la «veste embalable» de la requête, le client veut avant tout une veste. En effet, nous comprenons que «la veste» est un type de produit et que «embalable» est un attribut du produit. Le traitement du langage naturel (NLP) nous permet d'appliquer ce même raisonnement par programme. En termes simples, nous pouvons effectuer une requête Bool Elasticsearch dans laquelle nous devons avoir une correspondance pour «veste» et devons avoir une correspondance pour «Packable».
Premièrement, et surtout, ce n'est pas une mise en œuvre de la production. Le modèle NLP utilisé pour cet exemple est vraiment basique. Pour une utilisation en production, nous construisions quelque chose de bien plus robuste, formé avec les données de recherche historiques. Nous employons également une partie du marquage de la parole ainsi que l'analyse de dépendance pour mieux comprendre les phrases et les fragments de texte.
Deuxièmement, le code Elasticsearch est très basique. Pour une utilisation en production, nous voudrions utiliser des tokeniseurs personnalisés, des analyseurs et des synonymes. Bien sûr, nous aurions beaucoup plus de champs et beaucoup plus de documents.
Enfin, il n'y a pas de gestion des erreurs!.
Veuillez donc traiter cela dans l'esprit dans lequel il a été créé - une preuve de concept!
Le code Python a besoin d'un environnement 3.9.7+. Je recommande de l'exécuter dans un VirtualEnv en utilisant Venv ou Pyenv / VirtualEnv
$ pyenv install 3.9.7
$ pyenv virtualenv 3.9.7 nlp-search-poc
$ pyenv local nlp-search-poc
$ pip install -U pip
$ pip install -r requirements.txtJ'ai fourni un fichier docker-compose.yml, afin que vous puissiez tirer une simple instance Elasticsearch
$ docker-compose up -d elasticsearch-7Les dépendances et les chemins Python peuvent être délicats, j'ai donc fourni un utilitaire simple pour vérifier que tout fonctionne comme prévu. Remarque: Elasticsearch peut prendre quelques secondes pour s'accompagner.
$ python -m src.tools ping
Elasticsearch alive: True$ python -m src.tools create
productRepository INFO Creating products index
productRepository INFO products created
$ python -m src.tools ingest
productRepository INFO Ingesting lightweight black jacket
productRepository INFO Ingesting midweight black jacket
...J'ai créé un script de coquille d'emballage pour allumer Uvicorn / Fastapi
$ bin/server.sh
uvicorn.error INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
...Faites une demande de GET à http: // localhost: 8000 passant un corps JSON:
{
"query" : " lightweight black jacket less than $100 "
}Postman est probablement le meilleur outil pour cela, mais j'ai également inclus un client simple:
$ python -m src.client ' lightweight black jacket less than $100 ' {
"ner_prediction" : {
"text" : " lightweight black jacket less than $100 " ,
"product" : " jacket " ,
"price_from" : null ,
"price_to" : 100 ,
"colors" : [
" black "
],
"attrs" : [
" lightweight "
]
},
"results" : [
{
"title" : " lightweight black jacket " ,
"product_type" : " jacket " ,
"price" : 100 ,
"colors" : [
" black "
],
"attrs" : [
" lightweight "
]
}
]
}IMPORTANT: Si vous choisissez d'utiliser ce script, vous devez enfermer votre requête de recherche dans des devis uniques pour éviter l'expansion des variables.
Frapper ctrl + c
Ne vous inquiétez pas de l' asyncio.exceptions.CancelledError - il est causé par la fonction de rechargement chaud du serveur Uvicorn.
$ python -m src.tools drop
productRepository INFO Dropping products index
productRepository INFO products dropped$ docker-compose down
Stopping elasticsearch-7 ... done
Removing elasticsearch-7 ... done
Removing network nlp-search-poc_defaultJ'ai fourni un dockerfile au cas où vous voudriez tout exécuter à l'intérieur de Docker
$ docker build -t nlp-search-poc .Ensuite, exécutez Elasticsearch et le serveur
$ docker-compose up -dSi vous souhaitez également utiliser Docker pour ingérer les données de test dans Elasticsearch, vous pouvez le faire:
$ docker run -it --rm --network nlp-search-poc_default -e " ELASTIC_SEARCH_HOST=elasticsearch-7 " nlp-search-poc " python " " -m " " src.tools " " reset "Remarque : le nom du réseau est déterminé par les règles de réseautage de Docker
docker-compose.yml expose le port 8000 du serveur, vous pouvez donc interroger comme avant:
$ python -m src.client ' packable jacket '