- Added comprehensive AI Assistant system (aiassist/ directory): * Vector search and embedding capabilities * Typebot proxy integration * Elastic search functionality * Message classification and chat history * MCP proxy for external integrations - Implemented Court Status API (GetCourtStatus.php): * Real-time court document status checking * Integration with external court systems * Comprehensive error handling and logging - Enhanced S3 integration: * Improved file backup system with metadata * Batch processing capabilities * Enhanced error logging and recovery * Copy operations with URL fixing - Added Telegram contact creation API - Improved error logging across all modules - Enhanced callback system for AI responses - Extensive backup file storage with timestamps - Updated documentation and README files - File storage improvements: * Thousands of backup files with proper metadata * Fix operations for broken file references * Project-specific backup and recovery systems * Comprehensive file integrity checking Total: 26,461+ files added/modified including AWS SDK, vendor dependencies, and extensive backup system.
260 lines
9.0 KiB
PHP
260 lines
9.0 KiB
PHP
<?php
|
||
// aiassist/elastic.php
|
||
require_once 'logger.php';
|
||
|
||
if (!defined('ELASTIC_URL')) {
|
||
define('ELASTIC_URL', 'http://localhost:9200');
|
||
}
|
||
|
||
global $es;
|
||
$es = curl_init(ELASTIC_URL);
|
||
|
||
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;
|
||
}
|
||
|
||
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));
|
||
}
|
||
}
|
||
sort($currentHashes);
|
||
|
||
if ($previousHashes === $currentHashes) {
|
||
logMessage("✅ Файлы не изменились, используем старый результат.");
|
||
return $previousCase;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function saveAnalysisToElasticSearch($caseId, $analysis, $fileList) {
|
||
if (!is_array($fileList) || empty($fileList)) {
|
||
logMessage("❌ Ошибка: передан пустой или некорректный массив файлов в saveAnalysisToElasticSearch.");
|
||
return false;
|
||
}
|
||
|
||
$existingAnalysis = checkPreviousAnalysis($caseId, $fileList);
|
||
if ($existingAnalysis) {
|
||
logMessage("✅ Анализ уже существует в базе. Повторная запись не требуется.");
|
||
return true;
|
||
}
|
||
|
||
$es_url = ELASTIC_URL . "/cases/_doc/$caseId";
|
||
$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;
|
||
}
|
||
|
||
function saveCourtDecisionToElastic($caseId, $filename, $content) {
|
||
$es_url = ELASTIC_URL . "/court_decisions/_doc/";
|
||
$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 = [
|
||
'истец' => 'Не определено',
|
||
'ответчик' => 'Не определено',
|
||
'суть_спора' => 'Не определено'
|
||
];
|
||
|
||
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;
|
||
}
|
||
?>
|