Files
ai-shiliu/legacy/ai_helper_backup.txt

309 lines
20 KiB
Plaintext
Raw Permalink Normal View History

<EFBFBD><EFBFBD><?php
require_once __DIR__ . '/config.php';
require_once __DIR__ . '/db.php';
/**
* `m<>^I<>R<EFBFBD>k0<>m_<6D>aq<61><71><EFBFBD>p<EFBFBD>iZ<69>=<3D>AnV<6E>R_<52>S(<28><>R<EFBFBD>S<EFBFBD><53><EFBFBD><EFBFBD>ve<76><65>p2<70>
*/
function find_rule_reply(string $content): ?array
{
$pdo = get_pdo();
// O<>Xaq9p}\<5C>SV<53>R_<52>S<1B>}\@U̓<55>0<EFBFBD>[Z<><5A><EFBFBD>.\<5C><><EFBFBD>]}<7D>~<7E> W<>?MVP <17>Xpn
$sql = "SELECT * FROM auto_reply_rules WHERE is_active = 1 ORDER BY id ASC";
$stmt = $pdo->query($sql);
$rules = $stmt->fetchAll();
$contentLower = mb_strtolower($content, 'UTF-8');
error_log("=== Yt<59>R<EFBFBD>WV<57>R_<52>S<EFBFBD>[<5B> <20>o?===");
error_log(""<22>&1<>WZXOX<4F><58>q<EFBFBD>g: '{$content}'");
error_log("^g<00><>vP<76>k<>`: '{$contentLower}'");
error_log("Yt<59>R<EFBFBD>W<EFBFBD><57><EFBFBD>~<7E>f: " . count($rules));
foreach ($rules as $rule) {
$keyword = trim((string)$rule['keyword']);
if ($keyword === '') {
error_log("Yt<59>R<EFBFBD>WID {$rule['id']}: O<><4F>bme<6D>t<EFBFBD>]<1F><>~4s}<7D>t<EFBFBD>[C~");
continue;
}
$kwLower = mb_strtolower($keyword, 'UTF-8');
error_log("Yt<59>R<EFBFBD>WID {$rule['id']}: O<><4F>bme<6D>t?'{$keyword}', Op<4F>_SU='{$kwLower}', <00>~<7E><>7p={$rule['match_type']}");
if ($rule['match_type'] === 'equal') {
if ($contentLower === $kwLower) {
error_log("A<>?9p}\<5C>SV<53>R_<52>S<EFBFBD><53>,a<>Y<1B>}OQ~e<><65>pI<70>R<EFBFBD>gjD {$rule['id']}");
return $rule;
} else {
error_log("A<>?9p}\<5C>SV<53>R_<52>S<EFBFBD>o<EFBFBD><6F><EFBFBD><EFBFBD>: '{$contentLower}' !== '{$kwLower}'");
}
} else { // contain
if (mb_strpos($contentLower, $kwLower, 0, 'UTF-8') !== false) {
error_log("A<>?V<>mT<6D>`V<>R_<52>S<EFBFBD><53>,a<>Y<1B>}OQ~e<><65>pI<70>R<EFBFBD>gjD {$rule['id']}");
return $rule;
} else {
error_log("A<>?V<>mT<6D>`V<>R_<52>S<EFBFBD>o<EFBFBD><6F><EFBFBD><EFBFBD>");
}
}
}
error_log("ȓE<C893><45>XR<58><52><EFBFBD>bccm<63>f.\<5C><><EFBFBD>]I<>R<EFBFBD>?);
error_log("=== Yt<59>R<EFBFBD>WV<57>R_<52>S<>dko ===");
return null;
}
/**
* <00>~<7E> W<><57>f<EFBFBD><66><>q<EFBFBD>S<><7F><EFBFBD><EFBFBD>Y<EFBFBD>?/ P<>k<>S
*/
function get_setting(string $key, $default = null)
{
$pdo = get_pdo();
$stmt = $pdo->prepare("SELECT `value` FROM settings WHERE `key` = :k LIMIT 1");
$stmt->execute([':k' => $key]);
$row = $stmt->fetch();
if (!$row) {
return $default;
}
return $row['value'];
}
function set_setting(string $key, string $value): void
{
$pdo = get_pdo();
$stmt = $pdo->prepare("
INSERT INTO settings(`key`, `value`, updated_at)
VALUES(:k, :v, NOW())
ON DUPLICATE KEY UPDATE `value` = VALUES(`value`), updated_at = NOW()
");
$stmt->execute([':k' => $key, ':v' => $value]);
}
/**
* <00>t<EFBFBD>Qde<64>oDh<>?API<1B>#XV~<7E><>|\<5C>N OpenAI <00>mp<6D><70>}<1B>?
* <00>o<EFBFBD>P<EFBFBD>}"<22>%1WmP<6D>nTh<>6[}Y<><1A>jn<6A>Y<EFBFBD>0)<29>Ǔc2]<5D>t<EFBFBD>Qde<64><65>f<>}<7D><>?
*/
function call_ai(string $prompt, string $userId = ''): string
{
error_log("=== <00>t<EFBFBD>QdeAI<00>[<5B> <20>o?===");
error_log(""<22>&1<>WZXO: '{$prompt}'");
error_log("AI<00><>*a<>}_<>? " . AI_PROVIDER);
if (AI_PROVIDER === 'mock') {
return '<00><>/a<>VT<56>%1m<>o<EFBFBD>]<5D> b<>}R<>-l<>X<EFBFBD>t<EFBFBD>!|<1B>? . mb_substr($prompt, 0, 100, 'UTF-8');
}
// OpenAI O<>Nq<4E><EFBFBD>0[_
if (AI_PROVIDER === 'openai') {
$url = rtrim(OPENAI_API_BASE, '/') . '/chat/completions';
$headers = [
'Content-Type: application/json',
'Authorization: ' . 'Bearer ' . OPENAI_API_KEY,
];
$payload = [
'model' => OPENAI_MODEL,
'messages' => [
[
'role' => 'system',
'content' => 'cm<63>r<EFBFBD>i<EFBFBD>m<EFBFBD> <20>mC<6D>{<7B>m1l<31>k<EFBFBD>[<5B><><EFBFBD>O<EFBFBD>~xOYqig/a<>`T<>B%<25>X<1B><>\de<64>~<7E> 2Z}O<>V<12>AR<41>k<EFBFBD>m_<6D><5F>ge<67><65>p2<70>"<22>&1<>W<EFBFBD><57>?,
],
[
'role' => 'user',
'content' => $prompt,
],
],
'temperature' => 0.7,
'user' => $userId ?: null,
];
return do_llm_request($url, $headers, $payload);
}
// DeepSeek<1B>$WpenAI O<>Nq<4E><71> i<>^xr<1B>?
if (AI_PROVIDER === 'deepseek') {
$url = rtrim(DEEPSEEK_API_BASE, '/') . '/chat/completions';
error_log("<00>t <0B>0wURL: {$url}");
$headers = [
'Content-Type: application/json',
'Authorization: Bearer ' . DEEPSEEK_API_KEY,
];
$payload = [
'model' => DEEPSEEK_MODEL,
'messages' => [
[
'role' => 'system',
'content' => 'cm<63>r<EFBFBD>i<EFBFBD>m<EFBFBD> <20>mF<6D>]u2Z<32>O<EFBFBD>s<EFBFBD><73>"X<>k<EFBFBD>[<5B><><EFBFBD>OT<4F>B%<25>X<EFBFBD><58><EFBFBD>Pm<>o<EFBFBD>]<5D><><EFBFBD>Y<EFBFBD>P0}1.<00>m<EFBFBD> Y<><59>0=ve<76><65>p<EFBFBD>t<1B>|\ {<7B>tpTC~50p?2.<00>m<EFBFBD>]<5D><>_<EFBFBD>g<7F>h<EFBFBD><68><EFBFBD>]2<> 3.)<29>X[4^e<><65>p<EFBFBD>t•<74><C295>}<7D><1B>|\ {UtxOy<4F><79>oDi=v 4.<00>m<EFBFBD>]<5D><>cm<63><6D>deemojit&1Q',
],
[
'role' => 'user',
'content' => $prompt,
],
],
'temperature' => 0.7,
'max_tokens' => 100, // ĕ,a<>We<57><65>p2<70><32><EFBFBD><EFBFBD>W<EFBFBD>[
'user' => $userId ?: null,
];
return do_llm_request($url, $headers, $payload);
}
// Dify<1B>X<><58><EFBFBD>t<EFBFBD>o7p4d<34>ede<1B>?
if (AI_PROVIDER === 'dify') {
$url = rtrim(DIFY_API_BASE, '/') . '/chat-messages';
error_log("<00>t <0B>0wURL: {$url}");
$headers = [
'Content-Type: application/json',
'Authorization: Bearer ' . DIFY_API_KEY,
];
$payload = [
'inputs' => new stdClass(),
'query' => $prompt,
'response_mode' => 'streaming',
'user' => $userId ?: DIFY_USER,
];
return do_dify_request($url, $headers, $payload);
}
// O<>5g<35>|X<><58>PbfY<66><1A>jn<6A>Y<EFBFBD>0<EFBFBD>X^p?
return 'AI_PROVIDER ȓH<C893><48>S<><7F><1C><>~<7E><>}<7D>t <0B><><EFBFBD>̓?config.php<00><>?;
}
/**
* Dify <00>m<EFBFBD>dde<64>t <0B>0wOp}O<><4F>
*/
function do_dify_request(string $url, array $headers, array $payload): string
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload, JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 60); // <00>o<EFBFBD>p<EFBFBD>Y<EFBFBD>tnTX<>h<1B>~\ne<6E><65>{Ntreaming
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128); // Op<4F>_&}P<><50>c/\<1B>~\ne<6E><65>yOfy<66>[<5B>_<EFBFBD><5F>Y<EFBFBD>?
curl_setopt($ch, CURLOPT_NOPROGRESS, false); // O<>}O<><4F>ig<69>m<EFBFBD>[e<><65>p<EFBFBD>v
$response = curl_exec($ch);
if ($response === false) {
$err = curl_error($ch);
curl_close($ch);
error_log("cURL<00><>k<><6B>: {$err}");
return '<00><><EFBFBD><EFBFBD><EFBFBD>t<1B>L[ify ȓ<>]<5D><59>Pi<>m<EFBFBD>]r_"<22><><EFBFBD>}<7D><74>%Z<><5A>^@U<>t<EFBFBD>f<EFBFBD>}<1B>"X<>}<>nJe<4A>t$<24>0}' . $err . '<1B>?;
}
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
error_log("HTTP<18>5<EFBFBD><35> zOr: {$statusCode}");
error_log("]<5D><>]2|P<>mT<6D><54><EFBFBD><EFBFBD><EFBFBD>W<EFBFBD>[: " . strlen($response));
error_log("]<5D><>]2|P<>mT<6D><54>: {$response}");
// <00>o<EFBFBD>R<EFBFBD>`<60>~<7E>T7d4d?
if (empty($response)) {
error_log("Difyig<69>em<>~<7E>T7d4d?);
return '<00><><EFBFBD><EFBFBD><EFBFBD>t<1B>L[ify ȓ<>]<5D>Yig<69>em<>~<7E>T7d4d<34>e}<7D>t <0B><><EFBFBD>̓G<CC93>PI<00><><EFBFBD>]<5D>u<EFBFBD><75>?;
}
// <00>o<EFBFBD>R<EFBFBD>`streaming<00>Y3 !}(<28><>R7d4d<34>e}SSE͓Nq!}<1B>?
if (strpos($response, 'data:') !== false || strpos($response, 'event:') !== false) {
error_log("<00>Y<EFBFBD> 4Z*[<5B>Wstreaming<00>Y3 !}]<5D><>]2|");
$lines = explode("\n", $response);
$fullAnswer = '';
foreach ($lines as $line) {
$line = trim($line);
if (strpos($line, 'data:') === 0) {
$jsonStr = trim(substr($line, 5));
if (empty($jsonStr) || $jsonStr === '[DONE]') {
continue;
}
$data = json_decode($jsonStr, true);
if (json_last_error() === JSON_ERROR_NONE) {
// Dify streaming͓Nq!}<1B>k"event":"message","answer":"P<>mT<6D><54>"}
if (isset($data['answer'])) {
$fullAnswer .= $data['answer'];
}
// <00><>,h<> ?{"event":"agent_message","answer":"P<>mT<6D><54>"}
if (isset($data['event']) && $data['event'] === 'agent_message' && isset($data['answer'])) {
$fullAnswer .= $data['answer'];
}
}
}
}
if (!empty($fullAnswer)) {
error_log("Difye<><65>p2<70>(streaming): {$fullAnswer}");
error_log("=== <00>t<EFBFBD>QdeAI<>dko ===");
return trim($fullAnswer);
}
}
// <00>o<EFBFBD>R<EFBFBD>`blocking<00>Y3 !}(<28><>R7d4d<34>e}JSON͓Nq!}<1B>?
$data = json_decode($response, true);
if ($statusCode >= 400 || !is_array($data)) {
$msg = $data['message'] ?? 'ȓF<C893>aq<61><71>k<><6B>';
error_log("Dify API<00><>k<><6B>: {$msg}");
return '<00><><EFBFBD><EFBFBD><EFBFBD>t<1B>L[ify ȓ<>]<5D>Y<EFBFBD>t <0B>0w<30>o<EFBFBD><6F><EFBFBD><EFBFBD><1B><>\<5C><><EFBFBD>~<7E>]<5D>`P<><50>]/v<1D><>p}<18>5<EFBFBD><35> zOr ' . $statusCode . '<1B>? . $msg . '<1B>?;
}
// Dify ig<69>em͓Nq!}<1B>k"answer": "e<><65>p2<70>P<EFBFBD>mT<6D><54>", "conversation_id": "xxx"}
$content = $data['answer'] ?? '';
if (!$content) {
error_log("Difyig<69>emP<6D>mT<6D><54><EFBFBD>my<6D>%");
error_log("9p~\<5C>f]<5D><>]2|: " . print_r($data, true));
return '<00><><EFBFBD><EFBFBD><EFBFBD>t<1B>L[ify Ɠ<>Pi Z!AnZ<6E>"X<>`(<28><>Rm<>o<EFBFBD>]<5D> ?;
}
error_log("Difye<><65>p2<70>(blocking): {$content}");
error_log("=== <00>t<EFBFBD>QdeAI<>dko ===");
return trim($content);
}
/**
* <00><>1lde<64>oDh<>?HTTP <00>t <0B>0wOp}O<><4F>
*/
function do_llm_request(string $url, array $headers, array $payload): string
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload, JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 60); // <00>o<EFBFBD>p<EFBFBD>Y<EFBFBD>tnTX<>h<1B>~\ne<6E><65>{Ntreaming
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128); // Op<4F>_&}P<><50>c/\<1B>~\ne<6E><65>yOfy<66>[<5B>_<EFBFBD><5F>Y<EFBFBD>?
curl_setopt($ch, CURLOPT_NOPROGRESS, false); // O<>}O<><4F>ig<69>m<EFBFBD>[e<><65>p<EFBFBD>v
$response = curl_exec($ch);
if ($response === false) {
$err = curl_error($ch);
curl_close($ch);
error_log("cURL<00><>k<><6B>: {$err}");
return '<00><><EFBFBD><EFBFBD><EFBFBD>t<1B>I[I ȓ<>]<5D><59>Pi<>m<EFBFBD>]r_"<22><><EFBFBD>}<7D><74>%Z<><5A>^@U<>t<EFBFBD>f<EFBFBD>}<1B>"X<>}<>nJe<4A>t$<24>0}' . $err . '<1B>?;
}
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
error_log("HTTP<18>5<EFBFBD><35> zOr: {$statusCode}");
error_log("]<5D><>]2|P<>mT<6D><54>: {$response}");
$data = json_decode($response, true);
if ($statusCode >= 400 || !is_array($data)) {
$msg = $data['error']['message'] ?? 'ȓF<C893>aq<61><71>k<><6B>';
error_log("API<00><>k<><6B>: {$msg}");
return '<00><><EFBFBD><EFBFBD><EFBFBD>t<1B>I[I ȓ<>]<5D>Y<EFBFBD>t <0B>0w<30>o<EFBFBD><6F><EFBFBD><EFBFBD><1B><>\<5C><><EFBFBD>~<7E>]<5D>`P<><50>]/v<1D><>p}<18>5<EFBFBD><35> zOr ' . $statusCode . '<1B>? . $msg . '<1B>?;
}
$content = $data['choices'][0]['message']['content'] ?? '';
if (!$content) {
error_log("AIig<69>emP<6D>mT<6D><54><EFBFBD>my<6D>%");
return '<00><><EFBFBD><EFBFBD><EFBFBD>t<1B>I[I Ɠ<>Pi Z!AnZ<6E>"X<>`(<28><>Rm<>o<EFBFBD>]<5D> ?;
}
error_log("AIe<><65>p2<70>: {$content}");
error_log("=== <00>t<EFBFBD>QdeAI<>dko ===");
return trim($content);
}