新一代电话机器人开源PHP源代码

农民  金牌会员 | 2024-9-10 22:41:45 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 877|帖子 877|积分 2631

利用easyswoole 框架开发的 新一代电话机器人开源PHP源码
项目地址:https://gitee.com/ddrjcode/robotphp



  • 代理商页面演示地址
http://119.23.229.15:8080
用户名:c0508
密码:123456
包含 AI外呼管理,话术管理,CRM管理,坐席管理等功能。


  • 管理员背景演示地址
http://119.23.229.15
用户名:admin
密码:123456
包含  线路管理,代理商管理等功能

AI外呼管理截图


话术管理截图

坐席页面
管理员页面
线路管理


机器人话术代码:

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: WIN10
  5. * Date: 2021/12/18
  6. * Time: 16:04
  7. */
  8. namespace App\Traits;
  9. use App\Model\Speech\SpeechLabelSynonym;
  10. use App\Model\Speech\SpeechNodeModel;
  11. use App\Model\Speech\SpeechProcessModel;
  12. use App\Model\Speech\SpeechProcessNodeSettingModel;
  13. use App\Model\SpeechMul\SpeechMulLabelSynonym;
  14. use App\Model\SpeechMul\SpeechMulProcessSettingModel;
  15. trait SpeechExamineTrait{
  16.     //主流程匹配关键词结果数组
  17.     public function getResultSynonym($speechId)
  18.     {
  19.         $resultSynonym      = [];
  20.         $synonymList        = SpeechLabelSynonym::create()->getAll(["speech_id"=>$speechId]);
  21.         foreach ($synonymList as $val){
  22.             if(isset($val["sls_name"])) {
  23.                 $resultSynonym[$val["node_id"]][$val["sls_keyword"]][] = $val["sls_name"];
  24.             }
  25.         }
  26.         return $resultSynonym;
  27.     }
  28.     //获取主流程的$nodesInfo信息 节点信息
  29.     //$processQueuesReal      = []; //真实存在的主流程节点(只有节点才存在到这个主流程)
  30.     public function getNodesInfoList($where)
  31.     {
  32.         $nodesInfo              = [];//所有节点信息map=>(k,v)
  33.         $processNodes           = [];
  34.         $processQueuesReal      = []; //真实存在的主流程节点(只有节点才存在到这个主流程)
  35.         //所有节点的信息
  36.         $nodesInfoList          = SpeechNodeModel::create()->getAll($where);
  37.         foreach ($nodesInfoList as $kk=>$vv)
  38.         {
  39.             $nodesInfo[$vv["node_id"]] = $vv;
  40.             if(!isset($processNodes[$vv["process_id"]])){//真实存在
  41.                 array_push($processQueuesReal,$vv["process_id"]);
  42.             }else{
  43.                 $processNodes[$vv["process_id"]]         = [];
  44.             }
  45.         }
  46.         return [$nodesInfo,$processQueuesReal];
  47.     }
  48.     //$processNodesArr 所有节点的数组
  49.     //$processQueues  所有的流程按照顺序
  50.     public function getProcessQueues($where)
  51.     {
  52.         $processNodesArr        = [];
  53.         $processQueues          = [];//所有的流程按照顺序
  54.         $processArray           = SpeechProcessModel::create()->getAll($where,'process_id',["sort,process_id","ASC"]);
  55.         foreach ($processArray as $a=>$item){
  56.             array_push($processQueues,$item["process_id"]);
  57.             $processNodesArr[$item["process_id"]] = [];
  58.         }
  59.         return [$processNodesArr,$processQueues];
  60.     }
  61.     //所有的参数节点流程
  62.     public function getArgArray($where)
  63.     {
  64.         $argList  = SpeechProcessNodeSettingModel::create()->getAll($where,"set_key,set_value,node_id");//所有的参数节点流程
  65.         $argArray = [];
  66.         foreach ($argList as $argK=>$argValue){
  67.             $argArray[$argValue["node_id"]][$argValue["set_key"]] = $argValue["set_value"];
  68.         }
  69.         return $argArray;
  70.     }
  71.     //获取所有树的第一个节点集
  72.     // $nodes = SpeechNodeTreeModel::create()->getAll($where,'process_id,node_id,parent_id,nodes_id',["node_id","ASC"]);
  73.     public function getTreeFirstNode($nodes)
  74.     {
  75.         $treeFirstNode      = [];
  76.         foreach ($nodes as $key=>$value)
  77.         {
  78.             if($value["parent_id"]==0){
  79.                 $treeFirstNode[$value["process_id"]] = $value;
  80.             }
  81.         }
  82.         return $treeFirstNode;
  83.     }
  84.     public function getMulTreeFirstNode($nodes)
  85.     {
  86.         $treeFirstNode      = [];
  87.         foreach ($nodes as $key=>$value)
  88.         {
  89.             if($value["parent_id"]==0){
  90.                 $treeFirstNode[$value["process_mul_id"]] = $value;
  91.             }
  92.         }
  93.         return $treeFirstNode;
  94.     }
  95.     //获取流程的节点的集
  96.     //$processNodesNode 子集
  97.     // $nodes = SpeechNodeTreeModel::create()->getAll($where,'process_id,node_id,parent_id,nodes_id',["node_id","ASC"]);
  98.     //$resultSynonym  主流程匹配关键词结果数组集
  99.     //$childParent 父子节点数组        $childParent            = SpeechSmallNodeRelationModel::create()->getColumn($where,"node_id","small_node_id");
  100.     //$processReal  真实按照顺序的主流程
  101.     //$processRealFlip  主流程反转主流程
  102.     //$treeFirstNode   获取所有树的第一个节点集
  103.     //$nodeSynonymList  匹配的关键词
  104.     //$targetLabel
  105.     //$nodesInfo
  106.     public function getProcessNodesNode($nodes,$processNodesArr,$nodesInfo,$resultSynonym,$childParent,$processReal,$targetLabel,$processRealFlip,$treeFirstNode,$nodeSynonymList)
  107.     {
  108.         //判断是否有相同的节点
  109.         $sameNodeList       = [];
  110.         $processNodesNode   = [];
  111.         //用一个权重数组去获取最终值吧(始终取最大的)
  112.         $priorityArray      = [];
  113.         foreach ($nodes as $key=>$value)
  114.         {
  115.             $valueProcessId                                 = $value["process_id"];
  116.             $processNodesArr[$valueProcessId][]             = $value;
  117.             $subFlowModel   = [];
  118.             $valueNodesId   = $value["nodes_id"];
  119.             $valueParentId  = $value["parent_id"];
  120.             $valueNodeId    = $value["node_id"];
  121.             $priority       = "0"; //分支权重
  122.             if($valueNodesId) {
  123.                 $word = $targetLabel[$valueNodesId]??"";
  124.                 if ($word) {
  125.                     $synonymCode    =  "W." . $word;
  126.                     $yesSynonym     = [];
  127.                     $isMore         = 0;
  128.                     $arrSubFlow     = [];
  129.                     $synonymArray   = [];
  130.                     switch ($word){
  131.                         case "肯定":
  132.                             if(isset($resultSynonym[$childParent[$valueNodesId]]["yes"])) {
  133.                                 $yesSynonym = array_values($resultSynonym[$childParent[$valueNodesId]]["yes"]);
  134.                             }
  135.                             $priority = "5";
  136.                             break;
  137.                         case "否定":
  138.                             if(isset($resultSynonym[$childParent[$valueNodesId]]["no"])) {
  139.                                 $yesSynonym = array_values($resultSynonym[$childParent[$valueNodesId]]["no"]);
  140.                             }
  141.                             $priority = "10";
  142.                             break;
  143.                         case "拒绝":
  144.                             if(isset($resultSynonym[$childParent[$valueNodesId]]["reject"])) {
  145.                                 $yesSynonym = array_values($resultSynonym[$childParent[$valueNodesId]]["reject"]);
  146.                             }
  147.                             $priority = "12";
  148.                             break;
  149.                         case "默认":
  150.                             $priority = "2";
  151.                             $isMore = 1;
  152.                             break;
  153.                     }
  154.                     if($isMore==0) {//不是默认
  155.                         $synonymSystem = $yesSynonym ?: [$synonymCode];
  156.                         foreach ($synonymSystem as $item){
  157.                             $synonymArray[$item] = $word;
  158.                         }
  159.                         $arrSubFlow = [
  160.                             "condition" => [
  161.                                 "text" => $synonymSystem
  162.                             ],
  163.                             "priority" => $priority,
  164.                             "description" => $word
  165.                         ];
  166.                     }elseif($isMore==1){//是默认
  167.                         $arrSubFlow = [
  168.                             "condition" => [
  169.                                 "text" => ["any"]
  170.                             ],
  171.                             "priority" => $priority,
  172.                             "description" => $word
  173.                         ];
  174.                     }
  175.                     if(!isset($priorityArray[$valueNodeId])) {
  176.                         $priorityArray[$valueNodeId] = $priority;
  177.                     }else{
  178.                         if($priorityArray[$valueNodeId]<$priority){
  179.                             $priorityArray[$valueNodeId] =  $priority;
  180.                         }
  181.                     }
  182.                     if($nodesInfo[$valueNodeId]["info_talk_info"]) { //有信息的
  183.                         if(!isset($sameNodeList[$valueProcessId][$valueParentId][$valueNodeId])) {//是否存在当前流程,当前父id的,节点id
  184.                             //判断是否当前节点参数是否为空
  185.                             $subFlowModel["F" . $valueNodeId]   = $arrSubFlow;
  186.                             if($isMore==0) {//不是默认
  187.                                 $nodeSynonymList[$valueNodeId] = $synonymArray;
  188.                             }
  189.                             $sameNodeList[$valueProcessId][$valueParentId][$valueNodeId] = $key+1;
  190.                         }else{
  191.                             if(!isset($processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"])) {
  192.                                 $processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"] = [];
  193.                             }
  194.                             if($isMore==0) {//非默认
  195.                                 //有text关键词的操作
  196.                                 if ($yesSynonym) {
  197.                                     $processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"]  = array_merge($processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"] ,$yesSynonym);
  198.                                 }
  199.                                 //没有关键词的操作
  200.                                 if (!$yesSynonym) {
  201.                                     array_push($processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"], "W." . $word);
  202.                                 }
  203.                                 $nodeSynonymList[$valueNodeId] = array_merge($nodeSynonymList[$valueNodeId],$synonymArray);
  204.                             }
  205.                             if($isMore==1) {//默认
  206. //                                $processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"]= ["any"];
  207.                                 array_push($processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"], "any");
  208.                             }
  209.                             if(!isset($processNodesNode[$valueProcessId][$valueParentId]["F" . $valueNodeId]["description"])) {
  210.                                 $processNodesNode[$valueProcessId][$valueParentId]["F" . $valueNodeId]["description"] =  $word;
  211.                             }else{
  212.                                 $processNodesNode[$valueProcessId][$valueParentId]["F" . $valueNodeId]["description"] .= "," . $word;
  213.                             }
  214.                             $processNodesNode[$valueProcessId][$valueParentId]["F" . $valueNodeId]["priority"] = $priorityArray[$valueNodeId];
  215.                         }
  216.                     }
  217.                     elseif(!$nodesInfo[$valueNodeId]["info_talk_info"] && $nodesInfo[$valueNodeId]["type_id"]==2){
  218.                         $next           = $nodesInfo[$value["node_id"]]["next"];  //跳转的条件
  219.                         $nextId         = $nodesInfo[$value["node_id"]]["next_id"];//流程id
  220.                         $process_id     = $nodesInfo[$value["node_id"]]["process_id"]; //该流程id
  221.                         [$resReturnData,$returnKey,$resReturn] = $this->checkNextFlow($next,$nextId,$process_id,$processReal,$processRealFlip,$treeFirstNode,$arrSubFlow);//没有信息的就是跳转信息
  222.                         if(!isset($sameNodeList[$valueProcessId][$valueParentId][$returnKey])) {
  223.                             //判断是否当前节点参数是否为空
  224. //                            $subFlowModel["F".$returnKey]                               = $resReturn;
  225.                             if($resReturn){
  226.                                 if(!isset($subFlowModel["F" . $returnKey]["condition"]["text"])) {
  227.                                     $subFlowModel["F" . $returnKey]["condition"]["text"] = [];
  228.                                 }
  229.                                 if($isMore==0) {//非默认
  230.                                     if ($yesSynonym) {
  231.                                         $subFlowModel["F" . $returnKey]["condition"]["text"] = array_merge($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"],$yesSynonym);
  232.                                     }
  233.                                     if (!$yesSynonym ) {
  234.                                         array_push($subFlowModel ["F" . $returnKey]["condition"]["text"], "W." . $word);
  235.                                     }
  236.                                 }
  237.                                 if($isMore==1) {//默认
  238. //                                    $subFlowModel ["F" . $returnKey]["condition"]["text"]= ["any"];
  239.                                     array_push($subFlowModel ["F" . $returnKey]["condition"]["text"], "any");
  240.                                 }
  241.                                 $subFlowModel["F" . $returnKey]["priority"] = $priorityArray[$valueNodeId];
  242.                             }
  243.                             $nodeSynonymList[$returnKey]                                = $synonymArray;
  244.                             $sameNodeList[$valueProcessId][$valueParentId][$returnKey]  = $key+1;
  245.                         }else{
  246.                             if(!isset($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"])) {
  247.                                 $processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"] = [];
  248.                             }
  249.                             if($isMore==0) {//非默认
  250.                                 if ($yesSynonym) {
  251.                                     $processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"] = array_merge($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"],$yesSynonym);
  252.                                     $nodeSynonymList[$returnKey]      = array_merge($nodeSynonymList[$returnKey],$synonymArray);
  253.                                 }
  254.                                 if (!$yesSynonym ) {
  255.                                     array_push($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"], "W." . $word);
  256.                                     $nodeSynonymList[$returnKey] = array_merge($nodeSynonymList[$returnKey],$synonymArray);
  257.                                 }
  258.                             }
  259.                             if($isMore==1) {//默认
  260. //                                $processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"]= ["any"];
  261.                                 array_push($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"], "any");
  262.                             }
  263.                             if(isset($processNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["description"])) {
  264.                                 $processNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["description"] =  $word;
  265.                             }else{
  266.                                 $processNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["description"] .= "," . $word;
  267.                             }
  268.                             $processNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["priority"] = $priorityArray[$valueNodeId];
  269.                         }
  270.                     }
  271.                 }
  272.             }
  273.             //是否存在当前的流程的process的id的,父id
  274.             //不存在就是直接把subFlow赋值给他
  275.             if (!isset($processNodesNode[$valueProcessId][$valueParentId])) {
  276.                 $processNodesNode[$valueProcessId][$valueParentId] = $subFlowModel;
  277.             } else {
  278.                 //存在就是数组连接一起
  279.                 $processNodesNode[$valueProcessId][$valueParentId] = array_merge($processNodesNode[$valueProcessId][$valueParentId],$subFlowModel);
  280.             }
  281.         }
  282.         return [$processNodesArr,$processNodesNode,$nodeSynonymList];
  283.     }
  284.     //获取flow流程
  285.     //获取 $nodeSynonymList  匹配的关键词
  286.     //$firstNode
  287.     //第一个主流程节点
  288.     //$version 版本
  289.     //$processReal  真实按照顺序的主流程
  290.     //$processRealFlip  主流程反转主流程
  291.     //$treeFirstNode   获取所有树的第一个节点集
  292.     //$nodeSynonymList  匹配的关键词
  293.     //$targetLabel
  294.     //$nodesInfo
  295.     //$processNodesNode 子集
  296.     public function getFlowList($flow,$processNodesArr,$nodeSynonymList,$version,$nodesInfo,$processNodesNode,$processReal,$processRealFlip,$treeFirstNode,$argArray,$allNodeWavKey,$allSettingsKey,$priority){
  297.         $count                  = 0;
  298.         $firstNode              = "";//第一个节点
  299.         foreach ($processNodesArr as $ke=>$ve){
  300.             foreach ($ve as $kkk=>$vvv){
  301.                 $vvvNodeId = $vvv["node_id"];
  302.                 if($count==0){
  303.                     $flow["Start"] = [
  304.                         'action'=>'start',
  305.                         'position'=>[
  306.                             "x"=>2489,
  307.                             "y"=>72
  308.                         ],
  309.                         "subflow"=>['F'.$vvvNodeId."_".$version=>new \stdClass()]
  310.                     ];
  311.                 }
  312.                 $count++;
  313.                 $arg = [];
  314.                 $arg["action"]          = "cti_play_and_detect_speech";
  315.                 if($count==1){
  316.                     $firstNode = $vvvNodeId."_".$version;
  317.                 }
  318.                 //模式
  319.                 $argM       = $argArray[$vvvNodeId]["moshi"]??"1";
  320.                 if(isset($allSettingsKey[$vvvNodeId]['interrupt']) && $allSettingsKey[$vvvNodeId]['interrupt']) {
  321.                     $argM = "2";
  322.                 }
  323.                 $argLuZao   = $argArray[$vvvNodeId]["luzao"]??"";
  324.                 $argKaiShi  = $argArray[$vvvNodeId]["kaishi"]??"";
  325.                 $argTingZhi = $argArray[$vvvNodeId]["tingzhi"]??"";
  326.                 $argDengDai = $argArray[$vvvNodeId]["dengdai"]??"";
  327.                 $argZuiDa   = $argArray[$vvvNodeId]["zuida"]??"";
  328.                 $argCanShu  = $argArray[$vvvNodeId]["canshu"]??"";
  329.                 $argLuYin   = $argArray[$vvvNodeId]["luyin"]??"";
  330.                 //挂机不需要这些参数
  331.                 if($nodesInfo[$vvvNodeId]['next']!=1) {
  332.                     $arg["filter"] = [
  333.                         "text" => "S",
  334.                         "dtmf" => "none"
  335.                     ];
  336.                     if ($priority == 1) {
  337.                         $arg["kb_priority"] = 0;
  338.                     } elseif ($priority == 2) {
  339.                         $arg["kb_priority"] = 1;
  340.                     }
  341.                     $arg["timeoutplaybacks"] = [];
  342.                     $arg["timeoutrepetition"] = "";
  343.                     $arg["mismatchplaybacks"] = [];
  344.                     $arg["mismatchrepetition"] = "1";
  345.                     $arg["globalflow"] = [
  346.                         "all"
  347.                     ];
  348.                 }else{//挂机节点不起用asr
  349.                     $argM = 0;
  350.                 }
  351.                 $arg["argument"]        = "'$argM' '16' '' '$argLuZao' '' '$argKaiShi' '$argTingZhi' '$argDengDai' '$argZuiDa' '' '$argCanShu' '$argLuYin' '' ''";
  352.                 $arg["position"]        = [
  353.                     "x"=>$nodesInfo[$vvvNodeId]["node_x"],
  354.                     "y"=>$nodesInfo[$vvvNodeId]["node_y"]
  355.                 ];
  356.                 $arg["description"]     = $nodesInfo[$vvvNodeId]["info_title"];
  357.                 if(isset($allNodeWavKey[$vvvNodeId]) && $allNodeWavKey[$vvvNodeId]) {
  358.                     $arg["playbacks"] = [$allNodeWavKey[$vvvNodeId]];
  359.                 }else{
  360.                     $arg["playbacks"] = [$nodesInfo[$vvvNodeId]["info_talk_info"]];
  361.                 }
  362.                 $arg["kb"]          = 'C1';
  363.                 if(isset($processNodesNode[$vvv["process_id"]][$vvvNodeId])) {
  364.                     $arg["subflow"] = $processNodesNode[$vvv["process_id"]][$vvvNodeId];
  365.                 }else{
  366.                     $next           = $nodesInfo[$vvvNodeId]["next"];  //跳转的条件
  367.                     $nextId         = $nodesInfo[$vvvNodeId]["next_id"];//流程id
  368.                     $processId      = $nodesInfo[$vvvNodeId]["process_id"]; //该流程id
  369.                     [$arg["subflow"],$returnKey,$resReturn] = $this->checkNextFlow($next,$nextId,$processId,$processReal,$processRealFlip,$treeFirstNode);
  370.                 }
  371.                 if($nodesInfo[$vvvNodeId]["info_talk_info"]) {//如果是跳转节点,没有输入声音就是不输入
  372.                     if($count==1){
  373.                         $vvvNodeId .= "_".$version;
  374.                     }
  375.                     $flow["F" . $vvvNodeId] = $arg;
  376.                 }
  377.             }
  378.         }
  379.         return [$flow,$nodeSynonymList,$firstNode];
  380.     }
  381.     //生成一个挂机节点
  382.     public function addEndPoints($flow)
  383.     {
  384.         /**
  385.          * 生成一个挂机节点
  386.          */
  387.         $endPointsArray = [
  388.             'action'=>'hangup',
  389.             'position'=>[
  390.                 "x"=>67,
  391.                 "y"=>33
  392.             ]
  393.         ];
  394.         $flow["F9999999999999999999"]=$endPointsArray;
  395.         return $flow;
  396.     }
  397.     //生成一个等待用户回答节点
  398.     public function addWaitPoints($flow)
  399.     {
  400.         /**
  401.          * 生成一个挂机节点
  402.          */
  403.         $endWaitArray = [
  404.             'action'=>"cti_play_and_detect_speech",
  405.             "argument"=>"'1' '16' '' '' '' '' '' '' '' '' '' '' '' ''",
  406.             "position"=>[
  407.                 "x"=>391833,
  408.                 "y"=>2372
  409.             ],
  410.             "playbacks"=>[],
  411.             "description"=>"",
  412.             "sourceflowdepth"=>"1",
  413.             "globalflow"=>[
  414.                 "all"
  415.             ],
  416.             "kb"         => 'C1',
  417.             "kb_priority"=>2,
  418.             "condition"=> [
  419.             "complete"=> [],
  420.                 "text"=> []
  421.             ],
  422.             "timeoutrepetition"=>"",
  423.             "mismatchplaybacks"=> [],
  424.             "subflow"=>[]
  425.         ];
  426.         $flow["F88888888888888888888"]=$endWaitArray;
  427. //        $flow["F66666666666666666666"]=[
  428. //            "action"=> "return",
  429. //            "position"=> [
  430. //                "x"=> 2263,
  431. //                "y"=> 492
  432. //            ]
  433. //        ];
  434.         return $flow;
  435.     }
  436.     //生成一个挂机播放节点
  437.     public function addHangUpPlayContent($flow,$nodeId,$playbacks)
  438.     {
  439.         $hangUpArray = [
  440.             'action'=>"cti_play_and_detect_speech",
  441.             "argument"=>"'0' '16' '' '' '' '' '' '' '' '' '' '' '' ''",
  442.             "position"=>[
  443.                 "x"=>391833,
  444.                 "y"=>2372
  445.             ],
  446.             "playbacks"=>$playbacks,
  447.             "description"=>"",
  448.             "sourceflowdepth"=>"1",
  449.             "condition"=> [
  450.                 "text"=> []
  451.             ],
  452.             "mismatchplaybacks"=> [],
  453.             "subflow"=>[
  454.                 "F9999999999999999999"=> [
  455.                     "condition"=>[
  456.                         "complete"=> [
  457.                             "any"
  458.                         ],
  459.                     ],
  460.                 ]
  461.             ]
  462.         ];
  463.         $flow["F".$nodeId] = $hangUpArray;
  464.         return $flow;
  465.     }
  466.     //生成一个挂机播放节点
  467.     public function addHangUpPlay($flow)
  468.     {
  469.         $hangUpArray = [
  470.             'action'=>"cti_play_and_detect_speech",
  471.             "argument"=>"'0' '16' '' '' '' '' '' '' '' '' '' '' '' ''",
  472.             "position"=>[
  473.                 "x"=>391833,
  474.                 "y"=>2372
  475.             ],
  476.             "playbacks"=>[],
  477.             "description"=>"",
  478.             "sourceflowdepth"=>"1",
  479.             "condition"=> [
  480.                 "text"=> []
  481.             ],
  482.             "mismatchplaybacks"=> [],
  483.             "subflow"=>[
  484.                 "F9999999999999999999"=> [
  485.                 "condition"=>[
  486.                     "text"=> [
  487.                         "any"
  488.                         ],
  489.                     ],
  490.                 ]
  491.             ]
  492.         ];
  493.         $flow["F5555555555555555555555"] = $hangUpArray;
  494.         return $flow;
  495.     }
  496.     public function addWaitSubPoints(){
  497.         return [
  498.             "F9999999999999999999"=> [
  499.                 "condition"=>[
  500.                     "complete"=> [
  501.                         "timeout()"
  502.                     ]
  503.                 ],
  504.                 "description"=> "静音挂断"
  505.             ],
  506.             "F66666666666666666666"=>[
  507.                 "condition"=> [
  508.                     "complete"=> [],
  509.                     "text"=> [
  510.                         "F.+"
  511.                     ]
  512.                 ],
  513.                 "description"=> "有声音返回"
  514.             ]
  515.         ];
  516.     }
  517.     //生成一个挂机节点
  518.     public function addHangUpPoints()
  519.     {
  520.         $endPointsArray["F9999999999999999999"] = [
  521.             'condition'=>[
  522.                     'complete'=> [
  523.                         "any"
  524.                     ]
  525.             ],
  526.         ];
  527.         return $endPointsArray;
  528.     }
  529.     //跳转到指定主流程
  530.     public function toMainFlow($flowId)
  531.     {
  532.         $arg["F".$flowId]= [
  533.             "condition"=>[
  534.                 "complete"=> [],
  535.                     "text"=>[
  536.                     "any"
  537.                 ],
  538.                    "description"=>""
  539.                 ]
  540.         ];
  541.         return $arg;
  542.     }
  543.     //跳转到指定多伦会话
  544.     public function toMulFlow($flowId)
  545.     {
  546.         $arg["F".$flowId."_".$flowId]= [
  547.             "condition"=>[
  548.                 "complete"=> [],
  549.                 "text"=>[
  550.                     "any"
  551.                 ],
  552.                 "description"=>""
  553.             ]
  554.         ];
  555.         return $arg;
  556.     }
  557.     //判断主流程下个流程的节点
  558.     public function  checkNextFlow($next,$nextId,$process_id,$processReal,$processRealFlip,$treeFirstNode,$arrSubFlow=[])
  559.     {
  560.         $array          = [];
  561.         $keyNext        = $processRealFlip[$process_id]+1;//下一个next
  562.         $hangUp         = $arrSubFlow?:["description"=>"无效回答", "condition"=>["text"=>["any"]]];
  563.         $nextProcess    = $arrSubFlow?: ["condition" => ["text" => ["any"]], "description" => "跳转下一个流程"];
  564.         $keyReturn      = "";
  565.         $resReturn      = "";
  566.         switch ($next)
  567.         {
  568.             case 0:
  569.             case 2:
  570.                 if(isset($processReal[$keyNext])){
  571.                     $array["F" . $treeFirstNode[$processReal[$keyNext]]["node_id"]] = $nextProcess;
  572.                     $keyReturn   = $treeFirstNode[$processReal[$keyNext]]["node_id"];
  573.                     $resReturn   = $nextProcess;
  574.                 }else{
  575.                     $array["F9999999999999999999"] = $hangUp;
  576.                     $keyReturn  = "9999999999999999999";
  577.                     $resReturn   = $hangUp;
  578.                 }
  579.                 break;
  580.             case 1:
  581.                 $array["F9999999999999999999"] = $hangUp;
  582.                 $keyReturn  = "9999999999999999999";
  583.                 $resReturn   = $hangUp;
  584.                 break;
  585.             case 3:
  586.                 if(isset($treeFirstNode[$nextId])) {
  587.                     $fistNode = $treeFirstNode[$nextId];
  588.                     $array["F" . $fistNode["node_id"]] = $nextProcess;
  589.                     $keyReturn   = $fistNode["node_id"];
  590.                     $resReturn   = $nextProcess;
  591.                 }else{
  592.                     $array["F9999999999999999999"] = $hangUp;
  593.                     $keyReturn       = "9999999999999999999";
  594.                     $resReturn       = $hangUp;
  595.                 }
  596.                 break;
  597.             case 4://返回接口
  598.                 $keyReturn  = substr(microtime(true),2,8).rand(0,99);
  599.                 $resReturn= [
  600.                     'action'  =>'return',
  601.                     'position'=>[
  602.                         'x'=>4085,
  603.                         'y'=>377
  604.                     ],
  605.                 ];
  606.                 $array["F".$keyReturn] = $resReturn;
  607.                 break;
  608.             }
  609.         return [$array,$keyReturn,$resReturn];
  610.     }
  611.     //多伦会话匹配关键词结果数组
  612.     public function getMulResultSynonym($speechId)
  613.     {
  614.         $resultSynonym      = [];
  615.         $synonymList        = SpeechMulLabelSynonym::create()->getAll(["speech_id"=>$speechId]);
  616.         foreach ($synonymList as $val){
  617.             if(isset($val["sls_name"])) {
  618.                 $resultSynonym[$val["node_mul_id"]][$val["sls_keyword"]][] = $val["sls_name"];
  619.             }
  620.         }
  621.         return $resultSynonym;
  622.     }
  623.     //获取所有子节点
  624.     public function getMulProcessNodesNode($flow,$nodesMul,$resultMulSynonym,$childMulParent,$nodesMulInfo,$targetMulLabel,$nodeSynonymList,$treeFirstNode)
  625.     {
  626.         //判断是否有相同的节点
  627.         $sameNodeList           = [];
  628.         $processMulNodesNode    = [];
  629.         $processMulNodesArr     = [];//所有全局话术的根节点
  630.         //用一个权重数组去获取最终值吧(始终取最大的)
  631.         $priorityArray      = [];
  632.         foreach ($nodesMul as $key=>$value)
  633.         {
  634.             $valueProcessId                     = $value["process_mul_id"];
  635.             $processMulNodesArr[$valueProcessId][]          = $value;
  636.             $subFlowModel   = [];
  637.             $valueNodesId   = $value["nodes_id"];
  638.             $valueParentId  = $value["parent_id"];
  639.             $valueNodeId    = "F".$value["node_mul_id"]."_".$value["node_mul_id"];
  640.             $priority       = "0";
  641.             if($valueNodesId) {
  642.                 $word = $targetMulLabel[$valueNodesId]??"";
  643.                 if ($word) {
  644.                     $synonymCode    =  "W." . $word;
  645.                     $yesSynonym     = [];
  646.                     $isMore         = 0;
  647.                     $arrSubFlow     = [];
  648.                     $synonymArray   = [];
  649.                     switch ($word){
  650.                         case "肯定":
  651.                             if(isset($resultMulSynonym[$childMulParent[$valueNodesId]]["yes"])) {
  652.                                 $yesSynonym = array_values($resultMulSynonym[$childMulParent[$valueNodesId]]["yes"]);
  653.                             }
  654.                             $priority = "5";
  655.                             break;
  656.                         case "否定":
  657.                             if(isset($resultMulSynonym[$childMulParent[$valueNodesId]]["no"])) {
  658.                                 $yesSynonym = array_values($resultMulSynonym[$childMulParent[$valueNodesId]]["no"]);
  659.                             }
  660.                             $priority = "10";
  661.                             break;
  662.                         case "拒绝":
  663.                             if(isset($resultMulSynonym[$childMulParent[$valueNodesId]]["reject"])) {
  664.                                 $yesSynonym = array_values($resultMulSynonym[$childMulParent[$valueNodesId]]["reject"]);
  665.                             }
  666.                             $priority = "12";
  667.                             break;
  668.                         case "默认":
  669.                             $priority = "2";
  670.                             $isMore = 1;
  671.                             break;
  672.                     }
  673.                     if($isMore==0) {//不是默认
  674.                         $synonymSystem = $yesSynonym ?: [$synonymCode];
  675.                         foreach ($synonymSystem as $item){
  676.                             $synonymArray[$item] = $word;
  677.                         }
  678.                         $arrSubFlow = [
  679.                             "condition" => [
  680.                                 "text" => $synonymSystem
  681.                             ],
  682.                             "priority" => $priority,
  683.                             "description" => $word
  684.                         ];
  685.                     }elseif($isMore==1){//是默认
  686.                         $arrSubFlow = [
  687.                             "condition" => [
  688.                                 "text" => ["any"]
  689.                             ],
  690.                             "priority" => $priority,
  691.                             "description" => $word
  692.                         ];
  693.                     }
  694.                     if(!isset($priorityArray[$valueNodeId])) {
  695.                         $priorityArray[$valueNodeId] = $priority;
  696.                     }else{
  697.                         if($priorityArray[$valueNodeId]<$priority){
  698.                             $priorityArray[$valueNodeId] =  $priority;
  699.                         }
  700.                     }
  701.                     if($nodesMulInfo[$value["node_mul_id"]]["info_talk_info"]) { //有信息的(多伦会话只要有信息判断)
  702.                         if(!isset($sameNodeList[$valueProcessId][$valueParentId][$valueNodeId])) {//是否存在当前流程,当前父id的,节点id
  703.                             //判断是否当前节点参数是否为空
  704.                             $subFlowModel[$valueNodeId]   = $arrSubFlow;
  705.                             if($isMore==0) {//不是默认
  706.                                 $nodeSynonymList[$valueNodeId] = $synonymArray;
  707.                             }
  708.                             $sameNodeList[$valueProcessId][$valueParentId][$valueNodeId] = $key+1;
  709.                         }else{
  710.                             if(!isset($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"])) {
  711.                                 $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"] = [];
  712.                             }
  713.                             if($isMore==0) {//非默认
  714.                                 if ($yesSynonym) {
  715.                                     $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"]  = array_merge($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"] ,$yesSynonym);
  716.                                 }
  717.                                 if (!$yesSynonym) {
  718.                                     array_push($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"], "W." . $word);
  719.                                 }
  720.                                 $nodeSynonymList[$valueNodeId] = array_merge($nodeSynonymList[$valueNodeId],$synonymArray);
  721.                             }
  722.                             if($isMore==1) {//默认
  723. //                                $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"]= ["any"];
  724.                                 array_push($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"], "any");
  725.                             }
  726.                             if(!isset($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["description"])) {
  727.                                 $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["description"] =  $word;
  728.                             }else{
  729.                                 $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["description"] .= "," . $word;
  730.                             }
  731.                             $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["priority"] = $priorityArray[$valueNodeId];
  732.                         }
  733.                     }
  734.                     elseif(!$nodesMulInfo[$value["node_mul_id"]]["info_talk_info"] && $nodesMulInfo[$value["node_mul_id"]]["type_id"]==2){
  735.                         $next           = $nodesMulInfo[$value["node_mul_id"]]["next"];  //跳转的条件
  736.                         $nextId         = $nodesMulInfo[$value["node_mul_id"]]["next_id"];//流程id
  737.                         [$arrSubFlows,$returnKey,$resReturn,$flow] = $this->checkNextMulFlow($next,$nextId,$treeFirstNode,$flow);
  738.                         if(!isset($sameNodeList[$valueProcessId][$valueParentId][$returnKey])) {
  739.                             //判断是否当前节点参数是否为空
  740.                             if($resReturn){
  741.                                 if(!isset($subFlowModel["F" . $returnKey]["condition"]["text"])) {
  742.                                     $subFlowModel["F" . $returnKey]["condition"]["text"] = [];
  743.                                 }
  744.                                 if($isMore==0) {//非默认
  745.                                     if ($yesSynonym) {
  746.                                         $subFlowModel["F" . $returnKey]["condition"]["text"] = array_merge($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"],$yesSynonym);
  747.                                     }
  748.                                     if (!$yesSynonym ) {
  749.                                         array_push($subFlowModel ["F" . $returnKey]["condition"]["text"], "W." . $word);
  750.                                     }
  751.                                 }
  752.                                 if($isMore==1) {//默认
  753. //                                    $subFlowModel ["F" . $returnKey]["condition"]["text"]= ["any"];
  754.                                     array_push($subFlowModel ["F" . $returnKey]["condition"]["text"], "any");
  755.                                 }
  756.                                 $subFlowModel["F" . $returnKey]["priority"] = $priorityArray[$valueNodeId];
  757.                             }
  758.                             if($isMore==0) {//不是默认
  759.                                 $nodeSynonymList[$valueNodeId] = $synonymArray;
  760.                             }
  761. //                            $subFlowModel["F".$returnKey]                               = $resReturn;
  762.                             $sameNodeList[$valueProcessId][$valueParentId][$returnKey]  = $key+1;
  763.                         }else{
  764.                             if(!isset($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"])) {
  765.                                 $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"] = [];
  766.                             }
  767.                             if($isMore==0) {//非默认
  768.                                 if ($yesSynonym) {
  769.                                     $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"] = array_merge($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"],$yesSynonym);
  770.                                 }
  771.                                 if (!$yesSynonym ) {
  772.                                     array_push($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"], "W." . $word);
  773.                                 }
  774.                                 $nodeSynonymList[$valueNodeId] = array_merge($nodeSynonymList[$valueNodeId],$synonymArray);
  775.                             }
  776.                             if($isMore==1) {//默认
  777. //                                $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"]= ["any"];
  778.                                 array_push($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"], "any");
  779.                             }
  780.                             if(!isset($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["description"])){
  781.                                 $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["description"] = ",".$word;
  782.                             }else{
  783.                                 $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["description"] .= ",".$word;
  784.                             }
  785.                             $processMulNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["priority"] = $priorityArray[$valueNodeId];
  786.                         }
  787.                     }
  788.                 }
  789.             }
  790.             if (!isset($processMulNodesNode[$valueProcessId][$valueParentId])) {
  791.                 $processMulNodesNode[$valueProcessId][$valueParentId] = $subFlowModel;
  792.             } else {
  793.                 $processMulNodesNode[$valueProcessId][$valueParentId] = array_merge($processMulNodesNode[$valueProcessId][$valueParentId],$subFlowModel);
  794.             }
  795.         }
  796.         return [$processMulNodesNode,$nodeSynonymList,$processMulNodesArr,$flow];
  797.     }
  798.     //获取所有的
  799.     public function getMulFlowList($flow,$processMulNodesArr,$argMulArray,$nodesMulInfo,$treeFirstNode,$processMulNodesNode,$allNodeMulWavKey,$priority)
  800.     {
  801.         $count                  = 0;
  802.         foreach ($processMulNodesArr as $ke=>$ve){
  803.             foreach ($ve as $kkk=>$vvv){
  804.                 $vvvNodeId = $vvv["node_mul_id"];
  805.                 $count++;
  806.                 $arg = [];
  807.                 $arg["action"]          = "cti_play_and_detect_speech";
  808.                 //模式
  809.                 $argM       = $argMulArray[$vvvNodeId]["moshi"]??"1";
  810.                 $argLuZao   = $argMulArray[$vvvNodeId]["luzao"]??"";
  811.                 $argKaiShi  = $argMulArray[$vvvNodeId]["kaishi"]??"";
  812.                 $argTingZhi = $argMulArray[$vvvNodeId]["tingzhi"]??"";
  813.                 $argDengDai = $argMulArray[$vvvNodeId]["dengdai"]??"";
  814.                 $argZuiDa   = $argMulArray[$vvvNodeId]["zuida"]??"";
  815.                 $argCanShu  = $argMulArray[$vvvNodeId]["canshu"]??"";
  816.                 $argLuYin   = $argMulArray[$vvvNodeId]["luyin"]??"";
  817.                 //挂机不需要这些参数
  818.                 if($nodesMulInfo[$vvvNodeId]['next']!=1) {
  819.                     $arg["filter"] = [
  820.                         "text" => "S",
  821.                         "dtmf" => "none"
  822.                     ];
  823.                     if ($priority == 1) {
  824.                         $arg["kb_priority"] = 0;
  825.                     } elseif ($priority == 2) {
  826.                         $arg["kb_priority"] = 1;
  827.                     }
  828.                     $arg["timeoutplaybacks"] = [];
  829.                     $arg["timeoutrepetition"] = "";
  830.                     $arg["mismatchplaybacks"] = [];
  831.                     $arg["mismatchrepetition"] = "1";
  832.                     $arg["kb"] = 'C1';
  833.                     $arg["globalflow"] = [
  834.                         "all"
  835.                     ];
  836.                 }else{//挂机节点不起用asr
  837.                     $argM = 0;
  838.                 }
  839.                 $arg["argument"]        = "'$argM' '16' '' '$argLuZao' '' '$argKaiShi' '$argTingZhi' '$argDengDai' '$argZuiDa' '' '$argCanShu' '$argLuYin' '' ''";
  840.                 $arg["position"]        = [
  841.                     "x"=>$nodesMulInfo[$vvvNodeId]["node_x"],
  842.                     "y"=>$nodesMulInfo[$vvvNodeId]["node_y"]];
  843.                 $arg["description"]     = $nodesMulInfo[$vvvNodeId]["info_title"];
  844.                 if(isset($allNodeMulWavKey[$vvvNodeId]) && $allNodeMulWavKey[$vvvNodeId]) {
  845.                     $arg["playbacks"] = [$allNodeMulWavKey[$vvvNodeId]];
  846.                 }else{
  847.                     $arg["playbacks"] = [$nodesMulInfo[$vvvNodeId]["info_talk_info"]];
  848.                 }
  849.                 if(isset($processMulNodesNode[$vvv["process_mul_id"]][$vvvNodeId])) {
  850.                     $arg["subflow"] = $processMulNodesNode[$vvv["process_mul_id"]][$vvvNodeId];
  851.                 }else{
  852.                     $next           = $nodesMulInfo[$vvvNodeId]["next"];   //跳转的条件
  853.                     $nextId         = $nodesMulInfo[$vvvNodeId]["next_id"];//流程id
  854.                     [$arg["subflow"],$returnKey,$resReturn,$flow] = $this->checkNextMulFlow($next,$nextId,$treeFirstNode,$flow);
  855.                 }
  856.                 if($nodesMulInfo[$vvvNodeId]["info_talk_info"]) {//如果是跳转节点,没有输入声音就是不输入
  857.                     $keyNode = "F".$vvvNodeId."_".$vvvNodeId;
  858.                     $flow[$keyNode] = $arg;
  859.                 }
  860.             }
  861.         }
  862.         return $flow;
  863.     }
  864.     //多伦会话下一步
  865.     public function checkNextMulFlow($next,$nextId,$treeFirstNode,$flow)
  866.     {
  867.         $array          = [];
  868.         $info           = ["description"=>"默认回答", "condition"=>["text"=>["any"]]];
  869.         $keyReturn      = "";
  870.         $resReturn      = "";
  871.         switch ($next)
  872.         {
  873.             case 0://普通节点默认挂机
  874.             case 1://挂机
  875.                 $hangK              = substr(microtime(true),2,8).rand(0,99);
  876.                 $hangKey            = "F".$hangK;
  877.                 $array[$hangKey]    = $info;
  878.                 $keyReturn          = $hangK;
  879.                 $resReturn          = $info;
  880.                 //挂机节点需要添加挂机节点
  881.                 /**
  882.                  * 生成一个挂机节点
  883.                  */
  884.                 $endPointsArray = [
  885.                     'action'=>'hangup',
  886.                     'position'=>[
  887.                         "x"=>67,
  888.                         "y"=>33
  889.                     ]
  890.                 ];
  891.                 $flow[$hangKey]=$endPointsArray;
  892.                 break;
  893.             case 2://跳转指定多伦会话
  894.                 $hangKey            = "F".$nextId."_".$nextId;
  895.                 $array[$hangKey]    = $info;
  896.                 $keyReturn          = $nextId."_".$nextId;
  897.                 $resReturn          = $info;
  898.                 break;
  899.             case 3://指定主流程
  900.                 $hangKey            = "F".$treeFirstNode[$nextId]['node_id'];
  901.                 $array[$hangKey]    = $info;
  902.                 $keyReturn          = $treeFirstNode[$nextId]['node_id'];
  903.                 $resReturn          = $info;
  904.                 break;
  905.         }
  906.         return [$array,$keyReturn,$resReturn,$flow];
  907.     }
  908.     //所有的多伦会话节点流程
  909.     public function getMulArgArray($where)
  910.     {
  911.         $argList  = SpeechMulProcessSettingModel::create()->getAll($where,"set_key,set_value,node_mul_id");//所有的参数节点流程
  912.         $argArray = [];
  913.         foreach ($argList as $argK=>$argValue){
  914.             $argArray[$argValue["node_mul_id"]][$argValue["set_key"]] = $argValue["set_value"];
  915.         }
  916.         return $argArray;
  917.     }
  918. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农民

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表