Wskazówki dotyczące implementacji (Dialogflow)

Zapoznaj się ze wskazówkami poniżej, aby wdrożyć sprawdzone metody dotyczące projektowania rozmowy. w akcję.

Spodziewaj się odmian

Zrób to w sekcji „Użytkownik mówi” dane wejściowe w Dialogflow. Oprócz tego użyj więcej niż jednego intencję, która może być zmapowana na to samo działanie, gdzie każda intencja może być aktywowana za pomocą funkcji różne zestawy znaków użytkownika. wyrażeniami.

Przekazuj przydatne prośby i powoduj nieumyślne porzucanie ogólników.

Czasami akcja nie może przejść do przodu, ponieważ nie otrzymała danych wejściowych (tzw. no-input) lub nie rozumiem danych wejściowych użytkownika (tzw. brak dopasowania). Gdy tak się dzieje, Asystent najpierw próbuje określić, czy użytkownik chce w celu wywołania innej Akcji. Jeśli Asystent nie pasuje do danych wejściowych użytkownika do innej Akcji, użytkownik kontynuuje w kontekście tej akcji. Scenariusz może mieć miejsce w dowolnym momencie, dlatego sprawdzona metoda polega na podejściu przypadki braku danych wejściowych i brak dopasowania na każdym etapie rozmowy z użyciem kreacji zastępczej. Użycie kreacji zastępczych może pomóc użytkownikom rozwiązać problem.

Aby to zrobić, zainicjuj zmienną fallbackCount w obiekcie conv.data, i ustaw wartość 0. Przygotuj tablicę 2 promptów zastępczych (przekazywanie jej w jasny sposób). i ostatni prompt zastępczy, który kończy rozmowę.

Następnie utwórz intencję zastępczą (najlepiej po jednej dla każdej intencji zachęcającej do działania w tagu ). W module obsługi intencji pobierz liczbę kreacji zastępczych z conv.data. obiektu, zwiększ jego wartość, a jeśli jest mniejsza niż 3, pobierz prompt z tablicy z 3. Jeśli liczba wynosi 4 lub więcej, zamknij rozmowę przy użyciu ostatniej . We wszystkich intencjach, które nie są wartościami zastępczymi, zresetuj liczbę kreacji zastępczych do 0. Najlepiej utworzyć szablony zastępcze dla konkretnych intencji, aby były one dostosowane do nich.

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

Pomoc w każdej chwili

Utwórz intencję, która słucha zwrotów pomocy, takich jak „co mogę zrobić?”, „Co możesz mi powiedzieć” lub „Pomoc?”. W tym celu zaoferuj kilka (rotacja) odpowiedź, która zawiera ogólne informacje o tym, co agent może zrobić, i kieruje użytkowników do możliwe działania. Najlepiej jest skorzystać również z intencji pomocy w Dialogflow, tworzyć różne scenariusze pomocy z myślą o różnych intencjach.

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

Pozwól użytkownikom na ponowne odtwarzanie informacji

Opakuj wszystkie metody app.ask(output) funkcją serwera proxy, która dodaje parę klucz-wartość dane wyjściowe do conv.data.lastPrompt. Utwórz intencję powtarzania, która nasłuchuje na przykład pytania „co?”, „Powtórz to jeszcze raz?” lub „Czy możesz powtórzyć?”. Utwórz tablicę powtórzonych prefiksów, których można używać do przyjąć, że użytkownik poprosił o powtarzanie czegoś. W powtarzaniu modułu obsługi intencji, wywołaj ask() z połączonym ciągiem powtórzenia i wartość conv.data.lastPrompt. Pamiętaj, że musisz zmienić Tagi otwierające SSML, jeśli zostały użyte w ostatnim prompcie.

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

Personalizowanie rozmowy na podstawie ustawień użytkownika

Akcja może prosić użytkowników o podanie preferencji i zapamiętać je używać ich w przyszłości, co pozwala na spersonalizowanie przyszłych rozmów z tym użytkownikiem.

To przykładowe działanie wyświetla użytkownikom prognozę pogody dla kodu pocztowego. Poniżej przykładowy kod pyta użytkownika, czy akcja ma zapamiętać kod pocztowy do wykorzystania w późniejszych rozmowach.

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

Gdy w pierwszym oknie zapytasz użytkownika o kod pocztowy, mogą pominąć ten prompt podczas następnego wywołania i użyć tego samego kodu pocztowego. Nadal musisz podać trasę wyjścia (np. element z sugestią, który umożliwi im wybór innego kodu pocztowego), ale ograniczając liczbę rozmów na jest to dość powszechna sytuacja, zapewnia znacznie większą płynność procesu.

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

Dostosuj pod kątem powracających użytkowników

Zachowywanie pewnego stanu między rozmowami zapewnia znacznie bardziej naturalne z myślą o powracających użytkownikach. Pierwszym krokiem na drodze do stworzenia takiej funkcji jest różnie witać powracających użytkowników. Na przykład możesz zmienić zakres powitania lub wyświetlania przydatnych informacji na podstawie wcześniejszych rozmów. W tym celu użyj właściwość przychodząca AppRequest.User lastSeen pozwalająca określić, czy użytkownik kontaktował się już z Twoją akcją. Jeśli uwzględniona została właściwość lastSeen w ładunku żądania możesz użyć powitania innego niż zwykle.

Poniższy kod korzysta z biblioteki klienta Node.js do pobrania wartości 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();
}

Możesz dodatkowo ulepszyć to powitanie, dopasowując odpowiedź do rzeczywistego lastSeen. Na przykład użytkownicy, których ostatnia interakcja miała miejsce wiele miesięcy przed bieżącą interakcją może otrzymać inne powitanie niż którzy skorzystali z akcji dzień wcześniej.

Regulacja głośności w trakcie rozmowy

Na obsługiwanych urządzeniach Asystent umożliwia użytkownikom sterowanie głośnością w konwersacyjne, mówiąc na przykład „Zrób głośniej” lub „Ustaw głośność na 50 procent”. Jeśli masz intencje, które obsługują podobne wyrażenia na potrzeby trenowania, Twoje intencje mają pierwszeństwo. Zalecamy, aby Asystent wykonał te czynności chyba że akcja ma konkretny powód.