"error", "message" => "Некорректный ID."], JSON_UNESCAPED_UNICODE)); } // 2. Получение документов из CRM $pdo = getDbConnection(); $documents = fetchDocumentData($pdo, $id); if (empty($documents)) { logMessage("Документы не найдены для ID: $id"); die("Документы не найдены для ID: $id"); } logMessage("✅ Документы получены: " . json_encode($documents, JSON_UNESCAPED_UNICODE)); // Формирование массива путей документов для проверки $filePathList = array_map(function($doc) { return $doc['filepath']; }, $documents); /* // 3. Проверка на наличие ранее сохранённого анализа в ElasticSearch $previousAnalysis = checkPreviousAnalysis($id, $filePathList); logMessage("DEBUG: Значение предыдущего анализа: " . print_r($previousAnalysis, true)); if ($previousAnalysis) { logMessage("Найден сохранённый анализ, отправляем его в CRM."); sendAnalysisToCRM($id, $previousAnalysis); exit; } else { logMessage("Сохранённый анализ не найден, продолжаем обработку."); } */ // 3.5 Создание Vector Store и загрузка файлов $uploadResult = createVectorStoreAndUploadFiles($filePathList); if (!$uploadResult) { logMessage("Ошибка создания Vector Store или загрузки файлов"); die("Ошибка создания Vector Store или загрузки файлов"); } $vectorStoreId = $uploadResult['vectorStoreId']; $uploadedFileIds = $uploadResult['fileIds']; // 4. Формирование предварительного запроса в GPT // Объединяем текст из документов. Если не удалось извлечь текст (например, для изображений), пробуем OCR. $combinedContent = analyzeDocuments($documents, $uploadedFileIds); // пробуем новый подход logMessage("📄 Собранный контент для предварительного запроса:\n" . $combinedContent); if (empty($combinedContent)) { logMessage("❌ Ошибка: не удалось извлечь текст из документов."); die("Ошибка: не удалось извлечь текст из документов."); } // Создаем тред для общения с GPT $threadId = createNewThread(); if (!$threadId) { logMessage("❌ Ошибка создания треда GPT"); die("Ошибка создания треда"); } //9.1. тестируем ответ с базой знаний /* $knowledgeThreadId = "thread_zYRFzxYn0JTo59VUwz84D9p4"; // `thread_id` базы знаний $documentThreadId = $threadId; // `thread_id` с новыми документами $analysisResult2 = analyzeDocumentWithKnowledgeBase($knowledgeThreadId, $documentThreadId); logMessage( "📌 Анализ нового документа с учетом базы знаний:\n" . $analysisResult2); //---------------------------------------- */ /* // 5️⃣ Предварительный анализ через GPT-4 logMessage("📤 Отправляем предварительный запрос в GPT-4 для извлечения ключевых параметров..."); $prelimAnalysis = extractCaseDetailsWithGPT($threadId, ASSISTANT_ID, $vectorStoreId, $combinedContent); if (!$prelimAnalysis) { logMessage("❌ Ошибка анализа обращения через GPT-4 (предварительный ответ)."); die("Ошибка анализа обращения через GPT-4 (предварительный ответ)."); } logMessage("[INFO] ✅ Полученный JSON от GPT-4: " . json_encode($prelimAnalysis, JSON_UNESCAPED_UNICODE)); // Используем результат напрямую как JSON $jsonData = $prelimAnalysis; if (!$jsonData) { logMessage("[ERROR] ❌ Ошибка: JSON от GPT-4 пуст!"); die("Ошибка: JSON от GPT-4 пуст."); } // Убираем строки "null" → заменяем на null foreach (["articles", "claim_amount", "document_client_name"] as $key) { if (isset($jsonData[$key]) && $jsonData[$key] === "null") { $jsonData[$key] = null; } } // Проверяем `facts_full` перед векторизацией if (!isset($jsonData['facts_full']) || empty($jsonData['facts_full'])) { logMessage("[WARNING] ⚠️ `facts_full` пуст! Устанавливаем значение 'Не указано'."); $jsonData['facts_full'] = "Не указано"; } logMessage("🔹 JSON для Elasticsearch (исправленный): " . json_encode($jsonData, JSON_UNESCAPED_UNICODE)); // Получаем векторное представление `facts_full` $embedding = getTextEmbedding($jsonData['facts_full']); logMessage("📡 Векторизация facts_full:\n" . json_encode($embedding, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); */ // 5️⃣ Предварительный анализ через GPT-4 logMessage("📤 Отправляем предварительный запрос в GPT-4 для извлечения ключевых параметров..."); $prelimAnalysis = extractCaseDetailsWithGPT($threadId, ASSISTANT_ID, $vectorStoreId, $combinedContent); if (!$prelimAnalysis) { // ✅ Проверяем, что анализ не пустой logMessage("❌ Ошибка анализа обращения через GPT-4 (предварительный ответ)."); die("Ошибка анализа обращения через GPT-4 (предварительный ответ)."); } $parsedJson = []; if (!empty($prelimAnalysis['json_data'])) { $parsedJson = $prelimAnalysis['json_data']; } elseif (!empty($prelimAnalysis['text_data'])) { $parsedJson = extractCleanJsonFromGPT($prelimAnalysis['text_data']); } // ✅ Логируем полный JSON-ответ от GPT-4 logMessage("[INFO] ✅ Полученный JSON от GPT-4: " . json_encode($prelimAnalysis, JSON_UNESCAPED_UNICODE)); // ✅ Проверяем, где находится JSON $jsonData = isset($prelimAnalysis["json_data"]) && !empty($prelimAnalysis["json_data"]) ? $prelimAnalysis["json_data"] : json_decode($prelimAnalysis["text_data"][0]["text"]["value"], true); // ✅ Если JSON пуст, выбрасываем ошибку if (!$jsonData) { logMessage("[ERROR] ❌ Ошибка: JSON от GPT-4 пуст!"); die("Ошибка: JSON от GPT-4 пуст."); } // ✅ Убираем строки `"null"` → заменяем на `null` foreach (["articles", "claim_amount", "document_client_name"] as $key) { if (isset($jsonData[$key]) && $jsonData[$key] === "null") { $jsonData[$key] = null; } } // ✅ Проверяем `facts_full` перед векторизацией if (!isset($jsonData['facts_full']) || empty($jsonData['facts_full'])) { logMessage("[WARNING] ⚠️ `facts_full` пуст! Устанавливаем значение 'Не указано'."); $jsonData['facts_full'] = "Не указано"; // 🔹 Заполняем, чтобы избежать ошибки в векторизаторе } // ✅ Логируем, что передаём в векторизатор logMessage("🔹 JSON для Elasticsearch (исправленный): " . json_encode($jsonData, JSON_UNESCAPED_UNICODE)); // ✅ Получаем векторное представление `facts_full` $embedding = getTextEmbedding($jsonData['facts_full']); //logMessage("📡 Векторизация facts_full:\n" . json_encode($embedding, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); // ✅ Проверяем наличие векторов и нормализуем $normalizedEmbedding1024 = null; if (isset($embedding["embedding_1024"])) { $sumSquares = 0; foreach ($embedding["embedding_1024"] as $x) { $sumSquares += $x * $x; } $magnitude = sqrt($sumSquares); if ($magnitude > 0) { $normalizedEmbedding1024 = array_map(function ($x) use ($magnitude) { return $x / $magnitude; }, $embedding["embedding_1024"]); } } $normalizedEmbedding2048 = null; if (isset($embedding["embedding_2048"])) { $sumSquares = 0; foreach ($embedding["embedding_2048"] as $x) { $sumSquares += $x * $x; } $magnitude = sqrt($sumSquares); if ($magnitude > 0) { $normalizedEmbedding2048 = array_map(function ($x) use ($magnitude) { return $x / $magnitude; }, $embedding["embedding_2048"]); } } // ✅ Запускаем поиск, передавая `facts_short` и векторные embeddings $searchResults = searchSimilarCases([ 'category' => $jsonData['category'], 'facts_short' => $jsonData['facts_short'], 'facts_full' => $jsonData['facts_full'], 'embedding_1024' => $normalizedEmbedding1024, 'embedding_2048' => $normalizedEmbedding2048 ]); logMessage("✅ Найденные судебные акты: " . json_encode($searchResults, JSON_UNESCAPED_UNICODE)); // 🔍 Дополнительный уточнённый поиск по эталонному решению if (!empty($searchResults) && isset($searchResults[0]['court_decision'])) { $bestDecision = $searchResults[0]; $refinedText = $bestDecision['court_decision']; logMessage("🔁 Выполняем уточнённый поиск по эталонному решению..."); logMessage("⚙️ Текст эталона (первые 300 симв): " . mb_substr($refinedText, 0, 300)); $embeddingData = prepareEmbeddingForRefinedSearch($refinedText); if (!$embeddingData || !is_array($embeddingData)) { logMessage("❌ Ошибка: prepareEmbeddingForRefinedSearch вернул некорректные данные"); } else { $refinedResults = searchRefinedCasesFromBestExample( $refinedText, $embeddingData['embedding_2048'] ?? null, $embeddingData['embedding_1024'] ?? null ); logMessage("📌 Уточнённые решения: " . json_encode($refinedResults, JSON_UNESCAPED_UNICODE)); if (is_array($refinedResults) && !empty($refinedResults)) { $searchResults = array_merge($searchResults, $refinedResults); } } } //--------------------------------------------------------------------------------------------------------------------------------------- /* logMessage("📤 Отправляем предварительный запрос в GPT-4 для извлечения ключевых параметров..."); $prelimAnalysis = extractCaseDetailsWithGPT($threadId, ASSISTANT_ID, $vectorStoreId, $combinedContent); if (!$prelimAnalysis) { // ✅ Теперь проверяем правильную переменную logMessage("❌ Ошибка анализа обращения через GPT-4 (предварительный ответ)."); die("Ошибка анализа обращения через GPT-4 (предварительный ответ)."); } function normalizeEmbedding(array $embedding) { if (empty($embedding)) { logMessage("Эмбеддинг пустой"); return null; } $sumSquares = 0; foreach ($embedding as $value) { if (!is_numeric($value)) { logMessage("Невалидное значение в эмбеддинге: " . print_r($value, true)); return null; } $sumSquares += $value * $value; } $magnitude = sqrt($sumSquares); if ($magnitude == 0) { logMessage("Невозможно нормализовать эмбеддинг: нулевая величина."); return null; } return array_map(function($x) use ($magnitude) { return $x / $magnitude; }, $embedding); } // ✅ Исправляем имя переменной $queryParams = $prelimAnalysis["json_data"]; // JSON для поиска и анализа logMessage("🔹 JSON для Elasticsearch: " . json_encode($queryParams, JSON_UNESCAPED_UNICODE)); // ✅ Проверяем, есть ли `facts_full` if (!isset($queryParams['facts_full']) || empty($queryParams['facts_full'])) { logMessage("❌ Ошибка: Пустой текст передан в векторизатор!"); die("Ошибка: `facts_full` отсутствует или пуст."); } // ✅ Получаем векторное представление `facts_full` $embedding = getTextEmbedding($queryParams['facts_full']); logMessage("📡 Векторизация facts_full:\n" . json_encode($embedding, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); // ✅ Проверяем наличие векторов и нормализуем $normalizedEmbedding1024 = null; if (isset($embedding["embedding_1024"])) { $sumSquares = 0; foreach ($embedding["embedding_1024"] as $x) { $sumSquares += $x * $x; } $magnitude = sqrt($sumSquares); if ($magnitude > 0) { $normalizedEmbedding1024 = array_map(function ($x) use ($magnitude) { return $x / $magnitude; }, $embedding["embedding_1024"]); } } $normalizedEmbedding2048 = null; if (isset($embedding["embedding_2048"])) { $sumSquares = 0; foreach ($embedding["embedding_2048"] as $x) { $sumSquares += $x * $x; } $magnitude = sqrt($sumSquares); if ($magnitude > 0) { $normalizedEmbedding2048 = array_map(function ($x) use ($magnitude) { return $x / $magnitude; }, $embedding["embedding_2048"]); } } // ✅ Запускаем поиск, передавая `facts_short` и векторные embeddings $searchResults = searchSimilarCases([ 'category' => $queryParams['category'], 'facts_short' => $queryParams['facts_short'], 'facts_full' => $queryParams['facts_full'], 'embedding_1024' => $normalizedEmbedding1024, 'embedding_2048' => $normalizedEmbedding2048 ]); logMessage("✅ Найденные судебные акты: " . json_encode($searchResults, JSON_UNESCAPED_UNICODE)); */ //---------------------------------------------------------------------------------------------------------------------------------// /* $embedding = getTextEmbedding($jsonForElastic['facts_full']); logMessage("📡 вектортут:\n" . json_encode($embedding, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); $normalizedEmbedding1024 = isset($embedding["embedding_1024"]) ? normalizeEmbedding($embedding["embedding_1024"]) : null; $normalizedEmbedding2048 = isset($embedding["embedding_2048"]) ? normalizeEmbedding($embedding["embedding_2048"]) : null; logMessage("Нормализованный embedding_1024: " . json_encode($normalizedEmbedding1024, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); logMessage("Нормализованный embedding_2048: " . json_encode($normalizedEmbedding2048, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); // Вызов функции searchSimilarCases $searchResults = searchSimilarCases([ 'category' => $jsonForElastic['category'], 'facts' => $jsonForElastic['facts_short'], 'article' => implode(" ", $jsonForElastic['articles']), 'amount' => $jsonForElastic['claim_amount'], 'embedding_1024'=> $normalizedEmbedding1024, 'embedding_2048'=> $normalizedEmbedding2048 ]); // Логирование результатов logMessage("Результаты поиска: " . json_encode($searchResults, JSON_UNESCAPED_UNICODE)); */ //------------------------------------------------------------------------------------- /*$searchResults = searchSimilarCases([ 'category' => $jsonForElastic['category'], 'article' => implode(" ", $jsonForElastic['articles']), 'amount' => $jsonForElastic['claim_amount'], 'facts' => $jsonForElastic['facts'], 'embedding'=> $embedding ]); */ //logMessage("✅ Найденные судебные акты: " . json_encode($searchResults, JSON_UNESCAPED_UNICODE)); /* // 6. Поиск в ElasticSearch судебных актов на основе полученных параметров $embedding = getTextEmbedding($prelimResponse['facts']); logMessage("🔍 Полученный эмбеддинг (предварительный, первые 10 значений): " . json_encode(array_slice($embedding["embedding_1024"], 0, 10))); $searchResults = searchSimilarCases([ 'category' => $prelimResponse['category'], 'article' => implode(" ", $prelimResponse['articles']), 'amount' => $prelimResponse['claim_amount'], 'facts' => $prelimResponse['facts'], 'embedding'=> $embedding ]); logMessage("✅ Найденные судебные акты: " . json_encode($searchResults, JSON_UNESCAPED_UNICODE)); */ // 7. Формирование финального запроса с добавлением контекста из ElasticSearch --------------------------------------------------------- // 8. Отправка финального запроса в GPT и получение финального ответа ------------------------------------------------------------------ logMessage("📤 Отправляем финальный запрос в GPT-4..."); // $finalAnalysis = analyzeDocumentWithAssistantStream($threadId, ASSISTANT_ID, $fileIdCombined, $finalPrompt, $searchResults, $prelimResponse); // $finalAnalysis = analyzeDocumentWithAssistantStream($threadId, ASSISTANT_ID, "", $finalPrompt, $searchResults); //$finalAnalysis = analyzeDocumentWithAssistantStream($threadId, ASSISTANT_ID, $combinedContent, $finalPrompt, $searchResults); //logVectorStoreFiles($vectorStoreId); $finalAnalysis = analyzeDocumentWithAssistantStream($threadId, ASSISTANT_ID, $vectorStoreId, $fileId, $parsedJson, $searchResults, $id); if (!$finalAnalysis) { logMessage("❌ Ошибка финального анализа через GPT-4. Сырой ответ:"); logMessage("📜 Сырой ответ GPT-4 (финальный анализ): " . json_encode($finalAnalysis, JSON_UNESCAPED_UNICODE)); die("Ошибка финального анализа через GPT-4."); } logMessage("✅ Финальный ответ от GPT-4:\n" . json_encode($finalAnalysis, JSON_UNESCAPED_UNICODE)); // ✅ Проверяем, есть ли `content` в `finalAnalysis` if (!isset($finalAnalysis['data']) || !is_array($finalAnalysis['data'])) { logMessage("❌ Ошибка: В `finalAnalysis` нет `data`. Ответ:\n" . json_encode($finalAnalysis, JSON_UNESCAPED_UNICODE)); die("Ошибка в структуре данных от GPT-4."); } // ✅ Ищем `content` $extractedContent = null; foreach ($finalAnalysis['data'] as $message) { if ($message['role'] === 'assistant' && isset($message['content']) && is_array($message['content'])) { foreach ($message['content'] as $contentBlock) { if ($contentBlock['type'] === 'text' && isset($contentBlock['text']['value'])) { $extractedContent = trim($contentBlock['text']['value']); break 2; // Выходим из обоих циклов } } } } $saveResult = saveAnalysisToElasticSearch($id, $finalAnalysis, $filePathList); if ($saveResult) { logMessage("✅ Анализ успешно сохранён в ElasticSearch."); } else { logMessage("❌ Ошибка при сохранении анализа в ElasticSearch."); } // ✅ Логируем, что нашли if ($extractedContent) { logMessage("✅ Извлечённый `content`: " . substr($extractedContent, 0, 500) . "..."); $finalAnalysis['content'] = $extractedContent; } else { logMessage("⚠️ Не удалось извлечь `content`. Используем `анализ_gpt`."); $finalAnalysis['content'] = "Анализ не выполнен"; } // ✅ Отправляем исправленный `finalAnalysis` в CRM sendAnalysisToCRM($id, $finalAnalysis); logMessage("Обработка кейса завершена."); exit; } else { logMessage("Ошибка: запрос должен быть POST"); die("Ошибка: запрос должен быть POST"); } ?>