机敏的机器人:可以听,不会打扰

语音识别(以下称为ASR,自动语音识别)用于创建漫游器和/或IVR,以及用于自动轮询。 Voximplant使用“好公司”提供的ASR-Google识别可以快速且高精度地工作,但是……一如既往,有一个警告。 一个人甚至可以用短句暂停,我们需要保证ASR不会在回答结束时停顿。 如果ASR认为该人已经完成讲话,则在“答案”之后,脚本可能会包含语音合成以及以下问题-同时,该人将继续讲话并获得不良的用户体验:bot / IVR会打断该人。 今天,我们将告诉您如何处理此问题,以使您的用户在与铁助手进行交流时不会感到烦恼。


概念图


目的是提出一个问题并倾听一个人,而不会打扰并等待他的回答结束。 ASR由一个单独的模块表示,该模块中有一个ASR.Result事件-当一个人说完话就会触发。 Google的ASR的详细信息是ASR。带有识别文本的结果会在一个人停顿至少一会儿后返回,并且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秒内将计时器设置为静音,我们将计时器ID保存在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() }) }) 

可以看出, 调用startASRstartSilenceAndDurationTimeouts函数- 让我们看看这是什么以及为什么。

识别和超时


识别是在startASR功能中实现的。 它创建一个ASR实例并将人的声音定向到该实例;它还包含ASREvents.InterimResultASREvents.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) } 

函数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() }) } } 

handleSilence负责重复该问题:

 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/zh-CN431676/


All Articles