Implementierungstipps (Dialogflow)

Die folgenden Tipps helfen dir dabei, gute Methoden für das Unterhaltungsdesign in deiner Aktion zu implementieren.

Abweichungen sind zu erwarten

Verarbeiten Sie dies in der Eingabe „User sagt“ in Dialogflow. Außerdem können Sie mehrere Intents verwenden, die derselben Aktion zugeordnet werden können, wobei jeder Intent mit unterschiedlichen „User sagt“-Wortgruppen ausgelöst werden kann.

Hilfreiche Antworten geben und anmutig scheitern

Manchmal kann deine Aktion nicht fortfahren, weil sie keine Eingabe erhalten hat (keine Eingabe) oder die Eingabe eines Nutzers nicht verstanden hat (keine Übereinstimmung genannt). In diesem Fall versucht Assistant zuerst zu ermitteln, ob der Nutzer eine andere Aktion auslösen möchte. Wenn Assistant die Eingabe des Nutzers keiner anderen Aktion zuordnet, fährt der Nutzer im Kontext dieser Aktion fort. Dieses Szenario kann jederzeit vorkommen. Daher wird empfohlen, Situationen ohne Eingabe und Nichtübereinstimmung in jeder Runde in einer Unterhaltung mit einem Fallback zu behandeln. Mit Fallbacks können Sie Nutzern helfen, wieder auf Kurs zu kommen.

Initialisieren Sie dazu eine fallbackCount-Variable in Ihrem conv.data-Objekt und setzen Sie sie auf 0. Bereiten Sie ein Array von zwei Fallback-Aufforderungen (die verständlicher eskalieren) sowie eine letzte Fallback-Aufforderung vor, mit der die Unterhaltung beendet wird.

Erstellen Sie dann einen Fallback-Intent (idealerweise einen für jeden umsetzbaren Intent im Agent). Rufen Sie im Intent-Handler die Fallback-Anzahl aus dem Objekt conv.data ab und erhöhen Sie sie. Wenn er kleiner als 3 ist, rufen Sie die Aufforderung aus dem Array von 3 ab. Wenn die Anzahl bei 4 oder mehr liegt, schließen Sie die Unterhaltung mit der letzten Eingabeaufforderung. Setzen Sie die Fallback-Anzahl in allen Intents, die keine Fallbacks sind, auf 0 zurück. Idealerweise erstellen Sie Vorlagen für die Fallbacks für bestimmte Intents, damit diese spezifisch sind.

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();
}

Jederzeit hilfsbereit sein

Erstellen Sie einen Intent, der auf Hilfeformulierungen wie „Was kann ich tun?“ wartet. „Was kannst du mir sagen?“ oder „Hilfe“. Biete in diesem Intent eine (rotierende) Antwort an, die einen Überblick darüber bietet, was der Agent tun kann, und die Nutzer zu einer möglichen Aktion weiterleitet. Idealerweise sollten Sie auch Follow-up-Hilfe-Intents in Dialogflow verwenden, um verschiedene Hilfeszenarien für verschiedene umsetzbare Intents zu erstellen.

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();
}

Nutzer dürfen Informationen noch einmal wiedergeben

Umschließen Sie alle app.ask(output)-Methoden mit einer Proxyfunktion, die die Ausgabe zu conv.data.lastPrompt hinzufügt. Erstellen Sie einen Intent, der auf Aufforderungen wie „Was?“ wartet, „Sag das noch einmal“ oder „Kannst du das wiederholen?“. Erstellen Sie ein Array mit wiederholten Präfixen, mit denen bestätigt werden kann, dass der Nutzer eine Wiederholung angefordert hat. Rufen Sie im Handler für Wiederholungs-Intents ask() mit einem verketteten String aus dem Wiederholungspräfix und dem Wert von conv.data.lastPrompt auf. Sie müssen alle öffnenden SSML-Tags verschieben, wenn sie in der letzten Eingabeaufforderung verwendet wurden.

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();
}

Unterhaltungen mit Nutzereinstellungen personalisieren

Deine Aktion kann Nutzer nach ihren Einstellungen fragen und sie für die spätere Verwendung speichern. So kannst du zukünftige Unterhaltungen mit diesem Nutzer personalisieren.

Mit dieser Beispielaktion erhalten Nutzer einen Wetterbericht für eine Postleitzahl. Mit dem folgenden Beispielcode wird der Nutzer gefragt, ob die Aktion seine Postleitzahl für spätere Unterhaltungen speichern soll.

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();
}

Nachdem Sie den Nutzer während des ersten Dialogfelds gefragt haben, welche Postleitzahl er hat, können Sie diese Eingabeaufforderung beim nächsten Aufruf überspringen und dieselbe Postleitzahl verwenden. Sie sollten trotzdem eine Escape-Route bereitstellen (z. B. mit einem Vorschlags-Chip, mit dem die Nutzer eine andere Postleitzahl auswählen können), aber wenn Sie normalerweise eine Abwandlung der Unterhaltung reduzieren, schaffen Sie einen viel nahtloseren Ablauf.

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();
}

Für wiederkehrende Nutzer anpassen

Das Beibehalten eines Zustands zwischen Unterhaltungen sorgt für eine weitaus natürlichere Erfahrung für wiederkehrende Nutzer. Der erste Schritt bei der Gestaltung dieser Erfahrung besteht darin, Rückkehrer anders zu begrüßen. Sie können die Begrüßung beispielsweise verjüngt oder anhand früherer Konversationen nützliche Informationen anzeigen. Verwende dazu die eingehende lastSeen-Property AppRequest.User, um festzustellen, ob der Nutzer bereits mit deiner Aktion interagiert hat. Wenn das Attribut lastSeen in der Nutzlast der Anfrage enthalten ist, können Sie eine andere Begrüßung als normal verwenden.

Im folgenden Code wird die Node.js-Clientbibliothek verwendet, um den Wert von last.seen abzurufen.

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();
}

Sie können diese Begrüßung weiter verbessern, indem Sie die Antwort an den tatsächlichen Wert von lastSeen anpassen. Beispielsweise erhalten Nutzer, deren letzte Interaktion viele Monate vor der aktuellen Interaktion stattgefunden hat, möglicherweise eine andere Begrüßung als diejenigen, die die Aktion am Vortag verwendet haben.

Lautstärkeregelung während der Unterhaltung

Auf unterstützten Geräten können Nutzer mit Assistant die Gerätelautstärke in Ihrer Konversationsaktion steuern, indem sie Dinge wie „Lautstärke erhöhen“ oder „Lautstärke auf 50 % stellen“ sagen. Intents, die ähnliche Trainingsformulierungen verarbeiten, haben Vorrang. Wir empfehlen, Assistant die Bearbeitung dieser Nutzeranfragen zu überlassen, es sei denn, deine Aktion hat einen bestimmten Grund.