39961-vm/api/chat.php
Flatlogic Bot d2f3725560 TES1
2026-05-12 09:45:21 +00:00

160 lines
5.3 KiB
PHP

<?php
declare(strict_types=1);
header('Content-Type: application/json; charset=utf-8');
require_once __DIR__ . '/../db/schema.php';
require_once __DIR__ . '/../ai/LocalAIApi.php';
function findFaqReply(array $faqs, string $message): string
{
$normalizedMessage = function_exists('mb_strtolower')
? mb_strtolower($message, 'UTF-8')
: strtolower($message);
foreach ($faqs as $faq) {
$keywords = isset($faq['keywords']) && is_string($faq['keywords'])
? preg_split('/\s*,\s*/', $faq['keywords'])
: [];
foreach ($keywords as $keyword) {
if (!is_string($keyword) || $keyword === '') {
continue;
}
$needle = function_exists('mb_strtolower')
? mb_strtolower($keyword, 'UTF-8')
: strtolower($keyword);
$found = function_exists('mb_strpos')
? mb_strpos($normalizedMessage, $needle, 0, 'UTF-8') !== false
: strpos($normalizedMessage, $needle) !== false;
if ($needle !== '' && $found) {
return (string) ($faq['answer'] ?? '');
}
}
}
return '';
}
$rawInput = file_get_contents('php://input');
$input = json_decode($rawInput ?: '', true);
$message = '';
if (is_array($input) && isset($input['message']) && is_string($input['message'])) {
$message = trim($input['message']);
}
if ($message === '') {
echo json_encode(['reply' => 'Silakan tulis pertanyaan Anda terlebih dahulu.'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
try {
ensureSupportSchema();
$faqs = [];
try {
$stmt = db()->query('SELECT keywords, answer FROM faqs ORDER BY id ASC');
$faqs = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
} catch (Throwable $faqError) {
error_log('FAQ Load Error: ' . $faqError->getMessage());
}
$faqReply = findFaqReply($faqs, $message);
if ($faqReply !== '') {
try {
$stmt = db()->prepare('INSERT INTO messages (user_message, ai_response) VALUES (:user_message, :ai_response)');
$stmt->bindValue(':user_message', $message);
$stmt->bindValue(':ai_response', $faqReply);
$stmt->execute();
} catch (Throwable $saveError) {
error_log('DB Save Error: ' . $saveError->getMessage());
}
echo json_encode(['reply' => $faqReply], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
$knowledgeBase = "Berikut knowledge base website ini:
";
if ($faqs === []) {
$knowledgeBase .= "- Belum ada FAQ khusus yang dikonfigurasi.
";
} else {
foreach ($faqs as $faq) {
$knowledgeBase .= 'Q: ' . ($faq['keywords'] ?? '') . "
";
$knowledgeBase .= 'A: ' . ($faq['answer'] ?? '') . "
---
";
}
}
$systemPrompt = "Anda adalah asisten AI yang ramah untuk website ini. "
. "Gunakan knowledge base bila jawabannya tersedia. "
. "Jika pertanyaan tidak ada di knowledge base, bantu secara umum dan jelaskan dengan singkat. "
. "Jawab singkat, jelas, dan profesional dalam Bahasa Indonesia.
"
. $knowledgeBase;
$response = LocalAIApi::createResponse(
[
'input' => [
['role' => 'system', 'content' => $systemPrompt],
['role' => 'user', 'content' => $message],
],
],
[
'poll_interval' => 2,
'poll_timeout' => 45,
]
);
if (!empty($response['success'])) {
$aiReply = LocalAIApi::extractText($response);
if ($aiReply === '') {
$decoded = LocalAIApi::decodeJsonFromResponse($response);
if ($decoded) {
$aiReply = json_encode($decoded, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
}
if ($aiReply === '') {
$aiReply = 'Pesan Anda sudah diterima, tetapi balasan otomatis belum tersedia saat ini.';
}
try {
$stmt = db()->prepare('INSERT INTO messages (user_message, ai_response) VALUES (:user_message, :ai_response)');
$stmt->bindValue(':user_message', $message);
$stmt->bindValue(':ai_response', $aiReply);
$stmt->execute();
} catch (Throwable $saveError) {
error_log('DB Save Error: ' . $saveError->getMessage());
}
echo json_encode(['reply' => $aiReply], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
error_log('AI Error: ' . ($response['error'] ?? 'Unknown'));
$fallbackReply = 'Saya belum bisa membalas otomatis saat ini. Silakan coba lagi sebentar lagi.';
try {
$stmt = db()->prepare('INSERT INTO messages (user_message, ai_response) VALUES (:user_message, :ai_response)');
$stmt->bindValue(':user_message', $message);
$stmt->bindValue(':ai_response', $fallbackReply);
$stmt->execute();
} catch (Throwable $saveError) {
error_log('DB Save Error: ' . $saveError->getMessage());
}
echo json_encode(['reply' => $fallbackReply], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
} catch (Throwable $error) {
error_log('Chat Error: ' . $error->getMessage());
echo json_encode(['reply' => 'Terjadi kesalahan internal. Silakan coba lagi.'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}