AIAPI开发文档

简介

本手册提供 XSwitch AIAPI 运行说明,帮助开发者体验 AIAPI 流程,供使用 AIAPI 进行开发的开发者参考。

AIAPI 由mod_ai模块实现。参见: https://git.xswitch.cn/xyt/mod_ai

原理

呼入和呼出流程中最主要的部分都是 XSwitch 通过 mod_ai 向指定的地址发送 POST 请求,HTTP 服务器接收到请求后需要返回相应的 JSON 告诉 XSwitch 下一步怎么处理。其中呼入流程为用户呼叫 XSwitch,通过 mod_ai 向服务器请求服务并处理后续;而呼出流程则为服务器通过 JSON-RPC 调用 XSwitch 向用户发起呼叫,呼叫接通后再向服务器请求服务并处理后续。详细交互流程可参考protocol

快速入门

呼入流程

启动 HTTP 服务

服务器代码及启动命令请参考附件 HTTP 服务代码示例。注:服务器示例代码中调用的 AI 引擎为mod_ali,可根据实际需要更换。

XSwitch 配置

  • 需要加载 TTS/ASR 模块,如mod_ali等 AI 模块

  • XSwitch 界面上新建路由:【呼叫】⇨【路由】⇨【新建】

    • 其他属性如【被叫字冠】等按需要设定,其中【目的地类型】选择【系统】,输入如下内容:

      answer
      ai {url=http://192.168.1.25:9393/asr_test}
      

      注:其中的url是指定的 HTTP 服务器地址,指向下文中示例服务器代码运行的地址

操作流程

用户客户端呼叫指定的【被叫字冠】即可。

预期流程

  1. 用户拨打被叫字冠呼入指定路由,通话接通后 XSwitch 向接收到的路由中url指定的 HTTP 服务器的url/asr_test接口发送请求,HTTP 服务器接收到请求后向 XSwitch 发送动作指令play播放:say:尊敬的客户,您好,请说一句话,XSwitch 接收到动作指令后会调用 TTS 合成并播放给客户端,此时客户端用户听到 尊敬的客户,您好,请说一句话 这句 TTS 合成音;
  2. 之后 XSwitch 调用 ASR 接口等待用户说话,用户说完一句话后,XSwitch 会将 ASR 分析的结果发送到上次动作指令中附带的 url 地址url/asr_result接口,url/asr_result接口根据接收到的 ASR 分析结果拼接文本,并向 XSwitch 发送动作指令播放分析结果,XSwitch 接收到指令后执行完并向客户端播放,此时客户端会听到 TTS 合成音:您说的是+ASR分析结果 或者没有收到分析结果的时候为 对不起,我没听清您说什么
  3. 之后 XSwitch 会发送请求到url/asr_result接口返回的指令里url 中指向的url/hangup接口,服务器接收到请求后向 XSwitch 发送动作指令:hangup,之后通话挂断。

呼出流程

呼出流程也是通过 HTTP 接口实现,此时,HTTP 服务器需要向 XSwitch 发送附带通话信息的请求。呼出的请求分ai.dialai.dial2两种,前者适用于发起单独一路呼叫,呼叫后成功后再转接到服务的场景,后者适用于同时发起两路呼叫并桥接。

启动 HTTP 服务

服务器代码及启动命令请参考附件 HTTP 服务代码示例。

XSwitch 配置

  • 需要加载 TTS/ASR 模块,如mod_ali等 AI 模块
  • 配置需要呼叫的用户,需要外呼网关的需要额外设置

ai.dial

操作流程

这里使用 postman 模拟 HTTP 服务器向 XSwitch(一般端口为 8081,url 为v1)发送 POST 请求调用ai.dial方法:

POST http://192.168.1.25:8081/v1

Content-Type:application/json
X-XTRA-AUTH-ID:309fd439-4e79-4b26-a911-735e6204b187

{
    "jsonrpc": "2.0",
    "method": "ai.dial",
    "id": 1,
    "params":
    {
        "application": "ai",
        "from": "8888",
        "dial_string": "user/1011",
        "url": "http://192.168.1.25:9393/asr_test",
        "private_data":
        {
          "param1": "1",
          "seq": "2"
        }
    }
}
  • 参数说明:

    • jsonrpc:"2.0",请求 JSONRPC 请求 body 的固定格式

    • method:请求的 JSONRPC 方法

    • id:请求序列 id,此处模拟自己指定。实际应用中应由服务器生成

    • application:呼叫成功后 XSwitch 执行的 application

    • from:主叫显示的号码

    • dial_string:呼叫字符串,可以指定呼叫的用户。

      • 说明:如果需要呼叫外线,可在dial_string中包含网关和被叫号码名称,如"dial_string": "gateway/vos/95555"

      • 可以与user_gateway,outbound_gateway替换使用,即三种参数选一种生效,用以适应不同呼叫场景:

        • 指定 user_gateway 呼叫 user: 需要注意的是, 这里 to 和 user_gateway 的内容需要一致,不再需要指定dial_string

          "from": "8888",
          "user_gateway": "1001",
          "to":"1001",
          
        • 指定 outbound_gateway 呼叫外线: outbound_gateway 指定网关名称, to 指定被叫号码,此时同样不再需要指定dial_string

          "from": "8888",
          "to": "95555",
          "outbound_gateway": "vos",
          
    • url:呼叫接通后请求服务的地址

    • private_data:服务器指定的随路数据

预期流程

postman 模拟发送请求后:

  1. XSwitch 接收并分析指令,根据method指定的方法调用ai.dial发起外呼请求,此时请求中dial_string指向的用户分机响铃;
  2. 通话接通后 XSwitch 向接收到的指令中url指定的 HTTP 服务器的url/asr_test接口发送请求,HTTP 服务器接收到请求后向 XSwitch 发送动作指令play播放say:尊敬的客户,您好,请说一句话,XSwitch 接收到动作指令后会调用 TTS 合成并播放给客户端,此时客户端用户听到 尊敬的客户,您好,请说一句话 这句 TTS 合成音;
  3. 之后 XSwitch 调用 ASR 接口等待用户说话,用户说完一句话后,XSwitch 会将 ASR 分析的结果发送到上次动作指令中附带的 url 地址url/asr_result接口,url/asr_result接口根据接收到的 ASR 分析结果拼接文本,并向 XSwitch 发送动作指令播放分析结果,XSwitch 接收到指令后执行完并向客户端播放,此时客户端会听到 TTS 合成音:您说的是+ASR分析结果 或者没有收到分析结果的时候为 对不起,我没听清您说什么
  4. 之后 XSwitch 会发送请求到url/asr_result接口返回的指令里url 中指向的url/hangup接口,服务器接收到请求后向 XSwitch 发送动作指令:hangup,之后通话挂断。

ai.dial2

案例一:呼叫 dial_string(user/1001),成功后再 transfer 到 to (19999)
新建路由

XSwitch 界面上新建路由:【呼叫】⇨【路由】⇨【新建】

  • 【被叫字冠】设置为19999,其中【目的地类型】选择【系统】,输入如下内容:

    answer
    sleep 1000
    playback welcome.wav
    

    注:需要确保 welcome.wav 文件路径存在音频文件

操作流程

这里使用 postman 模拟 HTTP 服务器向 XSwitch(一般端口为 8081,url 为v1)发送 POST 请求调用ai.dial2方法:

POST http://192.168.1.25:8081/v1

Content-Type:application/json
X-XTRA-AUTH-ID:309fd439-4e79-4b26-a911-735e6204b187

{
  "jsonrpc": "2.0",
  "method": "ai.dial2",
  "id": 11,
  "params": {
    "application": "ai",
    "to": "19999 XML context-1",
    "cid_name": "test",
    "cid_number": "8888",
    "from": "8888",
    "dial_string": "user/1011",
    "early_media": true,
    "auto_answer": true,
    "external_tracking_id": "123-456-789",
    "callback_url": "http://192.168.1.25:9393/ai_dial2",
    "callback_method": "POST",
    "private_data": {
      "aaa": "111",
      "bbb": "2222"
    }
  }
}
预期流程

postman 模拟发送请求后,XSwitch 发起调用ai.dial2发起外呼请求,呼叫dial_string指向的分机,此时请求 body 中没有添加b参数,通话接通后 XSwitch 将调用transfer,参数为to中指向的路由,同时会发送 POST 请求到 HTTP 服务器的url/ai_dial2接口。

案例二:呼叫 user/1011, 再 bridge user/1005
{
  "jsonrpc": "2.0",
  "method": "ai.dial2",
  "id": 100,
  "params": {
    "application": "ai",
    "from": "8888",
    "to": "9999",
    "cid_name": "test",
    "cid_number": "8888",
    "dial_string": "user/1011",
    "early_media": true,
    "auto_answer": true,
    "external_tracking_id": "123-456-789",
    "callback_url": "http://192.168.1.25:9393/ai_dial2",
    "callback_method": "POST",
    "b": {
      "dial_string": "user/1005",
      "cid_name": "FreeSWITCH",
      "cid_number": "9999",
      "auto_answer": "true"
    },
    "private_data": {
      "aaa": "111",
      "bbb": "2222"
    }
  }
}
预期流程

postman 模拟发送请求后,XSwitch 发起调用ai.dial2发起外呼请求,首先呼叫dial_string指向的分机,通话接通后会呼叫b参数指向的分机,同时会发送 POST 请求到 HTTP 服务器的url/ai_dial2接口。

附件:服务器代码示例

代码示例

示例服务器代码语言使用Ruby,使用Sinatra框架。 安装好环境,下载好框架后,可使用shotgun server.rb -o IP -p PORT运行服务器示例代码。

  1 require 'sinatra'
  2 require 'json'
  3
  4 BASEURL="http://IP:PORT"
  5
  6 before do
  7   if (request.content_type && request.content_type.include?("application/json") && (request.content_length.to_i > 1))
  8     request.body.rewind
  9     @params = JSON.parse(request.body.read.to_s)
 10   end
 11 end
 12
 13 get '/' do
 14   'Hello AI'
 15 end
 16
 17 post '/asr_test' do
 18         content_type 'application/json'
 19
 20         puts "---------- request  -------------"
 21         puts params.to_s
 22
 23         obj = {
 24                 :action => "play",
 25                 :file => "say:尊敬的客户,您好,请说一句话",
 26                 :loops => 1,
 27                 :breakable => false,
 28                 :asr_engine => "ali",
 29                 :asr_grammar => "{accent=mandarin, barge-in=true, start-input-timers=true,no-input-timeout=4000,speech-timeout=2500}default",
 30                 :asr => true,
 31                 :next => "#{BASEURL}/asr_result",
 32                 :variables => {
 33                         :tts_engine => "ali",
 34                         :tts_voice => "default"
 35                 },
 36                 :private_data => {
 37                         :data1 => "a",
 38                         :data2 => 2
 39                 }
 40         }
 41
 42         puts "========== response ============="
 43         puts obj.to_json
 44         puts
 45
 46         obj.to_json
 47 end
 48
 49 post '/asr_result' do
 50         content_type 'application/json'
 51         text = nil
 52
 53         puts "---------- request  -------------"
 54         puts params.to_s
 55
 56         if params["asr_result"] && params["asr_result"]["text"]
 57                 text = params["asr_result"]["text"];
 58         end
 59
 60         if text == nil || text == ""
 61                 text = "对不起,我没听清您说什么"
 62         else
 63                 text = "您说的是:" + text
 64         end
 65
 66         obj = {
 67                 :action => "play",
 68                 :file => "say:" + text,
 69                 :loops => 1,
 70                 :next => "#{BASEURL}/hangup",
 71                 :variables => {
 72                         :tts_engine => "ali",
 73                         :tts_voice => "default"
 74                 },
 75                 :private_data => {
 76                         :data1 => "a",
 77                         :data2 => 2
 78                 }
 79         }
 80
 81         puts "========== response ============="
 82         puts obj.to_json
 83
 84         obj.to_json
 85 end
 86
 87 post '/hangup' do
 88         content_type 'application/json'
 89
 90         puts "---------- request  -------------"
 91         puts params.to_s
 92
 93         obj = {:action => "hangup"}
 94
 95         puts "========== response ============="
 96         puts obj.to_json
 97
 98         obj.to_json
 99 end
100
101 post '/ai_dial2' do
102         content_type 'application/json'
103
104 json = <<EOF
105 {
106         "resp": "ok"
107 }
108 EOF
109         puts json
110         json
111 end

接口示例详解

这里以asr_test接口为例详细讲解。下面接口讲解中用Ln表示第n行。更详细的说明请参考 aiapi 文档。

当前示例中,asr_test接口的功能为使用 TTS 播放提示音,等待用户说完一句话后,调用 ASR 处理用户说的话,并将 ASR 的结果发送到next中 url 指向的接口。

 17 post '/asr_test' do
 18         content_type 'application/json'
 19
 20         puts "---------- request  -------------"
 21         puts params.to_s
 22
 23         obj = {
 24                 :action => "play",
 25                 :file => "say:尊敬的客户,您好,请说一句话",
 26                 :loops => 1,
 27                 :breakable => false,
 28                 :asr_engine => "ali",
 29                 :asr_grammar => "{accent=mandarin, barge-in=true, start-input-timers=true,no-input-timeout=4000,speech-timeout=2500}default",
 30                 :asr => true,
 31                 :next => "#{BASEURL}/asr_result",
 32                 :variables => {
 33                         :tts_engine => "ali",
 34                         :tts_voice => "default"
 35                 },
 36                 :private_data => {
 37                         :data1 => "a",
 38                         :data2 => 2
 39                 }
 40         }
 41
 42         puts "========== response ============="
 43         puts obj.to_json
 44         puts
 45
 46         obj.to_json
 47 end
  • L18:指定返回的消息里 Header 的Content-Type属性为application/json

  • L20~L21:打印请求参数,即 XSwitch 发送到 HTTP 服务器的 POST 请求中附带的参数

  • L23~L40:构造返回给 XSwitch 的 JSON 数据obj

    • 组成 JSON 的数据里面一般需要包括:
      • action:里面包含接下来 XSwitch 需要执行的动作
      • next:下一次请求的接口地址
      • variables:需要在 XSwitch 中设置的通道变量
      • private_data:用户的私有数据
    • 这个过程使用的action为"play",为了完成接口功能需要增加的其他参数说明:
      • file:需要播放的语音文件,此处为调用 TTS 播放提示音
      • loops:指定播放文件的循环次数
      • breakable:指定 ASR 识别是否连续
      • asr_engine:指定 ASR 引擎
      • asr_grammar:指定 ASR 语法
      • asr:是否启用 ASR 识别
  • L42~L44:打印 response 消息

综述