روبوت ذكي: يمكنه الاستماع ولا يقطع

يتم استخدام التعرّف على الكلام (المشار إليه فيما يلي - ASR ، التعرف التلقائي على الكلام) لإنشاء برامج الروبوت و / أو IVR ، وكذلك للاستطلاعات الآلية. يستخدم Voximplant ASR الذي توفره شركة Good Corporation - يعمل التعرف على Google بسرعة وبدقة عالية ، ولكن ... كما هو الحال دائمًا ، هناك تحذير واحد. يمكن لأي شخص أن يتوقف مؤقتًا حتى في جمل قصيرة ، ونحن بحاجة إلى ضمان أن ASR لن يأخذ وقفة في نهاية الجواب. إذا اعتقد ASR أن الشخص قد انتهى من التحدث ، فبعد "الإجابة" ، قد يتضمن النص توليفًا صوتيًا مع السؤال التالي - في نفس الوقت سيستمر الشخص في التحدث والحصول على تجربة مستخدم سيئة: يقوم bot / IVR بمقاطعة الشخص. سنخبرك اليوم عن كيفية التعامل مع هذا الأمر حتى لا ينزعج المستخدمون لديك عند التواصل مع مساعدي الحديد.


مفهوم


الهدف هو طرح سؤال والاستماع إلى شخص دون مقاطعة وانتظار نهاية إجابته. يتم تمثيل ASR بواسطة وحدة منفصلة حيث يوجد حدث ASR.Result - يتم تشغيله عندما ينتهي الشخص من التحدث. تفاصيل ASR الخاصة بـ Google هي أن ASR.Result مع النص المعترف به سيعود بمجرد توقف الشخص لفترة قصيرة على الأقل وتقرر google أن العبارة المذكورة تم التعرف عليها وإكمالها.

لمنح الشخص فرصة للتوقف ، يمكنك استخدام حدث ASR.InterimResult . في ذلك ، ASR في عملية التعرف على كل النص "الخام" ، وتصحيحه وتغييره اعتمادا على السياق - وهلم جرا ، حتى يتم تشغيل ASR.Result. وبالتالي ، فإن حدث ASR.InterimResult هو مؤشر على أن الشخص يقول حاليًا شيئًا ما . سوف نركز عليه فقط ونرى كم من الوقت لا يأتي. والنصوص المعترف بها المتوسطة وردت من ASR.Result - لإضافة.

بعبارات عامة ، سيبدو كما يلي:

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

نكشف الجوهر. الموقتات


للعمل بشكل صحيح مع الإيقاف المؤقت ، يمكنك إنشاء كائن خاص:

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

بعد طرح سؤال ، يفكر الشخص غالبًا لبضع ثوان. من الأفضل ضبط المؤقت للصمت في البداية من 6 إلى 8 ثوان ، وسنحفظ معرف المؤقت في المعلمة timeouts.silence .

التوقف المؤقت في منتصف الإجابة هو الأمثل خلال 3-4 ثوانٍ ، بحيث يمكن للشخص أن يفكر ، لكنه لم يعاني في التوقع عندما ينتهي. هذه هي المعلمة timeouts.pause .

يكون الموقت العام للإجابة بالكامل - timeouts.duration - مفيدًا إذا كنا لا نريد أن يتحدث الشخص لفترة طويلة جدًا. كما أنه يحمينا من الحالات التي يكون فيها شخص في غرفة صاخبة بأصوات الخلفية التي سنتخذها لخطاب العميل. وأيضًا من الحالات عندما وصلنا إلى روبوت آخر يتحدث مع روبوتنا في دائرة.

لذلك ، في بداية البرنامج النصي ، نقوم بتوصيل وحدة ASR ، ونعلن المتغيرات ، وننشئ كائن مهلة :

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

مكالمة واردة


عند وصول مكالمة واردة في البرنامج النصي ، وقع الحدث AppEvents.CallAlerting . لنقم بإنشاء معالج لهذا الحدث: الرد على المكالمة ، وتحية العميل ، وبدء الاعتراف بعد الترحيب. ودعنا نسمح لأي شخص بمقاطعة الروبوت من منتصف السؤال المطروح (التفاصيل - أكثر قليلاً).

معالج 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() }) }) 

يمكن ملاحظة أن وظيفتي startASR و startSilenceAndDurationTimeouts - دعنا نرى ما هذا ولماذا.

الاعتراف والمهلة


يتم تنفيذ الاعتراف في وظيفة startASR . يقوم بإنشاء مثيل ASR ويوجه صوت الشخص إلى هذا المثيل ؛ كما أنه يحتوي على معالجات الأحداث لـ ASREvents.InterimResult و ASREvents.Result . كما قلنا أعلاه ، نعامل هنا ASR.InterimResult كعلامة على أن الشخص يتحدث. يقوم معالج هذا الحدث بمسح المهلات التي تم إنشاؤها مسبقًا ، ويعين قيمة جديدة لـ timeouts.pause ، ويوقف الصوت المركب أخيرًا (هذه هي الطريقة التي يمكن للشخص بها مقاطعة الروبوت). يعالج معالج ASREvents.Result ببساطة كل الاستجابات الناتجة في متغير الكلام . على وجه التحديد ، في هذا السيناريو ، لا يتم استخدام الكلام بأي طريقة ، ولكن يمكنك نقله إلى الواجهة الخلفية الخاصة بك ، على سبيل المثال ، إذا كنت ترغب في ذلك.

startASR
 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) } 

start startSilenceAndDurationTimeouts ... يكتب قيم الموقتات المقابلة:

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

وبعض الميزات الأخرى


speechAnalysis يتوقف عن التعرّف ويوزع النص من الكلام (والذي يتم الحصول عليه من ASREvents.Result ). إذا لم يكن هناك نص ، فسنكرر السؤال ؛ إذا كان هناك نص ، فقل وداعًا وداعًا.

كلام تحليل
 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() }) } } 

المقبض Silence مسؤول عن تكرار السؤال:

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

أخيرًا ، وظيفة مساعد لإيقاف ASR:

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

كل ذلك معا


قائمة النصي
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

يوضح السيناريو النهائي كيف يمكنك "إبطال" روبوت مستقيمي ، مع إضافة القليل من اللباقة والانتباه إليه. بالتأكيد هذه الطريقة ليست الطريقة الوحيدة الممكنة ، لذلك إذا كان لديك أي أفكار حول كيف يمكنك إنهاء التفاعل المعتاد بين الروبوت والشخص بأناقة ، شارك في التعليقات. بالنسبة لأولئك الذين يرغبون في الحصول على شيء أكثر تقدماً وفجأة لم يقرءوا البرنامج التعليمي الخاص بنا عن DialogFlow - نوصيك بأن تتعرف على نفسك .

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


All Articles