robot.class.php 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  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. //$this->_operation_search();
  36. }
  37. if ($operate == "excel") {
  38. $sql = common::deCode($_POST ['tmp_search'], 'D');
  39. $sql = substr($sql, 0, strripos($sql, " limit"));
  40. if(!empty($sql)){
  41. $rss = common::excuteListSql($sql);
  42. }
  43. foreach($rss as $key =>$val){
  44. $rss[$key]['Operation Time'] = $rss[$key]['_operation_time'];
  45. }
  46. common::echo_json_encode(200,array("msg"=>"success","Data" => $rss));
  47. exit;
  48. }
  49. }
  50. public function robot_prompt_configuration() {
  51. $operate = utils::_get('operate');
  52. $operate = strtolower($operate);
  53. if (empty($operate)) {
  54. //查询所有配置信息 目前只有一个表一个数据
  55. $configuration = common::excuteObjectSql("select id, character_name,professional_field,main_tasks,table_name,table_description,
  56. table_structure_configuration,response_rule_configuration,output_format_configuration,fixed_problem_configuration
  57. from public.kln_robot_prompt_configuration where id = 1");
  58. $PromptAndVue = $this->dealPromptFormatAndVue($configuration);
  59. //tableDat-VUE
  60. $tableData = $PromptAndVue["vuedata"]["tableData"];
  61. //stepData -VUE
  62. $stepData = $PromptAndVue["vuedata"]["stepData"];
  63. //formatList -VUE
  64. $formatListType = $PromptAndVue["vuedata"]["formatListType"];
  65. $formatList = $PromptAndVue["vuedata"]["formatList"];
  66. //promptFormat
  67. $promptFormat =$PromptAndVue["promptFormat"];
  68. //获取历史变更记录
  69. $old_configuration = $this->getChangedLog($configuration["id"]);
  70. $id = $configuration['id'];
  71. $character_name = $configuration['character_name'];
  72. $professional_field = $configuration['professional_field'];
  73. $main_tasks = $configuration['main_tasks'];
  74. $table_name = $configuration['table_name'];
  75. $table_description = $configuration['table_description'];
  76. $prompt_summary = array("您是专門从事".$professional_field."的".$character_name."...",
  77. "表名:{".$table_name."}...",
  78. "响应规则,请按以下步骤处理...");
  79. $data = array(
  80. "id"=>$id,
  81. "character_name"=>$character_name,
  82. "professional_field"=>$professional_field,
  83. "main_tasks"=>$main_tasks,
  84. "table_name"=>$table_name,
  85. "table_description"=>$table_description,
  86. "tableData"=>$tableData,
  87. "stepData"=>$stepData,
  88. "formatList"=>$formatList,
  89. "formatListType"=>$formatListType,
  90. "complete_prompt"=>$promptFormat,
  91. "prompt_summary"=>$prompt_summary,
  92. "prompt_log_record"=>$old_configuration
  93. );
  94. $data = utils::arrayRemoveNull($data);
  95. common::echo_json_encode(200,$data);
  96. exit();
  97. }
  98. if ($operate == "save") {
  99. $id =common::check_input($_POST['id']);
  100. $character_name = common::check_input($_POST['role_name']);
  101. $professional_field = common::check_input($_POST['professional_field']);
  102. $main_tasks = common::check_input($_POST['main_tasks']);
  103. $table_name = common::check_input($_POST['table_name']);
  104. $table_description = common::check_input($_POST['table_description']);
  105. $outputvalue = common::check_input($_POST['outputvalue']);
  106. $tableDataList = $_POST['tableDataList'];
  107. $stepData = $_POST['stepData'];
  108. $formatList = $_POST['formatList'];
  109. $table_structure_configuration = common::check_input(json_encode($tableDataList));
  110. $response_rule_configuration = common::check_input(json_encode($stepData));
  111. $output_data = array("output_type"=>$outputvalue,"data"=>$formatList);
  112. $output_format_configuration = common::check_input(json_encode($output_data));
  113. if(empty($id)){
  114. $sql = "INSERT INTO public.kln_robot_prompt_configuration(
  115. character_name, professional_field, main_tasks, table_name,
  116. table_description, table_structure_configuration, response_rule_configuration,
  117. output_format_configuration, created_by, created_time)
  118. VALUES ('$character_name', '$professional_field', '$main_tasks', '$table_name',
  119. '$table_description', '$table_structure_configuration', '$response_rule_configuration',
  120. '$output_format_configuration', '"._getLoginName()."', now());";
  121. }else{
  122. $sql = "update public.kln_robot_prompt_configuration
  123. set character_name = '$character_name',professional_field ='$professional_field', main_tasks = '$main_tasks',
  124. table_name = '$table_name',table_description = '$table_description',
  125. table_structure_configuration = '$table_structure_configuration',
  126. response_rule_configuration = '$response_rule_configuration',
  127. output_format_configuration = '$output_format_configuration'
  128. where id = '$id';";
  129. //插入变更日志记录
  130. $sql .= "INSERT INTO public.kln_robot_prompt_configuration_log(ref_id, character_name, professional_field, main_tasks, table_name,
  131. table_description, table_structure_configuration, response_rule_configuration,
  132. output_format_configuration, created_by, created_time)
  133. VALUES ('$id','$character_name', '$professional_field', '$main_tasks', '$table_name',
  134. '$table_description', '$table_structure_configuration', '$response_rule_configuration',
  135. '$output_format_configuration', '"._getLoginName()."', now());";
  136. }
  137. error_log($sql);
  138. $rs = common::excuteUpdateSql($sql);
  139. if (!$rs) {
  140. $data = array("msg" => "save Error");
  141. } else {
  142. $data = array("msg" => "save Successful");
  143. }
  144. $data = array("msg" => "save Successful");
  145. common::echo_json_encode(200,$data);
  146. exit();
  147. }
  148. if($operate == "preview_propmpt_witout_save"){
  149. $character_name = common::check_input($_POST['role_name']);
  150. $professional_field = common::check_input($_POST['professional_field']);
  151. $main_tasks = common::check_input($_POST['main_tasks']);
  152. $table_name = common::check_input($_POST['table_name']);
  153. $table_description = common::check_input($_POST['table_description']);
  154. $outputvalue = common::check_input($_POST['outputvalue']);
  155. $tableDataList = $_POST['tableDataList'];
  156. $stepData = $_POST['stepData'];
  157. $formatList = $_POST['formatList'];
  158. $table_structure_configuration = common::check_input(json_encode($tableDataList));
  159. $response_rule_configuration = common::check_input(json_encode($stepData));
  160. $output_data = array("output_type"=>$outputvalue,"data"=>$formatList);
  161. $output_format_configuration = common::check_input(json_encode($output_data));
  162. //组合拼接需要的数据
  163. $configuration = array("character_name"=>$character_name,
  164. "professional_field"=>$professional_field,
  165. "main_tasks"=>$main_tasks,
  166. "table_name"=>$table_name,
  167. "table_description"=>$table_description,
  168. "professional_field"=>$professional_field,
  169. "table_structure_configuration"=>$table_structure_configuration,
  170. "response_rule_configuration" =>$response_rule_configuration,
  171. "output_format_configuration" =>$output_format_configuration
  172. );
  173. $PromptAndVue = $this->dealPromptFormatAndVue($configuration);
  174. //promptFormat
  175. $promptFormat =$PromptAndVue["promptFormat"];
  176. $character_name = empty($configuration['character_name']) ? "" :$configuration['character_name'];
  177. $professional_field = empty($configuration['professional_field']) ? "" :$configuration['professional_field'];
  178. $main_tasks = empty($configuration['main_tasks']) ? "" :$configuration['main_tasks'];
  179. $table_name = empty($configuration['table_name']) ? "" :$configuration['table_name'];
  180. $table_description = empty($configuration['table_description']) ? "" :$configuration['table_description'];
  181. $prompt_summary = array("您是专門从事".$professional_field."的".$character_name."...",
  182. "表名:{".$table_name."}...",
  183. "响应规则,请按以下步骤处理...");
  184. $data = array(
  185. "complete_prompt"=>$promptFormat,
  186. "prompt_summary"=>$prompt_summary
  187. );
  188. common::echo_json_encode(200,$data);
  189. exit();
  190. }
  191. if($operate == "test_with_ds_claude"){
  192. //$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 ";
  193. //$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";
  194. //$return = array("type"=>"markdown","data" =>$data);
  195. //common::echo_json_encode(200,$return);
  196. //exit();
  197. //分担查询
  198. include ONLINE_ROOT . 'libs' . DS . 'map_config.ini.php';
  199. $ai_method = $_POST["test_ai_method"];
  200. $systemPrompt = $_POST["prompt"];
  201. $message = $_POST["test_question"];
  202. $model = $ai_method == 'DS' ? "deepseek" : "claude";
  203. //question_date request_time
  204. $request_question_time = date("Y-m-d H:i:s");
  205. $question_time = date("H:i:s");
  206. $item_value = common::excuteOneSql("select item_value from public.config where item = 'AIAPISetting'");
  207. $config = json_decode($item_value,true);
  208. $response = AIClientFactory::create($model, $config[$model], $systemPrompt, $message, $history = []);
  209. $response_time = date("Y-m-d H:i:s");
  210. $input_token = "";
  211. $output_token = "";
  212. $date1 = new DateTime($request_question_time);
  213. $date2 = new DateTime($response_time);
  214. $response_duration = $date2->getTimestamp() - $date1->getTimestamp();
  215. //回答问题类型,在没有超时的情况下,固定:AI回答
  216. $answer_type = "AI回答";
  217. if ($response_duration > 120){
  218. $answer_type = "回答超时";
  219. }
  220. //获取自然序列
  221. $sequence = common::getChatAiSequence();
  222. $name = $ai_method == 'DS' ? "DS" : "CD";
  223. $request_id = "R".$name."".date("Ymd").$sequence;
  224. $question_id = "Q"."".date("Ymd").$sequence;
  225. //处理一下参数
  226. $user_name = common::check_input(_getLoginName());
  227. $user_type = _isApexLogin() ? "employee" : "customer";
  228. //这里的测试,固定写自由文本
  229. $question_type = 'free text';
  230. $question_id = common::check_input($question_id);
  231. $question_content = common::check_input($message);
  232. $answer_type = common::check_input($answer_type);
  233. //记录回答展示给客户的具体内容
  234. $answer = common::check_input(common::getChatAimessage($response['message']));
  235. $ai_model = common::check_input($model);
  236. $input_token = common::check_input($input_token);
  237. $request_content = common::check_input(json_encode($response['data']));
  238. $ai_response_content = common::check_input(json_encode($response['full_response']));
  239. $output_token = common::check_input($output_token);
  240. $answer_template = "";
  241. $message = json_decode(common::getChatAimessage($response['message']),true);
  242. if($message["can_query"] == "true" && !empty($message["sql"])){
  243. $reference = $message["reference"];
  244. $answer_template = common::check_input($message["reference"]);
  245. $sql = $message["sql"];
  246. //拆分sql 存在多条的情况
  247. $sqlArr = explode(";", $sql);
  248. //给所有sql 拼接用户权限
  249. $sqlWhere = ' ' . common::searchExtendHand_KLN("ocean", $_SESSION["ONLINE_USER"]);
  250. //先不考虑总数,处理有难度
  251. foreach($sqlArr as $_sql){
  252. error_log($_sql);
  253. if(empty($_sql)){
  254. continue;
  255. }
  256. //根据public.kln_ocean 和 WHERE 的位置关系,带入权限
  257. $new_sql = utils::modifyString($_sql,$sqlWhere);
  258. //处理limit 超过10 先限制10
  259. $new_sql = utils::processLimitClause($new_sql);
  260. //$rs = common::excuteListSql($new_sql);
  261. $rs = $mapdb->GetAll($new_sql) or ( (!$mapdb->ErrorMsg()) or error_log(common::dbLog($mapdb, $new_sql), 0));
  262. $reference = utils::replacementsMultiline($rs,$reference,$new_sql);
  263. }
  264. //有就去掉{{#each hbol_list}}\n {{/each}}
  265. $reference = preg_replace([
  266. '/\{\{[^}]+\}\}\n/', // 匹配开始标签及换行
  267. '/\{\{\/[^}]+\}\}/' // 匹配结束标签
  268. ], '', $reference);
  269. //$reference = $reference.$message["reference"];
  270. $answer = $reference;
  271. //$response['message'] = json_decode(common::getChatAimessage($response['message']),true);
  272. //$answer = $response;
  273. }else{
  274. $answer = $message["response"];
  275. }
  276. //最后插入数据
  277. $sql = "INSERT INTO public.kln_robot_chat_log( question_id, user_name, user_type, question_type, question_content,
  278. answer_type, answer, answer_satisfication, answer_duration,answer_template, question_date,
  279. question_time, request_id, ai_model, request_content, input_token,
  280. ai_response_content, output_token, request_time, response_time,
  281. response_duration)
  282. VALUES ('$question_id', '$user_name', '$user_type', '$question_type', '$question_content',
  283. '$answer_type', '".common::check_input($answer)."', '', '$response_duration','$answer_template','$request_question_time',
  284. '$question_time', '$request_id', '$ai_model','$request_content', '$input_token',
  285. '$ai_response_content', '$output_token', '$request_question_time', '$response_time',
  286. '$response_duration');";
  287. $rs = common::excuteUpdateSql($sql);
  288. if (!$rs) {
  289. $data = array("msg" => "AI Chat Save Error");
  290. common::echo_json_encode(200,$data);
  291. exit();
  292. }
  293. $return = array("type"=>"markdown","data" =>$answer);
  294. common::echo_json_encode(200,$return);
  295. exit();
  296. }
  297. if ($operate == "download"){
  298. $sql = common::deCode($_REQUEST['tmp_search'], 'D');
  299. if(!empty($sql)){
  300. $rs = common::excuteListSql($sql);
  301. }
  302. common::echo_json_encode(200,array("msg"=>"success","Data" => $rs));
  303. exit;
  304. }
  305. }
  306. public function ai_chat(){
  307. $operate = utils::_get('operate');
  308. $operate = strtolower($operate);
  309. if($operate == "ai_chat_prompt"){
  310. //查询所有配置信息 目前只有一个表一个数据
  311. $configuration = common::excuteObjectSql("select id, character_name,professional_field,main_tasks,table_name,table_description,
  312. table_structure_configuration,response_rule_configuration,output_format_configuration,fixed_problem_configuration
  313. from public.kln_robot_prompt_configuration where id = 1");
  314. $PromptAndVue = $this->dealPromptFormatAndVue($configuration);
  315. //promptFormat
  316. $promptFormat =$PromptAndVue["promptFormat"];
  317. $data = array("msg" => "succssful","prompt"=>$promptFormat);
  318. common::echo_json_encode(200,$data);
  319. exit();
  320. }
  321. /**
  322. * ai 自由聊天
  323. */
  324. if($operate == "ai_chat"){
  325. //前端生成一个唯一的serial_no
  326. $serial_no = common::check_input($_POST["serial_no"]);
  327. //系统提示词
  328. $systemPrompt = common::check_input($_POST["prompt"]);
  329. $question_type = common::check_input($_POST['question_type']);
  330. $question_content = common::check_input($_POST['question_content']);
  331. //固定问题的原始问题
  332. $fixed_faq = common::check_input($_POST['fixed_faq']);
  333. //claude deepseek 根據賬號信息判断
  334. $model = common::getUserCountry();
  335. $answer_type = $question_type == "Free Question" ? "AI回答" : "预定义模板回答";
  336. //获取自然序列
  337. $sequence = common::getChatAiSequence();
  338. $name = $model == 'deepseek' ? "DS" : "CD";
  339. $request_id = "R".$name."".date("Ymd").$sequence;
  340. $question_id = "Q"."".date("Ymd").$sequence;
  341. //处理一下参数
  342. $user_name = common::check_input(_getLoginName());
  343. $user_type = _isApexLogin() ? "employee" : "customer";
  344. //首先生成基本记录数据 以便以后根据情况更新状态
  345. $sql = "INSERT INTO public.kln_robot_chat_log(serial_no, question_id, user_name, user_type, question_type, question_content,
  346. answer_type, question_date, question_time, request_id, request_time)
  347. VALUES ('$serial_no','$question_id', '$user_name', '$user_type', '$question_type', '$question_content',
  348. '$answer_type',now(),to_char(CURRENT_TIME::time, 'HH24:MI:SS'), '$request_id',now());";
  349. $rs = common::excuteUpdateSql($sql);
  350. if (!$rs) {
  351. $data = array("type"=>"markdown","data" => "AI Chat Save Error");
  352. common::echo_json_encode(200,$data);
  353. exit();
  354. }
  355. if ($question_type == 'Predefined Question'){
  356. $answer = $this->doFixedAnswerAndLog($serial_no,$fixed_faq,$question_content);
  357. } else {
  358. $answer = $this->doFreeAnswerAndLog($serial_no,$model,$systemPrompt, $question_content, $history = []);
  359. }
  360. $return = array("type"=>"markdown","data" =>$answer);
  361. common::echo_json_encode(200,$return);
  362. exit();
  363. }
  364. if($operate == "ai_chat_stop"){
  365. $serial_no = common::check_input($_POST["serial_no"]);
  366. $updateSql = "update public.kln_robot_chat_log set answer_type = '回答被动停止' where serial_no = '$serial_no'";
  367. $updateRs = common::excuteUpdateSql($updateSql);
  368. if (!$updateRs) {
  369. $data = array("msg" => "AI Chat Response Stop Error");
  370. }else{
  371. $data = array("msg" => "AI Chat Response Stop succssful");
  372. }
  373. common::echo_json_encode(200,$data);
  374. exit();
  375. }
  376. if($operate == "ai_chat_answer_mark"){
  377. $serial_no = common::check_input($_POST["serial_no"]);
  378. $answer_satisfication = common::check_input($_POST["answer_satisfication"]);
  379. $updateSql = "update public.kln_robot_chat_log set answer_satisfication = '$answer_satisfication' where serial_no = '$serial_no'";
  380. $updateRs = common::excuteUpdateSql($updateSql);
  381. if (!$updateRs) {
  382. $data = array("msg" => "AI Chat Response Mark Error");
  383. }else{
  384. $data = array("msg" => "AI Chat Response Mark succssful");
  385. }
  386. common::echo_json_encode(200,$data);
  387. exit();
  388. }
  389. }
  390. public function dealPromptFormatAndVue($configuration){
  391. //tableDat-VUE
  392. $tableData = array();
  393. $table_structure_text="[";
  394. $table_structure_configuration = json_decode($configuration['table_structure_configuration'],true);
  395. foreach($table_structure_configuration as $tk =>$tv){
  396. $tableData[] = $tv;
  397. $table_structure_text .='{
  398. "name": "'.$tv["name"].'",
  399. "type": "'.$tv["type"].'",
  400. "description": "'.$tv["description"].'",
  401. "exampledata": "'.$tv["exampledata"].'",
  402. }';
  403. if(count($table_structure_configuration)-1 > $tk){
  404. $table_structure_text .=",";
  405. }
  406. $table_structure_text .=common::splicedLlineBreaks();
  407. }
  408. $table_structure_text.="]";
  409. //stepData -VUE
  410. $stepData = array();
  411. $response_rule_text = "";
  412. $response_rule_configuration = json_decode($configuration['response_rule_configuration'],true);
  413. foreach($response_rule_configuration as $rk =>$rv){
  414. $tempTable = array();
  415. $tempTable["description"] = $rv["description"];
  416. $stepData[] = $tempTable;
  417. $response_rule_text .=($rk+1).'.'.$rv["description"];
  418. $response_rule_text .=common::splicedLlineBreaks();
  419. }
  420. //formatList -VUE
  421. $output_format_text = "{";
  422. $output_format_configuration = json_decode($configuration['output_format_configuration'],true);
  423. $formatListType = $output_format_configuration['output_type'];
  424. $formatList = empty($output_format_configuration['data']) ? array(): $output_format_configuration['data'];
  425. foreach($formatList as $ok =>$ov){
  426. $output_format_text .="\"".$ov['name']."\"".": "."\"".$ov['describe']."\"";
  427. $output_format_text .=common::splicedLlineBreaks();
  428. }
  429. $output_format_text .= "}";
  430. $promptFormat = $this->getCompletePromptFormat();
  431. $promptFormat = str_replace('<{professional_field}>', $configuration['character_name'], $promptFormat);
  432. $promptFormat = str_replace('<{character_name}>', $configuration['character_name'], $promptFormat);
  433. $promptFormat = str_replace('<{main_tasks}>', $configuration['main_tasks'], $promptFormat);
  434. $promptFormat = str_replace('<{table}>', $configuration['table_name'], $promptFormat);
  435. $promptFormat = str_replace('<{table_structure_configuration}>', $table_structure_text, $promptFormat);
  436. $promptFormat = str_replace('<{response_rule_configuration}>', $response_rule_text, $promptFormat);
  437. $promptFormat = str_replace('<{number}>', count($response_rule_configuration)+1, $promptFormat);
  438. $promptFormat = str_replace('<{output_type}>', $formatListType, $promptFormat);
  439. $promptFormat = str_replace('<{output_format_configuration}>', $output_format_text, $promptFormat);
  440. return array("vuedata"=>array("tableData"=>$tableData,"stepData"=>$stepData,"formatList"=>$formatList,"formatListType"=>$formatListType),
  441. "promptFormat" =>$promptFormat);
  442. }
  443. public function getChangedLog($id){
  444. $changeLogList = array();
  445. $configurationArr = common::excuteListSql("select id, character_name,professional_field,main_tasks,table_name,table_description,
  446. created_by,TO_CHAR(created_time, 'YYYY-mm-dd HH24:MI:SS') as created_time,
  447. table_structure_configuration,response_rule_configuration,output_format_configuration,fixed_problem_configuration
  448. from public.kln_robot_prompt_configuration_log where ref_id = '$id' order by id desc");
  449. foreach($configurationArr as $ca){
  450. $data = $this->dealPromptFormatAndVue($ca);
  451. $temp =array();
  452. $temp["time"] = $ca['created_time']." Prompt";
  453. $temp["person"] ="提交人:".$ca['created_by'];
  454. $temp["text"] = $data['promptFormat'];
  455. $changeLogList[] = $temp;
  456. }
  457. return $changeLogList;
  458. }
  459. public function getSystemPrompt(){
  460. //查询所有配置信息 目前只有一个表一个数据
  461. $configuration = common::excuteObjectSql("select id, character_name,professional_field,main_tasks,table_name,table_description,
  462. table_structure_configuration,response_rule_configuration,output_format_configuration,fixed_problem_configuration
  463. from public.kln_robot_prompt_configuration where id = 1");
  464. $PromptAndVue = $this->dealPromptFormatAndVue($configuration);
  465. //promptFormat
  466. $promptFormat =$PromptAndVue["promptFormat"];
  467. return $promptFormat;
  468. }
  469. public function getCompletePromptFormat() {
  470. $formatTpl = "
  471. 您是专门从<{professional_field}>的 <{character_name}>,请始终以<{output_type}>格式响应。您的主要任务是<{main_tasks}>
  472. 表名:<{table}>
  473. 表结构: \"columns\": <{table_structure_configuration}>
  474. 响应规则,请按以下步骤处理:
  475. <{response_rule_configuration}>
  476. <{number}>. 请用以下<{output_type}>格式回复:
  477. <{output_format_configuration}>";
  478. return $formatTpl;
  479. }
  480. public function doFreeAnswerAndLog($serial_no,$model,$systemPrompt, $question_content, $history){
  481. //分担查询
  482. include ONLINE_ROOT . 'libs' . DS . 'map_config.ini.php';
  483. //Ai response
  484. $item_value = common::excuteOneSql("select item_value from public.config where item = 'AIAPISetting'");
  485. $config = json_decode($item_value,true);
  486. $response = AIClientFactory::create($model, $config[$model], $systemPrompt, $question_content, $history = []);
  487. $input_token = "";
  488. $output_token = "";
  489. $answer_template = "";
  490. $answer ="";
  491. $response_pram = common::excuteObjectSql("select to_char(now(), 'YYYY-mm-dd HH24:MI:SS') as response_time,
  492. CEIL(EXTRACT(EPOCH FROM (now() - question_date))) AS response_duration from public.kln_robot_chat_log where serial_no = '$serial_no'");
  493. $response_duration = $response_pram['response_duration'];
  494. //回答问题类型,在没有超时的情况下,固定:AI回答
  495. $answer_type = "AI回答";
  496. if ($response_duration > 120){
  497. $answer_type = "回答超时";
  498. }
  499. $request_content = common::check_input(json_encode($response['data']));
  500. $ai_response_content = common::check_input(json_encode($response['full_response']));
  501. $message = json_decode(common::getChatAimessage($response['message']),true);
  502. if($message["can_query"] == "true" && !empty($message["sql"])){
  503. $reference = $message["reference"];
  504. $answer_template = common::check_input($message["reference"]);
  505. $sql = $message["sql"];
  506. //拆分sql 存在多条的情况
  507. $sqlArr = explode(";", $sql);
  508. //给所有sql 拼接用户权限
  509. $sqlWhere = ' ' . common::searchExtendHand_KLN("ocean", $_SESSION["ONLINE_USER"]);
  510. //先不考虑总数,处理有难度
  511. foreach($sqlArr as $_sql){
  512. if(empty($_sql)){
  513. continue;
  514. }
  515. //根据public.kln_ocean 和 WHERE 的位置关系,带入权限
  516. $new_sql = utils::modifyString($_sql,$sqlWhere);
  517. //处理limit 超过10 先限制10
  518. //$new_sql = utils::processLimitClause($new_sql);
  519. //$rs = common::excuteListSql($new_sql);
  520. $rs = $mapdb->GetAll($new_sql) or ( (!$mapdb->ErrorMsg()) or error_log(common::dbLog($mapdb, $new_sql), 0));
  521. $reference = utils::replacementsMultiline($rs,$reference,$new_sql);
  522. }
  523. //有就去掉{{#each hbol_list}}\n {{/each}}
  524. $reference = preg_replace([
  525. '/\{\{[^}]+\}\}\n/', // 匹配开始标签及换行
  526. '/\{\{\/[^}]+\}\}/' // 匹配结束标签
  527. ], '', $reference);
  528. $answer = $reference;
  529. }else{
  530. $answer = $message["response"];
  531. }
  532. //update 更新
  533. $updateSql = "update public.kln_robot_chat_log set answer_duration = '$response_duration',answer_template='$answer_template',
  534. answer_type = case when COALESCE(answer_type,'') = '回答被动停止' then '回答被动停止' else '$answer_type' end,
  535. request_content='$request_content',
  536. input_token='$input_token',ai_response_content='$ai_response_content',
  537. output_token='$output_token',response_time=now(),response_duration='$response_duration'
  538. where serial_no = '$serial_no'";
  539. $updateRs = common::excuteUpdateSql($updateSql);
  540. if (!$updateRs) {
  541. $data = array("type"=>"markdown","data" => "AI Chat Response Save Error");
  542. common::echo_json_encode(200,$data);
  543. exit();
  544. }
  545. return $answer;
  546. }
  547. public function doFixedAnswerAndLog($serial_no,$fixed_faq,$question_content){
  548. $input_token = "";
  549. $output_token = "";
  550. $answer_template = "";
  551. $answer ="";
  552. $fixedChat = common::excuteObjectSql("select * from public.kln_robot_chat_fixed where fixed_faq = '$fixed_faq'");
  553. if (empty($fixedChat['secondary_interaction_content']) || $question_content != $fixedChat['fixed_faq'] ){
  554. $reference = $fixedChat["answer_style"];
  555. $answer_template = common::check_input($fixedChat["answer_style"]);
  556. //执行sql 语句
  557. $sql = $fixedChat["fixed_sql"];
  558. //拆分sql 存在多条的情况
  559. $sqlArr = explode(";", $sql);
  560. //给所有sql 拼接用户权限
  561. $sqlWhere = ' ' . common::searchExtendHand_KLN("ocean", $_SESSION["ONLINE_USER"]);
  562. //先不考虑总数,处理有难度
  563. foreach($sqlArr as $_sql){
  564. if(empty($_sql)){
  565. continue;
  566. }
  567. //根据public.kln_ocean 和 WHERE 的位置关系,带入权限
  568. $new_sql = utils::modifyString($_sql,$sqlWhere);
  569. //处理limit 超过10 先限制10
  570. //$new_sql = utils::processLimitClause($new_sql);
  571. $rs = common::excuteListSql($new_sql);
  572. $reference = utils::replacementsMultiline($rs,$reference,$new_sql);
  573. }
  574. //有就去掉{{#each hbol_list}}\n {{/each}}
  575. $reference = preg_replace([
  576. '/\{\{[^}]+\}\}\n/', // 匹配开始标签及换行
  577. '/\{\{\/[^}]+\}\}/' // 匹配结束标签
  578. ], '', $reference);
  579. $answer = $reference;
  580. } else {
  581. $answer = $fixedChat['secondary_interaction_content'];
  582. }
  583. //回答完毕计时
  584. $response_pram = common::excuteObjectSql("select to_char(now(), 'YYYY-mm-dd HH24:MI:SS') as response_time,
  585. CEIL(EXTRACT(EPOCH FROM (now() - question_date))) AS response_duration from public.kln_robot_chat_log where serial_no = '$serial_no'");
  586. $response_duration = $response_pram['response_duration'];
  587. //回答问题类型,在没有超时的情况下,固定:AI回答
  588. $answer_type = "AI回答";
  589. if ($response_duration > 120){
  590. $answer_type = "回答超时";
  591. }
  592. $request_content = common::check_input($question_content);
  593. $ai_response_content = common::check_input($answer);
  594. //update 更新
  595. $updateSql = "update public.kln_robot_chat_log set answer_duration = '$response_duration',answer_template='$answer_template',
  596. answer_type = case when COALESCE(answer_type,'') = '回答被动停止' then '回答被动停止' else '$answer_type' end,
  597. request_content='$request_content',
  598. input_token='$input_token',ai_response_content='$ai_response_content',
  599. output_token='$output_token',response_time=now(),response_duration='$response_duration'
  600. where serial_no = '$serial_no'";
  601. $updateRs = common::excuteUpdateSql($updateSql);
  602. if (!$updateRs) {
  603. $data = array("type"=>"markdown","data" => "AI Chat Response Save Error");
  604. common::echo_json_encode(200,$data);
  605. exit();
  606. }
  607. return $answer;
  608. }
  609. }
  610. ?>