Suggerimenti per l'implementazione (Dialogflow)

Esamina i seguenti suggerimenti per implementare buone pratiche di progettazione delle conversazioni nell'azione.

Previste varianti

Gestiscilo nella sezione "L'utente dice" in Dialogflow. Inoltre, utilizza più di una intent che possono essere mappati alla stessa azione, in cui ogni intent può essere attivato serie diverse di "L'utente dice" frasi chiave.

Fornisci risposte utili e falli facilmente

A volte l'Azione non può andare avanti perché non ha ricevuto un input (noto di assenza di input) o di mancata comprensione dell'input dell'utente (operazione nota come mancata corrispondenza). In questi casi, l'assistente prova innanzitutto a determinare se l'utente vuole per attivare un'Azione diversa. Se l'assistente non corrisponde all'input dell'utente a un'altra Azione, l'utente continua nel contesto dell'Azione. Questo scenario può verificarsi in qualsiasi momento, quindi la best practice è gestire in modo univoco situazioni in cui non viene richiesto alcun input e nessuna corrispondenza a ogni turno di una conversazione con un video di riserva. Utilizzando i fallback, puoi aiutare gli utenti a tornare in pista.

Per farlo, inizializza una variabile fallbackCount nell'oggetto conv.data, e impostarlo su 0. Prepara un array di due prompt di fallback (riassegnati per chiarezza), e un prompt di fallback finale che termina la conversazione.

Poi, crea un intent di riserva (idealmente uno per ogni intent strategico di Google). Nel gestore di intent, estrai il conteggio dei fallback da conv.data incrementarlo e, se è inferiore a 3, eseguire il pull del prompt dall'array di 3. Se il conteggio è pari o superiore a 4, chiudi la conversazione utilizzando lo stato richiesta. In tutti gli intent che non sono di riserva, reimposta il conteggio dei fallback su 0. Idealmente, crea modelli dei fallback per intent specifici in modo che siano specifici per questi ultimi.

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

Fatti aiutare in qualsiasi momento

Crea un intent che ascolti frasi di aiuto come "Cosa posso fare?", "che cosa puoi dirmi" o "aiuto". A questo scopo, offrine alcune (a rotazione) risposta che offre una panoramica di ciò che l'agente può fare e indirizza gli utenti a una una possibile azione. Idealmente, usa anche gli intent della guida di follow-up in Dialogflow per creare diversi scenari di assistenza per intenti strategici diversi.

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

Consenti agli utenti di riprodurre di nuovo le informazioni

Aggrega tutti i metodi app.ask(output) con una funzione proxy che aggiunga la come output a conv.data.lastPrompt. Crea un intent ripetuto che ascolti di ripetere all'utente la richiesta "Cosa?", "dillo di nuovo" o "puoi lo ripeta?". Creare un array di prefissi ripetuti da utilizzare per riconoscere che l'utente ha richiesto qualcosa da ripetere. Nella ripetizione gestore di intent, chiama ask() con una stringa concatenata del prefisso di ripetizione e il valore di conv.data.lastPrompt. Ricorda che dovrai spostare qualsiasi Tag di apertura SSML se utilizzati nell'ultimo prompt.

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

Personalizza la conversazione con le preferenze dell'utente

L'Azione può chiedere agli utenti le loro preferenze e ricordarle per in un secondo momento, consentendoti di personalizzare le conversazioni future con quell'utente.

Questa Azione di esempio offre agli utenti un bollettino meteo per un codice postale. Le seguenti il codice di esempio chiede all'utente se vuole che l'azione memorizzi il codice postale per le conversazioni successive.

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

Dopo aver chiesto all'utente in quale codice postale si trova nella prima finestra di dialogo, può saltare la richiesta durante la chiamata successiva e utilizzare lo stesso codice postale. Devi comunque fornire una via di fuga (ad esempio un chip di suggerimento che consenta scegliere un codice postale diverso), ma riducendo il numero di conversazioni caso comune, crei un'esperienza molto più fluida.

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

Personalizza per gli utenti di ritorno

Il mantenimento di uno stato tra una conversazione e l'altra assicura una maggiore naturale per gli utenti di ritorno. Il primo passo nella creazione di questa esperienza è salutare gli utenti di ritorno in modo diverso. Ad esempio, puoi affinare l'annuncio mostrare informazioni utili basate sulle conversazioni passate. A questo scopo, utilizza in arrivo AppRequest.User lastSeen per determinare se l'utente ha già interagito con l'Azione. Se la proprietà lastSeen è inclusa nel payload della richiesta, puoi utilizzare un saluto diverso dal normale.

Il codice seguente utilizza la libreria client Node.js per recuperare il valore di 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();
}

Puoi migliorare ulteriormente questo saluto personalizzando la risposta all'effettiva pari a lastSeen. Ad esempio, gli utenti la cui ultima interazione si è verificata molte mesi prima dell'interazione corrente potrebbero ricevere un saluto diverso rispetto quelli che hanno usato l'Azione il giorno prima.

Controllo del volume nelle conversazioni

Sui dispositivi supportati, l'assistente consente agli utenti di regolare il volume del dispositivo all'interno delle un'azione conversazionale dicendo, ad esempio, "alza il volume" o "imposta volume al 50%". Se hai intent che gestiscono frasi di addestramento simili, i tuoi intent hanno la precedenza. Ti consigliamo di lasciare che sia l'assistente a gestire queste richieste dagli utenti, a meno che l'Azione non abbia un motivo specifico.