$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'); // Приводим к UTF-8 logMessage("DEBUG: Извлеченный текст: " . substr($text, 0, 500)); return trim($text); } /* function extractTextFromPDF($pdfPath) { $text = shell_exec("pdftotext -layout -enc UTF-8 " . escapeshellarg($pdfPath) . " -"); 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'); } $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" => "Нет данных."])); } $files_data = []; // Теперь инициализируем только один раз while ($row = $result->fetch_assoc()) { $title = $row["title"]; $filePath = $row["filepath"]; logMessage("Обрабатываем файл: " . $filePath); $tempFilePath = renameFileForProcessing($filePath); if (!$tempFilePath) continue; $text = extractTextFromPDF($tempFilePath); // Вызов функции $data = ["title" => $title]; if (!empty(trim($text)) && mb_strlen(trim($text), 'UTF-8') >= 20) { logMessage("DEBUG: Текст извлечён из $title: " . substr($text, 0, 500)); $data["text"] = $text; } else { logMessage("PDF '$title' пуст или содержит слишком мало текста, конвертируем в изображения."); $outputDir = "scanpdf/pdf_images_" . uniqid(); $images = convertPdfToImages($tempFilePath, $outputDir); if (!empty($images)) { logMessage("DEBUG: Изображения созданы из $title: " . implode(", ", $images)); // Применяем OCR (LSTM) $recognizedText = ""; foreach ($images as $imagePath) { $ocrText = shell_exec("tesseract " . escapeshellarg($imagePath) . " stdout -l rus+eng --oem 1"); if (!empty(trim($ocrText))) { $recognizedText .= trim($ocrText) . "\n"; } } if (!empty(trim($recognizedText)) && mb_strlen(trim($recognizedText), 'UTF-8') >= 20) { 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; // Теперь мы НЕ обнуляем массив, а добавляем файлы! } logMessage("DEBUG: JSON, отправляемый в OpenAI: " . json_encode($files_data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); /*$task = "🔹 Отвечай по шаблону. **Задача**: Проанализируй загруженные документы, выполнив следующие действия: 1️⃣ **Список файлов и проверка соответствия названий** - Перечисли все загруженные файлы. 🔹 Внимательно анализируй изображения. - Если изображение содержит текст, сначала **извлеки текст** и **проанализируй его содержание**. - Укажи, если текст плохо читается или частично распознан. - Если изображение не содержит текста, но является **важной частью документа**, опиши, что на нем изображено. - Определи их содержимое (например, \"договор\", \"претензия\", \"ответ на претензию\", \"подтверждение оплаты\" и т. д.). - Проверь, соответствует ли название файла его реальному содержимому. - Если обнаружено несоответствие, укажи, в чем именно проблема. 2️⃣ **Краткий анализ спора** - Определи **истца** (потребителя) и **ответчика** (компанию, на которую подана жалоба). - Опиши **суть спора** (что произошло и какая проблема заявлена). - Укажи **основные аргументы сторон** (что заявляет потребитель и какие возражения возможны у компании). 3️⃣ **Проверка на цензуру** - Проверь документы на наличие **ненормативной лексики** и **нецензурных изображений**. - **Анализируй изображения на наличие нецензурного контента, запрещенной символики, сцен насилия и других нарушений. Если найдены такие элементы, укажи это в отчете.** - Если обнаружены изображения, укажи что именно и требуется ли их ручная проверка. 4️⃣ **Выдача итогового вердикта** - **Прошло модерацию** – если всё соответствует названию и нет проблем. - **Не прошло модерацию (требуется участие человека)** – если есть несоответствия или потенциальные проблемы (укажи, что именно требует ручной проверки). 5️⃣ **Характер спора** - Дай краткую характеристику дела (например, \"некачественный товар\", \"товар не привезли\", \"не возвращают деньги\", \"некачественная услуга\" и т. д.). 📌 **Важно**: Отчет должен быть структурированным, четким и лаконичным. Укажи, какими нормами права РФ будет регулироваться рассмотение данного спора. Если требуется ручная проверка, укажи приоритетные файлы для проверки."; */ $task = "🔹 Отвечай по шаблону. **Задача**: Проанализируй загруженные документы, выполнив следующие действия: 1️⃣ **Список файлов и проверка соответствия названий** - Перечисли все загруженные файлы. - Внимательно анализируй изображения. - Если изображение содержит текст, сначала **извлеки текст** и **проанализируй его содержание**. - Укажи, если текст плохо читается или частично распознан. - Если изображение не содержит текста, опиши, что на нем изображено. **Особое внимание NSFW контенту в тексте и изображениях** - Если файл или изображение кажутся тебе подозрительными изучи его более внимательно и отдельно укажи в отчете что файл может содержать ТРЕШ-контент. Укажи, если файл требует дополнительной проверки или имеет проблемы с 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); //echo json_encode(["status" => "complete", "content" => json_decode($response, true)], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); logMessage("Ответ от GPT-4-Turbo: " . $response); // Преобразуем JSON-ответ в массив $gptAnalysis = json_decode($response, true); logMessage("Полный JSON-ответ от GPT: " . json_encode($gptAnalysis, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); // Проверяем, является ли $gptAnalysis массивом if (!is_array($gptAnalysis)) { logMessage("Ошибка: JSON-декодирование не удалось."); die(json_encode(["status" => "error", "message" => "Ошибка: JSON-декодирование не удалось."])); } // Проверяем, есть ли ключ 'choices' 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); // Возвращаем JSON с контентом echo json_encode(["status" => "complete", "content" => $content], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); ?>