["match" => ["case_id" => $caseId]] ]; $ch = curl_init($es_url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($query), CURLOPT_HTTPHEADER => ['Content-Type: application/json'] ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200) { logMessage("Ошибка ElasticSearch: HTTP $httpCode - " . $response); return null; } logMessage("ElasticSearch (проверка истории): " . $response); $data = json_decode($response, true); if (!isset($data["hits"]["total"]["value"])) { logMessage("Неверная структура ответа от ElasticSearch: " . json_encode($data)); return null; } if ($data["hits"]["total"]["value"] > 0) { $previousCase = $data["hits"]["hits"][0]["_source"]; $previousHashes = array_column($previousCase["файлы"], "checksum"); $currentHashes = array_map(function($file) { if (is_string($file) && file_exists($file)) { return hash_file('sha256', $file); } logMessage("Ошибка: hash_file получил некорректный путь: " . json_encode($file)); return null; }, $fileList); // Используем diff для сравнения хешей if (count(array_diff($previousHashes, $currentHashes)) === 0) { logMessage("✅ Файлы не изменились, используем старый результат."); return $previousCase; } } return null; } */ function checkPreviousAnalysis($caseId, $fileList) { $es_url = ELASTIC_URL . "/cases/_search"; $query = [ "query" => ["match" => ["case_id" => $caseId]] ]; $ch = curl_init($es_url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($query), CURLOPT_HTTPHEADER => ['Content-Type: application/json'] ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200) { logMessage("Ошибка ElasticSearch: HTTP $httpCode - " . $response); return null; } logMessage("ElasticSearch (проверка истории): " . $response); $data = json_decode($response, true); // Проверяем, корректен ли ответ if (!isset($data["hits"]["total"]["value"])) { logMessage("Неверная структура ответа от ElasticSearch: " . json_encode($data)); return null; } // Если запись найдена, достаём checksum if ($data["hits"]["total"]["value"] > 0) { $previousCase = $data["hits"]["hits"][0]["_source"]; // Старые хэши $previousHashes = array_column($previousCase["файлы"], "checksum"); sort($previousHashes); // Текущие хэши $currentHashes = []; foreach ($fileList as $file) { if (is_string($file) && file_exists($file)) { $currentHashes[] = hash_file('sha256', $file); } else { logMessage("Ошибка: hash_file получил некорректный путь: " . json_encode($file)); // Можем решить, как обрабатывать ситуацию — например, return null } } sort($currentHashes); // Сравниваем отсортированные массивы if ($previousHashes === $currentHashes) { logMessage("✅ Файлы не изменились, используем старый результат."); return $previousCase; } } return null; } // ✅ Сохранение анализа в ElasticSearch (для индекса cases) function saveAnalysisToElasticSearch($caseId, $analysis, $fileList) { if (!is_array($fileList) || empty($fileList)) { logMessage("❌ Ошибка: передан пустой или некорректный массив файлов в saveAnalysisToElasticSearch."); return false; } // ✅ Проверяем, нет ли уже идентичного анализа в ElasticSearch $existingAnalysis = checkPreviousAnalysis($caseId, $fileList); if ($existingAnalysis) { logMessage("✅ Анализ уже существует в базе. Повторная запись не требуется."); return true; } $es_url = ELASTIC_URL . "/cases/_doc/$caseId"; // Извлекаем детали кейса из содержания анализа с помощью функции extractCaseDetails() $caseDetails = extractCaseDetails($analysis['content'] ?? ''); $payload = [ "case_id" => $caseId, "истец" => $caseDetails['истец'] ?? 'Не определено', "ответчик" => $caseDetails['ответчик'] ?? 'Не определено', "суть_спора" => $caseDetails['суть_спора'] ?? 'Не определено', "анализ_gpt" => isset($analysis['content']) ? $analysis['content'] : 'Анализ не выполнен', "вывод_gpt" => isset($analysis['moderationVerdict']) ? $analysis['moderationVerdict'] : 'Не определен', "дата" => date('c'), "файлы" => array_map(function($file) { if (is_string($file) && file_exists($file)) { return [ "filename" => basename($file), "checksum" => hash_file('sha256', $file) ]; } logMessage("Ошибка: hash_file получил некорректный путь: " . json_encode($file)); return [ "filename" => "Неизвестно", "checksum" => null ]; }, $fileList) ]; $ch = curl_init($es_url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE), CURLOPT_HTTPHEADER => ['Content-Type: application/json'] ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); curl_close($ch); if ($curlError) { logMessage("❌ Ошибка cURL при сохранении анализа в ElasticSearch: " . $curlError); return false; } if ($httpCode !== 200 && $httpCode !== 201) { logMessage("❌ Ошибка ElasticSearch: HTTP $httpCode - " . $response); return false; } logMessage("✅ ElasticSearch (анализ сохранён): " . $response); return true; } // ✅ Функция сохранения судебных решений в отдельный индекс (court_decisions) function saveCourtDecisionToElastic($caseId, $filename, $content) { $es_url = ELASTIC_URL . "/court_decisions/_doc/"; // Формируем уникальный ID на основе md5 от caseId и filename $docId = md5($caseId . $filename); $payload = [ "case_id" => $caseId, "filename" => $filename, "text" => $content, "created_at"=> date('c') ]; $ch = curl_init($es_url . $docId); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE), CURLOPT_HTTPHEADER => ['Content-Type: application/json'] ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); curl_close($ch); if ($curlError) { logMessage("Ошибка cURL при сохранении судебного решения: " . $curlError); return false; } if ($httpCode !== 200 && $httpCode !== 201) { logMessage("❌ Ошибка ElasticSearch при сохранении судебного решения: HTTP $httpCode - " . $response); return false; } logMessage("✅ Судебное решение сохранено в ElasticSearch: " . $response); return true; } // ✅ Проверка истории запросов (чтобы не отправлять дубликаты) function checkQueryHistory($caseId, $queryText) { $es_url = ELASTIC_URL . "/query_history/_search"; $query = [ "query" => ["match" => ["case_id" => $caseId]] ]; $ch = curl_init($es_url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($query), CURLOPT_HTTPHEADER => ['Content-Type: application/json'] ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200) { logMessage("Ошибка ElasticSearch: HTTP $httpCode - " . $response); return false; } logMessage("ElasticSearch (проверка истории запросов): " . $response); $data = json_decode($response, true); if (!isset($data["hits"]["total"]["value"])) { logMessage("Неверная структура ответа от ElasticSearch: " . json_encode($data)); return false; } if ($data["hits"]["total"]["value"] > 0) { foreach ($data["hits"]["hits"] as $entry) { if ($entry["_source"]["query_text"] === $queryText) { logMessage("✅ Запрос уже выполнялся ранее, повторная отправка не требуется."); return true; } } } return false; } // ✅ Сохранение истории запроса function saveQueryToHistory($caseId, $queryText) { $es_url = ELASTIC_URL . "/query_history/_doc/"; $payload = [ "case_id" => $caseId, "query_text" => $queryText, "дата" => date("Y-m-d H:i:s") ]; $ch = curl_init($es_url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => ['Content-Type: application/json'] ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200 && $httpCode !== 201) { logMessage("Ошибка ElasticSearch: HTTP $httpCode - " . $response); return false; } logMessage("ElasticSearch (сохранение истории запроса): " . $response); return true; } // Парсинг данных из текста анализа function extractCaseDetails($analysisText) { $details = [ 'истец' => 'Не определено', 'ответчик' => 'Не определено', 'суть_спора' => 'Не определено' ]; // Используем модификаторы m (многострочный) и u (Unicode) // Парсим истца (например: "• Истец (потребитель): Гражданин Городничев И.А.") if (preg_match('/•\s*Истец\s*\(потребитель\):\s*(.+)/mu', $analysisText, $matches)) { $details['истец'] = trim($matches[1]); } // Парсим ответчика, учитывая варианты "компания" или "организация" if (preg_match('/•\s*Ответчик\s*\((?:компания|организация)\):\s*(.+)/mu', $analysisText, $matches)) { $details['ответчик'] = trim($matches[1]); } // Парсим суть или характер спора (приоритет: если есть "Суть спора", иначе "Характер спора") if (preg_match('/•\s*(?:Суть|Характер)\s+спора:\s*(.+)/mu', $analysisText, $matches)) { $details['суть_спора'] = trim($matches[1]); } return $details; } ?>