Sugerencias de implementación (Dialogflow)

Revisa las siguientes sugerencias para implementar buenas prácticas de diseño de conversación. en tu Action.

Espera variaciones

Maneja esto en la sección “El usuario dice” entrada en Dialogflow. Además, utiliza más de uno que se puede asignar a la misma acción, en la que cada intent se puede activar con diferentes conjuntos de “El usuario dice” frases.

Proporciona mensajes de respuesta útiles y falla de forma controlada

A veces, tu acción no puede avanzar porque no recibió una entrada. (se conoce como “sin entrada”) o no entendió la entrada del usuario (lo que se conoce como “sin coincidencias”). Cuando esto sucede, Asistente primero intenta determinar si el usuario quiere para activar una acción diferente. Si Asistente no coincide con la entrada del usuario a otra Acción, el usuario continúa en el contexto de tu Acción. Esta situación puede ocurrir en cualquier momento, por lo que la práctica recomendada es controlar de manera única situaciones sin entrada y sin coincidencia en cada turno de una conversación con resguardo. Con los resguardos, puedes ayudar a los usuarios a recuperarse.

Para ello, inicializa una variable fallbackCount en tu objeto conv.data. y la establece en 0. Preparar un array de dos instrucciones de resguardo (escalamiento con claridad) y un mensaje alternativo final que finalice la conversación.

Luego, crea un intent de resguardo (idealmente, uno para cada intent procesable en la agente). En el controlador de intents, extrae el recuento de resguardo de conv.data. objeto, auméntalo y, si es menor que 3, extrae la instrucción del array de 3. Si el recuento es de 4 o más, cierre la conversación con la última mensaje. En todos los intents que no sean de resguardo, restablece el recuento de resguardo a 0. Lo ideal es crear plantillas de los resguardos de intents específicos para que sean específicos de ellos.

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

Prepárate para ayudar en cualquier momento

Crear un intent que escucha frases de ayuda como "¿qué puedo hacer?", “qué puedes decirme” o “ayuda”. En este intent, ofrece algunos (rotación) que ofrece una descripción general de lo que el agente puede hacer y dirige a los usuarios a un acción posible. Lo ideal es que también uses intents de ayuda de seguimiento en Dialogflow para crear diferentes situaciones de ayuda para diferentes intents prácticos.

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

Cómo permitir que los usuarios vuelvan a reproducir información

Une todos tus métodos app.ask(output) con una función proxy que agregue el salida a conv.data.lastPrompt. Crea un intent repetido que escuche instrucciones que se repitan del usuario, como "¿qué?", "di eso de nuevo" o "¿puedes repetirlo?". Crear un array de prefijos de repetición que se pueda usar para reconoce que el usuario pidió que algo se repita. Repetición controlador de intent, llama a ask() con una cadena concatenada del prefijo de repetición y el valor de conv.data.lastPrompt Ten en cuenta que deberás cambiar Etiquetas de apertura del SSML si se usaron en el último mensaje.

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

Personaliza la conversación con las preferencias del usuario

Tu acción puede solicitar a los usuarios sus preferencias y recordarlos para usarlo más adelante, lo que te permitirá personalizar conversaciones futuras con ese usuario.

Esta Acción de ejemplo brinda a los usuarios un informe meteorológico de un código postal. Lo siguiente código de ejemplo le pregunta al usuario si desea que la acción recuerde su código postal para conversaciones posteriores.

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

Después de preguntarle al usuario en qué código postal se encuentra durante el primer diálogo, puedes omitir ese mensaje durante la siguiente invocación y usar el mismo código postal. Debes proporcionar una ruta de escape (como un chip de sugerencias que les permita elegir un código postal diferente), sino reduciendo el tiempo de conversación en la caso común, se crea una experiencia mucho más 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();
}

Personalización para usuarios recurrentes

Mantener algún estado entre conversaciones garantiza una para los usuarios recurrentes. El primer paso para crear esta experiencia Saludan a los usuarios recurrentes de manera diferente. Por ejemplo, puedes ajustar el saludo o para mostrar información útil a partir de conversaciones pasadas. Para hacerlo, usa el propiedad AppRequest.User lastSeen entrante para determinar si el usuario ha interactuado con tu Acción anteriormente. Si se incluye la propiedad lastSeen en la carga útil de la solicitud, puedes usar un saludo diferente del normal.

El siguiente código usa la biblioteca cliente de Node.js para recuperar el valor 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();
}

Puedes mejorar aún más este saludo adaptando la respuesta al mensaje valor de lastSeen. Por ejemplo, los usuarios cuya última interacción ocurrió muchos meses antes de la interacción actual podría recibir un saludo diferente al aquellos que usaron la Action el día anterior.

Control de volumen en las conversaciones

En dispositivos compatibles, Asistente permite que los usuarios controlen el volumen del dispositivo en tu acción de conversación diciendo cosas como "sube el volumen" o "establece volumen al 50%". Si tienes intents que manejan frases de entrenamiento similares, tus intents tendrán prioridad. Te recomendamos que permitas que Asistente se encargue de estas de usuario, a menos que tu Acción tenga un motivo específico.