461 lines
20 KiB
PHP
461 lines
20 KiB
PHP
|
|
<?php
|
|||
|
|
// iacode15.php
|
|||
|
|
require_once 'aiassist/config.php';
|
|||
|
|
require_once 'aiassist/logger.php';
|
|||
|
|
require_once 'aiassist/database.php';
|
|||
|
|
require_once 'aiassist/crmHandler.php';
|
|||
|
|
require_once 'aiassist/elastic.php';
|
|||
|
|
require_once 'aiassist/fileHandler.php';
|
|||
|
|
require_once 'aiassist/vectorgpt.php';
|
|||
|
|
require_once 'aiassist/gptAssistant.php';
|
|||
|
|
require_once 'aiassist/search.php';
|
|||
|
|
require_once 'aiassist/utils.php';
|
|||
|
|
|
|||
|
|
// 1. Получение ID кейса
|
|||
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||
|
|
$id = $_POST['id'] ?? null;
|
|||
|
|
if (!$id) {
|
|||
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|||
|
|
$id = $input['id'] ?? null;
|
|||
|
|
}
|
|||
|
|
if (!$id || !is_numeric($id)) {
|
|||
|
|
logMessage("Ошибка: Некорректный ID.");
|
|||
|
|
die(json_encode(["status" => "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));
|
|||
|
|
|
|||
|
|
//---------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
/*
|
|||
|
|
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");
|
|||
|
|
}
|
|||
|
|
?>
|
|||
|
|
|