|
@@ -27,7 +27,7 @@ class robot{
|
|
|
}
|
|
}
|
|
|
return self::$_robot;
|
|
return self::$_robot;
|
|
|
}
|
|
}
|
|
|
- public function robot_chat() {
|
|
|
|
|
|
|
+ public function robot_chat_log() {
|
|
|
$operate = utils::_get('operate');
|
|
$operate = utils::_get('operate');
|
|
|
$operate = strtolower($operate);
|
|
$operate = strtolower($operate);
|
|
|
|
|
|
|
@@ -286,6 +286,7 @@ class robot{
|
|
|
$sqlWhere = ' ' . common::searchExtendHand_KLN("ocean", $_SESSION["ONLINE_USER"]);
|
|
$sqlWhere = ' ' . common::searchExtendHand_KLN("ocean", $_SESSION["ONLINE_USER"]);
|
|
|
//先不考虑总数,处理有难度
|
|
//先不考虑总数,处理有难度
|
|
|
foreach($sqlArr as $_sql){
|
|
foreach($sqlArr as $_sql){
|
|
|
|
|
+ error_log($_sql);
|
|
|
if(empty($_sql)){
|
|
if(empty($_sql)){
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
@@ -295,7 +296,7 @@ class robot{
|
|
|
$new_sql = utils::processLimitClause($new_sql);
|
|
$new_sql = utils::processLimitClause($new_sql);
|
|
|
//$rs = common::excuteListSql($new_sql);
|
|
//$rs = common::excuteListSql($new_sql);
|
|
|
$rs = $mapdb->GetAll($new_sql) or ( (!$mapdb->ErrorMsg()) or error_log(common::dbLog($mapdb, $new_sql), 0));
|
|
$rs = $mapdb->GetAll($new_sql) or ( (!$mapdb->ErrorMsg()) or error_log(common::dbLog($mapdb, $new_sql), 0));
|
|
|
- $reference = utils::replacementsMultiline($rs,$reference);
|
|
|
|
|
|
|
+ $reference = utils::replacementsMultiline($rs,$reference,$new_sql);
|
|
|
}
|
|
}
|
|
|
//有就去掉{{#each hbol_list}}\n {{/each}}
|
|
//有就去掉{{#each hbol_list}}\n {{/each}}
|
|
|
$reference = preg_replace([
|
|
$reference = preg_replace([
|
|
@@ -344,6 +345,105 @@ class robot{
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ public function ai_chat(){
|
|
|
|
|
+ $operate = utils::_get('operate');
|
|
|
|
|
+ $operate = strtolower($operate);
|
|
|
|
|
+
|
|
|
|
|
+ if($operate == "ai_chat_prompt"){
|
|
|
|
|
+ //查询所有配置信息 目前只有一个表一个数据
|
|
|
|
|
+ $configuration = common::excuteObjectSql("select id, character_name,professional_field,main_tasks,table_name,table_description,
|
|
|
|
|
+ table_structure_configuration,response_rule_configuration,output_format_configuration,fixed_problem_configuration
|
|
|
|
|
+ from public.kln_robot_prompt_configuration where id = 1");
|
|
|
|
|
+
|
|
|
|
|
+ $PromptAndVue = $this->dealPromptFormatAndVue($configuration);
|
|
|
|
|
+ //promptFormat
|
|
|
|
|
+ $promptFormat =$PromptAndVue["promptFormat"];
|
|
|
|
|
+
|
|
|
|
|
+ $data = array("msg" => "succssful","prompt"=>$promptFormat);
|
|
|
|
|
+ common::echo_json_encode(200,$data);
|
|
|
|
|
+ exit();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * ai 自由聊天
|
|
|
|
|
+ */
|
|
|
|
|
+ if($operate == "ai_chat"){
|
|
|
|
|
+ //前端生成一个唯一的serial_no
|
|
|
|
|
+ $serial_no = common::check_input($_POST["serial_no"]);
|
|
|
|
|
+ //系统提示词
|
|
|
|
|
+ $systemPrompt = common::check_input($_POST["prompt"]);
|
|
|
|
|
+ $question_type = common::check_input($_POST['question_type']);
|
|
|
|
|
+ $question_content = common::check_input($_POST['question_content']);
|
|
|
|
|
+
|
|
|
|
|
+ //固定问题的原始问题
|
|
|
|
|
+ $fixed_faq = common::check_input($_POST['fixed_faq']);
|
|
|
|
|
+ //claude deepseek 根據賬號信息判断
|
|
|
|
|
+ $model = common::getUserCountry();
|
|
|
|
|
+ $answer_type = $question_type == "Free Question" ? "AI回答" : "预定义模板回答";
|
|
|
|
|
+
|
|
|
|
|
+ //获取自然序列
|
|
|
|
|
+ $sequence = common::getChatAiSequence();
|
|
|
|
|
+ $name = $model == 'deepseek' ? "DS" : "CD";
|
|
|
|
|
+ $request_id = "R".$name."".date("Ymd").$sequence;
|
|
|
|
|
+ $question_id = "Q"."".date("Ymd").$sequence;
|
|
|
|
|
+
|
|
|
|
|
+ //处理一下参数
|
|
|
|
|
+ $user_name = common::check_input(_getLoginName());
|
|
|
|
|
+ $user_type = _isApexLogin() ? "employee" : "customer";
|
|
|
|
|
+
|
|
|
|
|
+ //首先生成基本记录数据 以便以后根据情况更新状态
|
|
|
|
|
+ $sql = "INSERT INTO public.kln_robot_chat_log(serial_no, question_id, user_name, user_type, question_type, question_content,
|
|
|
|
|
+ answer_type, question_date, question_time, request_id, request_time)
|
|
|
|
|
+ VALUES ('$serial_no','$question_id', '$user_name', '$user_type', '$question_type', '$question_content',
|
|
|
|
|
+ '$answer_type',now(),to_char(CURRENT_TIME::time, 'HH24:MI:SS'), '$request_id',now());";
|
|
|
|
|
+ $rs = common::excuteUpdateSql($sql);
|
|
|
|
|
+ if (!$rs) {
|
|
|
|
|
+ $data = array("type"=>"markdown","data" => "AI Chat Save Error");
|
|
|
|
|
+ common::echo_json_encode(200,$data);
|
|
|
|
|
+ exit();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ($question_type == 'Predefined Question'){
|
|
|
|
|
+ $answer = $this->doFixedAnswerAndLog($serial_no,$fixed_faq,$question_content);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $answer = $this->doFreeAnswerAndLog($serial_no,$model,$systemPrompt, $question_content, $history = []);
|
|
|
|
|
+ }
|
|
|
|
|
+ $return = array("type"=>"markdown","data" =>$answer);
|
|
|
|
|
+ common::echo_json_encode(200,$return);
|
|
|
|
|
+ exit();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if($operate == "ai_chat_stop"){
|
|
|
|
|
+ $serial_no = common::check_input($_POST["serial_no"]);
|
|
|
|
|
+ $updateSql = "update public.kln_robot_chat_log set answer_type = '回答被动停止' where serial_no = '$serial_no'";
|
|
|
|
|
+
|
|
|
|
|
+ $updateRs = common::excuteUpdateSql($updateSql);
|
|
|
|
|
+ if (!$updateRs) {
|
|
|
|
|
+ $data = array("msg" => "AI Chat Response Stop Error");
|
|
|
|
|
+ }else{
|
|
|
|
|
+ $data = array("msg" => "AI Chat Response Stop succssful");
|
|
|
|
|
+ }
|
|
|
|
|
+ common::echo_json_encode(200,$data);
|
|
|
|
|
+ exit();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if($operate == "ai_chat_answer_mark"){
|
|
|
|
|
+ $serial_no = common::check_input($_POST["serial_no"]);
|
|
|
|
|
+ $answer_satisfication = common::check_input($_POST["answer_satisfication"]);
|
|
|
|
|
+ $updateSql = "update public.kln_robot_chat_log set answer_satisfication = '$answer_satisfication' where serial_no = '$serial_no'";
|
|
|
|
|
+
|
|
|
|
|
+ $updateRs = common::excuteUpdateSql($updateSql);
|
|
|
|
|
+ if (!$updateRs) {
|
|
|
|
|
+ $data = array("msg" => "AI Chat Response Mark Error");
|
|
|
|
|
+ }else{
|
|
|
|
|
+ $data = array("msg" => "AI Chat Response Mark succssful");
|
|
|
|
|
+ }
|
|
|
|
|
+ common::echo_json_encode(200,$data);
|
|
|
|
|
+ exit();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public function dealPromptFormatAndVue($configuration){
|
|
public function dealPromptFormatAndVue($configuration){
|
|
|
//tableDat-VUE
|
|
//tableDat-VUE
|
|
|
$tableData = array();
|
|
$tableData = array();
|
|
@@ -424,6 +524,18 @@ class robot{
|
|
|
return $changeLogList;
|
|
return $changeLogList;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ public function getSystemPrompt(){
|
|
|
|
|
+ //查询所有配置信息 目前只有一个表一个数据
|
|
|
|
|
+ $configuration = common::excuteObjectSql("select id, character_name,professional_field,main_tasks,table_name,table_description,
|
|
|
|
|
+ table_structure_configuration,response_rule_configuration,output_format_configuration,fixed_problem_configuration
|
|
|
|
|
+ from public.kln_robot_prompt_configuration where id = 1");
|
|
|
|
|
+
|
|
|
|
|
+ $PromptAndVue = $this->dealPromptFormatAndVue($configuration);
|
|
|
|
|
+ //promptFormat
|
|
|
|
|
+ $promptFormat =$PromptAndVue["promptFormat"];
|
|
|
|
|
+ return $promptFormat;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public function getCompletePromptFormat() {
|
|
public function getCompletePromptFormat() {
|
|
|
$formatTpl = "
|
|
$formatTpl = "
|
|
|
您是专门从<{professional_field}>的 <{character_name}>,请始终以<{output_type}>格式响应。您的主要任务是<{main_tasks}>
|
|
您是专门从<{professional_field}>的 <{character_name}>,请始终以<{output_type}>格式响应。您的主要任务是<{main_tasks}>
|
|
@@ -438,6 +550,145 @@ class robot{
|
|
|
<{output_format_configuration}>";
|
|
<{output_format_configuration}>";
|
|
|
return $formatTpl;
|
|
return $formatTpl;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ public function doFreeAnswerAndLog($serial_no,$model,$systemPrompt, $question_content, $history){
|
|
|
|
|
+ //分担查询
|
|
|
|
|
+ include ONLINE_ROOT . 'libs' . DS . 'map_config.ini.php';
|
|
|
|
|
+
|
|
|
|
|
+ //Ai response
|
|
|
|
|
+ $item_value = common::excuteOneSql("select item_value from public.config where item = 'AIAPISetting'");
|
|
|
|
|
+ $config = json_decode($item_value,true);
|
|
|
|
|
+ $response = AIClientFactory::create($model, $config[$model], $systemPrompt, $question_content, $history = []);
|
|
|
|
|
+
|
|
|
|
|
+ $input_token = "";
|
|
|
|
|
+ $output_token = "";
|
|
|
|
|
+ $answer_template = "";
|
|
|
|
|
+ $answer ="";
|
|
|
|
|
+ $response_pram = common::excuteObjectSql("select to_char(now(), 'YYYY-mm-dd HH24:MI:SS') as response_time,
|
|
|
|
|
+ CEIL(EXTRACT(EPOCH FROM (now() - question_date))) AS response_duration from public.kln_robot_chat_log where serial_no = '$serial_no'");
|
|
|
|
|
+ $response_duration = $response_pram['response_duration'];
|
|
|
|
|
+ //回答问题类型,在没有超时的情况下,固定:AI回答
|
|
|
|
|
+ $answer_type = "AI回答";
|
|
|
|
|
+ if ($response_duration > 120){
|
|
|
|
|
+ $answer_type = "回答超时";
|
|
|
|
|
+ }
|
|
|
|
|
+ $request_content = common::check_input(json_encode($response['data']));
|
|
|
|
|
+ $ai_response_content = common::check_input(json_encode($response['full_response']));
|
|
|
|
|
+ $message = json_decode(common::getChatAimessage($response['message']),true);
|
|
|
|
|
+ if($message["can_query"] == "true" && !empty($message["sql"])){
|
|
|
|
|
+ $reference = $message["reference"];
|
|
|
|
|
+ $answer_template = common::check_input($message["reference"]);
|
|
|
|
|
+ $sql = $message["sql"];
|
|
|
|
|
+ //拆分sql 存在多条的情况
|
|
|
|
|
+ $sqlArr = explode(";", $sql);
|
|
|
|
|
+ //给所有sql 拼接用户权限
|
|
|
|
|
+ $sqlWhere = ' ' . common::searchExtendHand_KLN("ocean", $_SESSION["ONLINE_USER"]);
|
|
|
|
|
+ //先不考虑总数,处理有难度
|
|
|
|
|
+ foreach($sqlArr as $_sql){
|
|
|
|
|
+ if(empty($_sql)){
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ //根据public.kln_ocean 和 WHERE 的位置关系,带入权限
|
|
|
|
|
+ $new_sql = utils::modifyString($_sql,$sqlWhere);
|
|
|
|
|
+ //处理limit 超过10 先限制10
|
|
|
|
|
+ //$new_sql = utils::processLimitClause($new_sql);
|
|
|
|
|
+ //$rs = common::excuteListSql($new_sql);
|
|
|
|
|
+ $rs = $mapdb->GetAll($new_sql) or ( (!$mapdb->ErrorMsg()) or error_log(common::dbLog($mapdb, $new_sql), 0));
|
|
|
|
|
+ $reference = utils::replacementsMultiline($rs,$reference,$new_sql);
|
|
|
|
|
+ }
|
|
|
|
|
+ //有就去掉{{#each hbol_list}}\n {{/each}}
|
|
|
|
|
+ $reference = preg_replace([
|
|
|
|
|
+ '/\{\{[^}]+\}\}\n/', // 匹配开始标签及换行
|
|
|
|
|
+ '/\{\{\/[^}]+\}\}/' // 匹配结束标签
|
|
|
|
|
+ ], '', $reference);
|
|
|
|
|
+ $answer = $reference;
|
|
|
|
|
+ }else{
|
|
|
|
|
+ $answer = $message["response"];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //update 更新
|
|
|
|
|
+ $updateSql = "update public.kln_robot_chat_log set answer_duration = '$response_duration',answer_template='$answer_template',
|
|
|
|
|
+ answer_type = case when COALESCE(answer_type,'') = '回答被动停止' then '回答被动停止' else '$answer_type' end,
|
|
|
|
|
+ request_content='$request_content',
|
|
|
|
|
+ input_token='$input_token',ai_response_content='$ai_response_content',
|
|
|
|
|
+ output_token='$output_token',response_time=now(),response_duration='$response_duration'
|
|
|
|
|
+ where serial_no = '$serial_no'";
|
|
|
|
|
+
|
|
|
|
|
+ $updateRs = common::excuteUpdateSql($updateSql);
|
|
|
|
|
+ if (!$updateRs) {
|
|
|
|
|
+ $data = array("type"=>"markdown","data" => "AI Chat Response Save Error");
|
|
|
|
|
+ common::echo_json_encode(200,$data);
|
|
|
|
|
+ exit();
|
|
|
|
|
+ }
|
|
|
|
|
+ return $answer;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function doFixedAnswerAndLog($serial_no,$fixed_faq,$question_content){
|
|
|
|
|
+ $input_token = "";
|
|
|
|
|
+ $output_token = "";
|
|
|
|
|
+ $answer_template = "";
|
|
|
|
|
+ $answer ="";
|
|
|
|
|
+ $fixedChat = common::excuteObjectSql("select * from public.kln_robot_chat_fixed where fixed_faq = '$fixed_faq'");
|
|
|
|
|
+
|
|
|
|
|
+ if (empty($fixedChat['secondary_interaction_content']) || $question_content != $fixedChat['fixed_faq'] ){
|
|
|
|
|
+ $reference = $fixedChat["answer_style"];
|
|
|
|
|
+ $answer_template = common::check_input($fixedChat["answer_style"]);
|
|
|
|
|
+ //执行sql 语句
|
|
|
|
|
+ $sql = $fixedChat["fixed_sql"];
|
|
|
|
|
+ //拆分sql 存在多条的情况
|
|
|
|
|
+ $sqlArr = explode(";", $sql);
|
|
|
|
|
+ //给所有sql 拼接用户权限
|
|
|
|
|
+ $sqlWhere = ' ' . common::searchExtendHand_KLN("ocean", $_SESSION["ONLINE_USER"]);
|
|
|
|
|
+ //先不考虑总数,处理有难度
|
|
|
|
|
+ foreach($sqlArr as $_sql){
|
|
|
|
|
+ if(empty($_sql)){
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ //根据public.kln_ocean 和 WHERE 的位置关系,带入权限
|
|
|
|
|
+ $new_sql = utils::modifyString($_sql,$sqlWhere);
|
|
|
|
|
+ //处理limit 超过10 先限制10
|
|
|
|
|
+ //$new_sql = utils::processLimitClause($new_sql);
|
|
|
|
|
+ $rs = common::excuteListSql($new_sql);
|
|
|
|
|
+ $reference = utils::replacementsMultiline($rs,$reference,$new_sql);
|
|
|
|
|
+ }
|
|
|
|
|
+ //有就去掉{{#each hbol_list}}\n {{/each}}
|
|
|
|
|
+ $reference = preg_replace([
|
|
|
|
|
+ '/\{\{[^}]+\}\}\n/', // 匹配开始标签及换行
|
|
|
|
|
+ '/\{\{\/[^}]+\}\}/' // 匹配结束标签
|
|
|
|
|
+ ], '', $reference);
|
|
|
|
|
+ $answer = $reference;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $answer = $fixedChat['secondary_interaction_content'];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //回答完毕计时
|
|
|
|
|
+ $response_pram = common::excuteObjectSql("select to_char(now(), 'YYYY-mm-dd HH24:MI:SS') as response_time,
|
|
|
|
|
+ CEIL(EXTRACT(EPOCH FROM (now() - question_date))) AS response_duration from public.kln_robot_chat_log where serial_no = '$serial_no'");
|
|
|
|
|
+ $response_duration = $response_pram['response_duration'];
|
|
|
|
|
+ //回答问题类型,在没有超时的情况下,固定:AI回答
|
|
|
|
|
+ $answer_type = "AI回答";
|
|
|
|
|
+ if ($response_duration > 120){
|
|
|
|
|
+ $answer_type = "回答超时";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $request_content = common::check_input($question_content);
|
|
|
|
|
+ $ai_response_content = common::check_input($answer);
|
|
|
|
|
+ //update 更新
|
|
|
|
|
+ $updateSql = "update public.kln_robot_chat_log set answer_duration = '$response_duration',answer_template='$answer_template',
|
|
|
|
|
+ answer_type = case when COALESCE(answer_type,'') = '回答被动停止' then '回答被动停止' else '$answer_type' end,
|
|
|
|
|
+ request_content='$request_content',
|
|
|
|
|
+ input_token='$input_token',ai_response_content='$ai_response_content',
|
|
|
|
|
+ output_token='$output_token',response_time=now(),response_duration='$response_duration'
|
|
|
|
|
+ where serial_no = '$serial_no'";
|
|
|
|
|
+
|
|
|
|
|
+ $updateRs = common::excuteUpdateSql($updateSql);
|
|
|
|
|
+ if (!$updateRs) {
|
|
|
|
|
+ $data = array("type"=>"markdown","data" => "AI Chat Response Save Error");
|
|
|
|
|
+ common::echo_json_encode(200,$data);
|
|
|
|
|
+ exit();
|
|
|
|
|
+ }
|
|
|
|
|
+ return $answer;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
?>
|
|
?>
|