新一代电话机器人开源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外呼管理截图

话术管理截图

坐席页面

管理员页面

线路管理

机器人话术代码:

<?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 function  checkNextFlow($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;
    }



}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/423930.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android java基础_异常

一.异常的概念 在Java中&#xff0c;异常&#xff08;Exception&#xff09;是指程序执行过程中可能出现的不正常情况或错误。它是一个事件&#xff0c;它会干扰程序的正常执行流程&#xff0c;并可能导致程序出现错误或崩溃。 异常在Java中是以对象的形式表示的&#xff0c;…

力扣hot100题解(python版48-50题)

48、路径总和III 给定一个二叉树的根节点 root &#xff0c;和一个整数 targetSum &#xff0c;求该二叉树里节点值之和等于 targetSum 的 路径 的数目。 路径 不需要从根节点开始&#xff0c;也不需要在叶子节点结束&#xff0c;但是路径方向必须是向下的&#xff08;只能从…

香港服务器选择指南(挑选香港服务器的几个标准)

​  随着全球化的加速和互联网的普及&#xff0c;跨境访问和外贸活动越来越频繁。在这个背景下&#xff0c;香港服务器作为一种国际化的基础设施&#xff0c;受到了广泛欢迎。本文将探讨企业在选择香港服务器时应关注的几个标准事项。 1.可靠性和正常运行时间 停机可能会给企…

Linux:kubernetes(k8s)node节点加入master主节点(3)

Linux&#xff1a;kubernetes&#xff08;k8s&#xff09;搭建mater节点&#xff08;kubeadm&#xff0c;kubectl&#xff0c;kubelet&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/136415575?spm1001.2014.3001.5502 我在上一章部署好了主节点&…

qsort使用

qsort 是用来排序的数据的库函数,底层使用的是快速排序的方式 排序方式有:选择,冒泡,插入,快速, 希尔...... 对于qsort这个库函数: void qsort(void* base,size_t num,size_t size,int (*compar)(const void*,const void*) 其中 void* base 是指针,指向的是待排序的数组的第…

棋牌室计时计费管理系统的灯控器连接教程

棋牌室计时计费管理系统的灯控器连接教程 一、前言 以下教程以 佳易王棋牌室计时计费管理系统软件V18.0为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 如上图&#xff0c;计时计费软件在开始计时的时候&#xff0c;点击 开始计时 如果连接了…

第19章-IPv6基础

1. IPv4的缺陷 2. IPv6的优势 3. 地址格式 3.1 格式 3.2 长度 4. 地址书写压缩 4.1 段内前导0压缩 4.2 全0段压缩 4.3 例子1 4.4 例子 5. 网段划分 5.1 前缀 5.2 接口标识符 5.3 前缀长度 5.4 地址规模分类 6. 地址分类 6.1 单播地址 6.2 组播地址 6.3 任播地址 6.4 例子 …

java-ssm-jsp-宠物常规护理知识管理系统设计与实现

java-ssm-jsp-宠物常规护理知识管理系统设计与实现 获取源码——》公主号&#xff1a;计算机专业毕设大全

VirtualBox 桥接网卡 未指定 “未能启动虚拟电脑Ubuntu,由于下述物理网卡未找到:”

解决办法&#xff0c;安装虚拟网卡&#xff0c;win11查找方式&#xff1a;控制面板→网络和共享中心→更改适配器设置 此时出现下面情况就算安装成功 但是如果报错&#xff1a;找不到指定的模块 则按下面步骤删除干净垃圾重新上面操作 先安装CCleaner, 链接:CCleaner Makes Y…

Salesforce CPQ - 02 - Quote Price

最近又有客户来咨询学习Salesforce CPQ&#xff0c;所以本人总结了下近几年CPQ培训的一些实际案例拿出来分享给大家&#xff1b; 再次介绍下本人是一位Salesforce十多年的从业者。 先来介绍下Salesforce的价格体系&#xff0c;再介绍下各个Product Price是如何配置及使用的&a…

2024 年 5 大移动应用安全预测

2024 年已经到来&#xff0c;企业必须为接下来的事情做好准备。为未来做好准备需要回顾过去。企业可以从那里判断自己当前的状态&#xff0c;从而做出准确的预测。 移动应用程序安全仍然是企业关注的一个重要问题&#xff0c;特别是当消费者依赖应用程序来完成更重要的任务时。…

docker三剑客compose+machine+swarm小结

背景 在容器领域&#xff0c;不少公司会使用docker三剑客composemachineswarm进行容器编排和部署&#xff0c;本文就简单记录下这几个工具的用法 三剑客composemachineswarm compose compose主要是用于容器编排&#xff0c;我们部署容器时&#xff0c;容器之间会有依赖&…

【yolov8部署实战】VS2019环境下使用C++和OpenCV环境部署yolo项目|含详细注释源码

一、前言 之前一阵子一直在做的就是怎么把yolo项目部署成c项目&#xff0c;因为项目需要嵌套进yolo模型跑算法。因为自己也是本科生小白一枚&#xff0c;基本上对这方面没有涉猎过&#xff0c;自己一个人从网上到处搜寻资料&#xff0c;写代码&#xff0c;调试&#xff0c;期间…

Android 基础入门 基础简介

1. 观察App运行日志 2.Android 开发设计的编程语言 koltin Java c c 3.工程目录结构 4.Gradle 5.build.gradle 文件解析 plugins {id("com.android.application")//用了哪些插件 主配置文件版本控制 所以这里不用写版本 }android {namespace "com.tiger.myap…

C#入门:简单数据类型和强制类型转换

本文由 简悦 SimpRead 转码&#xff0c; 原文地址 mp.weixin.qq.com 本期来讲讲 unity 的脚本语言 —C#&#xff0c;C# 的简单数据类型及范围和强制类型转化的方法。这可是 unity 游戏开发必备技能。 1. 简单数据类型 各个类型的范围&#xff1a; byte -> System.Byte (字节…

STM32利用标准库编写程序proteus仿真流水灯

首先就是建立一个proteus工程&#xff0c;导入元器件画图&#xff1a; 接下来就是下载我已经都复制好的工程&#xff0c;下载后直接解压缩就能用&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1Nx5p3Tif6eHBIVkcPfsj9w?pwd1234 提取码&#xff1a;1234 解压后打开…

Ps:快照

“历史记录” History面板可分为快照区和历史记录状态区两个部分。 Photoshop 的快照 snapshot功能允许用户保存当前工作状态的完整副本&#xff0c;这包括图像的所有图层&#xff08;包括图层可见性&#xff09;、图层样式、选区以及颜色模式、位深度等其他属性。 通过创建当前…

《猛兽派对》好玩吗值得买吗?苹果电脑也能装《猛兽派对》吗?猛兽派对好友通行证 动物派对 猛兽对战游戏

目录 一、《猛兽派对》好玩吗&#xff1f; 游戏玩法&#xff1a; 物理引擎&#xff1a; 关卡设计&#xff1a; 游戏特色&#xff1a; 评价&#xff1a; 荣誉&#xff1a; 二、苹果电脑也能装《猛兽派对》吗&#xff1f; 第1步&#xff1a;下载并安装CrossOver这款软件…

【python】1.python3.12.2和pycharm社区版的安装指南

欢迎来CILMY23的博客喔&#xff0c;本篇为【python】1.python3.12.2和pycharm社区版的安装指南&#xff0c;感谢观看&#xff0c;支持的可以给个一键三连&#xff0c;点赞关注收藏。 目录 一、python3.12.2的下载与安装 1.1下载 1.2安装 二、pycharm的安装 2.1下载安装 2…

windows下安装cnpm

cnpm是淘宝团队开发的一个针对中国用户的npm镜像源&#xff0c;它是npm的一个定制版本。由于国外的npm源在国内访问速度较慢&#xff0c;所以cnpm镜像源可以提供更快的下载速度。cnpm的使用方式与npm基本相同&#xff0c;只需将npm替换为cnpm即可。 要想使用cnpm等先安装node.…