Compréhension du langage courant (CLU), une fonctionnalité d’Azure AI Language, est la version mise à jour de LUIS.
Pour plus d'informations sur la prise en charge de compréhension du langage dans le kit de développement logiciel (SDK) Bot Framework, consultez Compréhension du langage naturel.
La capacité à comprendre ce que veut dire votre utilisateur du point de vue de la conversation et du contexte peut être une tâche difficile, mais peut donner à votre bot un sens de la conversation plus naturel. Le service de compréhension langagière, appelé Language Understanding (LUIS), est un service d’API cloud qui vous permet justement de faire cela ; votre bot peut ainsi reconnaître l’intention des messages de l’utilisateur, prendre en charge un langage plus naturel de l’utilisateur et mieux orienter le flux de la conversation.
Cette rubrique vous guide dans l’ajout de LUIS à une application de réservation de vol pour reconnaître les différentes intentions et entités contenues dans les entrées utilisateur.
Remarque
Les kits SDK JavaScript, C# et Python Bot Framework continueront d’être pris en charge. Toutefois, le kit de développement logiciel (SDK) Java est mis hors service avec une prise en charge finale à long terme se terminant en novembre 2023.
Les bots existants créés avec le kit de développement logiciel (SDK) Java continueront de fonctionner.
Cet exemple de bot de base montre l’exemple d’une application de réservation de vols d’un aéroport. Elle utilise un service LUIS pour reconnaître les entrées utilisateur et retourner les premières intentions LUIS reconnues.
Le modèle de langage contient trois intentions : Book Flight, Cancel et None. LUIS va utiliser ces intentions pour comprendre ce que l’utilisateur voulait dire lorsqu’il a envoyé un message au bot. Le modèle de langage définit également des entités que LUIS peut extraire de l’entrée de l’utilisateur, notamment l’aéroport d’origine ou de destination.
Après chaque traitement d’entrée utilisateur, DialogBot enregistre l’état actuel de UserState et de ConversationState. Lorsque toutes les informations nécessaires sont réunies, l'exemple de code crée une réservation de vol de démonstration. Dans cet article, nous allons aborder les aspects LUIS de cet exemple. Toutefois, le flux général de l'exemple est :
OnMembersAddedAsync est appelé lorsqu’un nouvel utilisateur est connecté et affiche une carte de bienvenue.
OnMessageActivityAsync est appelé pour chaque entrée d’utilisateur reçue.
Le module OnMessageActivityAsync exécute le dialogue approprié par le biais de la méthode d’extension de dialogue Run. La boîte de dialogue principale appelle alors l’assistance LUIS pour rechercher les intentions utilisateur les mieux notées. Si la meilleure intention pour l’entrée de l’utilisateur retourne « BookFlight », l’assistance remplit les informations de l’utilisateur retournées par LUIS. Après cela, le dialogue principal démarre BookingDialog, qui obtient des informations supplémentaires selon les besoins de l’utilisateur, par exemple :
Origin la ville d’origine
TravelDate la date de réservation du vol
Destination la ville de destination
Après chaque traitement d’entrée utilisateur, dialogBot enregistre l’état actuel de userState et de conversationState. Lorsque toutes les informations nécessaires sont réunies, l'exemple de code crée une réservation de vol de démonstration. Dans cet article, nous allons aborder les aspects LUIS de cet exemple. Toutefois, le flux général de l'exemple est :
onMembersAdded est appelé lorsqu’un nouvel utilisateur est connecté et affiche une carte de bienvenue.
OnMessage est appelé pour chaque entrée d’utilisateur reçue.
Le module onMessage exécute la mainDialog, qui collecte les entrées d'utilisateur.
La boîte de dialogue principale appelle alors l’assistance LUIS FlightBookingRecognizer pour rechercher les intentions utilisateur les mieux notées. Si la meilleure intention pour l’entrée de l’utilisateur retourne « BookFlight », l’assistance remplit les informations de l’utilisateur retournées par LUIS.
À réception, mainDialog conserve les informations pour l’utilisateur retournées par LUIS et démarre bookingDialog. bookingDialog acquiert les informations supplémentaires nécessaires auprès de l’utilisateur, par exemple :
destination la ville de destination.
origin la ville d’origine.
travelDate la date à laquelle réserver le vol.
Après chaque traitement d’entrée utilisateur, DialogBot enregistre l’état actuel de UserState et de ConversationState.
Lorsque toutes les informations nécessaires sont réunies, l'exemple de code crée une réservation de vol de démonstration.
Dans cet article, nous allons aborder les aspects LUIS de cet exemple. Toutefois, le flux général de l'exemple est :
onMembersAdded est appelé lorsqu’un nouvel utilisateur est connecté et affiche une carte de bienvenue.
onMessageActivity est appelé pour chaque entrée d’utilisateur reçue.
Le module onMessageActivity exécute le dialogue approprié par le biais de la méthode d’extension de dialogue run. La boîte de dialogue principale appelle alors l’assistance LUIS pour rechercher les intentions utilisateur les mieux notées. Si la meilleure intention pour l’entrée de l’utilisateur retourne « BookFlight », l’assistance remplit les informations de l’utilisateur retournées par LUIS. Après cela, le dialogue principal démarre BookingDialog, qui obtient des informations supplémentaires selon les besoins de l’utilisateur, par exemple :
Origin la ville d’origine
TravelDate la date de réservation du vol
Destination la ville de destination
Après chaque traitement d’entrée utilisateur, DialogBot enregistre l’état actuel de user_state et de conversation_state. Lorsque toutes les informations nécessaires sont réunies, l'exemple de code crée une réservation de vol de démonstration. Dans cet article, nous allons aborder les aspects LUIS de cet exemple. Toutefois, le flux général de l'exemple est :
on_members_added_activity est appelé lorsqu’un nouvel utilisateur est connecté et affiche une carte de bienvenue.
on_message_activity est appelé pour chaque entrée d’utilisateur reçue.
Le module on_message_activity exécute le dialogue approprié par le biais de la méthode d’extension de dialogue run_dialog. Le dialogue principal appelle ensuite LuisHelper pour rechercher l'intention utilisateur ayant le meilleur scoring. Si l’intention principale de l’entrée utilisateur retourne « BookFlight », la fonction d’assistance remplit les informations de l’utilisateur retournées par LUIS. Après cela, le dialogue principal démarre BookingDialog, qui obtient des informations supplémentaires selon les besoins de l’utilisateur, par exemple :
Sur la page des applications de conversation dans LUIS, sélectionnez Importer, puis Importer en JSON.
Dans le dialogue Importer une nouvelle application :
Sélectionnez le fichier FlightBooking.json dans le dossier CognitiveModels de l’exemple.
Entrez FlightBooking en tant que nom facultatif de l'application, puis sélectionnez Terminé.
Le site peut afficher comment créer une application LUIS efficace et mettre à niveau vos dialogues d'entités composites. Vous pouvez ignorer ces dialogues et continuer.
Entraînez votre application, puis publiez la dans l'environnement de production.
Pour plus d'informations, consultez la documentation de LUIS relative à la manière d'entraîner et de publier une application.
Pourquoi utiliser des entités
Les entités LUIS permettent à votre bot de comprendre les événements au-delà des intentions standard. Ainsi, vous pouvez recueillir des informations supplémentaires auprès des utilisateurs, ce qui permet à votre bot de poser des questions et de répondre de manière plus intelligente. En plus des définitions des trois intentions LUIS « Réserver le vol », « Annuler » et « Aucune », le fichier FlightBooking.json contient un ensemble d'entités, comme « From.Airport » et « To.Airport ». Ces entités permettent à LUIS de détecter et de retourner des informations supplémentaires contenues dans l’entrée d’origine de l’utilisateur, lorsque celui-ci fait une nouvelle demande de réservation de voyage.
Obtenir les valeurs de connexion à votre application LUIS
Une fois votre application LUIS publiée, vous pouvez y accéder à partir de votre bot. Vous devrez enregistrer plusieurs valeurs pour accéder à votre application LUIS à partir de votre bot. Vous pouvez récupérer ces informations à l’aide du portail LUIS.
Récupérer les informations de l’application à partir du portail LUIS.ai
Le fichier de paramètres (appsettings.json, .env ou config.py) agit comme lieu de rassemblement pour toutes les références de service. Les informations que vous récupérez sont ajoutées à ce fichier dans la section suivante.
Sélectionnez votre application LUIS publiée à partir du portail luis.ai.
Ouvrez votre application LUIS publiée, et sélectionnez l’onglet MANAGE (Gérer).
Sélectionnez l'onglet Paramètres sur le côté gauche et enregistrez la valeur indiquée pour l'ID de l'application comme étant < YOUR_APP_ID>.
Sélectionnez Ressources Azure, puis ressource de prédiction. Enregistrez la valeur indiquée pour l'emplacement sous la forme <YOUR_REGION> et la clé primaire sous la forme <YOUR_AUTHORING_KEY>.
Vous pouvez également utiliser la région et la clé primaire pour votre ressource de création.
Ajoutez les informations demandées pour accéder à votre application LUIS, notamment l'ID d'application, la clé de création et la région dans le fichier appsettings.json. À l'étape précédente, vous avez récupéré ces valeurs à partir de votre application LUIS publiée. Le nom d'hôte de l'API doit être au format <your region>.api.cognitive.microsoft.com.
Ajoutez les informations demandées pour accéder à votre application LUIS, notamment l'ID d'application, la clé de création et la région dans le fichier .env. À l'étape précédente, vous avez récupéré ces valeurs à partir de votre application LUIS publiée. Le nom d'hôte de l'API doit être au format <your region>.api.cognitive.microsoft.com.
Ajoutez les informations demandées pour accéder à votre application LUIS, notamment l'ID d'application, la clé de création et la région dans le fichier application.properties. À l'étape précédente, vous avez récupéré ces valeurs à partir de votre application LUIS publiée. Le nom d'hôte de l'API doit être au format <your region>.api.cognitive.microsoft.com.
Ajoutez les informations demandées pour accéder à votre application LUIS, notamment l'ID d'application, la clé de création et la région dans le fichier config.py. À l'étape précédente, vous avez récupéré ces valeurs à partir de votre application LUIS publiée. Le nom d'hôte de l'API doit être au format <your region>.api.cognitive.microsoft.com.
Vérifiez que le package NuGet Microsoft.Bot.Builder.AI.Luis est installé pour votre projet.
Pour se connecter au service LUIS, le bot utilise les informations que vous avez ajoutées au fichier appsetting.json. La classe FlightBookingRecognizer contient le code avec vos paramètres à partir du fichier appsetting.json et interroge le service LUIS en appelant la méthode RecognizeAsync.
FlightBookingRecognizer.cs
public class FlightBookingRecognizer : IRecognizer
{
private readonly LuisRecognizer _recognizer;
public FlightBookingRecognizer(IConfiguration configuration)
{
var luisIsConfigured = !string.IsNullOrEmpty(configuration["LuisAppId"]) && !string.IsNullOrEmpty(configuration["LuisAPIKey"]) && !string.IsNullOrEmpty(configuration["LuisAPIHostName"]);
if (luisIsConfigured)
{
var luisApplication = new LuisApplication(
configuration["LuisAppId"],
configuration["LuisAPIKey"],
"https://" + configuration["LuisAPIHostName"]);
// Set the recognizer options depending on which endpoint version you want to use.
// More details can be found in https://docs.microsoft.com/en-gb/azure/cognitive-services/luis/luis-migration-api-v3
var recognizerOptions = new LuisRecognizerOptionsV3(luisApplication)
{
PredictionOptions = new Bot.Builder.AI.LuisV3.LuisPredictionOptions
{
IncludeInstanceData = true,
}
};
_recognizer = new LuisRecognizer(recognizerOptions);
}
}
// Returns true if luis is configured in the appsettings.json and initialized.
public virtual bool IsConfigured => _recognizer != null;
public virtual async Task<RecognizerResult> RecognizeAsync(ITurnContext turnContext, CancellationToken cancellationToken)
=> await _recognizer.RecognizeAsync(turnContext, cancellationToken);
public virtual async Task<T> RecognizeAsync<T>(ITurnContext turnContext, CancellationToken cancellationToken)
where T : IRecognizerConvert, new()
=> await _recognizer.RecognizeAsync<T>(turnContext, cancellationToken);
}
Le FlightBookingEx.cs contient la logique d’extraction De, À et la TravelDate ; ii étend la classe partielle FlightBooking.cs utilisée pour stocker les résultats de LUIS lors de l’appel de FlightBookingRecognizer.RecognizeAsync<FlightBooking> à partir de la MainDialog.cs.
CognitiveModels\FlightBookingEx.cs
// Extends the partial FlightBooking class with methods and properties that simplify accessing entities in the luis results
public partial class FlightBooking
{
public (string From, string Airport) FromEntities
{
get
{
var fromValue = Entities?._instance?.From?.FirstOrDefault()?.Text;
var fromAirportValue = Entities?.From?.FirstOrDefault()?.Airport?.FirstOrDefault()?.FirstOrDefault();
return (fromValue, fromAirportValue);
}
}
public (string To, string Airport) ToEntities
{
get
{
var toValue = Entities?._instance?.To?.FirstOrDefault()?.Text;
var toAirportValue = Entities?.To?.FirstOrDefault()?.Airport?.FirstOrDefault()?.FirstOrDefault();
return (toValue, toAirportValue);
}
}
// This value will be a TIMEX. And we are only interested in a Date so grab the first result and drop the Time part.
// TIMEX is a format that represents DateTime expressions that include some ambiguity. e.g. missing a Year.
public string TravelDate
=> Entities.datetime?.FirstOrDefault()?.Expressions.FirstOrDefault()?.Split('T')[0];
}
Pour utiliser LUIS, votre projet doit installer le package npm botbuilder-ai.
Pour se connecter au service LUIS, le bot utilise les informations que vous avez ajoutées au fichier .env. La classe flightBookingRecognizer.js contient le code qui importe vos paramètres à partir du fichier .env et interroge le service LUIS en appelant la méthode recognize().
dialogs/flightBookingRecognizer.js
class FlightBookingRecognizer {
constructor(config) {
const luisIsConfigured = config && config.applicationId && config.endpointKey && config.endpoint;
if (luisIsConfigured) {
// Set the recognizer options depending on which endpoint version you want to use e.g v2 or v3.
// More details can be found in https://docs.microsoft.com/en-gb/azure/cognitive-services/luis/luis-migration-api-v3
const recognizerOptions = {
apiVersion: 'v3'
};
this.recognizer = new LuisRecognizer(config, recognizerOptions);
}
}
get isConfigured() {
return (this.recognizer !== undefined);
}
/**
* Returns an object with preformatted LUIS results for the bot's dialogs to consume.
* @param {TurnContext} context
*/
async executeLuisQuery(context) {
return await this.recognizer.recognize(context);
}
getFromEntities(result) {
let fromValue, fromAirportValue;
if (result.entities.$instance.From) {
fromValue = result.entities.$instance.From[0].text;
}
if (fromValue && result.entities.From[0].Airport) {
fromAirportValue = result.entities.From[0].Airport[0][0];
}
return { from: fromValue, airport: fromAirportValue };
}
getToEntities(result) {
let toValue, toAirportValue;
if (result.entities.$instance.To) {
toValue = result.entities.$instance.To[0].text;
}
if (toValue && result.entities.To[0].Airport) {
toAirportValue = result.entities.To[0].Airport[0][0];
}
return { to: toValue, airport: toAirportValue };
}
/**
* This value will be a TIMEX. And we are only interested in a Date so grab the first result and drop the Time part.
* TIMEX is a format that represents DateTime expressions that include some ambiguity. e.g. missing a Year.
*/
getTravelDate(result) {
const datetimeEntity = result.entities.datetime;
if (!datetimeEntity || !datetimeEntity[0]) return undefined;
const timex = datetimeEntity[0].timex;
if (!timex || !timex[0]) return undefined;
const datetime = timex[0].split('T')[0];
return datetime;
}
}
La logique d’extraction De, À et TravelDate est implémentée en tant que méthodes d’assistance à l’intérieur de flightBookingRecognizer.js. Ces méthodes sont utilisées après l'appel de flightBookingRecognizer.executeLuisQuery() à partir de mainDialog.js
Assurez-vous que le package com.microsoft.bot.bot-ai-luis-v3 est ajouté à votre fichier pom.xml.
Pour se connecter au service LUIS, le bot utilise les informations que vous avez ajoutées au fichier application.properties. La classe FlightBookingRecognizer contient le code avec vos paramètres à partir du fichier application.properties et interroge le service LUIS en appelant la méthode recognize.
FlightBookingRecognizer.java
/**
* The constructor of the FlightBookingRecognizer class.
*
* @param configuration The Configuration object to use.
*/
public FlightBookingRecognizer(Configuration configuration) {
Boolean luisIsConfigured = StringUtils.isNotBlank(configuration.getProperty("LuisAppId"))
&& StringUtils.isNotBlank(configuration.getProperty("LuisAPIKey"))
&& StringUtils.isNotBlank(configuration.getProperty("LuisAPIHostName"));
if (luisIsConfigured) {
LuisApplication luisApplication = new LuisApplication(
configuration.getProperty("LuisAppId"),
configuration.getProperty("LuisAPIKey"),
String.format("https://%s", configuration.getProperty("LuisAPIHostName"))
);
// Set the recognizer options depending on which endpoint version you want to use.
// More details can be found in
// https://docs.microsoft.com/en-gb/azure/cognitive-services/luis/luis-migration-api-v3
LuisRecognizerOptionsV3 recognizerOptions = new LuisRecognizerOptionsV3(luisApplication);
recognizerOptions.setIncludeInstanceData(true);
this.recognizer = new LuisRecognizer(recognizerOptions);
}
}
/**
* Runs an utterance through a recognizer and returns a generic recognizer result.
*
* @param turnContext Turn context.
* @return Analysis of utterance.
*/
@Override
public CompletableFuture<RecognizerResult> recognize(TurnContext turnContext) {
return this.recognizer.recognize(turnContext);
}
Le FlightBookingRecognizer.cs contient la logique permettant d'extraire From, To et TravelDate ; il est appelé à partir du MainDialog.java pour décoder les résultats de la requête Luis.
FlightBookingRecognizer.java
/**
* Gets the From data from the entities which is part of the result.
*
* @param result The recognizer result.
* @return The object node representing the From data.
*/
public ObjectNode getFromEntities(RecognizerResult result) {
String fromValue = "", fromAirportValue = "";
if (result.getEntities().get("$instance").get("From") != null) {
fromValue = result.getEntities().get("$instance").get("From").get(0).get("text")
.asText();
}
if (!fromValue.isEmpty()
&& result.getEntities().get("From").get(0).get("Airport") != null) {
fromAirportValue = result.getEntities().get("From").get(0).get("Airport").get(0).get(0)
.asText();
}
ObjectMapper mapper = new ObjectMapper().findAndRegisterModules();
ObjectNode entitiesNode = mapper.createObjectNode();
entitiesNode.put("from", fromValue);
entitiesNode.put("airport", fromAirportValue);
return entitiesNode;
}
/**
* Gets the To data from the entities which is part of the result.
*
* @param result The recognizer result.
* @return The object node representing the To data.
*/
public ObjectNode getToEntities(RecognizerResult result) {
String toValue = "", toAirportValue = "";
if (result.getEntities().get("$instance").get("To") != null) {
toValue = result.getEntities().get("$instance").get("To").get(0).get("text").asText();
}
if (!toValue.isEmpty() && result.getEntities().get("To").get(0).get("Airport") != null) {
toAirportValue = result.getEntities().get("To").get(0).get("Airport").get(0).get(0)
.asText();
}
ObjectMapper mapper = new ObjectMapper().findAndRegisterModules();
ObjectNode entitiesNode = mapper.createObjectNode();
entitiesNode.put("to", toValue);
entitiesNode.put("airport", toAirportValue);
return entitiesNode;
}
/**
* This value will be a TIMEX. And we are only interested in a Date so grab the first result and
* drop the Time part. TIMEX is a format that represents DateTime expressions that include some
* ambiguity. e.g. missing a Year.
*
* @param result A {link RecognizerResult}
* @return The Timex value without the Time model
*/
public String getTravelDate(RecognizerResult result) {
JsonNode datetimeEntity = result.getEntities().get("datetime");
if (datetimeEntity == null || datetimeEntity.get(0) == null) {
return null;
}
JsonNode timex = datetimeEntity.get(0).get("timex");
if (timex == null || timex.get(0) == null) {
return null;
}
String datetime = timex.get(0).asText().split("T")[0];
return datetime;
}
Vérifiez que le package PyPI botbuilder-ai est installé pour votre projet.
Pour se connecter au service LUIS, le bot utilise les informations que vous avez ajoutées au fichier config.py. La classe FlightBookingRecognizer contient le code qui importe vos paramètres à partir du fichier config.py et interroge le service LUIS en appelant la méthode recognize().
flight_booking_recognizer.py
class FlightBookingRecognizer(Recognizer):
def __init__(self, configuration: DefaultConfig):
self._recognizer = None
luis_is_configured = (
configuration.LUIS_APP_ID
and configuration.LUIS_API_KEY
and configuration.LUIS_API_HOST_NAME
)
if luis_is_configured:
# Set the recognizer options depending on which endpoint version you want to use e.g v2 or v3.
# More details can be found in https://docs.microsoft.com/azure/cognitive-services/luis/luis-migration-api-v3
luis_application = LuisApplication(
configuration.LUIS_APP_ID,
configuration.LUIS_API_KEY,
"https://" + configuration.LUIS_API_HOST_NAME,
)
self._recognizer = LuisRecognizer(luis_application)
@property
def is_configured(self) -> bool:
# Returns true if luis is configured in the config.py and initialized.
return self._recognizer is not None
async def recognize(self, turn_context: TurnContext) -> RecognizerResult:
return await self._recognizer.recognize(turn_context)
La logique d’extraction de From, To et travel_date est implémentée sous forme de méthodes d’assistance à partir de la classe LuisHelper dans luis_helper.py. Ces méthodes sont utilisées après l'appel de LuisHelper.execute_luis_query() à partir de main_dialog.py
helpers/luis_helper.py
class LuisHelper:
@staticmethod
async def execute_luis_query(
luis_recognizer: LuisRecognizer, turn_context: TurnContext
) -> (Intent, object):
"""
Returns an object with preformatted LUIS results for the bot's dialogs to consume.
"""
result = None
intent = None
try:
recognizer_result = await luis_recognizer.recognize(turn_context)
intent = (
sorted(
recognizer_result.intents,
key=recognizer_result.intents.get,
reverse=True,
)[:1][0]
if recognizer_result.intents
else None
)
if intent == Intent.BOOK_FLIGHT.value:
result = BookingDetails()
# We need to get the result from the LUIS JSON which at every level returns an array.
to_entities = recognizer_result.entities.get("$instance", {}).get(
"To", []
)
if len(to_entities) > 0:
if recognizer_result.entities.get("To", [{"$instance": {}}])[0][
"$instance"
]:
result.destination = to_entities[0]["text"].capitalize()
else:
result.unsupported_airports.append(
to_entities[0]["text"].capitalize()
)
from_entities = recognizer_result.entities.get("$instance", {}).get(
"From", []
)
if len(from_entities) > 0:
if recognizer_result.entities.get("From", [{"$instance": {}}])[0][
"$instance"
]:
result.origin = from_entities[0]["text"].capitalize()
else:
result.unsupported_airports.append(
from_entities[0]["text"].capitalize()
)
# This value will be a TIMEX. And we are only interested in a Date so grab the first result and drop
# the Time part. TIMEX is a format that represents DateTime expressions that include some ambiguity.
# e.g. missing a Year.
date_entities = recognizer_result.entities.get("datetime", [])
if date_entities:
timex = date_entities[0]["timex"]
if timex:
datetime = timex[0].split("T")[0]
result.travel_date = datetime
else:
result.travel_date = None
except Exception as exception:
print(exception)
return intent, result
LUIS est à présent configuré et connecté pour votre bot.
Exécutez l’exemple en local sur votre machine. Si vous avez besoin d'instructions, consultez le fichier README de l'exemple C#, de l'exemple JS ou de l'exemple Python.
Dans l'émulateur, saisissez un message, par exemple « voyage à paris » ou « aller de Paris à Berlin ». Utilisez n’importe quel énoncé trouvé dans le fichier FlightBooking.json pour l’apprentissage de l’intention « Réserver un vol ».
Si l'intention principale renvoyée par LUIS est « Réserver un vol », votre bot posera d'autres questions jusqu'à ce qu'il ait stocké suffisamment d'informations pour créer une réservation de voyage. À ce stade, il retourne ces informations de réservation à votre utilisateur.
À ce stade, la logique du bot de code est réinitialisée et vous pouvez continuer à créer d'autres réservations.
Informations supplémentaires
Pour plus d’informations sur LUIS, consultez sa documentation :
Les différentes parties du kit de développement logiciel (SDK) définissent des classes d'entités ou des éléments distincts.
Pour les entités de message, consultez Types d'entités et d'activités.