Conseils d'implémentation (Dialogflow)

Consultez les conseils suivants pour mettre en œuvre de bonnes pratiques de conception des conversations dans votre action.

Variations attendues

Gérez cela dans la section "L'utilisateur dit" dans Dialogflow. De plus, utilisez plusieurs d'un intent pouvant être mappé à la même action, où chaque intent peut être déclenché différents groupes de « L'utilisateur dit » de phrases.

Fournir de nouvelles invites utiles et échouer en douceur

Parfois, votre action ne peut pas avancer, car elle n'a pas reçu d'entrée (c'est ce que l'on appelle une "no-input") ou qui n'a pas compris l'entrée utilisateur (c'est ce que l'on appelle une non-correspondance). Lorsque cela se produit, l'Assistant tente d'abord de déterminer si l'utilisateur souhaite pour déclencher une autre action. Si l'Assistant ne correspond pas à la saisie de l'utilisateur à une autre action, l'utilisateur continue dans le contexte de votre action. Ce scénario peut se produire à tout moment. La meilleure pratique consiste donc à gérer de manière unique les situations de non-entrée et de non-correspondance à chaque tour d'une conversation, avec une création de remplacement. Les créations de remplacement vous permettent d'aider les utilisateurs à se remettre sur la bonne voie.

Pour ce faire, initialisez une variable fallbackCount dans votre objet conv.data : et le définir sur 0. Préparer un tableau de deux invites de remplacement (escalade de la clarté) et une dernière invite de remplacement qui met fin à la conversation.

Ensuite, créez un intent de remplacement (idéalement un pour chaque intent exploitable dans de l'agent). Dans le gestionnaire d'intents, extrayez le nombre de créations de remplacement à partir de conv.data. incrémentez-le et, s'il est inférieur à 3, extrayez l'invite du tableau sur 3. Si le nombre est de 4 ou plus, fermez la conversation en utilisant le dernier mot requête. Pour tous les intents qui ne sont pas des valeurs de remplacement, réinitialisez le nombre de remplacements sur 0. Idéalement, modéliser les créations de remplacement pour des intents spécifiques afin qu'ils soient spécifiques à ceux-ci.

Node.js

const GENERAL_FALLBACK = [
   'Sorry, what was that?',
   'I didn\'t quite get that. I can help you find good local restaurants, what do you want to know about?',
];

const LIST_FALLBACK = [
   'Sorry, what was that?',
   'I didn\'t catch that. Could you tell me which one you prefer?',
];

const FINAL_FALLBACK = 'I\'m sorry I\'m having trouble here. Let\'s talk again later.';

const handleFallback = (conv, promptFetch, callback) => {
 conv.data.fallbackCount = parseInt(conv.data.fallbackCount, 10);
 conv.data.fallbackCount++;
 if (conv.data.fallbackCount > 2) {
   conv.close(promptFetch.getFinalFallbackPrompt());
 } else {
   callback();
 }
}
// Intent handlers below
const generalFallback = (conv) => {
  handleFallback = (conv, promptFetch, () => {
    conv.ask(GENERAL_FALLBACK[conv.data.fallbackCount],
      getGeneralNoInputPrompts());
 });
}

const listFallback = (conv) => {
  handleFallback = (conv, promptFetch, () => {
   conv.ask(LIST_FALLBACK[conv.data.fallbackCount],
       getGeneralNoInputPrompts());
 });
}

const nonFallback = (conv) => {
  conv.data.fallbackCount = 0;
  conv.ask('A non-fallback message here');
}

Java

private static final List<String> GENERAL_FALLBACK =
    Arrays.asList(
        "Sorry, what was that?",
        "I didn\'t quite get that. I can tell you all about IO, like date or location, or about the sessions. What do you want to know about?");
private static final List<String> LIST_FALLBACK =
    Arrays.asList(
        "Sorry, what was that?",
        "I didn\'t catch that. Could you tell me which one you liked?");
private static final List<String> FINAL_FALLBACK =
    Arrays.asList("I\'m sorry I\'m having trouble here. Maybe we should try this again later.");

@ForIntent("General Fallback")
public ActionResponse generalFallback(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  int fallbackCount = (Integer) request.getConversationData().get("fallbackCount");
  fallbackCount++;
  request.getConversationData().put("fallbackCount", fallbackCount);
  if (fallbackCount > 2) {
    responseBuilder.add(getRandomPromptFromList(FINAL_FALLBACK)).endConversation();
  } else {
    responseBuilder.add(getRandomPromptFromList(GENERAL_FALLBACK));
  }
  return responseBuilder.build();
}

private String getRandomPromptFromList(List<String> prompts) {
  Random rand = new Random();
  int i = rand.nextInt(prompts.size());
  return prompts.get(i);
}

@ForIntent("List Fallback")
public ActionResponse listFallback(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  int fallbackCount = (Integer) request.getConversationData().get("fallbackCount");
  fallbackCount++;
  request.getConversationData().put("fallbackCount", fallbackCount);
  if (fallbackCount > 2) {
    responseBuilder.add(getRandomPromptFromList(FINAL_FALLBACK)).endConversation();
  } else {
    responseBuilder.add(getRandomPromptFromList(LIST_FALLBACK));
  }
  return responseBuilder.build();
}

@ForIntent("Non Fallback")
public ActionResponse nonFallback(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  request.getConversationData().put("fallbackCount", 0);
  responseBuilder.add("Non Fallback message");
  return responseBuilder.build();
}

Soyez prêt à vous aider à tout moment

Créez un intent qui écoute les phrases d'aide telles que "Que puis-je faire ?", "que peux-tu me dire" ou "aide". Dans cet intent, proposez une partie (rotation) qui offre un aperçu de ce que l'agent peut faire et qui redirige les utilisateurs vers un action possible. Idéalement, utilisez également les intents d'aide de suivi dans Dialogflow pour créer différents scénarios d'aide pour différents intents exploitables.

Node.js

const HELP_PROMPTS = [
   'There\'s a lot you might want to know about the local restaurants, and I can tell you all about it, like where it is and what kind of food they have. What do you want to know?',
   'I\'m here to help, so let me know if you need any help figuring out where or what to eat. What do you want to know?',
];

// Intent handler
const help = (conv) => {
 reply(conv, promptFetch.getHelpPrompt(), // fetches random entry from HELP_PROMPTS
     promptFetch.getGeneralNoInputPrompts());
}

Java

private static final List<String> HELP_PROMPTS =
    Arrays.asList(
        "There's a lot you might want to know about IO, and I can tell you all about it, like where it is and what the sessions are. What do you want to know?",
        "IO can be a little overwhelming, so I\'m here to help. Let me know if you need any help figuring out the event, like when it is, or what the sessions are. What do you want to know?");

@ForIntent("Help")
public ActionResponse help(ActionRequest request) {
  return getResponseBuilder(request).add(getRandomPromptFromList(HELP_PROMPTS)).build();
}

Autoriser les utilisateurs à relire les informations

Encapsulez toutes vos méthodes app.ask(output) avec une fonction de proxy qui ajoute le la sortie sur conv.data.lastPrompt. Créer un intent répété qui écoute des invites à répéter de l'utilisateur comme « quoi ? », « dites-en à nouveau » ou « peux-tu répéter ?". Créez un tableau de préfixes répétés pouvant être utilisés pour confirmer que l'utilisateur a demandé quelque chose à répéter. Dans la répétition d'intent, appelez ask() avec une chaîne concaténée du préfixe de répétition et la valeur de conv.data.lastPrompt. Gardez à l'esprit que vous devrez déplacer Balises d'ouverture SSML si elles sont utilisées dans la dernière invite.

Node.js

const REPEAT_PREFIX = [
    'Sorry, I said ',
    'Let me repeat that. ',
];

const reply = (conv, inputPrompt, noInputPrompts) => {
  conv.data.lastPrompt = inputPrompt;
  conv.data.lastNoInputPrompts = noInputPrompts;
  conv.ask(inputPrompt, noInputPrompts);
}
// Intent handlers
const normalIntent = (conv) => {
  reply(conv, 'Hey this is a question', SOME_NO_INPUT_PROMPTS);
}

const repeat = (conv) => {
  let repeatPrefix = promptFetch.getRepeatPrefix(); // randomly chooses from REPEAT_PREFIX
  // Move SSML start tags over
  if (conv.data.lastPrompt.startsWith(promptFetch.getSSMLPrefix())) {
    conv.data.lastPrompt =
        conv.data.lastPrompt.slice(promptFetch.getSSMLPrefix().length);
    repeatPrefix = promptFetch.getSSMLPrefix() + repeatPrefix;
  }
  conv.ask(repeatPrefix + conv.data.lastPrompt,
      conv.data.lastNoInputPrompts);
}

Java

private final List<String> REPEAT_PREFIX = Arrays.asList("Sorry, I said ", "Let me repeat that.");

private final String SsmlPrefix = "<speak>";

@ForIntent("Normal Intent")
public ActionResponse normalIntent(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  responseBuilder.getConversationData().put("lastPrompt", "Hey this is a question");
  return responseBuilder.build();
}

@ForIntent("repeat")
public ActionResponse repeat(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  String repeatPrefix = getRandomPromptFromList(REPEAT_PREFIX);
  // Move SSML start tags over
  String lastPrompt = (String) responseBuilder.getConversationData().get("lastPrompt");
  if (lastPrompt.startsWith(SsmlPrefix)) {
    String newLastPrompt = lastPrompt.substring(SsmlPrefix.length());
    responseBuilder.getConversationData().put("lastPrompt", newLastPrompt);
    repeatPrefix = SsmlPrefix + repeatPrefix;
  }
  responseBuilder.add(repeatPrefix + lastPrompt);
  return responseBuilder.build();
}

Personnaliser la conversation en fonction des préférences de l'utilisateur

Votre action peut demander aux utilisateurs leurs préférences et les mémoriser pour pour une utilisation ultérieure, ce qui vous permet de personnaliser vos futures conversations avec cet utilisateur.

Cet exemple d'action fournit aux utilisateurs un bulletin météo pour un code postal. Les éléments suivants : Exemple de code demandant à l'utilisateur s'il souhaite que l'action mémorise son code postal pour les conversations ultérieures.

Node.js

app.intent('weather_report', (conv) => {
  let zip = conv.arguments.get('zipcode');
  conv.data.zip = zip;
  conv.ask(getWeatherReport(zip));
  conv.ask(new Confirmation(`Should I remember ${zip} for next time?`));
});

app.intent('remember_zip', (conv, params, confirmation) => {
  if (confirmation) {
    conv.user.storage.zip = conv.data.zip;
    conv.close('Great! See you next time.');
  } else conv.close('Ok, no problem.');
});

Java

@ForIntent("weather_report")
public ActionResponse weatherReport(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  String zip = (String) request.getArgument("location").getStructuredValue().get("zipCode");
  responseBuilder.getConversationData().put("zip", zip);
  responseBuilder.add(getWeatherReport(zip));
  responseBuilder.add(
      new Confirmation().setConfirmationText("Should I remember " + zip + " for next time?"));
  return responseBuilder.build();
}

@ForIntent("remember_zip")
public ActionResponse rememberZip(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (request.getUserConfirmation()) {
    responseBuilder.getUserStorage().put("zip", responseBuilder.getConversationData().get("zip"));
    responseBuilder.add("Great! See you next time.").endConversation();
  } else {
    responseBuilder.add("Ok, no problem.").endConversation();
  }
  return responseBuilder.build();
}

Après avoir demandé à l'utilisateur à quel code postal il se trouvait lors de sa première boîte de dialogue, vous peuvent ignorer cette invite lors de leur prochain appel et utiliser le même code postal. Vous devez quand même fournir un itinéraire d'échappement (comme un chip de suggestion leur permettant choisir un autre code postal), mais en réduisant le tour de conversation cas fréquent, vous créez une expérience beaucoup plus fluide.

Node.js

app.intent('weather_report', (conv) => {
  let zip = conv.arguments.get('zipcode');
  if (zip) {
    conv.close(getWeatherReport(zip));
  } else if (conv.user.storage.zip) {
    conv.ask(new SimpleResponse(getWeatherReport(conv.user.storage.zip)));
    conv.ask(new Suggestions('Try another zipcode'));
  } else {
    conv.ask('What\'s your zip code?');
  }
});

app.intent('provide_zip_df', (conv) => {
  conv.user.storage.zip = conv.arguments.get('zipcode');
  conv.close(getWeatherReport(conv.user.storage.zip));
});

Java

public ActionResponse weatherReport2(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  String zip = (String) request.getArgument("location").getStructuredValue().get("zipCode");
  if (zip != null) {
    responseBuilder.add(getWeatherReport(zip)).endConversation();
  } else if ((zip = (String) responseBuilder.getUserStorage().get("zip")) != null) {
    responseBuilder.add(new SimpleResponse().setTextToSpeech(getWeatherReport(zip)));
    responseBuilder.add(new Suggestion().setTitle("Try another zipcode"));
  } else {
    responseBuilder.add("What's your zip code?");
  }
  return responseBuilder.build();
}

Personnaliser pour les utilisateurs connus

Le maintien d'un certain état entre les conversations garantit une expérience beaucoup plus naturelle pour les utilisateurs connus. Pour élaborer cette expérience, la première étape consiste à accueillent différemment les utilisateurs connus. Par exemple, vous pouvez réduire le message d'accueil ou afficher des informations utiles en fonction de conversations passées. Pour ce faire, utilisez la propriété lastSeen AppRequest.User entrante pour déterminer si l'utilisateur a déjà interagi avec votre action par le passé. Si la propriété lastSeen est incluse dans la charge utile de la requête, vous pouvez utiliser un message d'accueil différent du message d'accueil normal.

Le code ci-dessous utilise la bibliothèque cliente Node.js pour récupérer la valeur de last.seen

Node.js

// This function is used to handle the welcome intent
// In Dialogflow, the Default Welcome Intent ('input.welcome' action)
// In Actions SDK, the 'actions.intent.MAIN' intent
const welcome = (conv) => {
  if (conv.user.last.seen) {
    conv.ask(`Hey you're back...`);
  } else {
    conv.ask('Welcome to World Cities Trivia!...');
  }
}

Java

// This function is used to handle the welcome intent
// In Dialogflow, the Default Welcome Intent ('input.welcome' action)
// In Actions SDK, the 'actions.intent.MAIN' intent
public ActionResponse welcome(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (request.getUser().getLastSeen() != null) {
    responseBuilder.add("Hey you're back...");
  } else {
    responseBuilder.add("Welcome to Number Genie!...");
  }
  return responseBuilder.build();
}

Vous pouvez améliorer encore davantage ce message d'accueil en adaptant la réponse la valeur de lastSeen. Par exemple, les utilisateurs dont la dernière interaction s'est produit de nombreuses mois avant l'interaction en cours peuvent recevoir un message d'accueil différent de ceux qui ont utilisé l'action la veille.

Contrôle du volume pendant la conversation

Sur les appareils compatibles, l'Assistant permet aux utilisateurs de contrôler le volume de l'appareil dans les d'une action conversationnelle en disant, par exemple, "Monte le son" ou "Règle le le volume sur 50 %. Si vous avez des intents qui gèrent des phrases d'entraînement similaires, vos intents sont prioritaires. Nous vous recommandons de laisser l'Assistant s'en charger demandes utilisateur, sauf si votre action a une raison spécifique.