robot.class.php 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067
  1. <?php
  2. if (!defined('IN_ONLINE')) {
  3. exit('Access Denied');
  4. }
  5. /**
  6. * Description of robot
  7. *
  8. * @author Administrator
  9. */
  10. class robot{
  11. private static $_robot;
  12. function __construct() {
  13. }
  14. public static function getInstance() {
  15. global $memory_limit;
  16. $memory_limit = ini_get("memory_limit");
  17. ini_set("memory_limit", '2048M');
  18. if (!self::$_robot) {
  19. $c = __CLASS__;
  20. self::$_robot = new $c;
  21. }
  22. return self::$_robot;
  23. }
  24. public function robot_chat_log() {
  25. $operate = utils::_get('operate');
  26. $operate = strtolower($operate);
  27. if (empty($operate)) {
  28. $column = column::getInstance()->getDisplayColumn('Robot_Chat_Search');
  29. $OperationTableColumns = column::getInstance()->tableColumns('Robot_Chat_Search',$column);
  30. $data['OperationTableColumns'] = $OperationTableColumns;
  31. common::echo_json_encode(200,$data);
  32. exit();
  33. }
  34. if ($operate == "search") {
  35. $cp = common::check_input($_POST ['cp']); //current_page
  36. $ps = common::check_input($_POST ['ps']); //ps
  37. if (empty($ps))
  38. $ps = 10;
  39. $sqlWhere = ' where 1=1';
  40. $text_search = common::check_input($_POST ['text_search']);
  41. $user_type = common::check_input($_POST ['user_type']);
  42. $question_type = common::check_input($_POST ['question_type']);
  43. $answer_type = common::check_input($_POST ['answer_type']);
  44. $answer_satisfication = common::check_input($_POST ['answer_satisfication']);
  45. $response_duration_type = common::check_input($_POST ['response_duration_type']);
  46. $response_duration_num = common::check_input($_POST ['response_duration_num']);
  47. if (!empty($text_search)){
  48. $sqlWhere .= " and (question_id ilike '%" . $text_search . "%' or user_name ilike '%" . $text_search . "%')";
  49. }
  50. if (isset($_POST['question_date_start']) && !empty($_POST['question_date_start'])){
  51. $sqlWhere .= " and question_date >= '" . common::usDate2sqlDate($_POST['question_date_start']) . " 00:00:00'";
  52. }
  53. if (isset($_POST['question_date_end']) && !empty($_POST['question_date_end'])){
  54. $sqlWhere .= " and question_date <= '" . common::usDate2sqlDate($_POST['question_date_end']) . " 23:59:59'";
  55. }
  56. if (!empty($user_type)){
  57. $sqlWhere .= " and user_type = '".strtolower($user_type)."'";
  58. }
  59. if (!empty($question_type)){
  60. //$question_type = $question_type == 'Free Text' ? "Free Question" : $question_type;
  61. $sqlWhere .= " and question_type = '$question_type'";
  62. }
  63. if (!empty($answer_type)){
  64. $sqlWhere .= " and answer_type = '$answer_type'";
  65. }
  66. if (!empty($answer_satisfication)){
  67. $answer_satisfication = $answer_satisfication == 'Null' ? '' : $answer_satisfication;
  68. $sqlWhere .= " and COALESCE(answer_satisfication,'') = '$answer_satisfication'";
  69. }
  70. if (!empty($response_duration_type) && !empty($response_duration_num)){
  71. if($response_duration_type == "thanOrEqual"){
  72. $sqlWhere .= " and response_duration >= '$response_duration_num'";
  73. } elseif ($response_duration_type == "equal"){
  74. $sqlWhere .= " and response_duration = '$response_duration_num'";
  75. } else {
  76. $sqlWhere .= " and response_duration <= '$response_duration_num'";
  77. }
  78. }
  79. $rc = $_POST ['rc'];
  80. if ($rc == - 1) {
  81. $sql = "SELECT count(1) from public.kln_robot_chat_log" . $sqlWhere;
  82. error_log($sql);
  83. $rc = common::excuteOneSql($sql);
  84. }
  85. $tp = ceil($rc / $ps);
  86. $order_by = " id desc";
  87. if ($rc > 0) {
  88. $sql = "SELECT ".column::getInstance()->getSearchSqlForDisplay('Robot_Chat_Search').",
  89. to_char(response_time, 'YYYY/MM/DD HH24:MI:SS') as _response_time,
  90. to_char(request_time, 'YYYY/MM/DD HH24:MI:SS') as _request_time,
  91. request_id
  92. from public.kln_robot_chat_log " . $sqlWhere .
  93. " order by $order_by limit " . $ps . " offset " . ($cp - 1) * $ps;
  94. $rs = common::excuteListSql($sql);
  95. foreach($rs as $key => $val){
  96. $rs[$key]["response_time"] = $val["_response_time"];
  97. $rs[$key]["request_time"] = $val["_request_time"];
  98. }
  99. $arrTmp = array('searchData' => $rs,
  100. 'tmp_search' => common::deCode($sql, 'E'),
  101. 'rc' => intval($rc),
  102. 'ps' => intval($ps),
  103. 'cp' => intval($cp),
  104. 'tp' => intval($tp));
  105. } else {
  106. $arrTmp = array('searchData' => array(),
  107. 'tmp_search' => common::deCode($sql, 'E'),
  108. 'rc' => intval($rc),
  109. 'ps' => intval($ps),
  110. 'cp' => intval($cp),
  111. 'tp' => intval($tp));
  112. }
  113. common::echo_json_encode(200,$arrTmp);
  114. exit();
  115. }
  116. if ($operate == "excel") {
  117. $sql = common::deCode($_POST ['tmp_search'], 'D');
  118. $sql = substr($sql, 0, strripos($sql, " limit"));
  119. if(!empty($sql)){
  120. $rss = common::excuteListSql($sql);
  121. }
  122. foreach($rss as $key =>$val){
  123. $rs[$key]["response_time"] = $val["_response_time"];
  124. $rs[$key]["request_time"] = $val["_request_time"];
  125. }
  126. common::echo_json_encode(200,array("msg"=>"success","Data" => $rss));
  127. exit;
  128. }
  129. if ($operate == "api_log") {
  130. $request_id = common::check_input($_POST['request_id']);
  131. $sql = "select question_content,ai_response_content from public.kln_robot_chat_log where request_id = '$request_id'";
  132. $data = common::excuteObjectSql($sql);
  133. $question_content = $data['question_content'];
  134. $ai_response_content = json_decode($data['ai_response_content']);
  135. common::echo_json_encode(200,array("msg"=>"success","Data" => array("request_content" =>$question_content, "ai_response_content"=>$ai_response_content)));
  136. //common::echo_json_encode(200,array("msg"=>"success","Data" => $data));
  137. exit;
  138. }
  139. }
  140. public function robot_api_log() {
  141. $operate = utils::_get('operate');
  142. $operate = strtolower($operate);
  143. if (empty($operate)) {
  144. $column = column::getInstance()->getDisplayColumn('Robot_API_Search');
  145. $OperationTableColumns = column::getInstance()->tableColumns('Robot_API_Search',$column);
  146. $data['OperationTableColumns'] = $OperationTableColumns;
  147. common::echo_json_encode(200,$data);
  148. exit();
  149. }
  150. if ($operate == "search") {
  151. $cp = common::check_input($_POST ['cp']); //current_page
  152. $ps = common::check_input($_POST ['ps']); //ps
  153. if (empty($ps))
  154. $ps = 10;
  155. //只查询自由问题
  156. $sqlWhere = " where 1=1 and question_type = 'Free Text' ";
  157. $text_search = common::check_input($_POST ['text_search']);
  158. $ai_model = common::check_input($_POST ['ai_model']);
  159. $response_duration_type = common::check_input($_POST ['response_duration_type']);
  160. $response_duration_num = common::check_input($_POST ['response_duration_num']);
  161. if (!empty($text_search)){
  162. $sqlWhere .= " and (question_id ilike '%" . $text_search . "%' or request_id ilike '%" . $text_search . "%')";
  163. }
  164. if (!empty($ai_model)){
  165. $sqlWhere .= " and lower(ai_model) = '".strtolower($ai_model)."'";
  166. }
  167. if (isset($_POST['request_date_start']) && !empty($_POST['request_date_start']))
  168. $sqlWhere .= " and request_time >= '" . common::usDate2sqlDate($_POST['request_date_start']) . " 00:00:00'";
  169. if (isset($_POST['request_date_end']) && !empty($_POST['request_date_end']))
  170. $sqlWhere .= " and request_time <= '" . common::usDate2sqlDate($_POST['request_date_end']) . " 23:59:59'";
  171. if (!empty($response_duration_type) && !empty($response_duration_num)){
  172. if($response_duration_type == "thanOrEqual"){
  173. $sqlWhere .= " and response_duration >= '$response_duration_num'";
  174. } elseif ($response_duration_type == "equal"){
  175. $sqlWhere .= " and response_duration = '$response_duration_num'";
  176. } else {
  177. $sqlWhere .= " and response_duration <= '$response_duration_num'";
  178. }
  179. }
  180. $rc = $_POST ['rc'];
  181. if ($rc == - 1) {
  182. $sql = "SELECT count(1) from public.kln_robot_chat_log" . $sqlWhere;
  183. $rc = common::excuteOneSql($sql);
  184. }
  185. $tp = ceil($rc / $ps);
  186. $order_by = " id desc";
  187. if ($rc > 0) {
  188. $sql = "SELECT ".column::getInstance()->getSearchSqlForDisplay('Robot_API_Search').",
  189. to_char(response_time, 'YYYY/MM/DD HH24:MI:SS') as _response_time,
  190. to_char(request_time, 'YYYY/MM/DD HH24:MI:SS') as _request_time
  191. from public.kln_robot_chat_log " . $sqlWhere .
  192. " order by $order_by limit " . $ps . " offset " . ($cp - 1) * $ps;
  193. $rs = common::excuteListSql($sql);
  194. foreach($rs as $key => $val){
  195. $rs[$key]["response_time"] = $val["_response_time"];
  196. $rs[$key]["request_time"] = $val["_request_time"];
  197. }
  198. $arrTmp = array('searchData' => $rs,
  199. 'tmp_search' => common::deCode($sql, 'E'),
  200. 'rc' => $rc,
  201. 'ps' => $ps,
  202. 'cp' => $cp,
  203. 'tp' => $tp);
  204. } else {
  205. $arrTmp = array('searchData' => array(),
  206. 'tmp_search' => common::deCode($sql, 'E'),
  207. 'rc' => $rc,
  208. 'ps' => $ps,
  209. 'cp' => $cp,
  210. 'tp' => $tp);
  211. }
  212. common::echo_json_encode(200,$arrTmp);
  213. exit();
  214. }
  215. if ($operate == "excel") {
  216. $sql = common::deCode($_POST ['tmp_search'], 'D');
  217. $sql = substr($sql, 0, strripos($sql, " limit"));
  218. if(!empty($sql)){
  219. $rss = common::excuteListSql($sql);
  220. }
  221. foreach($rss as $key =>$val){
  222. $rs[$key]["response_time"] = $val["_response_time"];
  223. $rs[$key]["request_time"] = $val["_request_time"];
  224. }
  225. common::echo_json_encode(200,array("msg"=>"success","Data" => $rss));
  226. exit;
  227. }
  228. if ($operate == "api_log") {
  229. $request_id = common::check_input($_POST['request_id']);
  230. $sql = "select request_content,ai_response_content from public.kln_robot_chat_log where request_id = '$request_id'";
  231. $data = common::excuteObjectSql($sql);
  232. common::echo_json_encode(200,array("msg"=>"success","Data" => $data));
  233. exit;
  234. }
  235. }
  236. public function robot_prompt_configuration() {
  237. $operate = utils::_get('operate');
  238. $operate = strtolower($operate);
  239. if (empty($operate)) {
  240. //查询所有配置信息 目前只有一个表一个数据
  241. $configuration = common::excuteObjectSql("select id, character_name,professional_field,main_tasks,table_name,table_description,
  242. table_structure_configuration,response_rule_configuration,output_format_configuration,fixed_problem_configuration
  243. from public.kln_robot_prompt_configuration where id = 1");
  244. $PromptAndVue = $this->dealPromptFormatAndVue($configuration);
  245. //tableDat-VUE
  246. $tableData = $PromptAndVue["vuedata"]["tableData"];
  247. //stepData -VUE
  248. $stepData = $PromptAndVue["vuedata"]["stepData"];
  249. //formatList -VUE
  250. $formatListType = $PromptAndVue["vuedata"]["formatListType"];
  251. $formatList = $PromptAndVue["vuedata"]["formatList"];
  252. //promptFormat
  253. $promptFormat =$PromptAndVue["promptFormat"];
  254. //获取历史变更记录
  255. $old_configuration = $this->getChangedLog($configuration["id"]);
  256. $id = $configuration['id'];
  257. $character_name = $configuration['character_name'];
  258. $professional_field = $configuration['professional_field'];
  259. $main_tasks = $configuration['main_tasks'];
  260. $table_name = $configuration['table_name'];
  261. $table_description = $configuration['table_description'];
  262. $prompt_summary = array("您是专門从事".$professional_field."的".$character_name."...",
  263. "表名:{".$table_name."}...",
  264. "响应规则,请按以下步骤处理...");
  265. $data = array(
  266. "id"=>$id,
  267. "character_name"=>$character_name,
  268. "professional_field"=>$professional_field,
  269. "main_tasks"=>$main_tasks,
  270. "table_name"=>$table_name,
  271. "table_description"=>$table_description,
  272. "tableData"=>$tableData,
  273. "stepData"=>$stepData,
  274. "formatList"=>$formatList,
  275. "formatListType"=>$formatListType,
  276. "complete_prompt"=>$promptFormat,
  277. "prompt_summary"=>$prompt_summary,
  278. "prompt_log_record"=>$old_configuration
  279. );
  280. $data = utils::arrayRemoveNull($data);
  281. common::echo_json_encode(200,$data);
  282. exit();
  283. }
  284. if ($operate == "save") {
  285. $id =common::check_input($_POST['id']);
  286. $character_name = common::check_input($_POST['role_name']);
  287. $professional_field = common::check_input($_POST['professional_field']);
  288. $main_tasks = common::check_input($_POST['main_tasks']);
  289. $table_name = common::check_input($_POST['table_name']);
  290. $table_description = common::check_input($_POST['table_description']);
  291. $outputvalue = common::check_input($_POST['outputvalue']);
  292. $tableDataList = $_POST['tableDataList'];
  293. $stepData = $_POST['stepData'];
  294. $formatList = $_POST['formatList'];
  295. $table_structure_configuration = common::check_input(json_encode($tableDataList));
  296. $response_rule_configuration = common::check_input(json_encode($stepData));
  297. $output_data = array("output_type"=>$outputvalue,"data"=>$formatList);
  298. $output_format_configuration = common::check_input(json_encode($output_data));
  299. if(empty($id)){
  300. $sql = "INSERT INTO public.kln_robot_prompt_configuration(
  301. character_name, professional_field, main_tasks, table_name,
  302. table_description, table_structure_configuration, response_rule_configuration,
  303. output_format_configuration, created_by, created_time)
  304. VALUES ('$character_name', '$professional_field', '$main_tasks', '$table_name',
  305. '$table_description', '$table_structure_configuration', '$response_rule_configuration',
  306. '$output_format_configuration', '"._getLoginName()."', now());";
  307. }else{
  308. $sql = "update public.kln_robot_prompt_configuration
  309. set character_name = '$character_name',professional_field ='$professional_field', main_tasks = '$main_tasks',
  310. table_name = '$table_name',table_description = '$table_description',
  311. table_structure_configuration = '$table_structure_configuration',
  312. response_rule_configuration = '$response_rule_configuration',
  313. output_format_configuration = '$output_format_configuration'
  314. where id = '$id';";
  315. //插入变更日志记录
  316. $sql .= "INSERT INTO public.kln_robot_prompt_configuration_log(ref_id, character_name, professional_field, main_tasks, table_name,
  317. table_description, table_structure_configuration, response_rule_configuration,
  318. output_format_configuration, created_by, created_time)
  319. VALUES ('$id','$character_name', '$professional_field', '$main_tasks', '$table_name',
  320. '$table_description', '$table_structure_configuration', '$response_rule_configuration',
  321. '$output_format_configuration', '"._getLoginName()."', now());";
  322. }
  323. error_log($sql);
  324. $rs = common::excuteUpdateSql($sql);
  325. if (!$rs) {
  326. $data = array("msg" => "save Error");
  327. } else {
  328. $data = array("msg" => "save Successful");
  329. }
  330. $data = array("msg" => "save Successful");
  331. common::echo_json_encode(200,$data);
  332. exit();
  333. }
  334. if($operate == "preview_propmpt_witout_save"){
  335. $character_name = common::check_input($_POST['role_name']);
  336. $professional_field = common::check_input($_POST['professional_field']);
  337. $main_tasks = common::check_input($_POST['main_tasks']);
  338. $table_name = common::check_input($_POST['table_name']);
  339. $table_description = common::check_input($_POST['table_description']);
  340. $outputvalue = common::check_input($_POST['outputvalue']);
  341. $tableDataList = $_POST['tableDataList'];
  342. $stepData = $_POST['stepData'];
  343. $formatList = $_POST['formatList'];
  344. $table_structure_configuration = common::check_input(json_encode($tableDataList));
  345. $response_rule_configuration = common::check_input(json_encode($stepData));
  346. $output_data = array("output_type"=>$outputvalue,"data"=>$formatList);
  347. $output_format_configuration = common::check_input(json_encode($output_data));
  348. //组合拼接需要的数据
  349. $configuration = array("character_name"=>$character_name,
  350. "professional_field"=>$professional_field,
  351. "main_tasks"=>$main_tasks,
  352. "table_name"=>$table_name,
  353. "table_description"=>$table_description,
  354. "professional_field"=>$professional_field,
  355. "table_structure_configuration"=>$table_structure_configuration,
  356. "response_rule_configuration" =>$response_rule_configuration,
  357. "output_format_configuration" =>$output_format_configuration
  358. );
  359. $PromptAndVue = $this->dealPromptFormatAndVue($configuration);
  360. //promptFormat
  361. $promptFormat =$PromptAndVue["promptFormat"];
  362. $character_name = empty($configuration['character_name']) ? "" :$configuration['character_name'];
  363. $professional_field = empty($configuration['professional_field']) ? "" :$configuration['professional_field'];
  364. $main_tasks = empty($configuration['main_tasks']) ? "" :$configuration['main_tasks'];
  365. $table_name = empty($configuration['table_name']) ? "" :$configuration['table_name'];
  366. $table_description = empty($configuration['table_description']) ? "" :$configuration['table_description'];
  367. $prompt_summary = array("您是专門从事".$professional_field."的".$character_name."...",
  368. "表名:{".$table_name."}...",
  369. "响应规则,请按以下步骤处理...");
  370. $data = array(
  371. "complete_prompt"=>$promptFormat,
  372. "prompt_summary"=>$prompt_summary
  373. );
  374. common::echo_json_encode(200,$data);
  375. exit();
  376. }
  377. if($operate == "test_with_ds_claude"){
  378. //$data = "### 查询结果\n\n- **总hbol数量**: 3581667\n\n- **前10票hbol信息**:\n\n | HBOL | MBOL | 运输方式 | 服务类型 | 发货人 | 收货人 | 数量 | 总重量(KG) | 预计离港时间 | 预计到港时间 |\n |------|------|----------|----------|--------|--------|------|------------|--------------|--------------|\n | E1205546127 | UASUCNNBO432262 | sea | CY/CY | HANGZHOU ZHONGSHEN BAGS & LUGGAGES CO.LTD. | C.Y IMPORT CORPORATION | 455 | 8689.000 | 2012-05-31 | 2012-07-09 |\n| E120537061 | HJSCFOC202818100 | sea | CY/DOOR | NANLIN(FUJIAN) INDUSTRIES CO.,LTD | CHICAGO STOOL & CHAIR INC | 1200 | 14400.000 | 2012-05-31 | 2012-06-18 |\n| E120537095 | MAEU602116826 | sea | CY/CY | LONG SHAN IMP & EXP CO LTD | COMPOSITE TECHNOLOGY INTERNATIONAL INC | 12 | 19900.000 | 2012-05-27 | 2012-07-02 |\n| E1205570012 | COSU6025917580 | sea | CY/DOOR | SHAANXI FUHUA CHEMICAL CO., LTD | CIMBAR PERFORMANCE MINERALS | 38 | 34396.000 | 2012-05-29 | 2012-07-06 |\n| E1205391561A | YMLUW230775660 | sea | CFS/CY | WISTRON NEWEB (KUNSHAN) CORPORATION | ARUBA NETWORKS | 30 | 391.000 | 2012-05-29 | 2012-06-16 |\n| A1208395110 | ZIMUSNH5455049 | sea | CFS/CFS | SHANGHAI EAST BEST INT'L BUSINESS DEV.CO | LUMINA GLOBAL, INC. | 2 | 2600.000 | 2012-08-25 | 2012-09-06 |\n| E1205391561 | YMLUW230775660 | sea | CY/CY | SERCOMM CORP. C/O SERNET | ARUBA NETWORKS | 354 | 2833.940 | 2012-05-29 | 2012-06-16 |\n| E1205395237 | YMLUW230777029 | sea | CY/CY | UNIPAK RESOURCES CO.,LTD. | PAN PACIFIC PLASTIC | 404 | 2424.000 | 2012-05-29 | 2012-06-16 |\n| X1205480323 | YMLUW241023500 | sea | CY/CY | SHANGHAI AUTOMOBILE IMPORT&EXPORT CO.,LTD. | AMERICAN CONDENSER | 1082 | 5178.000 | 2012-05-25 | 2012-06-12 |\n| E1205359270 | MAEU602108615 | sea | CY/CY | LZ CASKET MANUFACTURING CO.,LTD | BRICK ALLEY,LLC | 64 | 5901.700 | 2012-05-29 | 2012-07-06 |\n ";
  379. //$data = "### 查询结果\n\n- **总hbol数量**: 3581667\n\n- **前10票hbol信息**:\n\n| HBOL | MBOL | 运输方式 | 服务类型 | 发货人 | 收货人 | 数量 | 总重量(KG) | 预计离港时间 | 预计到港时间 |\n|------|------|----------|----------|--------|--------|------|------------|--------------|--------------|\n| E1205546127 | UASUCNNBO432262 | sea | CY/CY | HANGZHOU ZHONGSHEN BAGS & LUGGAGES CO.LTD. | C.Y IMPORT CORPORATION | 455 | 8689.000 | 2012-05-31 | 2012-07-09 |\n| E120537061 | HJSCFOC202818100 | sea | CY/DOOR | NANLIN(FUJIAN) INDUSTRIES CO.,LTD | CHICAGO STOOL & CHAIR INC | 1200 | 14400.000 | 2012-05-31 | 2012-06-18 |\n| E120537095 | MAEU602116826 | sea | CY/CY | LONG SHAN IMP & EXP CO LTD | COMPOSITE TECHNOLOGY INTERNATIONAL INC | 12 | 19900.000 | 2012-05-27 | 2012-07-02 |\n| E1205570012 | COSU6025917580 | sea | CY/DOOR | SHAANXI FUHUA CHEMICAL CO., LTD | CIMBAR PERFORMANCE MINERALS | 38 | 34396.000 | 2012-05-29 | 2012-07-06 |\n| E1205391561A | YMLUW230775660 | sea | CFS/CY | WISTRON NEWEB (KUNSHAN) CORPORATION | ARUBA NETWORKS | 30 | 391.000 | 2012-05-29 | 2012-06-16 |\n| A1208395110 | ZIMUSNH5455049 | sea | CFS/CFS | SHANGHAI EAST BEST INT'L BUSINESS DEV.CO | LUMINA GLOBAL, INC. | 2 | 2600.000 | 2012-08-25 | 2012-09-06 |\n| E1205391561 | YMLUW230775660 | sea | CY/CY | SERCOMM CORP. C/O SERNET | ARUBA NETWORKS | 354 | 2833.940 | 2012-05-29 | 2012-06-16 |\n| E1205395237 | YMLUW230777029 | sea | CY/CY | UNIPAK RESOURCES CO.,LTD. | PAN PACIFIC PLASTIC | 404 | 2424.000 | 2012-05-29 | 2012-06-16 |\n| X1205480323 | YMLUW241023500 | sea | CY/CY | SHANGHAI AUTOMOBILE IMPORT&EXPORT CO.,LTD. | AMERICAN CONDENSER | 1082 | 5178.000 | 2012-05-25 | 2012-06-12 |\n| E1205359270 | MAEU602108615 | sea | CY/CY | LZ CASKET MANUFACTURING CO.,LTD | BRICK ALLEY,LLC | 64 | 5901.700 | 2012-05-29 | 2012-07-06 |\n";
  380. //$return = array("type"=>"markdown","data" =>$data);
  381. //common::echo_json_encode(200,$return);
  382. //exit();
  383. //分担查询
  384. include ONLINE_ROOT . 'libs' . DS . 'map_config.ini.php';
  385. $ai_method = $_POST["test_ai_method"];
  386. $systemPrompt = $_POST["prompt"];
  387. $message = $_POST["test_question"];
  388. $model = $ai_method == 'DS' ? "deepseek" : "claude";
  389. //question_date request_time
  390. $request_question_time = date("Y-m-d H:i:s");
  391. $question_time = date("H:i:s");
  392. $item_value = common::excuteOneSql("select item_value from public.config where item = 'AIAPISetting'");
  393. $config = json_decode($item_value,true);
  394. $response = AIClientFactory::create($model, $config[$model], $systemPrompt, $message, $history = []);
  395. $response_time = date("Y-m-d H:i:s");
  396. $input_token = "";
  397. $output_token = "";
  398. $date1 = new DateTime($request_question_time);
  399. $date2 = new DateTime($response_time);
  400. $response_duration = $date2->getTimestamp() - $date1->getTimestamp();
  401. //回答问题类型,在没有超时的情况下,固定:AI回答
  402. $answer_type = "AI Answer";
  403. if ($response_duration > 120){
  404. $answer_type = "Timeout";
  405. }
  406. //获取自然序列
  407. $sequence = common::getChatAiSequence();
  408. $name = $ai_method == 'DS' ? "DS" : "CD";
  409. $request_id = "R".$name."".date("Ymd").$sequence;
  410. $question_id = "Q"."".date("Ymd").$sequence;
  411. //处理一下参数
  412. $user_name = common::check_input(_getLoginName());
  413. $user_type = _isApexLogin() ? "employee" : "customer";
  414. //这里的测试,固定写自由文本
  415. $question_type = 'Free Text';
  416. $question_id = common::check_input($question_id);
  417. $question_content = common::check_input($message);
  418. $answer_type = common::check_input($answer_type);
  419. //记录回答展示给客户的具体内容
  420. $answer = common::check_input(common::getChatAimessage($response['message']));
  421. $ai_model = common::check_input($model);
  422. $input_token = common::check_input($input_token);
  423. $request_content = common::check_input(json_encode($response['data']));
  424. $ai_response_content = common::check_input(json_encode($response['full_response']));
  425. $output_token = common::check_input($output_token);
  426. $answer_template = "";
  427. $message = json_decode(common::getChatAimessage($response['message']),true);
  428. if($message["can_query"] == "true" && !empty($message["sql"])){
  429. $reference = $message["reference"];
  430. $answer_template = common::check_input($message["reference"]);
  431. $sql = $message["sql"];
  432. //拆分sql 存在多条的情况
  433. $sqlArr = explode(";", $sql);
  434. //给所有sql 拼接用户权限
  435. $sqlWhere = ' ' . common::searchExtendHand_KLN("ocean", $_SESSION["ONLINE_USER"]);
  436. //先不考虑总数,处理有难度
  437. foreach($sqlArr as $_sql){
  438. error_log($_sql);
  439. if(empty($_sql)){
  440. continue;
  441. }
  442. //根据public.kln_ocean 和 WHERE 的位置关系,带入权限
  443. $new_sql = utils::modifyString($_sql,$sqlWhere);
  444. //处理limit 超过10 先限制10
  445. $new_sql = utils::processLimitClause($new_sql);
  446. //$rs = common::excuteListSql($new_sql);
  447. $rs = $mapdb->GetAll($new_sql) or ( (!$mapdb->ErrorMsg()) or error_log(common::dbLog($mapdb, $new_sql), 0));
  448. $reference = utils::replacementsMultiline($rs,$reference,$new_sql);
  449. }
  450. //有就去掉{{#each hbol_list}}\n {{/each}}
  451. $reference = preg_replace([
  452. '/\{\{[^}]+\}\}\n/', // 匹配开始标签及换行
  453. '/\{\{\/[^}]+\}\}/' // 匹配结束标签
  454. ], '', $reference);
  455. //$reference = $reference.$message["reference"];
  456. $answer = $reference;
  457. //$response['message'] = json_decode(common::getChatAimessage($response['message']),true);
  458. //$answer = $response;
  459. }else{
  460. $answer = $message["response"];
  461. }
  462. //最后插入数据
  463. $sql = "INSERT INTO public.kln_robot_chat_log( question_id, user_name, user_type, question_type, question_content,
  464. answer_type, answer, answer_satisfication, answer_duration,answer_template, question_date,
  465. question_time, request_id, ai_model, request_content, input_token,
  466. ai_response_content, output_token, request_time, response_time,
  467. response_duration)
  468. VALUES ('$question_id', '$user_name', '$user_type', '$question_type', '$question_content',
  469. '$answer_type', '".common::check_input($answer)."', '', '$response_duration','$answer_template','$request_question_time',
  470. '$question_time', '$request_id', '$ai_model','$request_content', '$input_token',
  471. '$ai_response_content', '$output_token', '$request_question_time', '$response_time',
  472. '$response_duration');";
  473. $rs = common::excuteUpdateSql($sql);
  474. if (!$rs) {
  475. $data = array("msg" => "AI Chat Save Error");
  476. common::echo_json_encode(200,$data);
  477. exit();
  478. }
  479. $return = array("type"=>"markdown","data" =>$answer);
  480. common::echo_json_encode(200,$return);
  481. exit();
  482. }
  483. if ($operate == "download"){
  484. $sql = common::deCode($_REQUEST['tmp_search'], 'D');
  485. if(!empty($sql)){
  486. $rs = common::excuteListSql($sql);
  487. }
  488. common::echo_json_encode(200,array("msg"=>"success","Data" => $rs));
  489. exit;
  490. }
  491. }
  492. public function ai_chat(){
  493. $operate = utils::_get('operate');
  494. $operate = strtolower($operate);
  495. if($operate == "ai_chat_prompt"){
  496. //查询所有配置信息 目前只有一个表一个数据
  497. $configuration = common::excuteObjectSql("select id, character_name,professional_field,main_tasks,table_name,table_description,
  498. table_structure_configuration,response_rule_configuration,output_format_configuration,fixed_problem_configuration
  499. from public.kln_robot_prompt_configuration where id = 1");
  500. $PromptAndVue = $this->dealPromptFormatAndVue($configuration);
  501. //promptFormat
  502. $promptFormat =$PromptAndVue["promptFormat"];
  503. $data = array("msg" => "succssful","prompt"=>$promptFormat);
  504. common::echo_json_encode(200,$data);
  505. exit();
  506. }
  507. if ($operate == "ai_chat_fixed_init"){
  508. $rs = common::excuteListSql("select fixed_faq,secondary_interaction_content from public.kln_robot_chat_fixed where active = true order by id");
  509. $data = array();
  510. foreach($rs as $v){
  511. $data[] = array("label" => $v['fixed_faq'],"value" =>$v['fixed_faq'],"isLong" => strlen($v['fixed_faq']) >80);
  512. }
  513. $data = array("msg" => "succssful","fixed_question"=>$data);
  514. common::echo_json_encode(200,$data);
  515. exit();
  516. }
  517. /**
  518. * ai 自由聊天
  519. */
  520. if($operate == "ai_chat"){
  521. try {
  522. //前端生成一个唯一的serial_no
  523. $serial_no = common::check_input($_POST["serial_no"]);
  524. //系统提示词
  525. $systemPrompt = common::check_input($_POST["prompt"]);
  526. $question_type = common::check_input($_POST['question_type']);
  527. $question_type = $question_type == 'Free Question' ? "Free Text" : $question_type;
  528. $question_content = common::check_input($_POST['question_content']);
  529. //固定问题的原始问题
  530. $fixed_faq = common::check_input($_POST['fixed_faq']);
  531. //claude deepseek 根據賬號信息判断
  532. $model = common::getUserCountry();
  533. //$model = "deepseek";
  534. //获取自然序列
  535. $sequence = common::getChatAiSequence();
  536. $name = $model == 'deepseek' ? "DS" : "CD";
  537. $request_id = "R".$name."".date("Ymd").$sequence;
  538. $question_id = "Q"."".date("Ymd").$sequence;
  539. //处理一下参数
  540. $user_name = common::check_input(_getLoginName());
  541. $user_type = _isApexLogin() ? "employee" : "customer";
  542. //首先生成基本记录数据 以便以后根据情况更新状态
  543. $sql = "INSERT INTO public.kln_robot_chat_log(serial_no, question_id, user_name, user_type, question_type, question_content,
  544. question_date, question_time, request_id, request_time,ai_model)
  545. VALUES ('$serial_no','$question_id', '$user_name', '$user_type', '$question_type', '$question_content',
  546. now(),to_char(CURRENT_TIME::time, 'HH24:MI:SS'), '$request_id',now(),'$model');";
  547. $rs = common::excuteUpdateSql($sql);
  548. if (!$rs) {
  549. $data = array("type"=>"markdown","data" => "AI Chat Save Error");
  550. common::echo_json_encode(200,$data);
  551. exit();
  552. }
  553. if ($question_type == 'Predefined Question'){
  554. $answer = $this->doFixedAnswerAndLog($serial_no,$fixed_faq,$question_content);
  555. //判断固定回答是否结束
  556. $is_fixedAnswer_end = false;
  557. $fixedChat = common::excuteObjectSql("select * from public.kln_robot_chat_fixed where fixed_faq = '$fixed_faq'");
  558. if (empty($fixedChat['secondary_interaction_content']) || $question_content != $fixedChat['fixed_faq'] ){
  559. $is_fixedAnswer_end = true;
  560. }
  561. } else {
  562. $answer = $this->doFreeAnswerAndLog($serial_no,$model,$systemPrompt, $question_content, $history = []);
  563. //自由问题固定为true
  564. $is_fixedAnswer_end = true;
  565. }
  566. $return = array("type"=>"markdown","is_fixedAnswer_end"=>$is_fixedAnswer_end,"data" =>$answer);
  567. common::echo_json_encode(200,$return);
  568. exit();
  569. } catch (Exception $e) {
  570. error_log("ai_chat_exception: ".$e->getMessage());
  571. $return = array("type"=>"markdown","is_fixedAnswer_end"=>true,"data" =>"Invalid response");
  572. common::echo_json_encode(200,$return);
  573. exit();
  574. }
  575. }
  576. if($operate == "ai_chat_stop"){
  577. $serial_no = common::check_input($_POST["serial_no"]);
  578. $updateSql = "update public.kln_robot_chat_log set answer_type = 'Suspend' where serial_no = '$serial_no'";
  579. $updateRs = common::excuteUpdateSql($updateSql);
  580. if (!$updateRs) {
  581. $data = array("msg" => "AI Chat Response Stop Error");
  582. }else{
  583. $data = array("msg" => "AI Chat Response Stop succssful");
  584. }
  585. common::echo_json_encode(200,$data);
  586. exit();
  587. }
  588. if($operate == "ai_chat_answer_mark"){
  589. $serial_no = common::check_input($_POST["serial_no"]);
  590. $answer_satisfication = common::check_input($_POST["feedback"]);
  591. $updateSql = "update public.kln_robot_chat_log set answer_satisfication = '$answer_satisfication' where serial_no = '$serial_no'";
  592. $updateRs = common::excuteUpdateSql($updateSql);
  593. if (!$updateRs) {
  594. $data = array("msg" => "AI Chat Response Mark Error");
  595. }else{
  596. $data = array("msg" => "AI Chat Response Mark succssful");
  597. }
  598. common::echo_json_encode(200,$data);
  599. exit();
  600. }
  601. if($operate == "download"){
  602. $faq = common::deCode($_GET['faq'], 'D');
  603. $sql = common::getFaqSql($faq);
  604. $columns = common::getFaqColumnSql($faq);
  605. //拼接用户权限
  606. $sqlWhere = ' ' . common::searchExtendHand_KLN("ocean", $_SESSION["ONLINE_USER"]);
  607. $sql = str_replace('<{ExtendHand_KLN}>', $sqlWhere, $sql);
  608. $rss = common::excuteListSql($sql);
  609. $rss = common::dealDataWithFaq($faq,$rss);
  610. //XLSXWriter输出
  611. $writer = new XLSXWriter();
  612. $sheetName = date('mdy');
  613. foreach ($rss as $k => $v) {
  614. $column = array();
  615. $value_temp = array();
  616. foreach($columns as $col){
  617. $value_temp[] = $v[$col['database_column_name']];
  618. if($k == 0){
  619. $column[] = $col['display_name'];
  620. }
  621. }
  622. if($k == 0){
  623. //输出column
  624. $writer->writeSheetRow($sheetName, $column);
  625. }
  626. $writer->writeSheetRow($sheetName, $value_temp, []);
  627. }
  628. $outfile = "Complete Data_" .date("Y-m-d H:i:s") . ".xlsx";
  629. if (file_exists($outfile)) {
  630. $outfile = "Complete Data_" .date("Y-m-d H:i:s") . "_". md5(uniqid(rand(), true)) . ".xlsx";
  631. }
  632. ob_end_clean();
  633. header('Content-Type: application/vnd.ms-excel');
  634. header("Expires: 0");
  635. header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
  636. header("Pragma: can-cache");
  637. header('Content-Disposition:attachment;filename="' . $outfile . '"');
  638. $writer->writetostdout();
  639. }
  640. }
  641. public function dealPromptFormatAndVue($configuration){
  642. //tableDat-VUE
  643. $tableData = array();
  644. $table_structure_text="[";
  645. $table_structure_configuration = json_decode($configuration['table_structure_configuration'],true);
  646. foreach($table_structure_configuration as $tk =>$tv){
  647. $tableData[] = $tv;
  648. $table_structure_text .='{
  649. "name": "'.$tv["name"].'",
  650. "type": "'.$tv["type"].'",
  651. "description": "'.$tv["description"].'",
  652. "exampledata": "'.$tv["exampledata"].'",
  653. }';
  654. if(count($table_structure_configuration)-1 > $tk){
  655. $table_structure_text .=",";
  656. }
  657. $table_structure_text .=common::splicedLlineBreaks();
  658. }
  659. $table_structure_text.="]";
  660. //stepData -VUE
  661. $stepData = array();
  662. $response_rule_text = "";
  663. $response_rule_configuration = json_decode($configuration['response_rule_configuration'],true);
  664. foreach($response_rule_configuration as $rk =>$rv){
  665. $tempTable = array();
  666. $tempTable["description"] = $rv["description"];
  667. $stepData[] = $tempTable;
  668. $response_rule_text .=($rk+1).'.'.$rv["description"];
  669. $response_rule_text .=common::splicedLlineBreaks();
  670. }
  671. //formatList -VUE
  672. $output_format_text = "{";
  673. $output_format_configuration = json_decode($configuration['output_format_configuration'],true);
  674. $formatListType = $output_format_configuration['output_type'];
  675. $formatList = empty($output_format_configuration['data']) ? array(): $output_format_configuration['data'];
  676. foreach($formatList as $ok =>$ov){
  677. $describe = $ov['describe'];
  678. if ($ov['selecttype'] == '必填字段') {
  679. $describe .= " . 必填要求:所有情况必填";
  680. } elseif ($ov['selecttype'] == '有条件必填'){
  681. $requirements = $ov['requirements'];
  682. $describe .= " . 必填要求:".$ov['selecttype']."(".$requirements.")";
  683. }
  684. $output_format_text .="\"".$ov['name']."\"".": "."\"".$describe."\"";
  685. $output_format_text .=common::splicedLlineBreaks();
  686. }
  687. $output_format_text .= "}";
  688. $output_format_text_two = "";
  689. foreach($formatList as $ok =>$ov){
  690. $describe = $ov['describe'];
  691. if ($ov['selecttype'] == '必填字段') {
  692. $describe .= " . 必填要求:所有情况必填";
  693. } elseif ($ov['selecttype'] == '有条件必填'){
  694. $requirements = $ov['requirements'];
  695. $describe .= " . 必填要求:".$ov['selecttype']."(".$requirements.")";
  696. }
  697. $output_format_text_two .="-".$ov['name'].": ".$describe;
  698. $output_format_text_two .=common::splicedLlineBreaks();
  699. }
  700. $promptFormat = $this->getCompletePromptFormat();
  701. $promptFormat = str_replace('<{professional_field}>', $configuration['character_name'], $promptFormat);
  702. $promptFormat = str_replace('<{character_name}>', $configuration['character_name'], $promptFormat);
  703. $promptFormat = str_replace('<{main_tasks}>', $configuration['main_tasks'], $promptFormat);
  704. $promptFormat = str_replace('<{table}>', $configuration['table_name'], $promptFormat);
  705. $promptFormat = str_replace('<{table_structure_configuration}>', $table_structure_text, $promptFormat);
  706. $promptFormat = str_replace('<{response_rule_configuration}>', $response_rule_text, $promptFormat);
  707. $promptFormat = str_replace('<{number}>', count($response_rule_configuration)+1, $promptFormat);
  708. $promptFormat = str_replace('<{output_type}>', $formatListType, $promptFormat);
  709. $promptFormat = str_replace('<{output_format_configuration}>', $output_format_text_two, $promptFormat);
  710. return array("vuedata"=>array("tableData"=>$tableData,"stepData"=>$stepData,"formatList"=>$formatList,"formatListType"=>$formatListType),
  711. "promptFormat" =>$promptFormat);
  712. }
  713. public function getChangedLog($id){
  714. $changeLogList = array();
  715. $configurationArr = common::excuteListSql("select id, character_name,professional_field,main_tasks,table_name,table_description,
  716. created_by,TO_CHAR(created_time, 'YYYY-mm-dd HH24:MI:SS') as created_time,
  717. table_structure_configuration,response_rule_configuration,output_format_configuration,fixed_problem_configuration
  718. from public.kln_robot_prompt_configuration_log where ref_id = '$id' order by id desc");
  719. foreach($configurationArr as $ca){
  720. $data = $this->dealPromptFormatAndVue($ca);
  721. $temp =array();
  722. $temp["time"] = $ca['created_time']." Prompt";
  723. $temp["person"] ="提交人:".$ca['created_by'];
  724. $temp["text"] = $data['promptFormat'];
  725. $changeLogList[] = $temp;
  726. }
  727. return $changeLogList;
  728. }
  729. public function getSystemPrompt(){
  730. //查询所有配置信息 目前只有一个表一个数据
  731. $configuration = common::excuteObjectSql("select id, character_name,professional_field,main_tasks,table_name,table_description,
  732. table_structure_configuration,response_rule_configuration,output_format_configuration,fixed_problem_configuration
  733. from public.kln_robot_prompt_configuration where id = 1");
  734. $PromptAndVue = $this->dealPromptFormatAndVue($configuration);
  735. //promptFormat
  736. $promptFormat =$PromptAndVue["promptFormat"];
  737. return $promptFormat;
  738. }
  739. public function getCompletePromptFormat() {
  740. $formatTpl = "
  741. 您是专门从<{professional_field}>的 <{character_name}>,请始终以<{output_type}>格式响应。您的主要任务是<{main_tasks}>
  742. 表名:<{table}>
  743. 表结构: \"columns\": <{table_structure_configuration}>
  744. 响应规则,请按以下步骤处理:
  745. <{response_rule_configuration}>
  746. <{number}>.请严格按照以下格式输出<{output_type}>,不要包含任何其他文字或说明:
  747. {\"can_query\": true,\"query_type\": \"货物跟踪\",\"reason\": \"分析原因\",\"sql\": \"生成的SQL語句\",\"reference\": \"Markdown格式的回复模板\",\"response\": \"直接回答內容或空字符串\"}
  748. 或者
  749. {\"can_query\": false,\"query_type\": \"空字符串\",\"reason\": \"分析原因\",\"sql\": \"空字符串\",\"reference\": \"Markdown格式的回复模板\",\"response\": \"can_query是False的時候必填,直接回答內容\"}
  750. 请确保:你的输出必须是一个合法的 JSON 字符串
  751. 字段說明:
  752. <{output_format_configuration}>
  753. 重要:请只返回合法JSON格式,不要包含任何解释文字或代码块标记";
  754. return $formatTpl;
  755. }
  756. public function doFreeAnswerAndLog($serial_no,$model,$systemPrompt, $question_content, $history){
  757. //分担查询
  758. include ONLINE_ROOT . 'libs' . DS . 'map_config.ini.php';
  759. //Ai response
  760. $item_value = common::excuteOneSql("select item_value from public.config where item = 'AIAPISetting'");
  761. $config = json_decode($item_value,true);
  762. $response = AIClientFactory::create($model, $config[$model], $systemPrompt, $question_content, $history = []);
  763. $input_token = "";
  764. $output_token = "";
  765. $answer_template = "";
  766. $answer ="";
  767. $response_pram = common::excuteObjectSql("select to_char(now(), 'YYYY-mm-dd HH24:MI:SS') as response_time,
  768. CEIL(EXTRACT(EPOCH FROM (now() - question_date))) AS response_duration from public.kln_robot_chat_log where serial_no = '$serial_no'");
  769. $response_duration = $response_pram['response_duration'];
  770. //回答问题类型,在没有超时的情况下,固定:AI回答
  771. $answer_type = "AI Answer";
  772. if ($response_duration > 120){
  773. $answer_type = "Timeout";
  774. }
  775. $request_content = common::check_input(json_encode($response['data'],JSON_UNESCAPED_UNICODE));
  776. //不存在 键,说明AI 返回的是异常情况
  777. if (!isset($response['data'])) {
  778. $request_content = common::check_input(json_encode($response,JSON_UNESCAPED_UNICODE));
  779. }
  780. $ai_response_content = common::check_input(json_encode($response['full_response'],JSON_UNESCAPED_UNICODE));
  781. //不存在 键,说明AI 返回的是异常情况
  782. if (!isset($response['full_response'])) {
  783. $ai_response_content = common::check_input(json_encode($response,JSON_UNESCAPED_UNICODE));
  784. }
  785. //提前记录AI 返回,如果sql异常掉了的话,可以查找原因
  786. $updateSql = "update public.kln_robot_chat_log set answer_duration = '$response_duration',answer_template='$answer_template',
  787. answer_type = case when COALESCE(answer_type,'') = 'Suspend' then 'Suspend' else '$answer_type' end,
  788. request_content='$request_content',
  789. input_token='$input_token',ai_response_content='$ai_response_content',
  790. output_token='$output_token',response_time=now(),response_duration='$response_duration'
  791. where serial_no = '$serial_no'";
  792. $updateRs = common::excuteUpdateSql($updateSql);
  793. if (!$updateRs) {
  794. $data = array("type"=>"markdown","data" => "AI Chat Response Save Error");
  795. common::echo_json_encode(200,$data);
  796. exit();
  797. }
  798. /**
  799. * JSON_ERROR_NONE 0 没有错误
  800. * JSON_ERROR_DEPTH 1 超出最大堆栈深度
  801. * JSON_ERROR_STATE_MISMATCH 2 JSON 格式不一致或无效
  802. * JSON_ERROR_CTRL_CHAR 3 控制字符错误,可能编码不对
  803. * JSON_ERROR_SYNTAX 4 语法错误(如缺失括号、逗号等)
  804. * JSON_ERROR_UTF8 5 编码错误,非 UTF-8 字符
  805. * JSON_ERROR_RECURSION 6 检测到递归引用
  806. * JSON_ERROR_INF_OR_NAN 7 不能编码 INF 或 NAN
  807. * JSON_ERROR_UNSUPPORTED_TYPE 8 不支持的数据类型
  808. */
  809. error_log("Real_message:".common::getChatAimessage($response['message']));
  810. $brokenJson = common::getChatAimessage($response['message']);
  811. $message = json_decode($brokenJson,true);
  812. if ($message === null) {
  813. // 获取最后一次 JSON 操作的错误码
  814. $errorCode = json_last_error();
  815. // 获取错误描述(PHP 5.5+)
  816. $errorMsg = json_last_error_msg();
  817. error_log("AI Message JSON Decode Error : {$errorCode} - {$errorMsg}");
  818. // 2:对reference,response,sql 用 \n 替换实际换行符后,再进行第二次解析json_decode
  819. $fixedJson = common::secondaryReplacement(common::getChatAimessage($response['message']));
  820. $message = json_decode($fixedJson,true);
  821. if ($message === null) {
  822. //3:进行最后一次解析处理
  823. //当解析失败时,手工的字符串定位和截取方法 已经做trim处理
  824. //$keysToExtract = ['can_query', 'sql', 'reference', 'response'];
  825. $extractedValues = common::customizeParsing(common::getChatAimessage($response['message']));
  826. $message = array();
  827. $message["can_query"] = $extractedValues['can_query'];
  828. $message["sql"] = $extractedValues['sql'];
  829. $message["reference"] = $extractedValues['reference'];
  830. $message["response"] = $extractedValues['response'];
  831. }
  832. }
  833. if($message["can_query"] == "true" && !empty($message["sql"])){
  834. $reference = $message["reference"];
  835. $answer_template = common::check_input($message["reference"]);
  836. $sql = $message["sql"];
  837. //拆分sql 存在多条的情况
  838. $sqlArr = explode(";", $sql);
  839. //给所有sql 拼接用户权限
  840. $sqlWhere = ' ' . common::searchExtendHand_KLN("ocean", $_SESSION["ONLINE_USER"]);
  841. //这里在返回一个sql的时候,做查询总数的删,(大多数情况是一条sql,如遇到两条不查询)
  842. $total = 0;
  843. foreach($sqlArr as $_sql){
  844. if(empty($_sql)){
  845. continue;
  846. }
  847. //首先检查sql 是否有非法的字符和不规范查询
  848. $safe = common::checkSafeSql($_sql);
  849. if(!$safe){
  850. $reference = "The answer is incorrect. It has been filtered.";
  851. break;
  852. }
  853. //根据public.kln_ocean 和 WHERE 的位置关系,带入权限
  854. $new_sql = utils::modifyString($_sql,$sqlWhere);
  855. //处理limit 超过100 先限制100
  856. $new_data = utils::processLimitClause($new_sql);
  857. $new_sql = $new_data['sql'];
  858. //$rs = common::excuteListSql($new_sql);
  859. $rs = $mapdb->GetAll($new_sql) or ( (!$mapdb->ErrorMsg()) or error_log(common::dbLog($mapdb, $new_sql), 0));
  860. $reference = utils::replacementsMultiline($rs,$reference,$new_sql);
  861. if (count($sqlArr) == 1){
  862. if(!empty($rs) && !empty($rs[0]['total_count'])){
  863. $total = $rs[0]['total_count'];
  864. }
  865. //代表sql本身就返回limit 10 < 100,不需要去取total_count,不准确了
  866. if($new_data['is_limit']){
  867. $total = 0;
  868. }
  869. }
  870. }
  871. //有就去掉{{#each hbol_list}}\n {{/each}}
  872. $reference = preg_replace([
  873. '/\{\{[^}]+\}\}\n/', // 匹配开始标签及换行
  874. '/\{\{\/[^}]+\}\}/' // 匹配结束标签
  875. ], '', $reference);
  876. if ($total > 100){
  877. $tip = "\n\n* Tips: Due to limited display space, only 100 records are shown by default. You can search again with more specific criteria.";
  878. // 拼接结果
  879. $reference = $reference . $tip;
  880. }
  881. $answer = $reference;
  882. }else{
  883. $answer = $message["response"];
  884. if(!$response['success']){
  885. $answer = "Invalid response";
  886. }
  887. }
  888. //update 更新 answer
  889. $updateSql = "update public.kln_robot_chat_log set answer = '".common::check_input($answer)."'
  890. where serial_no = '$serial_no'";
  891. $updateRs = common::excuteUpdateSql($updateSql);
  892. if (!$updateRs) {
  893. $data = array("type"=>"markdown","data" => "AI Chat Response Save Error");
  894. common::echo_json_encode(200,$data);
  895. exit();
  896. }
  897. return $answer;
  898. }
  899. public function doFixedAnswerAndLog($serial_no,$fixed_faq,$question_content){
  900. $input_token = "";
  901. $output_token = "";
  902. $answer_template = "";
  903. $answer ="";
  904. $fixedChat = common::excuteObjectSql("select * from public.kln_robot_chat_fixed where fixed_faq = '$fixed_faq'");
  905. if (empty($fixedChat['secondary_interaction_content']) || $question_content != $fixedChat['fixed_faq'] ){
  906. $answer_template = common::check_input($fixedChat["answer_style"]);
  907. $answer = common::FixedAnswerAndLogData($fixedChat,$question_content);
  908. } else {
  909. $answer = $fixedChat['secondary_interaction_content'];
  910. }
  911. //回答完毕计时
  912. $response_pram = common::excuteObjectSql("select to_char(now(), 'YYYY-mm-dd HH24:MI:SS') as response_time,
  913. CEIL(EXTRACT(EPOCH FROM (now() - question_date))) AS response_duration from public.kln_robot_chat_log where serial_no = '$serial_no'");
  914. $response_duration = $response_pram['response_duration'];
  915. //回答问题类型,在没有超时的情况下,固定:AI回答
  916. $answer_type = "Predefined Template";
  917. if ($response_duration > 120){
  918. $answer_type = "Timeout";
  919. }
  920. $request_content = common::check_input($question_content);
  921. $ai_response_content = common::check_input($answer);
  922. //update 更新
  923. $updateSql = "update public.kln_robot_chat_log set answer_duration = '$response_duration',answer_template='$answer_template',answer = '".common::check_input($answer)."',
  924. answer_type = case when COALESCE(answer_type,'') = 'Suspend' then 'Suspend' else '$answer_type' end,
  925. request_content='$request_content',
  926. input_token='$input_token',ai_response_content='$ai_response_content',
  927. output_token='$output_token',response_time=now(),response_duration='$response_duration'
  928. where serial_no = '$serial_no'";
  929. $updateRs = common::excuteUpdateSql($updateSql);
  930. if (!$updateRs) {
  931. $data = array("type"=>"markdown","data" => "AI Chat Response Save Error");
  932. common::echo_json_encode(200,$data);
  933. exit();
  934. }
  935. return $answer;
  936. }
  937. }
  938. ?>