农民 发表于 2024-9-10 22:41:45

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

利用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外呼管理截图
https://i-blog.csdnimg.cn/blog_migrate/639d4aff60271f190c66daea7266ca3e.png

话术管理截图
https://i-blog.csdnimg.cn/blog_migrate/0292040c973844e6c1da8a0493d5788c.png
坐席页面
https://i-blog.csdnimg.cn/blog_migrate/12bf584f5ef1429ae070f0277543ca6e.png管理员页面
https://i-blog.csdnimg.cn/blog_migrate/2046e6ed6e934ce30b8534121ff4f81b.png线路管理
https://i-blog.csdnimg.cn/blog_migrate/5a7c4f8d3c8e5a9c231f71cac9ad8103.png

机器人话术代码:

<?php
/**
* Created by PhpStorm.
* User: WIN10
* Date: 2021/12/18
* Time: 16:04
*/
namespace App\Traits;
use App\Model\Speech\SpeechLabelSynonym;
use App\Model\Speech\SpeechNodeModel;
use App\Model\Speech\SpeechProcessModel;
use App\Model\Speech\SpeechProcessNodeSettingModel;
use App\Model\SpeechMul\SpeechMulLabelSynonym;
use App\Model\SpeechMul\SpeechMulProcessSettingModel;

trait SpeechExamineTrait{


    //主流程匹配关键词结果数组
    public function getResultSynonym($speechId)
    {
      $resultSynonym      = [];
      $synonymList      = SpeechLabelSynonym::create()->getAll(["speech_id"=>$speechId]);
      foreach ($synonymList as $val){
            if(isset($val["sls_name"])) {
                $resultSynonym[$val["node_id"]][$val["sls_keyword"]][] = $val["sls_name"];
            }
      }
      return $resultSynonym;
    }


    //获取主流程的$nodesInfo信息 节点信息
    //$processQueuesReal      = []; //真实存在的主流程节点(只有节点才存在到这个主流程)
    public function getNodesInfoList($where)
    {
      $nodesInfo            = [];//所有节点信息map=>(k,v)
      $processNodes         = [];
      $processQueuesReal      = []; //真实存在的主流程节点(只有节点才存在到这个主流程)
      //所有节点的信息
      $nodesInfoList          = SpeechNodeModel::create()->getAll($where);
      foreach ($nodesInfoList as $kk=>$vv)
      {
            $nodesInfo[$vv["node_id"]] = $vv;
            if(!isset($processNodes[$vv["process_id"]])){//真实存在
                array_push($processQueuesReal,$vv["process_id"]);
            }else{
                $processNodes[$vv["process_id"]]         = [];
            }
      }
      return [$nodesInfo,$processQueuesReal];
    }


    //$processNodesArr 所有节点的数组
    //$processQueues所有的流程按照顺序
    public function getProcessQueues($where)
    {
      $processNodesArr      = [];
      $processQueues          = [];//所有的流程按照顺序
      $processArray         = SpeechProcessModel::create()->getAll($where,'process_id',["sort,process_id","ASC"]);
      foreach ($processArray as $a=>$item){
            array_push($processQueues,$item["process_id"]);
            $processNodesArr[$item["process_id"]] = [];
      }
      return [$processNodesArr,$processQueues];
    }


    //所有的参数节点流程
    public function getArgArray($where)
    {
      $argList= SpeechProcessNodeSettingModel::create()->getAll($where,"set_key,set_value,node_id");//所有的参数节点流程
      $argArray = [];
      foreach ($argList as $argK=>$argValue){
            $argArray[$argValue["node_id"]][$argValue["set_key"]] = $argValue["set_value"];
      }
      return $argArray;
    }


    //获取所有树的第一个节点集
    // $nodes = SpeechNodeTreeModel::create()->getAll($where,'process_id,node_id,parent_id,nodes_id',["node_id","ASC"]);
    public function getTreeFirstNode($nodes)
    {
      $treeFirstNode      = [];
      foreach ($nodes as $key=>$value)
      {
            if($value["parent_id"]==0){
                $treeFirstNode[$value["process_id"]] = $value;
            }
      }
      return $treeFirstNode;
    }

    public function getMulTreeFirstNode($nodes)
    {
      $treeFirstNode      = [];
      foreach ($nodes as $key=>$value)
      {
            if($value["parent_id"]==0){
                $treeFirstNode[$value["process_mul_id"]] = $value;
            }
      }
      return $treeFirstNode;
    }


    //获取流程的节点的集
    //$processNodesNode 子集
    // $nodes = SpeechNodeTreeModel::create()->getAll($where,'process_id,node_id,parent_id,nodes_id',["node_id","ASC"]);
    //$resultSynonym主流程匹配关键词结果数组集
    //$childParent 父子节点数组      $childParent            = SpeechSmallNodeRelationModel::create()->getColumn($where,"node_id","small_node_id");
    //$processReal真实按照顺序的主流程
    //$processRealFlip主流程反转主流程
    //$treeFirstNode   获取所有树的第一个节点集
    //$nodeSynonymList匹配的关键词
    //$targetLabel
    //$nodesInfo
    public function getProcessNodesNode($nodes,$processNodesArr,$nodesInfo,$resultSynonym,$childParent,$processReal,$targetLabel,$processRealFlip,$treeFirstNode,$nodeSynonymList)
    {
      //判断是否有相同的节点
      $sameNodeList       = [];
      $processNodesNode   = [];
      //用一个权重数组去获取最终值吧(始终取最大的)
      $priorityArray      = [];
      foreach ($nodes as $key=>$value)
      {
            $valueProcessId                                 = $value["process_id"];
            $processNodesArr[$valueProcessId][]             = $value;
            $subFlowModel   = [];
            $valueNodesId   = $value["nodes_id"];
            $valueParentId= $value["parent_id"];
            $valueNodeId    = $value["node_id"];
            $priority       = "0"; //分支权重
            if($valueNodesId) {
                $word = $targetLabel[$valueNodesId]??"";
                if ($word) {
                  $synonymCode    ="W." . $word;
                  $yesSynonym   = [];
                  $isMore         = 0;
                  $arrSubFlow   = [];
                  $synonymArray   = [];
                  switch ($word){
                        case "肯定":
                            if(isset($resultSynonym[$childParent[$valueNodesId]]["yes"])) {
                              $yesSynonym = array_values($resultSynonym[$childParent[$valueNodesId]]["yes"]);
                            }
                            $priority = "5";
                            break;
                        case "否定":
                            if(isset($resultSynonym[$childParent[$valueNodesId]]["no"])) {
                              $yesSynonym = array_values($resultSynonym[$childParent[$valueNodesId]]["no"]);
                            }
                            $priority = "10";
                            break;
                        case "拒绝":
                            if(isset($resultSynonym[$childParent[$valueNodesId]]["reject"])) {
                              $yesSynonym = array_values($resultSynonym[$childParent[$valueNodesId]]["reject"]);
                            }
                            $priority = "12";
                            break;
                        case "默认":
                            $priority = "2";
                            $isMore = 1;
                            break;
                  }
                  if($isMore==0) {//不是默认
                        $synonymSystem = $yesSynonym ?: [$synonymCode];
                        foreach ($synonymSystem as $item){
                            $synonymArray[$item] = $word;
                        }
                        $arrSubFlow = [
                            "condition" => [
                              "text" => $synonymSystem
                            ],
                            "priority" => $priority,
                            "description" => $word
                        ];
                  }elseif($isMore==1){//是默认
                        $arrSubFlow = [
                            "condition" => [
                              "text" => ["any"]
                            ],
                            "priority" => $priority,
                            "description" => $word
                        ];
                  }
                  if(!isset($priorityArray[$valueNodeId])) {
                        $priorityArray[$valueNodeId] = $priority;
                  }else{
                        if($priorityArray[$valueNodeId]<$priority){
                            $priorityArray[$valueNodeId] =$priority;
                        }
                  }
                  if($nodesInfo[$valueNodeId]["info_talk_info"]) { //有信息的
                        if(!isset($sameNodeList[$valueProcessId][$valueParentId][$valueNodeId])) {//是否存在当前流程,当前父id的,节点id
                            //判断是否当前节点参数是否为空
                            $subFlowModel["F" . $valueNodeId]   = $arrSubFlow;
                            if($isMore==0) {//不是默认
                              $nodeSynonymList[$valueNodeId] = $synonymArray;
                            }
                            $sameNodeList[$valueProcessId][$valueParentId][$valueNodeId] = $key+1;
                        }else{
                            if(!isset($processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"])) {
                              $processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"] = [];
                            }
                            if($isMore==0) {//非默认
                              //有text关键词的操作
                              if ($yesSynonym) {
                                    $processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"]= array_merge($processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"] ,$yesSynonym);
                              }
                              //没有关键词的操作
                              if (!$yesSynonym) {
                                    array_push($processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"], "W." . $word);
                              }
                              $nodeSynonymList[$valueNodeId] = array_merge($nodeSynonymList[$valueNodeId],$synonymArray);
                            }
                            if($isMore==1) {//默认
//                              $processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"]= ["any"];
                              array_push($processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"], "any");
                            }
                            if(!isset($processNodesNode[$valueProcessId][$valueParentId]["F" . $valueNodeId]["description"])) {
                              $processNodesNode[$valueProcessId][$valueParentId]["F" . $valueNodeId]["description"] =$word;
                            }else{
                              $processNodesNode[$valueProcessId][$valueParentId]["F" . $valueNodeId]["description"] .= "," . $word;
                            }
                            $processNodesNode[$valueProcessId][$valueParentId]["F" . $valueNodeId]["priority"] = $priorityArray[$valueNodeId];
                        }
                  }
                  elseif(!$nodesInfo[$valueNodeId]["info_talk_info"] && $nodesInfo[$valueNodeId]["type_id"]==2){
                        $next         = $nodesInfo[$value["node_id"]]["next"];//跳转的条件
                        $nextId         = $nodesInfo[$value["node_id"]]["next_id"];//流程id
                        $process_id   = $nodesInfo[$value["node_id"]]["process_id"]; //该流程id
                        [$resReturnData,$returnKey,$resReturn] = $this->checkNextFlow($next,$nextId,$process_id,$processReal,$processRealFlip,$treeFirstNode,$arrSubFlow);//没有信息的就是跳转信息
                        if(!isset($sameNodeList[$valueProcessId][$valueParentId][$returnKey])) {
                            //判断是否当前节点参数是否为空
//                            $subFlowModel["F".$returnKey]                               = $resReturn;
                            if($resReturn){
                              if(!isset($subFlowModel["F" . $returnKey]["condition"]["text"])) {
                                    $subFlowModel["F" . $returnKey]["condition"]["text"] = [];
                              }
                              if($isMore==0) {//非默认
                                    if ($yesSynonym) {
                                        $subFlowModel["F" . $returnKey]["condition"]["text"] = array_merge($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"],$yesSynonym);
                                    }
                                    if (!$yesSynonym ) {
                                        array_push($subFlowModel ["F" . $returnKey]["condition"]["text"], "W." . $word);
                                    }
                              }
                              if($isMore==1) {//默认
//                                    $subFlowModel ["F" . $returnKey]["condition"]["text"]= ["any"];
                                    array_push($subFlowModel ["F" . $returnKey]["condition"]["text"], "any");
                              }
                              $subFlowModel["F" . $returnKey]["priority"] = $priorityArray[$valueNodeId];
                            }
                            $nodeSynonymList[$returnKey]                              = $synonymArray;
                            $sameNodeList[$valueProcessId][$valueParentId][$returnKey]= $key+1;
                        }else{
                            if(!isset($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"])) {
                              $processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"] = [];
                            }
                            if($isMore==0) {//非默认
                              if ($yesSynonym) {
                                    $processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"] = array_merge($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"],$yesSynonym);
                                    $nodeSynonymList[$returnKey]      = array_merge($nodeSynonymList[$returnKey],$synonymArray);
                              }
                              if (!$yesSynonym ) {
                                    array_push($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"], "W." . $word);
                                    $nodeSynonymList[$returnKey] = array_merge($nodeSynonymList[$returnKey],$synonymArray);
                              }
                            }
                            if($isMore==1) {//默认
//                              $processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"]= ["any"];
                              array_push($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"], "any");
                            }
                            if(isset($processNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["description"])) {
                              $processNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["description"] =$word;
                            }else{
                              $processNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["description"] .= "," . $word;
                            }
                            $processNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["priority"] = $priorityArray[$valueNodeId];
                        }
                  }
                }
            }
            //是否存在当前的流程的process的id的,父id
            //不存在就是直接把subFlow赋值给他
            if (!isset($processNodesNode[$valueProcessId][$valueParentId])) {
                $processNodesNode[$valueProcessId][$valueParentId] = $subFlowModel;
            } else {
                //存在就是数组连接一起
                $processNodesNode[$valueProcessId][$valueParentId] = array_merge($processNodesNode[$valueProcessId][$valueParentId],$subFlowModel);
            }
      }
      return [$processNodesArr,$processNodesNode,$nodeSynonymList];
    }


    //获取flow流程
    //获取 $nodeSynonymList匹配的关键词
    //$firstNode
    //第一个主流程节点
    //$version 版本
    //$processReal真实按照顺序的主流程
    //$processRealFlip主流程反转主流程
    //$treeFirstNode   获取所有树的第一个节点集
    //$nodeSynonymList匹配的关键词
    //$targetLabel
    //$nodesInfo
    //$processNodesNode 子集
    public function getFlowList($flow,$processNodesArr,$nodeSynonymList,$version,$nodesInfo,$processNodesNode,$processReal,$processRealFlip,$treeFirstNode,$argArray,$allNodeWavKey,$allSettingsKey,$priority){
      $count                  = 0;
      $firstNode            = "";//第一个节点
      foreach ($processNodesArr as $ke=>$ve){
            foreach ($ve as $kkk=>$vvv){
                $vvvNodeId = $vvv["node_id"];
                if($count==0){
                  $flow["Start"] = [
                        'action'=>'start',
                        'position'=>[
                            "x"=>2489,
                            "y"=>72
                        ],
                        "subflow"=>['F'.$vvvNodeId."_".$version=>new \stdClass()]
                  ];
                }
                $count++;
                $arg = [];
                $arg["action"]          = "cti_play_and_detect_speech";
                if($count==1){
                  $firstNode = $vvvNodeId."_".$version;
                }
                //模式
                $argM       = $argArray[$vvvNodeId]["moshi"]??"1";
                if(isset($allSettingsKey[$vvvNodeId]['interrupt']) && $allSettingsKey[$vvvNodeId]['interrupt']) {
                  $argM = "2";
                }
                $argLuZao   = $argArray[$vvvNodeId]["luzao"]??"";
                $argKaiShi= $argArray[$vvvNodeId]["kaishi"]??"";
                $argTingZhi = $argArray[$vvvNodeId]["tingzhi"]??"";
                $argDengDai = $argArray[$vvvNodeId]["dengdai"]??"";
                $argZuiDa   = $argArray[$vvvNodeId]["zuida"]??"";
                $argCanShu= $argArray[$vvvNodeId]["canshu"]??"";
                $argLuYin   = $argArray[$vvvNodeId]["luyin"]??"";
                //挂机不需要这些参数
                if($nodesInfo[$vvvNodeId]['next']!=1) {
                  $arg["filter"] = [
                        "text" => "S",
                        "dtmf" => "none"
                  ];
                  if ($priority == 1) {
                        $arg["kb_priority"] = 0;
                  } elseif ($priority == 2) {
                        $arg["kb_priority"] = 1;
                  }
                  $arg["timeoutplaybacks"] = [];
                  $arg["timeoutrepetition"] = "";
                  $arg["mismatchplaybacks"] = [];
                  $arg["mismatchrepetition"] = "1";
                  $arg["globalflow"] = [
                        "all"
                  ];
                }else{//挂机节点不起用asr
                  $argM = 0;
                }
                $arg["argument"]      = "'$argM' '16' '' '$argLuZao' '' '$argKaiShi' '$argTingZhi' '$argDengDai' '$argZuiDa' '' '$argCanShu' '$argLuYin' '' ''";
                $arg["position"]      = [
                  "x"=>$nodesInfo[$vvvNodeId]["node_x"],
                  "y"=>$nodesInfo[$vvvNodeId]["node_y"]
                ];
                $arg["description"]   = $nodesInfo[$vvvNodeId]["info_title"];
                if(isset($allNodeWavKey[$vvvNodeId]) && $allNodeWavKey[$vvvNodeId]) {
                  $arg["playbacks"] = [$allNodeWavKey[$vvvNodeId]];
                }else{
                  $arg["playbacks"] = [$nodesInfo[$vvvNodeId]["info_talk_info"]];
                }

                $arg["kb"]          = 'C1';
                if(isset($processNodesNode[$vvv["process_id"]][$vvvNodeId])) {
                  $arg["subflow"] = $processNodesNode[$vvv["process_id"]][$vvvNodeId];
                }else{
                  $next         = $nodesInfo[$vvvNodeId]["next"];//跳转的条件
                  $nextId         = $nodesInfo[$vvvNodeId]["next_id"];//流程id
                  $processId      = $nodesInfo[$vvvNodeId]["process_id"]; //该流程id
                  [$arg["subflow"],$returnKey,$resReturn] = $this->checkNextFlow($next,$nextId,$processId,$processReal,$processRealFlip,$treeFirstNode);
                }
                if($nodesInfo[$vvvNodeId]["info_talk_info"]) {//如果是跳转节点,没有输入声音就是不输入
                  if($count==1){
                        $vvvNodeId .= "_".$version;
                  }
                  $flow["F" . $vvvNodeId] = $arg;
                }
            }
      }
      return [$flow,$nodeSynonymList,$firstNode];
    }

    //生成一个挂机节点
    public function addEndPoints($flow)
    {
      /**
         * 生成一个挂机节点
         */
      $endPointsArray = [
            'action'=>'hangup',
            'position'=>[
                "x"=>67,
                "y"=>33
            ]
      ];
      $flow["F9999999999999999999"]=$endPointsArray;
      return $flow;
    }
    //生成一个等待用户回答节点
    public function addWaitPoints($flow)
    {
      /**
         * 生成一个挂机节点
         */
      $endWaitArray = [
            'action'=>"cti_play_and_detect_speech",
            "argument"=>"'1' '16' '' '' '' '' '' '' '' '' '' '' '' ''",
            "position"=>[
                "x"=>391833,
                "y"=>2372
            ],
            "playbacks"=>[],
            "description"=>"",
            "sourceflowdepth"=>"1",
            "globalflow"=>[
                "all"
            ],
            "kb"         => 'C1',
            "kb_priority"=>2,
            "condition"=> [
            "complete"=> [],
                "text"=> []
            ],
            "timeoutrepetition"=>"",
            "mismatchplaybacks"=> [],
            "subflow"=>[]
      ];
      $flow["F88888888888888888888"]=$endWaitArray;
//      $flow["F66666666666666666666"]=[
//            "action"=> "return",
//            "position"=> [
//                "x"=> 2263,
//                "y"=> 492
//            ]
//      ];
      return $flow;
    }

    //生成一个挂机播放节点
    public function addHangUpPlayContent($flow,$nodeId,$playbacks)
    {
      $hangUpArray = [
            'action'=>"cti_play_and_detect_speech",
            "argument"=>"'0' '16' '' '' '' '' '' '' '' '' '' '' '' ''",
            "position"=>[
                "x"=>391833,
                "y"=>2372
            ],
            "playbacks"=>$playbacks,
            "description"=>"",
            "sourceflowdepth"=>"1",
            "condition"=> [
                "text"=> []
            ],
            "mismatchplaybacks"=> [],
            "subflow"=>[
                "F9999999999999999999"=> [
                  "condition"=>[
                        "complete"=> [
                            "any"
                        ],
                  ],
                ]
            ]
      ];
      $flow["F".$nodeId] = $hangUpArray;
      return $flow;
    }

    //生成一个挂机播放节点
    public function addHangUpPlay($flow)
    {
      $hangUpArray = [
            'action'=>"cti_play_and_detect_speech",
            "argument"=>"'0' '16' '' '' '' '' '' '' '' '' '' '' '' ''",
            "position"=>[
                "x"=>391833,
                "y"=>2372
            ],
            "playbacks"=>[],
            "description"=>"",
            "sourceflowdepth"=>"1",
            "condition"=> [
                "text"=> []
            ],
            "mismatchplaybacks"=> [],
            "subflow"=>[
                "F9999999999999999999"=> [
                "condition"=>[
                  "text"=> [
                        "any"
                        ],
                  ],
                ]
            ]
      ];
      $flow["F5555555555555555555555"] = $hangUpArray;
      return $flow;
    }

    public function addWaitSubPoints(){
      return [
            "F9999999999999999999"=> [
                "condition"=>[
                  "complete"=> [
                        "timeout()"
                  ]
                ],
                "description"=> "静音挂断"
            ],
            "F66666666666666666666"=>[
                "condition"=> [
                  "complete"=> [],
                  "text"=> [
                        "F.+"
                  ]
                ],
                "description"=> "有声音返回"
            ]
      ];
    }




    //生成一个挂机节点
    public function addHangUpPoints()
    {
      $endPointsArray["F9999999999999999999"] = [
            'condition'=>[
                  'complete'=> [
                        "any"
                  ]
            ],
      ];
      return $endPointsArray;
    }


    //跳转到指定主流程
    public function toMainFlow($flowId)
    {
      $arg["F".$flowId]= [
            "condition"=>[
                "complete"=> [],
                  "text"=>[
                  "any"
                ],
                   "description"=>""
                ]
      ];
      return $arg;
    }

    //跳转到指定多伦会话
    public function toMulFlow($flowId)
    {
      $arg["F".$flowId."_".$flowId]= [
            "condition"=>[
                "complete"=> [],
                "text"=>[
                  "any"
                ],
                "description"=>""
            ]
      ];
      return $arg;
    }


    //判断主流程下个流程的节点
    public functioncheckNextFlow($next,$nextId,$process_id,$processReal,$processRealFlip,$treeFirstNode,$arrSubFlow=[])
    {
      $array          = [];
      $keyNext      = $processRealFlip[$process_id]+1;//下一个next
      $hangUp         = $arrSubFlow?:["description"=>"无效回答", "condition"=>["text"=>["any"]]];
      $nextProcess    = $arrSubFlow?: ["condition" => ["text" => ["any"]], "description" => "跳转下一个流程"];
      $keyReturn      = "";
      $resReturn      = "";
      switch ($next)
      {
            case 0:
            case 2:
                if(isset($processReal[$keyNext])){
                  $array["F" . $treeFirstNode[$processReal[$keyNext]]["node_id"]] = $nextProcess;
                  $keyReturn   = $treeFirstNode[$processReal[$keyNext]]["node_id"];
                  $resReturn   = $nextProcess;
                }else{
                  $array["F9999999999999999999"] = $hangUp;
                  $keyReturn= "9999999999999999999";
                  $resReturn   = $hangUp;
                }
                break;
            case 1:
                $array["F9999999999999999999"] = $hangUp;
                $keyReturn= "9999999999999999999";
                $resReturn   = $hangUp;
                break;
            case 3:
                if(isset($treeFirstNode[$nextId])) {
                  $fistNode = $treeFirstNode[$nextId];
                  $array["F" . $fistNode["node_id"]] = $nextProcess;
                  $keyReturn   = $fistNode["node_id"];
                  $resReturn   = $nextProcess;
                }else{
                  $array["F9999999999999999999"] = $hangUp;
                  $keyReturn       = "9999999999999999999";
                  $resReturn       = $hangUp;
                }
                break;
            case 4://返回接口
                $keyReturn= substr(microtime(true),2,8).rand(0,99);
                $resReturn= [
                  'action'=>'return',
                  'position'=>[
                        'x'=>4085,
                        'y'=>377
                  ],
                ];
                $array["F".$keyReturn] = $resReturn;
                break;
            }

      return [$array,$keyReturn,$resReturn];
    }



    //多伦会话匹配关键词结果数组
    public function getMulResultSynonym($speechId)
    {
      $resultSynonym      = [];
      $synonymList      = SpeechMulLabelSynonym::create()->getAll(["speech_id"=>$speechId]);
      foreach ($synonymList as $val){
            if(isset($val["sls_name"])) {
                $resultSynonym[$val["node_mul_id"]][$val["sls_keyword"]][] = $val["sls_name"];
            }
      }
      return $resultSynonym;
    }


    //获取所有子节点
    public function getMulProcessNodesNode($flow,$nodesMul,$resultMulSynonym,$childMulParent,$nodesMulInfo,$targetMulLabel,$nodeSynonymList,$treeFirstNode)
    {
      //判断是否有相同的节点
      $sameNodeList         = [];
      $processMulNodesNode    = [];
      $processMulNodesArr   = [];//所有全局话术的根节点
      //用一个权重数组去获取最终值吧(始终取最大的)
      $priorityArray      = [];
      foreach ($nodesMul as $key=>$value)
      {
            $valueProcessId                     = $value["process_mul_id"];
            $processMulNodesArr[$valueProcessId][]          = $value;
            $subFlowModel   = [];
            $valueNodesId   = $value["nodes_id"];
            $valueParentId= $value["parent_id"];
            $valueNodeId    = "F".$value["node_mul_id"]."_".$value["node_mul_id"];
            $priority       = "0";
            if($valueNodesId) {
                $word = $targetMulLabel[$valueNodesId]??"";
                if ($word) {
                  $synonymCode    ="W." . $word;
                  $yesSynonym   = [];
                  $isMore         = 0;
                  $arrSubFlow   = [];
                  $synonymArray   = [];
                  switch ($word){
                        case "肯定":
                            if(isset($resultMulSynonym[$childMulParent[$valueNodesId]]["yes"])) {
                              $yesSynonym = array_values($resultMulSynonym[$childMulParent[$valueNodesId]]["yes"]);
                            }
                            $priority = "5";
                            break;
                        case "否定":
                            if(isset($resultMulSynonym[$childMulParent[$valueNodesId]]["no"])) {
                              $yesSynonym = array_values($resultMulSynonym[$childMulParent[$valueNodesId]]["no"]);
                            }
                            $priority = "10";
                            break;
                        case "拒绝":
                            if(isset($resultMulSynonym[$childMulParent[$valueNodesId]]["reject"])) {
                              $yesSynonym = array_values($resultMulSynonym[$childMulParent[$valueNodesId]]["reject"]);
                            }
                            $priority = "12";
                            break;
                        case "默认":
                            $priority = "2";
                            $isMore = 1;
                            break;
                  }
                  if($isMore==0) {//不是默认
                        $synonymSystem = $yesSynonym ?: [$synonymCode];
                        foreach ($synonymSystem as $item){
                            $synonymArray[$item] = $word;
                        }
                        $arrSubFlow = [
                            "condition" => [
                              "text" => $synonymSystem
                            ],
                            "priority" => $priority,
                            "description" => $word
                        ];
                  }elseif($isMore==1){//是默认
                        $arrSubFlow = [
                            "condition" => [
                              "text" => ["any"]
                            ],
                            "priority" => $priority,
                            "description" => $word
                        ];
                  }
                  if(!isset($priorityArray[$valueNodeId])) {
                        $priorityArray[$valueNodeId] = $priority;
                  }else{
                        if($priorityArray[$valueNodeId]<$priority){
                            $priorityArray[$valueNodeId] =$priority;
                        }
                  }
                  if($nodesMulInfo[$value["node_mul_id"]]["info_talk_info"]) { //有信息的(多伦会话只要有信息判断)
                        if(!isset($sameNodeList[$valueProcessId][$valueParentId][$valueNodeId])) {//是否存在当前流程,当前父id的,节点id
                            //判断是否当前节点参数是否为空
                            $subFlowModel[$valueNodeId]   = $arrSubFlow;
                            if($isMore==0) {//不是默认
                              $nodeSynonymList[$valueNodeId] = $synonymArray;
                            }
                            $sameNodeList[$valueProcessId][$valueParentId][$valueNodeId] = $key+1;
                        }else{
                            if(!isset($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"])) {
                              $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"] = [];
                            }
                            if($isMore==0) {//非默认
                              if ($yesSynonym) {
                                    $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"]= array_merge($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"] ,$yesSynonym);
                              }
                              if (!$yesSynonym) {

                                    array_push($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"], "W." . $word);
                              }
                              $nodeSynonymList[$valueNodeId] = array_merge($nodeSynonymList[$valueNodeId],$synonymArray);
                            }
                            if($isMore==1) {//默认
//                              $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"]= ["any"];
                              array_push($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"], "any");
                            }
                            if(!isset($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["description"])) {
                              $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["description"] =$word;
                            }else{
                              $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["description"] .= "," . $word;
                            }
                            $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["priority"] = $priorityArray[$valueNodeId];
                        }
                  }
                  elseif(!$nodesMulInfo[$value["node_mul_id"]]["info_talk_info"] && $nodesMulInfo[$value["node_mul_id"]]["type_id"]==2){
                        $next         = $nodesMulInfo[$value["node_mul_id"]]["next"];//跳转的条件
                        $nextId         = $nodesMulInfo[$value["node_mul_id"]]["next_id"];//流程id
                        [$arrSubFlows,$returnKey,$resReturn,$flow] = $this->checkNextMulFlow($next,$nextId,$treeFirstNode,$flow);
                        if(!isset($sameNodeList[$valueProcessId][$valueParentId][$returnKey])) {
                            //判断是否当前节点参数是否为空
                            if($resReturn){
                              if(!isset($subFlowModel["F" . $returnKey]["condition"]["text"])) {
                                    $subFlowModel["F" . $returnKey]["condition"]["text"] = [];
                              }
                              if($isMore==0) {//非默认
                                    if ($yesSynonym) {
                                        $subFlowModel["F" . $returnKey]["condition"]["text"] = array_merge($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"],$yesSynonym);
                                    }
                                    if (!$yesSynonym ) {
                                        array_push($subFlowModel ["F" . $returnKey]["condition"]["text"], "W." . $word);
                                    }
                              }
                              if($isMore==1) {//默认
//                                    $subFlowModel ["F" . $returnKey]["condition"]["text"]= ["any"];
                                    array_push($subFlowModel ["F" . $returnKey]["condition"]["text"], "any");
                              }
                              $subFlowModel["F" . $returnKey]["priority"] = $priorityArray[$valueNodeId];
                            }
                            if($isMore==0) {//不是默认
                              $nodeSynonymList[$valueNodeId] = $synonymArray;
                            }
//                            $subFlowModel["F".$returnKey]                               = $resReturn;
                            $sameNodeList[$valueProcessId][$valueParentId][$returnKey]= $key+1;
                        }else{
                            if(!isset($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"])) {
                              $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"] = [];
                            }
                            if($isMore==0) {//非默认
                              if ($yesSynonym) {
                                    $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"] = array_merge($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"],$yesSynonym);
                              }
                              if (!$yesSynonym ) {
                                    array_push($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"], "W." . $word);
                              }
                              $nodeSynonymList[$valueNodeId] = array_merge($nodeSynonymList[$valueNodeId],$synonymArray);
                            }
                            if($isMore==1) {//默认
//                              $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"]= ["any"];
                              array_push($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"], "any");
                            }
                            if(!isset($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["description"])){
                              $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["description"] = ",".$word;
                            }else{
                              $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["description"] .= ",".$word;
                            }
                            $processMulNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["priority"] = $priorityArray[$valueNodeId];
                        }
                  }
                }
            }
            if (!isset($processMulNodesNode[$valueProcessId][$valueParentId])) {
                $processMulNodesNode[$valueProcessId][$valueParentId] = $subFlowModel;
            } else {
                $processMulNodesNode[$valueProcessId][$valueParentId] = array_merge($processMulNodesNode[$valueProcessId][$valueParentId],$subFlowModel);
            }
      }
      return [$processMulNodesNode,$nodeSynonymList,$processMulNodesArr,$flow];
    }

    //获取所有的
    public function getMulFlowList($flow,$processMulNodesArr,$argMulArray,$nodesMulInfo,$treeFirstNode,$processMulNodesNode,$allNodeMulWavKey,$priority)
    {
      $count                  = 0;
      foreach ($processMulNodesArr as $ke=>$ve){
            foreach ($ve as $kkk=>$vvv){
                $vvvNodeId = $vvv["node_mul_id"];
                $count++;
                $arg = [];
                $arg["action"]          = "cti_play_and_detect_speech";
                //模式
                $argM       = $argMulArray[$vvvNodeId]["moshi"]??"1";
                $argLuZao   = $argMulArray[$vvvNodeId]["luzao"]??"";
                $argKaiShi= $argMulArray[$vvvNodeId]["kaishi"]??"";
                $argTingZhi = $argMulArray[$vvvNodeId]["tingzhi"]??"";
                $argDengDai = $argMulArray[$vvvNodeId]["dengdai"]??"";
                $argZuiDa   = $argMulArray[$vvvNodeId]["zuida"]??"";
                $argCanShu= $argMulArray[$vvvNodeId]["canshu"]??"";
                $argLuYin   = $argMulArray[$vvvNodeId]["luyin"]??"";
                //挂机不需要这些参数
                if($nodesMulInfo[$vvvNodeId]['next']!=1) {
                  $arg["filter"] = [
                        "text" => "S",
                        "dtmf" => "none"
                  ];
                  if ($priority == 1) {
                        $arg["kb_priority"] = 0;
                  } elseif ($priority == 2) {
                        $arg["kb_priority"] = 1;
                  }
                  $arg["timeoutplaybacks"] = [];
                  $arg["timeoutrepetition"] = "";
                  $arg["mismatchplaybacks"] = [];
                  $arg["mismatchrepetition"] = "1";
                  $arg["kb"] = 'C1';
                  $arg["globalflow"] = [
                        "all"
                  ];
                }else{//挂机节点不起用asr
                  $argM = 0;
                }
                $arg["argument"]      = "'$argM' '16' '' '$argLuZao' '' '$argKaiShi' '$argTingZhi' '$argDengDai' '$argZuiDa' '' '$argCanShu' '$argLuYin' '' ''";
                $arg["position"]      = [
                  "x"=>$nodesMulInfo[$vvvNodeId]["node_x"],
                  "y"=>$nodesMulInfo[$vvvNodeId]["node_y"]];
                $arg["description"]   = $nodesMulInfo[$vvvNodeId]["info_title"];
                if(isset($allNodeMulWavKey[$vvvNodeId]) && $allNodeMulWavKey[$vvvNodeId]) {
                  $arg["playbacks"] = [$allNodeMulWavKey[$vvvNodeId]];
                }else{
                  $arg["playbacks"] = [$nodesMulInfo[$vvvNodeId]["info_talk_info"]];
                }

                if(isset($processMulNodesNode[$vvv["process_mul_id"]][$vvvNodeId])) {
                  $arg["subflow"] = $processMulNodesNode[$vvv["process_mul_id"]][$vvvNodeId];
                }else{
                  $next         = $nodesMulInfo[$vvvNodeId]["next"];   //跳转的条件
                  $nextId         = $nodesMulInfo[$vvvNodeId]["next_id"];//流程id
                  [$arg["subflow"],$returnKey,$resReturn,$flow] = $this->checkNextMulFlow($next,$nextId,$treeFirstNode,$flow);
                }
                if($nodesMulInfo[$vvvNodeId]["info_talk_info"]) {//如果是跳转节点,没有输入声音就是不输入
                  $keyNode = "F".$vvvNodeId."_".$vvvNodeId;
                  $flow[$keyNode] = $arg;
                }
            }
      }
      return $flow;
    }

    //多伦会话下一步
    public function checkNextMulFlow($next,$nextId,$treeFirstNode,$flow)
    {
      $array          = [];
      $info         = ["description"=>"默认回答", "condition"=>["text"=>["any"]]];
      $keyReturn      = "";
      $resReturn      = "";
      switch ($next)
      {
            case 0://普通节点默认挂机
            case 1://挂机
                $hangK            = substr(microtime(true),2,8).rand(0,99);
                $hangKey            = "F".$hangK;
                $array[$hangKey]    = $info;
                $keyReturn          = $hangK;
                $resReturn          = $info;
                //挂机节点需要添加挂机节点
                /**
               * 生成一个挂机节点
               */
                $endPointsArray = [
                  'action'=>'hangup',
                  'position'=>[
                        "x"=>67,
                        "y"=>33
                  ]
                ];
                $flow[$hangKey]=$endPointsArray;
                break;
            case 2://跳转指定多伦会话
                $hangKey            = "F".$nextId."_".$nextId;
                $array[$hangKey]    = $info;
                $keyReturn          = $nextId."_".$nextId;
                $resReturn          = $info;
                break;
            case 3://指定主流程
                $hangKey            = "F".$treeFirstNode[$nextId]['node_id'];
                $array[$hangKey]    = $info;
                $keyReturn          = $treeFirstNode[$nextId]['node_id'];
                $resReturn          = $info;
                break;
      }
      return [$array,$keyReturn,$resReturn,$flow];
    }


    //所有的多伦会话节点流程
    public function getMulArgArray($where)
    {
      $argList= SpeechMulProcessSettingModel::create()->getAll($where,"set_key,set_value,node_mul_id");//所有的参数节点流程
      $argArray = [];
      foreach ($argList as $argK=>$argValue){
            $argArray[$argValue["node_mul_id"]][$argValue["set_key"]] = $argValue["set_value"];
      }
      return $argArray;
    }



}

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 新一代电话机器人开源PHP源代码