Die Spracherkennung (im Folgenden: ASR, Automatic Speech Recognition) wird zum Erstellen von Bots und / oder IVR sowie für automatisierte Abfragen verwendet. Voximplant verwendet die von der Good Corporation bereitgestellte ASR - die Google-Erkennung funktioniert schnell und mit hoher Genauigkeit, aber ... Wie immer gibt es eine Einschränkung. Eine Person kann sogar in kurzen Sätzen pausieren, und wir brauchen eine Garantie, dass die ASR keine Pause als Ende der Antwort einlegt. Wenn der ASR der Meinung ist, dass die Person das Sprechen beendet hat, kann das Skript nach der „Antwort“ eine Sprachsynthese mit der folgenden Frage enthalten - gleichzeitig spricht die Person weiter und erhält eine schlechte Benutzererfahrung: Der Bot / IVR unterbricht die Person. Heute werden wir Ihnen erklären, wie Sie damit umgehen sollen, damit sich Ihre Benutzer nicht über die Kommunikation mit Eisenassistenten aufregen.
Konzept
Das Ziel ist es, eine Frage zu stellen und einer Person zuzuhören, ohne sie zu unterbrechen und auf das Ende ihrer Antwort zu warten. ASR wird durch ein
separates Modul dargestellt, in dem ein
ASR.Result- Ereignis
vorliegt. Es wird ausgelöst, wenn eine Person mit dem Sprechen fertig ist. Die Besonderheiten von Googles ASR sind, dass ASR. Das Ergebnis mit erkanntem Text wird zurückgegeben, sobald eine Person mindestens eine Weile innehält und Google entscheidet, dass diese Phrase erkannt und vervollständigt wird.
Um einer Person die Möglichkeit zu geben, eine Pause
einzulegen , können Sie das Ereignis
ASR.InterimResult verwenden . Darin gibt ASR während des Erkennungsprozesses den gesamten "rohen" Text zurück und korrigiert und ändert ihn je nach Kontext - und so weiter, bis das ASR.Result ausgelöst wird. Somit ist das Ereignis ASR.InterimResult
ein Indikator dafür, dass eine Person gerade etwas sagt . Wir werden uns nur auf ihn konzentrieren und sehen, wie lange es nicht kommt. Und die von ASR.Result erhaltenen Zwischenerkennungs-Texte - hinzufügen.
Im Allgemeinen wird es so aussehen:
asr.addEventListener(ASREvents.InterimResult, e => { clearTimeout(timer) timer = setTimeout(stop, 3000) }) asr.addEventListener(ASREvents.Result, e => { answer += " " + e.text }) function stop(){
Wir enthüllen die Essenz. Timer
Um mit Pausen richtig zu arbeiten, können Sie ein spezielles Objekt erstellen:
timeouts = { silence: null, pause: null, duration: null }
Nach dem Stellen einer Frage denkt eine Person oft einige Sekunden nach. Es ist besser, den Timer für die Stille am Anfang von 6-8 Sekunden einzustellen. Wir speichern die Timer-ID im Parameter
timeouts.silence .
Pausen in der Mitte der Antwort sind in 3-4 Sekunden optimal, so dass eine Person denken kann, aber nicht in Erwartung gelitten hat, wenn sie fertig ist. Dies ist der Parameter
timeouts.pause .
Der allgemeine Timer für die gesamte Antwort -
timeouts.duration - ist nützlich, wenn die Person nicht zu lange sprechen soll. Es schützt uns auch vor Fällen, in denen sich eine Person in einem lauten Raum mit Hintergrundstimmen befindet, die von uns für die Rede des Kunden verwendet werden. Und auch aus Fällen, in denen wir zu einem anderen Roboter kamen, der im Kreis mit unserem Roboter spricht.
Zu Beginn des Skripts schließen wir das ASR-Modul an, deklarieren die Variablen und erstellen ein
Timeout- Objekt:
require(Modules.ASR) let call, asr, speech = "" timeouts = { silence: null, pause: null, duration: null }
Eingehender Anruf
Wenn ein eingehender Anruf im Skript
eingeht , wird das Ereignis
AppEvents.CallAlerting ausgelöst . Erstellen wir einen Handler für dieses Ereignis: Beantworten Sie den Anruf, begrüßen Sie den Client und starten Sie die Erkennung nach der Begrüßung. Lassen wir eine Person den Roboter von der Mitte der gestellten Frage aus unterbrechen (Details - etwas weiter).
Handler AppEvents.CallAlerting VoxEngine.addEventListener(AppEvents.CallAlerting, e => { call = e.call
Es ist ersichtlich, dass die Funktionen
startASR und
startSilenceAndDurationTimeouts aufgerufen werden -
lassen Sie uns sehen, was dies ist und warum.
Erkennung und Zeitüberschreitungen
Die Erkennung ist in der Funktion
startASR implementiert. Es erstellt eine ASR-Instanz und leitet die Stimme der Person an diese Instanz weiter. Außerdem enthält es Ereignishandler für die
Ereignisse ASREvents.InterimResult und
ASREvents.Result . Wie oben erwähnt, behandeln wir ASR.InterimResult hier als Zeichen dafür, dass eine Person spricht. Der Handler dieses Ereignisses löscht zuvor erstellte Zeitüberschreitungen, legt einen neuen Wert für
timeouts.pause fest und stoppt schließlich die synthetisierte Stimme (auf diese Weise kann eine Person den Bot unterbrechen). Der ASREvents.Result-Handler verkettet einfach alle resultierenden Antworten in der Sprachvariablen. In diesem Szenario wird
Sprache in keiner Weise verwendet, aber Sie können
sie beispielsweise auf Wunsch in Ihr Backend übertragen.
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 => {
Funktion
startSilenceAndDurationTimeouts ... Schreibt die Werte der entsprechenden Timer:
function startSilenceAndDurationTimeouts() { timeouts.silence = setTimeout(speechAnalysis, 8000) timeouts.duration = setTimeout(speechAnalysis, 30000) }
Und noch ein paar Features
Die Sprachanalyse stoppt die Erkennung und analysiert den Text aus der
Sprache (die von
ASREvents.Result abgerufen
wird ). Wenn es keinen Text gibt, wiederholen wir die Frage; Wenn es einen Text gibt, dann verabschieden Sie sich höflich und legen Sie auf.
Sprachanalyse function speechAnalysis() {
Das
handleSilence ist für die Wiederholung der Frage verantwortlich:
function handleSilence() { call.say(", . , , ?", Language.RU_RUSSIAN_FEMALE)
Schließlich eine Hilfsfunktion zum Stoppen von ASR:
function stopASR() { asr.stop() call.removeEventListener(CallEvents.PlaybackFinished) clearTimeout(timeouts.duration) }
Alle zusammen
Skriptliste | 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) |
| } |
Das letzte Szenario zeigt, wie Sie einen geradlinigen Roboter "adeln" können, indem Sie ihm ein wenig Fingerspitzengefühl und Aufmerksamkeit verleihen. Sicherlich ist diese Methode nicht die einzig mögliche. Wenn Sie also darüber nachdenken, wie Sie die übliche Interaktion zwischen einem Bot und einer Person elegant beenden können, teilen Sie dies in den Kommentaren mit. Für diejenigen, die etwas Fortgeschritteneres wollen und plötzlich unser Tutorial über DialogFlow nicht gelesen haben - wir
empfehlen Ihnen, sich vertraut zu machen .