Uygulama ipuçları (Dialogflow)

İşleminize iyi görüşme tasarımı uygulamaları uygulamak için aşağıdaki ipuçlarını inceleyin.

Farklılıklar görebilirsiniz

Bu işlemi Dialogflow'daki "Kullanıcı diyor" girişinden yapın. Ayrıca, aynı işlemle eşleştirilebilen birden fazla amaç kullanın. Bu amaçlar, her bir amacın farklı "Kullanıcı diyor" ifade gruplarıyla tetiklenebilir.

Faydalı yeniden istemler sunma ve başarılı bir şekilde başarısız olma

Bazen İşleminiz giriş almadığı (giriş yok) veya kullanıcı girişini anlamadığı (eşleşme yok) nedeniyle devam edemeyebilir. Bu durumda, Asistan ilk olarak kullanıcının farklı bir İşlemi tetiklemek isteyip istemediğini belirlemeye çalışır. Asistan, kullanıcının girişini başka bir İşlemle eşleştirmezse kullanıcı, İşleminizin bağlamında devam eder. Bu senaryo herhangi bir zamanda gerçekleşebilir. Bu nedenle, en iyi uygulama, yedek içeren bir ileti dizisindeki her dönüşte girilemeyen ve eşleşmeyen durumları benzersiz şekilde ele almaktır. Yedekleri kullanarak kullanıcıların işinize devam etmesini sağlayabilirsiniz.

Bunu yapmak için conv.data nesnenizde bir fallbackCount değişkeni başlatın ve 0 olarak ayarlayın. İki yedek istem (artık anlaşılır şekilde eskale edilir) ve ileti dizisini sonlandıran son bir yedek istem dizisi hazırlayın.

Ardından bir yedek intent (ideal olarak aracıdaki işlem yapılabilir her amaç için bir yedek) oluşturun. Amaç işleyicide, conv.data nesnesinden yedek sayısını geri çekin, değeri artırın ve 3'ten küçükse istemi 3 dizisinden çekin. Sayı 4 veya daha fazlaysa son istemi kullanarak görüşmeyi kapatın. Yedek olmayan tüm amaçlarda yedek sayısını 0 olarak sıfırlayın. İdeal olarak belirli niyetlerin yedeklerini bunlara özgü olacak şekilde hazırlayın.

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

Her zaman yardıma hazır olun

"Ne yapabilirim?" gibi yardım ifadelerini dinleyen bir amaç oluşturun. "bana neler söyleyebilirsin" veya "yardım" ifadelerini kullanabilirsin. Bu amaç doğrultusunda, aracının ne yapabileceğine dair genel bir bakış sunan ve kullanıcıları olası bir işleme yönlendiren bir yanıt (dönen) sunun. İdeal olarak, farklı eylem türlerine yönelik farklı yardım senaryoları oluşturmak için Dialogflow'da takip amaçlı yardım amaçları da kullanın.

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

Kullanıcıların bilgileri tekrar oynatmasına izin verme

Tüm app.ask(output) yöntemlerinizi, çıkışı conv.data.lastPrompt öğesine ekleyen bir proxy işleviyle sarmalayın. Kullanıcıdan gelen istemlerin "ne?" gibi tekrarlanmasını dinleyen bir tekrar intent oluşturun. ya da "tekrar edebilir misin?" Kullanıcının bir şeyin tekrarlanmasını istediğini onaylamak için kullanılabilecek bir dizi yinelenen ön ek oluşturun. Tekrar amaç işleyicisinde, tekrarlama önekinin ve conv.data.lastPrompt değeriyle birleştirilmiş bir dizeyle ask() yöntemini çağırın. Son istemde kullanılıyorsa SSML açılış etiketlerini değiştirmeniz gerekeceğini unutmayın.

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

Kullanıcı tercihleriyle sohbeti kişiselleştirin

İşleminiz kullanıcılardan tercihlerini isteyerek daha sonra kullanmak için hatırlayabilir. Böylece, söz konusu kullanıcıyla ileride yapacağınız görüşmeleri kişiselleştirebilirsiniz.

Bu örnek İşlem, kullanıcılara bir posta koduyla ilgili hava durumu raporu sunar. Aşağıdaki örnek kod, kullanıcıya İşlemin sonraki görüşmeler için posta kodunu hatırlamasını isteyip istemediğini sorar.

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

Kullanıcıya ilk diyalog sırasında hangi posta kodunu sorduğunu sorduktan sonra, bir sonraki çağrı sırasında bu istemi atlayabilir ve aynı posta kodunu kullanabilirsiniz. Yine de bir kaçış rotası (ör. farklı bir posta kodu seçmelerine olanak tanıyan bir öneri çipi gibi) sağlamanız gerekir ancak yaygın durumda iletişim akışını azaltarak çok daha sorunsuz bir deneyim sağlamış olursunuz.

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

Geri gelen kullanıcılar için özelleştirin

Görüşmeler arasındaki durumun sürdürülmesi, geri gelen kullanıcılar için çok daha doğal bir deneyim sağlar. Bu deneyimi tasarlamanın ilk adımı, geri gelen kullanıcıları farklı bir şekilde karşılamaktır. Örneğin, selamlamaya odaklanabilir veya geçmiş konuşmalara dayalı faydalı bilgiler bulabilirsiniz. Bunu yapmak için kullanıcının daha önce İşleminizle etkileşimde bulunup bulunmadığını belirlemek amacıyla gelen AppRequest.User lastSeen özelliğini kullanın. lastSeen özelliği, istek yüküne dahilse normalden farklı bir karşılama mesajı kullanabilirsiniz.

Aşağıdaki kod, last.seen değerini getirmek için Node.js istemci kitaplığını kullanır.

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

Yanıtı gerçek lastSeen değerine uyarlayarak bu karşılama mesajını daha da iyileştirebilirsiniz. Örneğin, son etkileşimi mevcut etkileşimden aylar önce gerçekleşmiş olan kullanıcılar, işlemi bir gün önce kullananlardan farklı bir karşılama mesajı alabilir.

Görüşme sırasında ses seviyesi kontrolü

Desteklenen cihazlarda Asistan, kullanıcıların "sesi aç" veya "sesi yüzde 50'ye ayarla" gibi şeyler söyleyerek görüşme işlemi sırasında cihaz ses düzeyini kontrol etmelerine olanak tanır. Benzer eğitim ifadelerini işleyen amaçlarınız varsa amaçlarınız önceliklidir. İşleminiz özel bir nedeni yoksa Asistan'ın bu kullanıcı istekleriyle ilgilenmesine izin vermenizi öneririz.