278 lines
12 KiB
PHP
278 lines
12 KiB
PHP
<?php
|
|
|
|
namespace web\ambap;
|
|
|
|
class aiapi {
|
|
public static function json_rawai($param = null, $debug = false) {
|
|
global $db;
|
|
$post = new \ciy\post($param);
|
|
$aikey = $post->getint('aikey');
|
|
$aikeyrow = null;
|
|
if ($aikey > 0) {
|
|
$csql = new \ciy\sql('zc_ai_key');
|
|
$csql->where('id', $aikey);
|
|
$aikeyrow = $db->getone($csql);
|
|
if (!is_array($aikeyrow))
|
|
return errjson('AI Key不存在');
|
|
}
|
|
if (!is_array($aikeyrow)) {
|
|
$csql = new \ciy\sql('zc_ai_key');
|
|
$csql->where('id', 1);
|
|
$aikeyrow = $db->getone($csql);
|
|
if (!is_array($aikeyrow))
|
|
return errjson('AI Key未设置');
|
|
}
|
|
$system = $post->get('system');
|
|
$chat = $post->get('chat');
|
|
if(empty($chat))
|
|
return errjson('请输入聊天内容');
|
|
$openai = new \ciy\openai($aikeyrow);
|
|
$openai->debug($debug);
|
|
$openai->setparam($post->get('aiprange'));
|
|
$openai->newsystem($system);
|
|
$retai = $openai->completion($chat, strpos($chat . $system, 'JSON') !== false);
|
|
if (is_string($retai))
|
|
return errjson($retai);
|
|
$ret['ai'] = $retai;
|
|
return succjson($ret);
|
|
}
|
|
public static function json_aidecision($param = null, $debug = false) {
|
|
global $db;
|
|
set_time_limit(0);
|
|
$timespan = time();
|
|
$post = new \ciy\post($param);
|
|
$id = $post->getint('id');
|
|
$csql = new \ciy\sql('zc_ai_decision');
|
|
$csql->where('id', $id);
|
|
$decisionrow = $db->getone($csql);
|
|
if (!is_array($decisionrow))
|
|
return errjson('AI决策单元不存在');
|
|
$csql = new \ciy\sql('zc_ai_key');
|
|
$csql->where('id', $decisionrow['aikey']);
|
|
$aikeyrow = $db->getone($csql);
|
|
if (!is_array($aikeyrow))
|
|
return errjson('AI Key未设置');
|
|
|
|
$funcdatarows = null;
|
|
if (!empty($decisionrow['funcids'])) {
|
|
$csql = new \ciy\sql('zc_ai_funcdata');
|
|
$csql->where('id in', trim($decisionrow['funcids'], ','));
|
|
$funcdatarows = $db->get($csql);
|
|
}
|
|
if (strpos($decisionrow['sysprompt'] . $decisionrow['roleprompt'], '{{know.') === false) {
|
|
$csql = new \ciy\sql('zc_ai_knowcata');
|
|
$knowcatarows = $db->get($csql);
|
|
if (count($knowcatarows) > 0) {
|
|
if ($funcdatarows == null)
|
|
$funcdatarows = array();
|
|
$descs = '';
|
|
foreach ($knowcatarows as $knowcatarow) {
|
|
$descs .= "\n{知识库ID:" . $knowcatarow['id'] . ", " . $knowcatarow['name'] . ',' . $knowcatarow['aiguide'] . '}';
|
|
}
|
|
$funcdatarows[] = array(
|
|
'id' => 0,
|
|
'name' => 'know',
|
|
'funcname' => 'know',
|
|
'descs' => '如果需要补充学习专业知识库信息,调用该函数。知识库列表有,' . $descs,
|
|
'paramjson' => '*ID=准确的知识库ID',
|
|
'funcparam' => ''
|
|
);
|
|
}
|
|
}
|
|
$csql = new \ciy\sql('zc_ai_key');
|
|
$csql->where('id', $decisionrow['aikey']);
|
|
$aikeyrow = $db->getone($csql);
|
|
if (!is_array($aikeyrow))
|
|
return errjson('AI Key不存在');
|
|
$system = preg_replace_callback('/\{\{([^}]+)\}\}/', function ($matches) use ($db, $post) {
|
|
$key = $matches[1];
|
|
if (substr($key, 0, 5) == 'know.') {
|
|
$knowcataname = substr($key, 5);
|
|
$csql = new \ciy\sql('zc_ai_knowcata');
|
|
$csql->where('name', $knowcataname);
|
|
$knowcatarow = $db->getone($csql);
|
|
if (!is_array($knowcatarow))
|
|
return '';
|
|
$csql = new \ciy\sql('zc_ai_knowledge');
|
|
$csql->where('cataid', $knowcatarow['id']);
|
|
$knowrows = $db->get($csql);
|
|
$knowstr = '';
|
|
foreach ($knowrows as $knowrow) {
|
|
$knowstr .= $knowrow['content'] . "\n";
|
|
}
|
|
return $knowstr;
|
|
}
|
|
$val = $post->get($key);
|
|
if (is_array($val))
|
|
$val = json_encode($val, JSON_UNESCAPED_UNICODE);
|
|
return $val . '';
|
|
}, $decisionrow['sysprompt']);
|
|
$roleprompt = preg_replace_callback('/\{\{([^}]+)\}\}/', function ($matches) use ($db, $post) {
|
|
$key = $matches[1];
|
|
if (substr($key, 0, 5) == 'know.') {
|
|
$knowcataname = substr($key, 5);
|
|
$csql = new \ciy\sql('zc_ai_knowcata');
|
|
$csql->where('name', $knowcataname);
|
|
$knowcatarow = $db->getone($csql);
|
|
if (!is_array($knowcatarow))
|
|
return '';
|
|
$csql = new \ciy\sql('zc_ai_knowledge');
|
|
$csql->where('cataid', $knowcatarow['id']);
|
|
$knowrows = $db->get($csql);
|
|
$knowstr = '';
|
|
foreach ($knowrows as $knowrow) {
|
|
$knowstr .= $knowrow['content'] . "\n";
|
|
}
|
|
return $knowstr;
|
|
}
|
|
$val = $post->get($key);
|
|
if (is_array($val))
|
|
$val = json_encode($val, JSON_UNESCAPED_UNICODE);
|
|
return $val . '';
|
|
}, $decisionrow['roleprompt']);
|
|
|
|
$openai = new \ciy\openai($aikeyrow);
|
|
$openai->debug($debug);
|
|
$openai->setparam($decisionrow['aiprange']);
|
|
$openai->newsystem($system);
|
|
$retai = $openai->completion($roleprompt, strpos($roleprompt . $system, 'JSON') !== false, $funcdatarows, function ($funcarray) use ($funcdatarows) {
|
|
$funcdatarow = ccode($funcdatarows, substr($funcarray['name'], 1), 'id', null);
|
|
if (!is_array($funcdatarow))
|
|
return 'ERR未定义函数:' . $funcarray['name'];
|
|
$funcname = $funcdatarow['funcname'];
|
|
if ($funcname[0] != '\\')
|
|
$funcname = '\\web\\admin\\aifunc\\' . $funcname;
|
|
if (!class_exists($funcname))
|
|
return 'ERR无效类:' . $funcname;
|
|
if (!method_exists($funcname, 'main'))
|
|
return 'ERR无效函数:' . $funcname . '::main';
|
|
$funcname .= '::main';
|
|
$arguments = json_decode($funcarray['arguments'], true);
|
|
$funcparams = getstrparam($funcdatarow['funcparam'], "\n");
|
|
foreach ($funcparams as $key => $val) {
|
|
$arguments[$key] = $val;
|
|
}
|
|
return call_user_func($funcname, $arguments);
|
|
});
|
|
if (is_string($retai))
|
|
return errjson('AI识别失败: ' . $retai);
|
|
|
|
$decci = 0;
|
|
$aichat = json_encode($openai->messages, JSON_UNESCAPED_UNICODE);
|
|
$resulttxt = json_encode($retai, JSON_UNESCAPED_UNICODE);
|
|
if ($decisionrow['aicalkey'] > 0 && !empty($decisionrow['calprompt'])) {
|
|
$post->post['result.ai'] = $aichat;
|
|
$post->post['result.data'] = $resulttxt;
|
|
$csql = new \ciy\sql('zc_ai_key');
|
|
$csql->where('id', $decisionrow['aicalkey']);
|
|
$aikeyrow = $db->getone($csql);
|
|
if (!is_array($aikeyrow))
|
|
return errjson('AI Key不存在');
|
|
$calprompt = preg_replace_callback('/\{\{([^}]+)\}\}/', function ($matches) use ($db, $post) {
|
|
$key = $matches[1];
|
|
if (substr($key, 0, 5) == 'know.') {
|
|
$knowcataname = substr($key, 5);
|
|
$csql = new \ciy\sql('zc_ai_knowcata');
|
|
$csql->where('name', $knowcataname);
|
|
$knowcatarow = $db->getone($csql);
|
|
if (!is_array($knowcatarow))
|
|
return '';
|
|
$csql = new \ciy\sql('zc_ai_knowledge');
|
|
$csql->where('cataid', $knowcatarow['id']);
|
|
$knowrows = $db->get($csql);
|
|
$knowstr = '';
|
|
foreach ($knowrows as $knowrow) {
|
|
$knowstr .= $knowrow['content'] . "\n";
|
|
}
|
|
return $knowstr;
|
|
}
|
|
$val = $post->get($key);
|
|
if (is_array($val))
|
|
$val = json_encode($val, JSON_UNESCAPED_UNICODE);
|
|
return $val . '';
|
|
}, $decisionrow['calprompt']);
|
|
$openai = new \ciy\openai($aikeyrow);
|
|
$openai->debug($debug);
|
|
$openai->setparam($decisionrow['aicalprange']);
|
|
$openai->newsystem();
|
|
$retcalai = $openai->completion($calprompt, true);
|
|
$decci = toint($retcalai['confidence']);
|
|
} else if ($decisionrow['aicalkey'] == 0 && !empty($decisionrow['aicalfunc'])) {
|
|
$funcname = $decisionrow['aicalfunc'];
|
|
if ($funcname[0] != '\\')
|
|
$funcname = '\\web\\admin\\aifunc\\' . $funcname;
|
|
if (!class_exists($funcname))
|
|
return errjson('无效类:' . $funcname);
|
|
if (!method_exists($funcname, 'main'))
|
|
return errjson('无效函数:' . $funcname . '::main');
|
|
$funcname .= '::main';
|
|
$decci = call_user_func($funcname, $retai, $decisionrow['calprompt']);
|
|
}
|
|
$ret['sec'] = time() - $timespan + 1; //用时
|
|
$ret['ci'] = $decci; //置信度
|
|
$ret['ai'] = $retai; //结果
|
|
if ($post->get('_more') == 'ok') {
|
|
$ret['messages'] = $openai->messages; //交互过程
|
|
$ret['roleprompt'] = $roleprompt; //提示词
|
|
$ret['system'] = $system; //角色描述
|
|
}
|
|
return succjson($ret);
|
|
}
|
|
public static function multiparam($input, $sep) {
|
|
$len = strlen($input);
|
|
$ips = array();
|
|
$i = 0;
|
|
$inMultiline = false;
|
|
$currentParam = '';
|
|
$currentValue = '';
|
|
|
|
while ($i < $len) {
|
|
if (!$inMultiline) {
|
|
$paramStart = $i;
|
|
while ($i < $len && $input[$i] !== $sep) {
|
|
if ($input[$i] === "\n")
|
|
return '参数格式不合法';
|
|
$i++;
|
|
}
|
|
if ($i == $len)
|
|
return '参数格式不合法,应用' . $sep . '号分隔';
|
|
$currentParam = trim(substr($input, $paramStart, $i - $paramStart));
|
|
if (empty($currentParam))
|
|
return '参数没有参数名';
|
|
$i++;
|
|
if ($i < $len && $input[$i] === '`') {
|
|
$inMultiline = true;
|
|
$i++;
|
|
$currentValue = '';
|
|
} else {
|
|
$valueStart = $i;
|
|
while ($i < $len && $input[$i] !== "\n")
|
|
$i++;
|
|
$currentValue = trim(substr($input, $valueStart, $i - $valueStart));
|
|
$ips[] = $currentParam . $sep . $currentValue;
|
|
$i++;
|
|
}
|
|
} else {
|
|
$valueStart = $i;
|
|
while ($i < $len && $input[$i] !== '`')
|
|
$i++;
|
|
$currentValue .= trim(substr($input, $valueStart, $i - $valueStart));
|
|
if ($i < $len && $input[$i] === '`') {
|
|
$ips[] = $currentParam . $sep . $currentValue;
|
|
$inMultiline = false;
|
|
$i++;
|
|
if ($i < $len && $input[$i] === "\n") {
|
|
$i++;
|
|
}
|
|
} else {
|
|
$ips[] = $currentParam . $sep . $currentValue;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (count($ips) == 0)
|
|
return '参数都不符合条件';
|
|
return $ips;
|
|
}
|
|
}
|