Dicas de implementação (Dialogflow)

Confira as dicas a seguir para implementar boas práticas de design de conversas. em sua ação.

Espere variações

Resolva isso no campo "O usuário diz" entrada no Dialogflow. Além disso, use mais de um que pode ser mapeada para a mesma ação, em que cada intent pode ser acionada com conjuntos diferentes de "O usuário diz" frases

Fornecer novas instruções úteis e falhar normalmente

Às vezes, sua Ação não consegue avançar porque não recebeu uma entrada (conhecido como sem entrada) ou não entendeu a entrada de um usuário (conhecido como sem correspondência). Quando isso acontece, o Google Assistente primeiro tenta determinar se o usuário quer para acionar uma ação diferente. Se o Google Assistente não corresponder à entrada do usuário para outra ação, o usuário continua no contexto dela. Esse cenário pode acontecer a qualquer momento, então a prática recomendada é lidar de forma exclusiva. situações sem entrada e sem correspondência em cada turno de uma conversa com um substituto. Com o uso de substitutos, você pode ajudar os usuários a voltar aos trilhos.

Para fazer isso, inicialize uma variável fallbackCount no objeto conv.data. e defini-lo como 0. Prepare uma matriz de duas instruções substitutas (encaminhando para um supervisor com clareza), e um comando substituto final para encerrar a conversa.

Em seguida, crie uma intent substituta (de preferência uma para cada intent acionável da agente). No gerenciador de intents, extraia a contagem de substitutos do conv.data objeto, incremente-o e, se for menor que 3, extraia o prompt da matriz de 3. Se a contagem for igual a quatro ou mais, encerre a conversa usando o prompt de comando. Redefina a contagem de substitutos para 0 em todas as intents que não são substitutas. O ideal é criar modelos de substitutos para intents específicas.

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

Esteja preparado para ajudar a qualquer momento

Crie uma intent que detecte frases de ajuda, como "O que posso fazer?", "o que você pode me dizer" ou "ajuda". Nessa intent, ofereça algumas (rotação) resposta que oferece uma visão geral do que o agente pode fazer e direciona os usuários para um uma possível ação. O ideal é usar intents de ajuda de continuidade no Dialogflow para criar diferentes cenários de ajuda para diferentes intents acionáveis.

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

Permitir que os usuários reproduzam informações

Una todos os métodos app.ask(output) com uma função proxy que adicione o saída para conv.data.lastPrompt. Criar uma intent repetida que detecte comandos para o usuário repetir, como "o quê?", “fale de novo” ou “você pode repetir isso?". Crie uma matriz de prefixos repetidos que podem ser usados para reconheça que o usuário pediu que algo fosse repetido. Na repetição gerenciador de intent, chame ask() com uma string concatenada do prefixo de repetição e o valor de conv.data.lastPrompt. Tenha em mente que você terá que mudar Tags de abertura SSML, se usadas no último comando.

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

Personalizar a conversa com as preferências do usuário

Sua Ação pode pedir preferências e lembrar dos usuários usar posteriormente, permitindo personalizar conversas futuras com esse usuário.

Este exemplo de ação fornece aos usuários a previsão do tempo para um CEP. O seguinte o código de exemplo pergunta ao usuário se ele gostaria que a ação se lembrasse do código postal para conversas futuras.

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

Depois de perguntar ao usuário em qual CEP ele está na primeira caixa de diálogo, você pode pular essa solicitação na próxima invocação e usar o mesmo CEP. Você ainda precisa fornecer uma rota de fuga (como um ícone de sugestão que permite escolher um CEP diferente), mas reduzindo a rotatividade da conversa na caso comum, você cria uma experiência muito mais perfeita.

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

Personalizar para usuários recorrentes

Manter um certo estado entre as conversas garante uma conversa muito mais natural para usuários recorrentes. O primeiro passo na criação dessa experiência é cumprimentam os usuários que retornam de forma diferente. Por exemplo, você pode diminuir a saudação mostrar informações úteis com base em conversas anteriores. Para fazer isso, use o método propriedade AppRequest.User lastSeen de entrada para determinar se o usuário já interagiu com sua Ação. Se a propriedade lastSeen estiver incluída no payload da solicitação, use uma saudação diferente do normal.

O código abaixo usa a biblioteca de cliente Node.js para buscar o 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();
}

É possível aprimorar ainda mais essa saudação, personalizando a resposta ao estilo de lastSeen. Por exemplo, usuários cuja última interação ocorreu muitos meses antes da interação atual, podem receber uma saudação diferente aqueles que usaram a ação no dia anterior.

Controle de volume durante a conversa

Em dispositivos compatíveis, o Assistente permite que os usuários controlem o volume do dispositivo no seu ação conversacional dizendo coisas como "aumentar o volume" ou "definir o o volume em 50%". Se você tem intents que processam frases de treinamento semelhantes, suas intents terão precedência. Recomendamos deixar o Assistente cuidar disso solicitações do usuário, a menos que sua ação tenha um motivo específico.