基于freeswitch打造智能语音客服五

    OpenVXI是一个用来解释VoiceXML对话标记语言的开源库,它严格支持VoiceXML2.0草案。OpenVXI提供了一个强大的基本框架让使用者构建自己的语音平台。

1. VoiceXML简介

       OpenVXI是一个开源的语音XML(VoiceXML)解释器,用于构建语音应用程序。使用VoiceXML的应用系统中,不要求用户学习复杂的高级语言,就可灵活扩充新业务。而无需再与开发商联系,重新定制开发,只需要编写几个VoiceXML页面就可以实现新的业务流程。而且编制好的VoiceXML脚本可以随时随地加入到系统中,而不会影响系统的正常运行。

VoiceXML2.0规范

2. OpenVXI系统架构

    

    OpenVXI由以下实现:

  • VXI:解析所有的VoiceXML标记,并且担任程序中的主控角色。VXI实现了所有Voice2.0规范中所需要的部分功能和大部分可选功能。

  • VXI Parser Interface: 提供了对XML DOM解析器的访问,OpenVXI中使用的是开源的Apache Xerces SAX and DOM的解析接口。

  • Internet Interface:提供了通过http://和file://的方式访问应用文档,同时也支持POSTING数据返回到应用服务器。

  • ECMAScript Interface: 提供了对ECMAScript(JavaScript)执行服务的访问。OpenVXI的实现整合了Mozilla SpiderMonkey开源引擎。

  • Logging Interface:用来报告系统操作的错误,事件以及诊断信息。OpenVXI的实现包括输出日志到文件和可选的标准输出。

    实现平台必须提供以下资源接口:

  • Recognizer Interface: 提供语法管理和必须由VoiceXML指定的识别,包括动态创建和启用语法。它通过电话平台来获得呼叫输入。

  • Prompt Interface:提供完整的放音服务,能够处理静态音频文件并且提供语音合成服务。

  • Telephony Interface:提供呼叫控制服务,包括转接、挂断呼叫并提供电话时间的能力。

  • Object Interface:提供对象访问,平台可以通过对象元素访问已定义的VoiceXML语言扩展。对象能够很容易地被定义以满足指定的电话扩展、CTI系统的弹屏显示以及其他需求。

3. 介于OpenVXI开发自定义对话控制

3.1 Recognizer Interface

    VXIrecInterface是OpenVXI中用于处理语音识别功能的接口。该接口提供了语音识别的核心功能,包括初始化、语法加载、识别启动与停止、结果获取等,是OpenVXI平台中实现语音交互的重要组成部分。

Recognizer接口定义如下:

typedef struct VXIrecInterface {
  // 获取接口实现的版本号
  VXIint32 (*GetVersion)(void);
  
  // 获取接口实现的名称
  const VXIchar* (*GetImplementationName)(void);
  
  // 开始会话,为每个新会话调用,允许进行特定于调用的处理或资源绑定
  VXIrecResult (*BeginSession)(struct VXIrecInterface  *pThis,  VXIMap *args);

  // 结束会话,在呼叫结束时进行清理,允许进行特定于呼叫的终止或资源释放
  VXIrecResult (*EndSession)(struct VXIrecInterface  *pThis, VXIMap *args);

  // 通过URI加载语法,非阻塞接口
  VXIrecResult (*LoadGrammarURI)(struct VXIrecInterface  *pThis,
                                 const VXIMap            *properties,
                                 const VXIchar           *type, 
                                 const VXIchar           *uri,
                                 const VXIMap            *uriArgs,
                                 VXIrecGrammar          **gram);


  // 加载一个内嵌在VoiceXML页面的语法,非阻塞接口
  VXIrecResult (*LoadGrammarString)(struct VXIrecInterface  *pThis,
                                    const VXIMap            *properties,
                                    const VXIchar           *type,
                                    const VXIchar           *gramDef,
                                    VXIrecGrammar          **gram);

  // 激活加载的语法以进行后续识别调用
  VXIrecResult (*ActivateGrammar)(struct VXIrecInterface  *pThis,
                                  const VXIMap            *properties,
                                  VXIrecGrammar           *gram);

  // 停用加载的语法文件以进行后续识别调用。
  VXIrecResult (*DeactivateGrammar)(struct VXIrecInterface  *pThis,
                                    VXIrecGrammar           *gram);

  // 释放已加载的语法文件
  VXIrecResult (*FreeGrammar)(struct VXIrecInterface  *pThis,
                              VXIrecGrammar          **gram);

  // 使用当前激活的语法进行识别,接口会阻塞直到识别完成、按键输入
  // 完成或者超时或出现错误
  VXIrecResult (*Recognize)(struct VXIrecInterface    *pThis,
                            const VXIMap              *properties,
                            VXIrecRecognitionResult  **recogResult);

  // 保存录音信息
  VXIrecResult (*Record)(struct VXIrecInterface  *pThis,
                         const VXIMap            *properties,
                         VXIrecRecordResult     **recordResult);

  // 获取识别结果ID匹配的语法
  VXIrecResult (*GetMatchedGrammar)(struct VXIrecInterface * pThis,
                                    const VXIchar *grammarID,
                                    const VXIrecGrammar **gram);

  // 使用VoiceXMl元素创建语法
  VXIrecResult (*LoadGrammarOption)(struct VXIrecInterface  *pThis,
                                    const VXIMap            *properties,
                                    const VXIVector         *gramChoices,
                                    const VXIVector         *gramValues,
                                    const VXIVector         *gramAcceptance,
                                    const VXIbool            isDTMF,
                                    VXIrecGrammar          **gram);

  // 提供热词识别终止转接
  VXIrecResult (*HotwordTransfer)(struct VXIrecInterface * pThis,
                                  struct VXItelInterface * tel,
                                  const VXIMap *properties,
                                  const VXIchar* transferDest,
                                  VXIrecTransferResult  ** transferResult);

  // 是否支持热词识别终止转接
  VXIbool (*SupportsHotwordTransfer)(struct VXIrecInterface *pThis,
                                  const VXIMap  * properties,
                                  const VXIchar * transferDest);

} VXIrecInterface;

   Recognizer示例:

   

<form id="ASR-1">
  <property name="maxspeechtime" value="10000"/>
  <field name="user_input" type="voice dtmf">
    <prompt bargein="true">
       请说出您要查询的城市名
    </prompt>
    <grammar src="/grammars/voice.grxml" type="application/srgs+xml"/>
    <filled>
      <assign name="asr_result" expr="user_input"/>
      <goto next="#LogicCompare-2"/>
    </filled>
  </field>
</form>

   field是一个输入域,用户必须给field提供一个值,否则就不可能进行到form中的下一个元素。如上图,type表示接受的是语音输入还是按键输入。OpenVXI在执行时,执行Prompt放音并调用Recognize接口,该接口实现我们将启动识别,并阻塞在等待识别结果返回后指定filled。识别接结果会填写到field,通过user_input获取到识别结果。

3.2 Prompt Interface

    VXIpromptInterface接口提供了一套用于处理语音提示的功能。这些功能包括获取版本信息、获取实现名称、开始和结束会话、播放队列中的提示、预取提示、排队提示、等待提示播放完成等。这些功能共同作用,使得系统能够高效地处理语音提示,提供良好的响应时间和低CPU及网络开销。

    Prompt接口定义如下:

typedef struct VXIpromptInterface {
  // 获取接口实现的版本号
  VXIint32 (*GetVersion)(void);

  // 获取实现的名称,要确保每个实现的名称都是唯一的
  const VXIchar* (*GetImplementationName)(void);

  // 为新会话进行初始化,可以设计资源绑定或运行时调用特定操作
  VXIpromptResult (*BeginSession)(struct VXIpromptInterface *pThis, VXIMap *args);

  // 在通话结束时进行清理,可能释放资源或执行其他终止操作
  VXIpromptResult (*EndSession)(struct VXIpromptInterface *pThis, VXIMap *args);

  // 开始播放队列中的提示,这是一个非阻塞操作
  VXIpromptResult (*Play)(struct VXIpromptInterface  *pThis);

  // 播放特殊填充提示,通常用于在文档获取期间播放提示,并在获取完成后中断
  VXIpromptResult (*PlayFiller)(struct VXIpromptInterface *pThis,
                                const VXIchar             *type,
                                const VXIchar             *src,
                                const VXIchar             *text,
                                const VXIMap              *properties,
                                VXIlong                    minPlayMsec);

  // 预取提示,以便在需要时快速播放,这是一个非阻塞操作
  VXIpromptResult (*Prefetch)(struct VXIpromptInterface *pThis,
                              const VXIchar             *type,
                              const VXIchar             *src,  /* deprecated - NOT USED */
                              const VXIchar             *text,
                              const VXIMap              *properties);

  // 将提示放到播放队列,直到调用Play方法后开始播放队列
  VXIpromptResult (*Queue)(struct VXIpromptInterface *pThis,
                           const VXIchar             *type,
                           const VXIchar             *src, /* deprecated - NOT USED */
                           const VXIchar             *text,
                           const VXIMap              *properties);

  // 等待所有已排队的提示播放完毕,这是一个阻塞操作
  VXIpromptResult (*Wait)(struct VXIpromptInterface *pThis,
                          VXIpromptResult           *playResult);
} VXIpromptInterface;

Prompt示例:

<prompt bargein="true">
      <audio src="http://172.31.185.37:6036/ivr-audio.wav"/>
      欢迎拨打这个演示系统
</prompt>

    OpenVXI在执行Prompt时,会调用PlayFiller接口,PlayFile传参type表示文本格式,src对应audio原始的src属性,播放静态提示音时使用。text对应prompt的文本内容,将播放tts合成音。properties则携带prompt的属性,比如上例中的bargein。

    

3.3 Telephony Interface

    VXItelInterface用于处理与电信相关的操作。这些操作包括获取版本信息、实现名称、会话管理、状态查询、断开连接、盲转接、桥转接和咨询转接等。 

    Telephony接口定义如下:  

typedef struct VXItelInterface {
  // 返回当前实现的版本号 
  VXIint32 (*GetVersion)(void);
  
  // 返回实现的名称
  const VXIchar* (*GetImplementationName)(void);

  // 开始会话,看具体实现,可能是无用接口
  VXItelResult (*BeginSession)(struct VXItelInterface *pThis, VXIMap *args);

  // 结束会话,看具体实现,可能是无用接口
  VXItelResult (*EndSession)(struct VXItelInterface *pThis, VXIMap *args);

  // 获取当前线路的状态
  VXItelResult (*GetStatus)(struct VXItelInterface *pThis, VXItelStatus *status);

  // 挂断通话
  VXItelResult (*Disconnect)(struct VXItelInterface *pThis, const VXIMap *namelist);

  // 盲转到指定目标
  VXItelResult (*TransferBlind)(struct VXItelInterface *  pThis,
        const VXIMap *properties,
        const VXIchar *transferDestination,
        VXIMap **resp);

  // 桥接转,这个接口实现依赖平台的具体实现。这个接口只会阻塞到开始发起转接,不会等待被叫应答
  VXItelResult (*TransferBridge)(struct VXItelInterface *pThis,
         const VXIMap *properties,
         const VXIchar* transferDestination,
         VXIMap **resp);

  // 咨询转,接口会阻塞,直到连接完成(被叫应答、被叫未应答、被叫忙活其他方式结束)
  VXItelResult (*TransferConsultation)(struct VXItelInterface *  pThis,
         const VXIMap *properties,
         const VXIchar* transferDestination,
         VXIMap **resp);
} VXItelInterface;

3.4 Object Interface

    VXIobjectInterface接口用于实现VoiceXML对象的功能。通过这个接口,开发者可以定义和执行VoiceXML语言扩展,从而为应用程序提供几乎任何所需的扩展功能。

    该接口的目的是为VoiceXML解释器提供一个统一的机制,一边在多线程/多线路环境中执行自定义的VoiceXML对象。这些对象可以包含复杂的逻辑和功能,并且可以通过标准的接口进行调用和管理。

    接口使用场景:

  1. 开发VoiceXML解释器的集成工具或插件。
  2. 需要扩展VoiceXML标准功能的应用程序。
  3. 需要在VoiceXML中添加自定义对象以处理特定业务逻辑的场景。

    Object接口定义如下:    

typedef struct VXIobjectInterface {
  
  // 获取接口实现的版本号
  VXIint32 (*GetVersion)(void);
  
  // 获取实现的名称
  const VXIchar* (*GetImplementationName)(void);
  
  // 执行对象名称
  VXIobjResult (*Execute)(struct VXIobjectInterface *pThis,
			  const VXIMap              *properties,
			  const VXIMap              *parameters,
			  VXIValue                 **result);

  // 验证对象的正确性
  VXIobjResult (*Validate)(struct VXIobjectInterface *pThis,
			   const VXIMap              *properties,
			   const VXIMap              *parameters);

} VXIobjectInterface;

下面是一个object示例:

<form id="query_weather">
  <object name="weather_result" classid="weather" data="http://172.20.106.102:6003/weather">
      <param name="location" expr="asr_result"/>
  </object>
  <block>
      <if cond="weather_result.data==''">
          <prompt bargein="false">对不起,无法查询您要的信息</prompt>
          <goto next="#server_finished"/>
      <else/>
          <prompt bargein="false"><value expr="weather_result.data"/></prompt>
      </if>
  </block>
</form>

    OpenVXI在执行VoiceXML的object时,会调用到上述Execute接口,可在properties中获取到object的属性(上例中的name、classid、data),parameters中获取到object的参数(如上例中的location)。执行后返回的结果通过result返回。

以上实现以上四个接口,通过接口控制freeswitch放音、启动识别就可以驱动对话流程执行。

### 通义千问 IT 应用与开源项目 #### 通义千问简介 通义千问是一个强大的多模态预训练模型,能够理解并生成高质量的自然语言文本。该技术已经被广泛应用于各种领域,尤其是在智能客服系统中的集成,为企业提供了更加高效的服务解决方案[^4]。 #### 开源项目推荐 对于希望利用通义千问构建自定义应用程序的企业和个人开发者而言,可以考虑以下几个流行的开源框架: - **Rasa**: Rasa 是一个用于创建对话式 AI 的开源工具包,支持多种消息传递平台,并允许用户轻松地将通义千问集成为其核心组件之一。 - **LangChain**: LangChain 提供了一套完整的 API 和 SDK 来简化基于大模型的应用程序开发过程,包括但不限于微调、推理和服务部署等功能模块[^3]. - **Hugging Face Transformers**: Hugging Face 社区维护了一个庞大的预训练模型库,其中也包含了多个版本的通义千问变种。这些资源可以帮助快速启动新项目的原型设计阶段。 #### 实际应用场景展示 当谈到具体的使用案例时,有一个特别值得注意的例子就是将其同 FreeSWITCH 结合起来打造智能化呼叫中心。这种组合方式不仅实现了自动化的语音交互流程管理,而且大大提高了客户满意度和运营效率。此外,在面对复杂业务需求的情况下,还可以借助通义千问的强大语义解析能力来进行更深层次的数据分析工作,从而为决策层提供更多有价值的见解和支持。 ```python from transformers import AutoModelForCausalLM, AutoTokenizer tokenizer = AutoTokenizer.from_pretrained("qwen/Qwen") model = AutoModelForCausalLM.from_pretrained("qwen/Qwen") def generate_response(prompt): inputs = tokenizer(prompt, return_tensors="pt").input_ids outputs = model.generate(inputs) response = tokenizer.decode(outputs[0], skip_special_tokens=True) return response ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值