Tout sur les Question-Answering et comment l'implémenter en utilisant flask et elasticsearch.
Il ne fait aucun doute aujourd’hui que le Question-Answering est l’une des principales approches pour rendre la recherche plus similaire à une conversation avec un vieil ami qui sait tout sur tout, plutôt qu’avec une machine. Pour ce faire, le Question Answering mêle les techniques de recherche d’informations (RI) au traitement automatique du langage naturel (TAL).
Dans ce contexte de Question-Answering, un modèle entraîné peut être utilisé pour récupérer la réponse à une question à partir d’un texte donné, qui représente le contexte de recherche. Ce processus appelé « QA extractif » diffère du QA génératif ouvert et du QA génératif fermé, car dans le premier cas il n’y a pas de question et dans le second il n’y a pas de contexte. Dans le cas du Question-Answering extractif, il est nécessaire d’avoir une question et un contexte, mais, souvent, cela ne suffit pas pour déduire une réponse (ou du moins la bonne). En effet chaque réponse aura un score qui représente le niveau de certitude que la réponse donnée est la bonne.
Pour Adelean, en tant que leader de l’innovation dans le domaine des moteurs de recherche, le Question-Answering représente un défi non seulement pour rendre la recherche plus pertinente, mais aussi plus amicale et familière. De plus, compte tenu de la nature collaborative de all.site, nous pensons que le Question-Answering peut répondre aux besoins de l’utilisateur de la meilleure façon.
Passons au cœur du sujet : comment le question-answering a été implémenté dans notre moteur de recherche collaboratif.
Tout d’abord, il est important de préciser que, puisque elasticsearch ne propose pas de solution open-source à proprement parler, nous avons décidé de développer notre propre solution sous la forme d’une API REST, combinant la flexibilité de Python avec le potentiel du microframework flask.
Alors, comment tout cela fonctionne :
A partir de la question de l’utilisateur, les termes les plus pertinents sont extraits pour effectuer la recherche. Ce filtrage, qui s’effectue à l’aide d’une liste de stop-words, permet de créer une meilleure requête de recherche qui se traduira par une meilleure sélection des documents qui vont servir de contexte dans la tâche de question-answering.
Chaque document est envoyé à l’api flask avec la question. Ici, un nettoyage supplémentaire et une sélection du fragment le plus pertinent sont effectués, afin d’avoir un contexte propre.
Une fois cela fait, la question et le contexte sont prêts : ce qui manque, c’est le modèle.
Il est possible de créer et d’entraîner son propre modèle, ou d’utiliser des modèles pré-entraînés, en les téléchargeant depuis
Hugging Face - Question Answering
Pour nos besoins, nous avons décidé de choisir le modèle tinyroberta : il s’agit d’une version distillée du modèle de base roberta qui fournit des prédictions comparables plus rapidement. Voici quelques exemples d’importation du modèle pré-entraîné.
model_name = "deepset/tinyroberta-squad2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = ORTModelForQuestionAnswering.from_pretrained(model_name, from_transformers=True)
nlp = pipeline("question-answering", model=model, tokenizer=tokenizer)
Dans ce cas, nous avons décidé d’utiliser un modèle ORT plus approprié pour une utilisation dans des environnements à taille limitée.
La fonction pipeline() simplifie l’utilisation du modèle pour l’inférence : dans l’apprentissage automatique, l’inférence de modèle est le processus d’utilisation d’un modèle formé pour faire des prédictions sur de nouvelles données. En d’autres termes, une fois que vous avez appris à un modèle d’apprentissage automatique à reconnaître certains modèles, l’inférence de modèle permet au modèle d’appliquer automatiquement ces connaissances à de nouveaux points de données et de faire des prédictions à leur sujet.
La prédiction renvoie un résultat pour chaque document de fragment donné : ce résultat est composé de deux parties, une réponse et son score relatif. Ce n’est que si le score est supérieur à un seuil donné que la réponse sera considérée comme correcte et qu’elle sera renvoyée à l’utilisateur.
for hit in resp['hits']['hits']:
for fragment in hit['highlight']['attachment.content']:
context = cleanAndTrim(fragment)
QA_input = {'question': question,
'context' : context}
answer = nlp(QA_input)
if (answer.get('score') > 0.50):
return answer.get('answer')
Définir la valeur de seuil la plus correcte peut être extrêmement difficile : en effet, si un seuil trop bas augmente le rappel et diminue le temps de réponse, en revanche un seuil trop élevé augmente la précision, mais peut diminuer le temps de réponse. Il est également très important que le contexte utilisé dans le processus d’inférence soit propre, clair et pertinent.
C’est pour cela que les différentes étapes d’optimisation sont nécessaires.
L’apprentissage automatique pose chaque jour de nouveaux défis pour l’avenir. En tant que leaders de l’innovation, nous devons être toujours à l’affût des nouvelles solutions et des nouvelles technologies : le question-answering n’est qu’un premier pas vers la révolution qui va rendre les moteurs de recherche plus puissants.
Par exemple, la recherche vectorielle et les transformers pré-génératifs sont de nouvelles technologies prometteuses.