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

news2024/9/22 21:24:01

使用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;
    }



}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简易内存池2 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 200分 题解&#xff1a; Java / Python / C 题目描述 请实现一个简易内存池,根据请求命令完成内存分配和释放。 内存池支持两种操作命令&#xff0c;REQUEST和RELEASE&#xff0c;其格式为: REQUEST请求的内存大小 …

golang学习5,glang的web的restful接口

1. //返回json r.GET("/getJson", controller.GetUserInfo) package mainimport (/*"net/http"*/"gin/src/main/controller""github.com/gin-gonic/gin" )func main() {r : gin.Default()r.GET("/get", func(ctx *…

【研发日记】Matlab/Simulink技能解锁(三)——在Stateflow编辑窗口Debug

文章目录 前言 State断点 Transition断点 条件断点 按State步进 Watch Data Value Sequence Viewer 分析和应用 总结 前言 见《【研发日记】Matlab/Simulink技能解锁(一)——在Simulink编辑窗口Debug》 见《【研发日记】Matlab/Simulink技能解锁(二)——在Function编辑…

数据结构开篇

目录 一. 如何学好数据结构二. 基本概念和术语2.1 区分数据、数据元素、数据项、数据对象2.2 数据结构2.2.1 逻辑结构2.2.2 存储结构 2.3 数据类型和抽象数据类型2.4 抽象数据类型的实现 \quad 一. 如何学好数据结构 勤于思考;多做练习;多上机;善于寻求帮助;不怕困难&#xff…

NLP算法实战项目:使用 BERT 进行文本多分类

大多数研究人员将他们的研究论文提交给学术会议&#xff0c;因为这是更快地使研究结果可用的途径。寻找和选择合适的会议一直是一项具有挑战性的任务&#xff0c;特别是对于年轻的研究人员来说。基于先前会议论文集的数据&#xff0c;研究人员可以增加其论文被接受和发表的机会…

基于协同过滤算法的图书推荐系统

目录 一、功能介绍 二、开发环境 三、安装部署说明 一、功能介绍 本系统是一个采用协同过滤算法的图书推荐系统。 数据集&#xff1a;数据集来自亚马逊开源的Book-Crossings数据集。Book-Crossings数据集包含 278,858 个用户的 271,379 本书的 1,149,780 个评分。评分范围从1…

FL Studio选购指南:新手小白应该选择哪个版本FL Studio?

很多打算入手正版FL Studio的新手朋友都会纠结一个问题&#xff1a;哪个版本的FL Studio更适合我&#xff0c;到底应该入手哪一款FL Studio&#xff1f;本文会介绍每个版本之间的差异点&#xff0c;并带大家选择适合自己的FL Sudio版本。 FL Studio全版本 在选购前有一些小知识…

25高数考研张宇 -- 公式总结(更新中)

1. 两个重要极限 (1) lim ⁡ x → 0 sin ⁡ x x 1 \lim _{x \rightarrow 0} \frac{\sin x}{x}1 limx→0​xsinx​1, 推广形式 lim ⁡ f ( x ) → 0 sin ⁡ f ( x ) f ( x ) 1 \lim _{f(x) \rightarrow 0} \frac{\sin f(x)}{f(x)}1 limf(x)→0​f(x)sinf(x)​1. (2) lim ⁡…

小项目:2024/3/2

一、TCP机械臂测试 代码&#xff1a; #include <myhead.h> #define SER_IP "192.168.125.254" //服务器端IP #define SER_PORT 8888 //服务器端端口号#define CLI_IP "192.168.199.131" //客户端IP #define CLI_P…

Linux线程【互斥与同步】

目录 1.资源共享问题 1.1多线程并发访问 1.2临界区和临界资源 1.3互斥锁 2.多线程抢票 2.1并发抢票 2.2 引发问题 3.线程互斥 3.1互斥锁相关操作 3.1.1互斥锁创建与销毁 3.1.2、加锁操作 3.1.3 解锁操作 3.2.解决抢票问题 3.2.1互斥锁细节 3.3互斥…

[NSSCTF 2nd] web复现

1.php签到 <?phpfunction waf($filename){$black_list array("ph", "htaccess", "ini");$ext pathinfo($filename, PATHINFO_EXTENSION);foreach ($black_list as $value) {if (stristr($ext, $value)){return false;}}return true; }if(i…

【Spring IoC】实验四:特殊值处理

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

【NDK系列】Android tombstone文件分析

文件位置 data/tombstone/tombstone_xx.txt 获取tombstone文件命令&#xff1a; adb shell cp /data/tombstones ./tombstones 触发时机 NDK程序在发生崩溃时&#xff0c;它会在路径/data/tombstones/下产生导致程序crash的文件tombstone_xx&#xff0c;记录了死亡了进程的…

electron nsis 安装包 window下任务栏无法正常固定与取消固定 Pin to taskbar

问题 win10系统下&#xff0c;程序任务栏在固定后取消固定&#xff0c;展示的程序内容异常。 排查 1.通过论坛查询&#xff0c;应该是与app的api setAppUserModelId 相关 https://github.com/electron/electron/issues/3303 2.electron-builder脚本 electron-builder…

ABAP - SALV教程04 添加状态栏

CL_SALV_TABLE中提供了 GET_FUNCTIONS方法.GET_FUNCTIONS方法返回的是一个CL_SALV_FUNCTIONS_LIST类型的实例对象. 类CL_SALV_FUNCTIONS_LIST两个方法(SET_ALL、SET_DEFAULT)可以添加标准状态栏 实现步骤: 定义SET_STATUS私有方法. PRIVATE SECTION.METHODS:set_status CHA…

qt 基于百度API的人脸识别

百度云官网&#xff1a;点击跳转 一、创建应用 跳转进去&#xff0c;可以看到以下界面&#xff1a; 点击红色圈内的“去创建”&#xff0c;创建自己的项目。可以看到以下界面&#xff1a; 输入“应用名称”&#xff0c;并勾选“人脸对比”&#xff0c;还要到页面的最后输入“应…

董兆祥出席工业废水资源化,开创变废为宝新途径演讲

演讲嘉宾&#xff1a;董兆祥 董事长 河北奥博水处理有限公司 演讲题目&#xff1a;工业废水资源化&#xff0c;开创变废为宝新途径 会议简介 “十四五”规划中提出&#xff0c;提高工业、能源领城智能化与信息化融合&#xff0c;明确“低碳经济”新的战略目标&#xff0c;热…

C++之stack

1、stack简介 stack是实现的一个先进后出&#xff0c;后进先出的容器。它只有一个出口&#xff0c;只能操作最顶端元素。 2、stack库函数 &#xff08;1&#xff09;push() //向栈压入一个元素 &#xff08;2&#xff09;pop() //移除栈顶元素 &#xff08;3…

‘conda‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件

如果你在运行 conda 命令时收到了 ‘conda’ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 的错误消息&#xff0c;这可能意味着 Anaconda 并没有正确地添加到你的系统路径中。 1.你可以尝试手动添加 Anaconda 到系统路径中。以下是在 Windows 系统上添加…

RPA中国 x UiPath | 第六届RPA极客挑战赛,3月16日上海开赛!

随着人工智能技术的不断进步以及数字化转型的深入&#xff0c;企业对于高效、精准、自动化的业务流程需求日益迫切。RPA技术作为连接人类工作与机器操作的桥梁&#xff0c;正逐渐从规则驱动发展为智能决策的助手。 由RPA中国联合UiPath共同主办的【第六届RPA极客挑战赛】将于2…