Robot Tactful: dapat mendengarkan dan tidak mengganggu

Pengenalan ucapan (selanjutnya - ASR, Pengenalan Ucapan Otomatis) digunakan untuk membuat bot dan / atau IVR, serta untuk jajak pendapat otomatis. Voximplant menggunakan ASR yang disediakan oleh Good Corporation - Pengakuan Google bekerja dengan cepat dan dengan akurasi tinggi, tetapi ... Seperti biasa, ada satu peringatan. Seseorang dapat berhenti bahkan dalam kalimat pendek, dan kami membutuhkan jaminan bahwa ASR tidak akan mengambil jeda sebagai akhir dari jawaban. Jika ASR berpikir bahwa orang tersebut telah selesai berbicara, maka setelah "jawaban" skrip dapat memasukkan sintesis suara dengan pertanyaan berikut - pada saat yang sama orang tersebut akan terus berbicara dan mendapatkan pengalaman pengguna yang buruk: bot / IVR mengganggu orang tersebut. Hari ini kami akan memberi tahu Anda cara menangani hal ini agar pengguna Anda tidak kesal saat berkomunikasi dengan asisten besi.


Konsep


Tujuannya adalah untuk mengajukan pertanyaan dan mendengarkan seseorang tanpa mengganggu dan menunggu akhir jawabannya. ASR diwakili oleh modul terpisah , di mana ada acara ASR. Hasil - dipicu ketika seseorang telah selesai berbicara. Kekhususan ASR Google adalah bahwa ASR. Hasil dengan teks yang dikenali akan kembali segera setelah seseorang berhenti sebentar setidaknya dan Google memutuskan bahwa frasa tersebut dikenali dan diselesaikan.

Untuk memberi seseorang kesempatan untuk berhenti, Anda dapat menggunakan acara ASR.InterimResult . Di dalamnya, ASR dalam proses pengakuan mengembalikan semua teks "mentah", mengoreksi dan mengubahnya tergantung pada konteksnya - dan seterusnya, hingga ASR. Hasil dipicu. Dengan demikian, acara ASR.InterimResult adalah indikator bahwa seseorang saat ini mengatakan sesuatu . Kami akan fokus hanya padanya dan melihat berapa lama itu tidak datang. Dan teks-teks yang diakui antara diterima dari ASR.Hasil - untuk menambahkan.

Secara umum, akan terlihat seperti ini:

asr.addEventListener(ASREvents.InterimResult, e => { clearTimeout(timer) timer = setTimeout(stop, 3000) }) asr.addEventListener(ASREvents.Result, e => { answer += " " + e.text }) function stop(){ //... } 

Kami mengungkapkan esensinya. Pengatur waktu


Untuk bekerja dengan benar dengan jeda, Anda dapat membuat objek khusus:

 timeouts = { silence: null, pause: null, duration: null } 

Setelah mengajukan pertanyaan, seseorang sering berpikir selama beberapa detik. Lebih baik mengatur penghitung waktu hening di awal 6-8 detik, kami akan menyimpan ID penghitung waktu di timeouts.silence parameter.

Jeda di tengah jawaban optimal dalam 3-4 detik, sehingga seseorang dapat berpikir, tetapi tidak menderita dengan harapan ketika ia selesai. Ini adalah parameter timeouts.pause .

Pengatur waktu umum untuk seluruh jawaban - timeouts.duration - berguna jika kita tidak ingin orang itu berbicara terlalu lama. Ini juga melindungi kita dari kasus ketika seseorang berada di ruangan yang bising dengan suara latar belakang yang akan diambil oleh kita untuk pidato klien. Dan juga dari kasus ketika kami sampai ke robot lain yang berbicara dengan robot kami dalam lingkaran.

Jadi, di awal skrip, kita pasang modul ASR, deklarasikan variabelnya, dan buat objek timeout :

 require(Modules.ASR) let call, asr, speech = "" timeouts = { silence: null, pause: null, duration: null } 

Panggilan masuk


Ketika panggilan masuk tiba di skrip, acara AppEvents.CallAlerting menyala . Mari kita membuat penangan untuk acara ini: menjawab panggilan, menyapa klien, memulai pengakuan setelah sambutan. Dan mari kita biarkan seseorang mengganggu robot dari tengah pertanyaan yang diajukan (detail - sedikit lebih jauh).

handler AppEvents.CallAlerting
 VoxEngine.addEventListener(AppEvents.CallAlerting, e => { call = e.call //    .     Connected call.answer() call.addEventListener(CallEvents.Connected, e => { call.say(",      . , ,        ?", Language.RU_RUSSIAN_FEMALE) //    4          setTimeout(startASR, 4000) //        call.addEventListener(CallEvents.PlaybackFinished, startSilenceAndDurationTimeouts) }); call.addEventListener(CallEvents.Disconnected, e => { VoxEngine.terminate() }) }) 

Dapat dilihat bahwa fungsi startASR dan startSilenceAndDurationTimeouts disebut - mari kita lihat apa ini dan mengapa.

Pengakuan dan batas waktu


Pengakuan diimplementasikan dalam fungsi startASR . Ini membuat instance ASR dan mengarahkan suara orang ke instance ini, tetapi juga berisi pengendali acara untuk ASREvents.InterimResult dan ASREvents.Result events . Seperti yang kami katakan di atas, di sini kami memperlakukan ASR.InterimResult sebagai tanda bahwa seseorang sedang berbicara. Pawang acara ini membersihkan batas waktu yang dibuat sebelumnya, menetapkan nilai baru untuk batas waktu. Jeda, dan akhirnya menghentikan suara yang disintesis (ini adalah bagaimana seseorang dapat mengganggu bot). ASREvents.Result handler hanya menggabungkan semua respons yang dihasilkan dalam variabel pidato . Secara khusus, dalam skenario ini, ucapan tidak digunakan dengan cara apa pun, tetapi Anda dapat mentransfernya ke backend Anda, misalnya, jika Anda mau.

mulaiASR
 function startASR() { asr = VoxEngine.createASR({ lang: ASRLanguage.RUSSIAN_RU, interimResults: true }) asr.addEventListener(ASREvents.InterimResult, e => { clearTimeout(timeouts.pause) clearTimeout(timeouts.silence) timeouts.pause = setTimeout(speechAnalysis, 3000) call.stopPlayback() }) asr.addEventListener(ASREvents.Result, e => { //    speech += " " + e.text }) //    ASR call.sendMediaTo(asr) } 

Fungsi startSilenceAndDurationTimeouts ... Menulis nilai dari penghitung waktu yang sesuai:

 function startSilenceAndDurationTimeouts() { timeouts.silence = setTimeout(speechAnalysis, 8000) timeouts.duration = setTimeout(speechAnalysis, 30000) } 

Dan beberapa fitur lainnya


speechAnalysis menghentikan pengenalan dan mem-parsing teks dari ucapan (yang diperoleh dari ASREvents.Result ). Jika tidak ada teks, maka kami ulangi pertanyaannya; jika ada teks, maka dengan sopan mengucapkan selamat tinggal dan menutup telepon.

Analisis pidato
 function speechAnalysis() { //   ASR stopASR() const cleanText = speech.trim().toLowerCase() if (!cleanText.length) { //     ,       , // ..     ,   , ,    handleSilence() } else { call.say( "   !  !", Language.RU_RUSSIAN_FEMALE ) call.addEventListener(CallEvents.PlaybackFinished, () => { call.removeEventListener(CallEvents.PlaybackFinished) call.hangup() }) } } 

HandleSilence bertanggung jawab untuk mengulangi pertanyaan:

 function handleSilence() { call.say(",   . , ,        ?", Language.RU_RUSSIAN_FEMALE) //    3          setTimeout(startASR, 3000) call.addEventListener(CallEvents.PlaybackFinished, startSilenceAndDurationTimeouts) } 

Akhirnya, fungsi pembantu untuk menghentikan ASR:

 function stopASR() { asr.stop() call.removeEventListener(CallEvents.PlaybackFinished) clearTimeout(timeouts.duration) } 

Semuanya bersama


daftar skrip
require(Modules.ASR)
let call,
asr,
speech = ""
timeouts = {
silence: null,
pause: null,
duration: null
}
// CallAlerting ,
VoxEngine.addEventListener(AppEvents.CallAlerting, e => {
call = e.call
// . Connected
call.answer()
call.addEventListener(CallEvents.Connected, e => {
call.say(", . , , ?", Language.RU_RUSSIAN_FEMALE)
// 4
setTimeout(startASR, 4000)
//
call.addEventListener(CallEvents.PlaybackFinished, startSilenceAndDurationTimeouts)
});
call.addEventListener(CallEvents.Disconnected, e => {
VoxEngine.terminate()
})
})
function startASR() {
asr = VoxEngine.createASR({
lang: ASRLanguage.RUSSIAN_RU,
interimResults: true
})
asr.addEventListener(ASREvents.InterimResult, e => {
clearTimeout(timeouts.pause)
clearTimeout(timeouts.silence)
timeouts.pause = setTimeout(speechAnalysis, 3000)
call.stopPlayback()
})
asr.addEventListener(ASREvents.Result, e => {
//
speech += " " + e.text
})
// ASR
call.sendMediaTo(asr)
}
function startSilenceAndDurationTimeouts() {
timeouts.silence = setTimeout(speechAnalysis, 8000)
timeouts.duration = setTimeout(speechAnalysis, 30000)
}
function speechAnalysis() {
// ASR
stopASR()
const cleanText = speech.trim().toLowerCase()
if (!cleanText.length) {
// , ,
// .. , , ,
handleSilence()
} else {
call.say(
" ! !",
Language.RU_RUSSIAN_FEMALE
)
call.addEventListener(CallEvents.PlaybackFinished, () => {
call.removeEventListener(CallEvents.PlaybackFinished)
call.hangup()
})
}
}
function handleSilence() {
call.say(", . , , ?", Language.RU_RUSSIAN_FEMALE)
// 3
setTimeout(startASR, 3000)
call.addEventListener(CallEvents.PlaybackFinished, startSilenceAndDurationTimeouts)
}
function stopASR() {
asr.stop()
call.removeEventListener(CallEvents.PlaybackFinished)
clearTimeout(timeouts.duration)
}
view raw asr.js hosted with ❤ by GitHub

Skenario terakhir menunjukkan bagaimana Anda dapat "memuliakan" robot bujursangkar, menambahkan sedikit kebijaksanaan dan perhatian padanya. Tentunya metode ini bukan satu-satunya yang mungkin, jadi jika Anda memiliki pemikiran tentang bagaimana Anda dapat dengan elegan menyelesaikan interaksi yang biasa antara bot dan seseorang, bagikan dalam komentar. Bagi mereka yang menginginkan sesuatu yang lebih maju dan tiba-tiba tidak membaca tutorial kami tentang DialogFlow - kami sarankan Anda membiasakan diri .

Source: https://habr.com/ru/post/id431676/


All Articles