Files
crm.clientright.ru/testgpt4.php

371 lines
18 KiB
PHP
Raw Permalink Normal View History

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
ini_set('log_errors', 1);
ini_set('error_log', 'scanpdf/php_errors.log');
define('LOG_FILE', 'logs/CheckPDF17.log');
define('OPENAI_API_KEY', 'sk-GS24OxHQYfq8ErW5CRLoN5F1CfJPxNsY');
define('OPENAI_API_URL', 'https://api.proxyapi.ru/openai/v1/chat/completions');
function logMessage($message) {
$message = mb_convert_encoding($message, 'UTF-8', 'auto');
file_put_contents(LOG_FILE, date('Y-m-d H:i:s') . " - " . $message . "\n", FILE_APPEND | LOCK_EX);
}
function transliterate($text) {
$cyr = ['а','б','в','г','д','е','ё','ж','з','и','й','к','л','м','н','о','п','р','с','т','у','ф','х','ц','ч','ш','щ','ъ','ы','ь','э','ю','я'];
$lat = ['a','b','v','g','d','e','yo','zh','z','i','y','k','l','m','n','o','p','r','s','t','u','f','h','ts','ch','sh','shch','','y','','e','yu','ya'];
return str_replace($cyr, $lat, mb_strtolower($text));
}
function classifyImage($imagePath) {
$absolutePath = realpath($imagePath);
if (!$absolutePath) {
logMessage("ERROR: Не удалось получить абсолютный путь для " . $imagePath);
return [];
}
logMessage("DEBUG: Абсолютный путь для классификации: " . $absolutePath);
$escapedPath = escapeshellarg($absolutePath);
logMessage("DEBUG: Экранированный путь для классификации: " . $escapedPath);
// Изменяем команду, чтобы Python выводил корректный JSON
$command = "python3 -c \"import json; from nudenet import NudeClassifier; classifier = NudeClassifier(); print(json.dumps(classifier.classify($escapedPath)))\"";
logMessage("DEBUG: Выполнение команды: " . $command);
$output = shell_exec($command);
logMessage("DEBUG: Вывод команды: " . $output);
if ($output === null) {
logMessage("ERROR: shell_exec вернул null при выполнении NudeClassifier");
return [];
}
return json_decode(trim($output), true);
}
function renameFileForProcessing($filePath, $targetFolder = "scanpdf") {
$pathInfo = pathinfo($filePath);
$newName = transliterate($pathInfo['filename']) . "_" . uniqid() . "." . $pathInfo['extension'];
$newPath = rtrim($targetFolder, "/") . "/" . $newName;
if (copy($filePath, $newPath)) {
logMessage("Файл переименован: $filePath -> $newPath");
return $newPath;
} else {
logMessage("Ошибка при копировании файла: $filePath");
return null;
}
}
function extractTextFromPDF($pdfPath) {
$text = shell_exec("pdftotext -layout -enc UTF-8 " . escapeshellarg($pdfPath) . " -");
$text = mb_convert_encoding($text, 'UTF-8', 'auto');
logMessage("DEBUG: Извлеченный текст: " . substr($text, 0, 500));
return trim($text);
}
function convertPdfToImages($pdfPath, $outputDir) {
if (!file_exists($outputDir)) {
mkdir($outputDir, 0777, true);
logMessage("Создана директория для изображений: $outputDir");
}
$imagePattern = $outputDir . '/page-%03d.jpg';
$command = "convert -density 300 " . escapeshellarg($pdfPath) . " -quality 90 " . escapeshellarg($imagePattern);
logMessage("Выполняем команду: " . $command);
exec($command . " 2>&1", $output, $returnVar);
logMessage("DEBUG: Вывод convert: " . implode("\n", $output));
if ($returnVar !== 0) {
logMessage("Ошибка при конвертации PDF в изображения.");
return [];
}
return glob($outputDir . '/*.jpg');
}
function deleteFolderAndContents($folderPath) {
if (is_dir($folderPath)) {
$files = array_diff(scandir($folderPath), array('.', '..'));
foreach ($files as $file) {
$filePath = $folderPath . DIRECTORY_SEPARATOR . $file;
if (is_dir($filePath)) {
deleteFolderAndContents($filePath);
} else {
unlink($filePath);
}
}
rmdir($folderPath);
logMessage("Удалена подпапка и её содержимое: $folderPath");
}
}
// Подключение к БД
$dbconfig = [
'db_server' => 'localhost',
'db_port' => '3306',
'db_username' => 'ci20465_72new',
'db_password' => 'EcY979Rn',
'db_name' => 'ci20465_72new'
];
$conn = new mysqli(
$dbconfig['db_server'],
$dbconfig['db_username'],
$dbconfig['db_password'],
$dbconfig['db_name'],
$dbconfig['db_port']
);
if ($conn->connect_error) {
logMessage("Ошибка подключения к БД: " . $conn->connect_error);
die(json_encode(["status" => "error", "message" => "Ошибка подключения к БД."]));
}
$conn->set_charset("utf8mb4");
$id = $_POST['id'] ?? null;
if (!$id || !is_numeric($id)) {
logMessage("Ошибка: Некорректный ID.");
die(json_encode(["status" => "error", "message" => "Некорректный ID."]));
}
$sql = "
SELECT n.title,
CASE WHEN a.storedname IS NOT NULL
THEN CONCAT(a.path, a.attachmentsid, '_', a.storedname)
ELSE CONCAT(a.path, a.attachmentsid, '_', a.name)
END AS filepath
FROM vtiger_senotesrel r
LEFT JOIN vtiger_notes n ON n.notesid = r.notesid
LEFT JOIN vtiger_crmentity e ON e.crmid = r.notesid
LEFT JOIN vtiger_seattachmentsrel r2 ON r2.crmid = r.notesid
LEFT JOIN vtiger_attachments a ON a.attachmentsid = r2.attachmentsid
WHERE r.crmid = ? AND e.deleted = 0
AND (a.type = 'application/pdf' OR a.type = 'application/octet-stream')
";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows == 0) {
logMessage("Ошибка: Данные не найдены в БД.");
die(json_encode(["status" => "error", "message" => "Нет данных."]));
}
// Создаем уникальную рабочую папку для текущего запуска
$uniqueFolder = "scanpdf/" . uniqid('run_', true);
if (!file_exists($uniqueFolder)) {
mkdir($uniqueFolder, 0777, true);
logMessage("Создана подпапка для работы: $uniqueFolder");
}
$files_data = [];
while ($row = $result->fetch_assoc()) {
$title = $row["title"];
$filePath = $row["filepath"];
logMessage("Обрабатываем файл: " . $filePath);
$tempFilePath = renameFileForProcessing($filePath, $uniqueFolder);
if (!$tempFilePath) continue;
$text = extractTextFromPDF($tempFilePath);
$data = ["title" => $title];
if (!empty(trim($text)) && mb_strlen(trim($text), 'UTF-8') >= 100) {
logMessage("DEBUG: Текст извлечён из $title: " . substr($text, 0, 500));
$data["text"] = $text;
} else {
logMessage("PDF '$title' пуст или содержит слишком мало текста, конвертируем в изображения.");
$outputDir = $uniqueFolder . "/pdf_images_" . uniqid();
$images = convertPdfToImages($tempFilePath, $outputDir);
if (!empty($images)) {
logMessage("DEBUG: Изображения созданы из $title: " . implode(", ", $images));
$recognizedText = "";
$data["nsfw_alert"] = false; // Инициализируем флаг NSFW
// новый код
foreach ($images as $imagePath) {
logMessage("DEBUG: Отправляем изображение '$imagePath' на проверку NSFW.");
$absImagePath = realpath($imagePath);
logMessage("DEBUG: Абсолютный путь для проверки NSFW: " . $absImagePath);
$classification = classifyImage($imagePath);
if ($classification === null) {
logMessage("DEBUG: Классификатор вернул null для изображения '$absImagePath'. Устанавливаем nsfw_alert в true.");
$data["nsfw_alert"] = true;
} elseif (isset($classification[$absImagePath])) {
$unsafeProbability = $classification[$absImagePath]['unsafe'];
logMessage("DEBUG: Для изображения '$absImagePath' получено unsafeProbability = " . $unsafeProbability);
if ($unsafeProbability > 0.8) {
logMessage("⚠️ Обнаружено NSFW-изображение: $absImagePath (unsafe = " . $unsafeProbability . ")");
$data["nsfw_alert"] = true;
} else {
logMessage("DEBUG: unsafeProbability для '$absImagePath' ниже порогового значения (0.8). Значение = " . $unsafeProbability);
}
} else {
logMessage("DEBUG: Нет данных проверки NSFW для изображения '$absImagePath'.");
}
$ocrText = shell_exec("tesseract " . escapeshellarg($imagePath) . " stdout -l rus+eng --oem 1");
if (!empty(trim($ocrText))) {
$recognizedText .= trim($ocrText) . "\n";
}
}
// новый код конец
/*
foreach ($images as $imagePath) {
logMessage("DEBUG: Отправляем изображение '$imagePath' на проверку NSFW.");
$classification = classifyImage($imagePath);
if ($classification === null) {
logMessage("DEBUG: Классификатор вернул null для изображения '$imagePath'. Устанавливаем nsfw_alert в true.");
$data["nsfw_alert"] = true;
} elseif (isset($classification[$imagePath])) {
$unsafeProbability = $classification[$imagePath]['unsafe'];
logMessage("DEBUG: Для изображения '$imagePath' получено unsafeProbability = " . $unsafeProbability);
if ($unsafeProbability > 0.8) {
logMessage("⚠️ Обнаружено NSFW-изображение: $imagePath (unsafe = " . $unsafeProbability . ")");
$data["nsfw_alert"] = true;
} else {
logMessage("DEBUG: unsafeProbability для '$imagePath' ниже порогового значения (0.8). Значение = " . $unsafeProbability);
}
} else {
logMessage("DEBUG: Нет данных проверки NSFW для изображения '$imagePath'.");
}
$ocrText = shell_exec("tesseract " . escapeshellarg($imagePath) . " stdout -l rus+eng --oem 1");
if (!empty(trim($ocrText))) {
$recognizedText .= trim($ocrText) . "\n";
}
}
*/
// Если обнаружен NSFW-контент, отдаем изображения вместо OCR-текста
if (isset($data["nsfw_alert"]) && $data["nsfw_alert"] === true) {
logMessage("DEBUG: Обнаружен NSFW-контент, поэтому вместо OCR-текста передаем изображения.");
unset($data["text"]);
$data["images"] = $images;
} else {
if (!empty(trim($recognizedText)) && mb_strlen(trim($recognizedText), 'UTF-8') >= 100) {
logMessage("DEBUG: OCR-текст (LSTM) извлечён из изображений $title: " . substr($recognizedText, 0, 500));
$data["text"] = $recognizedText;
} else {
logMessage("PDF '$title' остаётся без читаемого текста, отправляем изображения в GPT.");
$data["images"] = $images;
}
}
} else {
logMessage("Ошибка: PDF пуст, OCR не дал результатов, изображения не созданы.");
}
}
$files_data[] = $data;
if (isset($data["nsfw_alert"]) && $data["nsfw_alert"] === true) {
logMessage("DEBUG: Обнаружен NSFW-контент в документе '$title'.");
}
}
logMessage("DEBUG: JSON, отправляемый в OpenAI: " . json_encode($files_data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
$task = "🔹 Отвечай по шаблону. **Задача**:
Проанализируй загруженные документы, выполнив следующие действия:
1️⃣ **Список файлов и проверка соответствия названий**
- Перечисли все загруженные файлы.
- Внимательно анализируй изображения.
- Если изображение содержит текст, сначала **извлеки текст** и **проанализируй его содержание**.
- Укажи, если текст плохо читается или частично распознан.
- Если изображение не содержит текста, опиши, что на нем изображено.
**Особое внимание NSFW контенту в тексте и изображениях**
- Обрати внимание на пометку `nsfw_alert`. Если она установлена в `true`, это значит, что файл содержит потенциально неприемлемый контент. Изучи его более внимательно. Опиши, что изображено. Отдельно укажи в отчете что файл может содержать ТРЕШ-контент. Укажи, если файл требует дополнительной проверки или имеет проблемы с NSFW.
2️⃣ **Краткий анализ спора**
- Определи **истца** (потребителя) и **ответчика** (компанию, на которую подана жалоба).
- Опиши **суть спора** (что произошло и какая проблема заявлена).
- Укажи **основные аргументы сторон** (что заявляет потребитель и какие возражения возможны у компании).
3️⃣ **Проверка на цензуру**
- Проверь документы на наличие **ненормативной лексики** и **нецензурных изображений**.
- **Анализируй изображения на наличие нецензурного контента, запрещенной символики, сцен насилия и других нарушений. Если найдены такие элементы, укажи это в отчете.**
- Если обнаружены изображения, укажи что именно и требуется ли их ручная проверка.
4️⃣ **Выдача итогового вердикта**
- **Прошло модерацию** если всё соответствует названию и нет проблем.
- **Не прошло модерацию (требуется участие человека)** если есть несоответствия или потенциальные проблемы (укажи, что именно требует ручной проверки).
5️⃣ **Характер спора**
- Дай краткую характеристику дела (например, \"некачественный товар\", \"товар не привезли\", \"не возвращают деньги\", \"некачественная услуга\" и т. д.).
📌 **Важно**:
Отчет должен быть структурированным, четким и лаконичным. Укажи, какими нормами права РФ будет регулироваться рассмотение данного спора. Если требуется ручная проверка, укажи приоритетные файлы для проверки.";
$body = json_encode([
// "model" => "gpt-4-turbo",
"model" => "o1",
"messages" => [
["role" => "system", "content" => "Ты юридический аналитик. Проанализируй материалы согласно инструкции."],
["role" => "user", "content" => $task],
["role" => "user", "content" => json_encode($files_data, JSON_UNESCAPED_UNICODE)]
],
// "max_tokens" => 4000
"max_completion_tokens" => 4000
]);
logMessage("DEBUG: JSON, отправляемый в OpenAI: " . $body);
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => OPENAI_API_URL,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . OPENAI_API_KEY
]
]);
$response = curl_exec($curl);
curl_close($curl);
logMessage("Ответ от GPT-4-Turbo: " . $response);
$gptAnalysis = json_decode($response, true);
logMessage("Полный JSON-ответ от GPT: " . json_encode($gptAnalysis, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
if (!is_array($gptAnalysis)) {
logMessage("Ошибка: JSON-декодирование не удалось.");
die(json_encode(["status" => "error", "message" => "Ошибка: JSON-декодирование не удалось."]));
}
if (!isset($gptAnalysis['choices']) || empty($gptAnalysis['choices'])) {
logMessage("Ошибка: в JSON-ответе отсутствует ключ 'choices'.");
die(json_encode(["status" => "error", "message" => "Ошибка: в JSON-ответе отсутствует ключ 'choices'."]));
}
$content = $gptAnalysis['choices'][0]['message']['content'] ?? null;
if (!$content) {
logMessage("Ошибка: контент не найден в ответе от GPT.");
die(json_encode(["status" => "error", "message" => "Ошибка: контент не найден в ответе от GPT."]));
}
logMessage("DEBUG: Извлеченный контент: " . $content);
echo json_encode(["status" => "complete", "content" => $content], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
deleteFolderAndContents($uniqueFolder);
?>