天天看点

构建简单的智能客服系统(一)——FreeSWITCH 搭建与配置

最近部署了几台第三方的智能语音系统,提供了如 ARS、TTS 相关服务。而 MRCP 能够对不同厂商提供的接口进行统一的封装,对于上游 FreeSWITCH 服务器只需要关心需要什么服务,而不需要再针对不同厂商进行相应接口开发。

智能客服系统简介

FreeSWITCH 是一个电话的软交换解决方案,包括一个软电话和软交换机用以提供语音和聊天的产品驱动。FreeSWITCH 可以用作交换机引擎、PBX、多媒体网关以及多媒体服务器等。

FreeSWITCH 可以通过 XML、脚本实现基本的 IVR 功能,再配合 mod_unimrcp 模块与 MRCP 服务器的 TTS、ASR资源进行通信,即可实现一个简单的智能客服系统。

FreeSWITCH 架构

如下图所示,FreeSWITCH 的扩展性非常强

构建简单的智能客服系统(一)——FreeSWITCH 搭建与配置

系统架构

系统架构如下图所示,FreeSWITCH 通过 mod_unimrcp 与 MRCP Server 进行通信。

构建简单的智能客服系统(一)——FreeSWITCH 搭建与配置

安装 FreeSWITCH

在 macOS 下安装,参考官网 “Download and Install the macOS FreeSWITCH™ Installer”,下载安装文件后,即可傻瓜式安装。但是安装尽然失败了。

构建简单的智能客服系统(一)——FreeSWITCH 搭建与配置

搜索了一下,是 1.6.20 版本的问题,所以选择了“Install Master Development” 安装最新开发版。

安装完成后会生成日志文件,日志里其实就是安装脚本的所有安装步骤执行 Shell 命令:

构建简单的智能客服系统(一)——FreeSWITCH 搭建与配置

测试 FreeSWITCH

运行 FreeSWITCH

FreeSWITCH 默认安装到目录

/usr/local/freeswitch

,执行文件在改目录的

bin

下面。启动FreeSWITCH:

1
      
./freeswitch
      

FreeSWITCH 安装后,默认配置了20个用户(1000-1019),密码 1234,同时包含了一个功能齐全的 IVR 示例,随便使用一个分机号登陆服务器,拨5000,就可以听到菜单提示了。

登陆 FreeSWITCH

使用 SIP 客户端即可登陆我们刚刚安装完的 FreeSWITCH 服务器,这里我使用了 iOS 下的 AdoreSIPClient,参考配置如下:

构建简单的智能客服系统(一)——FreeSWITCH 搭建与配置

我们可以使用两个客户端进行 VoIP 通话,也可以拨打 5000,即可听到默认设置的 IVR。

配置 FreeSWITCH

mod_unimrcp 配置

官网参考文档:mod_unimrcp

mod_unimrcp 安装

加载非默认模块的方法:

  • 编辑freeswitch/modules.conf文件,找到要安装的模块,去掉前面的注释符号#。
  • 在命令行执行make mod_xxx-install命令,这样就编译相应模块,并把编译后的动态库安装的/usr/local/freeswitch/mod目录下了。
  • 如果想启动freeswitch的时候就自动加载,修改/usr/local/freeswitch/conf/autoload_configs/modules.conf.xml,去掉注释符号就可以了。

按照上面步骤安装 mod_unimrcp 即可。

mrcp_profiles/unimrcpserver-mrcp-v2.xml

mrcp_profiles

目录新建

unimrcpserver-mrcp-v2.xml

配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
      
<include>
  <!-- UniMRCP Server MRCPv2 -->
  <!-- 后面我们使用该配置文件,均使用 name 作为唯一标识,而不是文件名 -->
  <profile name="unimrcpserver-mrcp2" version="2">
    <!-- MRCP 服务器地址 -->
    <param name="server-ip" value="192.168.2.244"/>
    <!-- MRCP SIP 端口号 -->
    <param name="server-port" value="7010"/>
    <param name="resource-location" value=""/>

    <!-- FreeSWITCH IP、端口以及 SIP 传输方式 -->
    <param name="client-ip" value="192.168.1.153" />
    <param name="client-port" value="5069"/>
    <param name="sip-transport" value="udp"/>


    <param name="speechsynth" value="speechsynthesizer"/>
    <param name="speechrecog" value="speechrecognizer"/>
    <!--param name="rtp-ext-ip" value="auto"/-->
    <param name="rtp-ip" value="192.168.1.153"/>
    <param name="rtp-port-min" value="4000"/>
    <param name="rtp-port-max" value="5000"/>
    <param name="codecs" value="PCMU PCMA L16/96/8000"/>

    <!-- Add any default MRCP params for SPEAK requests here -->
    <synthparams>
    </synthparams>

    <!-- Add any default MRCP params for RECOGNIZE requests here -->
    <recogparams>
      <!--param name="start-input-timers" value="false"/-->
    </recogparams>
  </profile>
</include>
      

autoload_configs/unimrcp.conf.xml

看目录名也大概能猜到,这里面的配置是 FreeSWITCH 运行后自动加载的。

修改

unimrcp.conf.xml

,将”default-tts-profile”、”default-asr-profile”修改为我们上面配置的”unimrcpserver-mrcp2”(注意是 name 值而不是文件名),这样我们后面使用的时候可以不指定配置名直接使用默认配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
      
<configuration name="unimrcp.conf" description="UniMRCP Client">
  <settings>
    <!-- UniMRCP profile to use for TTS -->
    <param name="default-tts-profile" value="unimrcpserver-mrcp2"/>
    <!-- UniMRCP profile to use for ASR -->
    <param name="default-asr-profile" value="unimrcpserver-mrcp2"/>
    <!-- UniMRCP logging level to appear in freeswitch.log.  Options are:
         EMERGENCY|ALERT|CRITICAL|ERROR|WARNING|NOTICE|INFO|DEBUG -->
    <param name="log-level" value="DEBUG"/>
    <!-- Enable events for profile creation, open, and close -->
    <param name="enable-profile-events" value="false"/>

    <param name="max-connection-count" value="100"/>
    <param name="offer-new-connection" value="1"/>
    <param name="request-timeout" value="3000"/>
  </settings>

  <profiles>
    <X-PRE-PROCESS cmd="include" data="../mrcp_profiles/*.xml"/>
  </profiles>

</configuration>
      

IVR 配置

查看默认配置

conf/dialplan/default.xml

我们可以看到如下配置,这就是默认的 5000 配置:

1
2
3
4
5
6
7
8
      
<!-- a sample IVR  -->
   <extension name="ivr_demo">
     <condition field="destination_number" expression="^5000$">
       	<action application="answer"/>
       	<action application="sleep" data="2000"/>
	 	<action application="ivr" data="demo_ivr"/>
     </condition>
   </extension>
      

新增 IVR 配置

conf/dialplan/default.xml

里新增如下配置:

1
2
3
4
5
6
      
<extension name="unimrcp">
     <condition field="destination_number" expression="^5001$">
   		<action application="answer"/>
		<action application="lua" data="names.lua"/>
     </condition>
   </extension>
      

跟 5000 配置不同的是,我们使用了 lua 脚本,当拨打 5001 时,FreeSWITCH 将会回调 names.lua 脚本。

智能 IVR 脚本

scripts

目录下新增

names.lua

脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
      
session:answer()

--freeswitch.consoleLog("INFO", "Called extension is '".. argv[1]"'\n")
welcome = "ivr/ivr-welcome_to_freeswitch.wav"
menu = "ivr/ivr-this_ivr_will_let_you_test_features.wav"
--
grammar = "hello"
no_input_timeout = 80000
recognition_timeout = 80000
confidence_threshold = 0.2
--
session:streamFile(welcome)
--freeswitch.consoleLog("INFO", "Prompt file is \n")

tryagain = 1
 while (tryagain == 1) do
 --
       session:execute("play_and_detect_speech",menu .. "detect:unimrcp {start-input-timers=false,no-input-timeout=" .. no_input_timeout .. ",recognition-timeout=" .. recognition_timeout .. "}" .. grammar)
       xml = session:getVariable('detect_speech_result')
 --
       if (xml == nil) then
               freeswitch.consoleLog("CRIT","Result is 'nil'\n")
               tryagain = 0
       else
               freeswitch.consoleLog("CRIT","Result is '" .. xml .. "'\n")
               tryagain = 0

	end
end
 --
 -- put logic to forward call here
 --
 session:sleep(250)
 session:set_tts_parms("unimrcp", "xiaofang");
 session:speak("今天天气不错啊");
 session:hangup()
      

同时我们需要在

grammar

目录新增

hello.gram

语法文件,可以为空语法文件须满足语音识别语法规范1.0标准(简称SRGS1.0),该语法文件 ASR 引擎在进行识别时可以使用。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
      
<?xml version="1.0" encoding="utf-8" ?>
<grammar version="1.0" xml: root="Menu" tag-format="semantics/1.0"
      xmlns=http://www.w3.org/2001/06/grammar
    xmlns:sapi="http://schemas.microsoft.com/Speech/2002/06/SRGSExtensions"><!- 这些都是必不可少的-->
  <rule id="city" scope="public">
    <one-of>     <!-- 匹配其中一个短语-->
      <item>北京</item>
      <item>上海</item>
    </one-of>
  </rule>
  <rule id="cross" scope="public">
    <one-of>
      <item>到</item>
      <item>至</item>
      <item>飞往</item>
    </one-of>
  </rule>
  <rule id="Menu" scope="public">
    <item>
      <ruleref uri="#date"/>         <!--指定关联的其他规则的节点-->
      <tag>out.date = reles.latest();</tag>
    </item>
    <item repeat="0-1">从</item>    <!--显示1次或0次-->
    <item>
      <ruleref uri="#city"/>
      <tag>out.city = rulels.latest();</tag>
    </item>
    <item>
      <ruleref uri="#cross"/>
      <tag>out.cross = rulels.latest();</tag>
    </item>
    <item>
      <ruleref uri="#city"/>
      <tag>out.city = rulels.latest();</tag>
    </item>
  </rule>
</grammar>
      

脚本中,我们使用 unimrcp 默认配置,”play_and_detect_speech” 调用了 ASR 服务,”speak” 调用了 TTS 服务。你可以在循环中,尝试分析解析到的语句,根据内容进行导航、反馈。

最终测试

SIP 客户端登陆后拨打 5001 分机,就可以听到我们配置的导航内容了。

最后

本文只是对 FreeSWITCH 的最简单的使用,FreeSWITCH 是一个很强大的系统,若要完全掌握需要花费更多的精力去学习它的架构、配置。而我使用 FreeSWITCH 目前只是为了方便调试自己编写的 UniMRCP Plugin,后面我将通过整合科大讯飞提供的ASR、TTS服务,整理一下 UniMRCP Plugin 的实现。

继续阅读