当前位置:   article > 正文

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

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

话术管理截图

坐席页面

管理员页面

线路管理

机器人话术代码:

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/247676
推荐阅读
相关标签
  

闽ICP备14008679号