Tinjau tips berikut untuk menerapkan praktik desain percakapan yang baik ke dalam Action Anda.
Diperkirakan variasi
Tangani ini di bagian "Pengguna berkata" di Dialogflow. Selain itu, gunakan lebih dari satu intent yang dapat memetakan ke tindakan yang sama, di mana setiap intent dapat dipicu dengan rangkaian yang berbeda, kata pengguna, frase-frase tertentu.
Memberikan perintah ulang yang bermanfaat dan gagal dengan baik
Terkadang Action Anda tidak dapat melanjutkan karena tidak menerima input (dikenal sebagai no-input) atau tidak memahami input pengguna (dikenal sebagai tidak ada kecocokan). Saat hal ini terjadi, Asisten akan mencoba menentukan terlebih dahulu apakah pengguna ingin untuk memicu Action berbeda. Jika Asisten tidak cocok dengan input pengguna ke Action lain, pengguna melanjutkan dalam konteks Action Anda. Skenario ini dapat terjadi kapan saja, jadi praktik terbaik adalah menangani situasi tidak ada input dan tidak ada kecocokan di setiap kesempatan dalam percakapan dengan penggantian. Menggunakan penggantian, Anda dapat membantu pengguna kembali ke jalurnya.
Untuk melakukannya, lakukan inisialisasi variabel fallbackCount
di objek conv.data
,
dan menyetelnya ke 0. Siapkan array dua perintah penggantian (eskalasi yang lebih jelas),
dan prompt penggantian terakhir yang mengakhiri percakapan.
Kemudian, buat intent penggantian (idealnya satu untuk setiap intent yang dapat ditindaklanjuti dalam
). Di pengendali intent, tarik jumlah penggantian dari conv.data
tambahkan, tambahkan, dan jika kurang dari 3, tarik prompt dari array
dari 3. Jika jumlahnya 4 atau lebih, tutup percakapan dengan menggunakan
. Di semua intent yang bukan fallback, reset jumlah fallback ke 0.
Idealnya, buat template fallback untuk intent tertentu agar spesifik untuk intent tersebut.
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(); }
Siap membantu kapan saja
Buat intent yang mendengarkan frasa bantuan seperti "apa yang bisa saya lakukan?", "apa yang bisa kamu ceritakan kepadaku", atau "bantuan". Dalam intent ini, tawarkan beberapa (memutar) yang menawarkan gambaran umum tentang apa yang dapat dilakukan agen dan mengarahkan pengguna ke tindakan yang dapat dilakukan. Idealnya, gunakan juga intent bantuan tindak lanjut di Dialogflow untuk membuat berbagai skenario bantuan untuk berbagai intent yang dapat ditindaklanjuti.
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(); }
Izinkan pengguna memutar ulang informasi
Gabungkan semua metode app.ask(output)
Anda dengan fungsi proxy yang menambahkan
output ke conv.data.lastPrompt
. Membuat intent berulang yang mendengarkan
untuk mengulanginya dari
pengguna seperti "apa?", "ucapkan itu lagi", atau "bisakah kamu
mengulanginya?". Buat array awalan berulang yang dapat digunakan untuk
mengakui bahwa pengguna meminta
sesuatu untuk diulangi. Dalam pengulangan
pengendali intent, panggil ask()
dengan string gabungan dari awalan berulang dan
nilai conv.data.lastPrompt
. Ingatlah bahwa Anda harus
mengubah setiap {i>wireframe<i}
Tag pembuka SSML jika digunakan dalam perintah terakhir.
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(); }
Personalisasi percakapan dengan preferensi pengguna
Action Anda dapat meminta preferensi pengguna dan mengingatnya untuk digunakan di lain waktu, sehingga Anda dapat mempersonalisasi percakapan berikutnya dengan pengguna tersebut.
Contoh Action ini memberi pengguna laporan cuaca untuk sebuah kode pos. Hal berikut kode contoh menanyakan pengguna apakah mereka ingin Action mengingat zip mereka kode untuk percakapan berikutnya.
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(); }
Setelah bertanya kepada pengguna tentang kode pos mana mereka berada selama dialog pertama, Anda bisa melewatkan perintah itu selama pemanggilan berikutnya dan menggunakan kode pos yang sama. Anda tetap harus menyediakan rute escape (seperti chip saran yang memungkinkan mereka memilih kode pos lain), tetapi dengan mengurangi pengalihan percakapan di umum, Anda menciptakan pengalaman yang jauh lebih mulus.
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(); }
Menyesuaikan untuk pengguna yang kembali
Mempertahankan beberapa status di antara percakapan akan memastikan
bagi pengguna yang kembali. Langkah pertama dalam menyusun
pengalaman ini adalah
menyapa pengguna yang kembali secara berbeda. Misalnya, Anda dapat mengetuk
sapaan atau
menampilkan informasi yang berguna berdasarkan percakapan sebelumnya. Untuk melakukannya, gunakan
properti AppRequest.User
lastSeen
yang masuk untuk menentukan apakah pengguna
pernah berinteraksi dengan Action Anda sebelumnya. Jika properti lastSeen
disertakan
dalam payload permintaan, Anda bisa menggunakan
sapaan yang berbeda dari biasanya.
Kode di bawah ini menggunakan library klien Node.js untuk mengambil nilai
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(); }
Anda dapat menyempurnakan sapaan ini lebih lanjut dengan menyesuaikan respons dengan
senilai lastSeen
. Misalnya, pengguna yang interaksi terakhirnya terjadi
bulan sebelum interaksi saat ini mungkin menerima salam yang berbeda dari
mereka yang menggunakan Action sehari sebelumnya.
Kontrol volume dalam percakapan
Di perangkat yang didukung, Asisten memungkinkan pengguna mengontrol volume perangkat dalam Tindakan percakapan dengan mengucapkan hal-hal seperti "naikkan volume" atau "setel hingga 50 persen". Jika Anda memiliki intent yang menangani frasa pelatihan serupa, intent Anda akan diprioritaskan. Sebaiknya izinkan Asisten menangani permintaan pengguna kecuali Action Anda memiliki alasan tertentu.