- 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.
386 lines
14 KiB
PHP
386 lines
14 KiB
PHP
<?php
|
||
// aiassist/vectorgpt.php
|
||
require_once 'config.php';
|
||
require_once 'logger.php';
|
||
|
||
function createVectorStore() {
|
||
$curl = curl_init();
|
||
$payload = json_encode(['name' => 'Vector Store']);
|
||
logMessage("Создание Vector Store. Отправляем payload: " . $payload);
|
||
curl_setopt_array($curl, [
|
||
CURLOPT_URL => OPENAI_VECTOR_STORES_API,
|
||
CURLOPT_RETURNTRANSFER => true,
|
||
CURLOPT_POST => true,
|
||
CURLOPT_POSTFIELDS => $payload,
|
||
CURLOPT_HTTPHEADER => [
|
||
'Content-Type: application/json',
|
||
'Authorization: Bearer ' . OPENAI_API_KEY,
|
||
'OpenAI-Beta: assistants=v2'
|
||
]
|
||
]);
|
||
$response = curl_exec($curl);
|
||
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||
$curlError = curl_error($curl);
|
||
curl_close($curl);
|
||
logMessage("Ответ OpenAI (создание Vector Store): HTTP $httpCode - " . $response);
|
||
if ($curlError) {
|
||
logMessage("Ошибка cURL при создании Vector Store: " . $curlError);
|
||
return null;
|
||
}
|
||
$decoded = json_decode($response, true);
|
||
if ($httpCode !== 200 || !isset($decoded['id'])) {
|
||
logMessage("Ошибка при создании Vector Store: " . json_encode($decoded, JSON_UNESCAPED_UNICODE));
|
||
return null;
|
||
}
|
||
return $decoded['id'];
|
||
}
|
||
function uploadFileToOpenAI($filePath) {
|
||
if (!file_exists($filePath) || filesize($filePath) == 0) {
|
||
logMessage("❌ Ошибка: Файл не найден или пустой! $filePath");
|
||
return null;
|
||
}
|
||
|
||
logMessage("📤 Загружаем файл в OpenAI: $filePath");
|
||
logMessage("🔑 Используем API-ключ: " . substr(OPENAI_API_KEY, 0, 8) . "********");
|
||
|
||
$curl = curl_init();
|
||
curl_setopt_array($curl, [
|
||
CURLOPT_URL => OPENAI_FILES_API,
|
||
CURLOPT_RETURNTRANSFER => true,
|
||
CURLOPT_POST => true,
|
||
CURLOPT_POSTFIELDS => [
|
||
'file' => new CURLFile($filePath),
|
||
'purpose' => 'assistants'
|
||
],
|
||
CURLOPT_HTTPHEADER => [
|
||
"Authorization: Bearer " . OPENAI_API_KEY,
|
||
"OpenAI-Beta: assistants=v2"
|
||
// Content-Type: multipart/form-data автоматически добавляется cURL с правильным boundary
|
||
]
|
||
]);
|
||
|
||
$response = curl_exec($curl);
|
||
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||
$curlError = curl_error($curl);
|
||
curl_close($curl);
|
||
|
||
logMessage("📡 Ответ OpenAI (загрузка файла): HTTP $httpCode - " . $response);
|
||
|
||
if ($curlError) {
|
||
logMessage("❌ Ошибка cURL при загрузке файла: " . $curlError);
|
||
return null;
|
||
}
|
||
|
||
$decoded = json_decode($response, true);
|
||
if ($httpCode !== 200 || !isset($decoded['id'])) {
|
||
logMessage("❌ Ошибка при загрузке файла в OpenAI: " . json_encode($decoded, JSON_UNESCAPED_UNICODE));
|
||
return null;
|
||
}
|
||
|
||
logMessage("✅ Файл успешно загружен в OpenAI (ID: " . $decoded['id'] . ")");
|
||
return $decoded['id'];
|
||
}
|
||
|
||
/*function uploadFileToOpenAI($filePath) {
|
||
logMessage("Загрузка файла в OpenAI: $filePath");
|
||
$curl = curl_init();
|
||
curl_setopt_array($curl, [
|
||
CURLOPT_URL => OPENAI_FILES_API,
|
||
CURLOPT_RETURNTRANSFER => true,
|
||
CURLOPT_POST => true,
|
||
CURLOPT_POSTFIELDS => [
|
||
'file' => new CURLFile($filePath),
|
||
'purpose' => 'assistants'
|
||
],
|
||
CURLOPT_HTTPHEADER => [
|
||
'Authorization: Bearer ' . OPENAI_API_KEY,
|
||
'OpenAI-Beta: assistants=v2'
|
||
]
|
||
]);
|
||
$response = curl_exec($curl);
|
||
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||
$curlError = curl_error($curl);
|
||
curl_close($curl);
|
||
logMessage("Ответ OpenAI (загрузка файла): HTTP $httpCode - " . $response);
|
||
if ($curlError) {
|
||
logMessage("Ошибка cURL при загрузке файла: " . $curlError);
|
||
return null;
|
||
}
|
||
$decoded = json_decode($response, true);
|
||
if ($httpCode !== 200 || !isset($decoded['id'])) {
|
||
logMessage("Ошибка при загрузке файла: " . json_encode($decoded, JSON_UNESCAPED_UNICODE));
|
||
return null;
|
||
}
|
||
return $decoded['id'];
|
||
}
|
||
*/
|
||
function addFileToVectorStore($vectorStoreId, $fileId) {
|
||
$curl = curl_init();
|
||
$payload = json_encode(['file_id' => $fileId]);
|
||
logMessage("Добавление файла в Vector Store. Payload: " . $payload);
|
||
curl_setopt_array($curl, [
|
||
CURLOPT_URL => OPENAI_VECTOR_STORES_API . "/$vectorStoreId/files",
|
||
CURLOPT_RETURNTRANSFER => true,
|
||
CURLOPT_POST => true,
|
||
CURLOPT_POSTFIELDS => $payload,
|
||
CURLOPT_HTTPHEADER => [
|
||
'Content-Type: application/json',
|
||
'Authorization: Bearer ' . OPENAI_API_KEY,
|
||
'OpenAI-Beta: assistants=v2'
|
||
]
|
||
]);
|
||
$response = curl_exec($curl);
|
||
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||
$curlError = curl_error($curl);
|
||
curl_close($curl);
|
||
logMessage("Ответ OpenAI (добавление файла): HTTP $httpCode - " . $response);
|
||
if ($curlError) {
|
||
logMessage("Ошибка cURL при добавлении файла в Vector Store: " . $curlError);
|
||
return false;
|
||
}
|
||
$decoded = json_decode($response, true);
|
||
if ($httpCode !== 200 || !isset($decoded['id'])) {
|
||
logMessage("Ошибка добавления файла: " . json_encode($decoded, JSON_UNESCAPED_UNICODE));
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
function updateAssistantWithVectorStore($vectorStoreId) {
|
||
$data = [
|
||
'tool_resources' => [
|
||
'file_search' => [
|
||
'vector_store_ids' => [$vectorStoreId]
|
||
]
|
||
]
|
||
];
|
||
$curl = curl_init();
|
||
$payload = json_encode($data);
|
||
logMessage("Обновление ассистента. Payload: " . $payload);
|
||
curl_setopt_array($curl, [
|
||
CURLOPT_URL => OPENAI_ASSISTANT_API . "/" . ASSISTANT_ID,
|
||
CURLOPT_RETURNTRANSFER => true,
|
||
CURLOPT_CUSTOMREQUEST => 'POST',
|
||
CURLOPT_POSTFIELDS => $payload,
|
||
CURLOPT_HTTPHEADER => [
|
||
'Content-Type: application/json',
|
||
'Authorization: Bearer ' . OPENAI_API_KEY,
|
||
'OpenAI-Beta: assistants=v2'
|
||
]
|
||
]);
|
||
$response = curl_exec($curl);
|
||
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||
$curlError = curl_error($curl);
|
||
curl_close($curl);
|
||
logMessage("Ответ OpenAI (обновление ассистента): HTTP $httpCode - " . $response);
|
||
if ($curlError) {
|
||
logMessage("Ошибка обновления ассистента: " . $curlError);
|
||
return false;
|
||
}
|
||
$decoded = json_decode($response, true);
|
||
if ($httpCode !== 200 || !isset($decoded['id'])) {
|
||
logMessage("Ошибка обновления ассистента: " . json_encode($decoded, JSON_UNESCAPED_UNICODE));
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
function getTextEmbedding($text) {
|
||
$command = "sudo -u fastuser /var/www/laws/legal/bin/python3 /var/www/laws/legal/vectorize.py";
|
||
|
||
$descriptors = [
|
||
0 => ["pipe", "r"], // stdin (передаем текст)
|
||
1 => ["pipe", "w"], // stdout (читаем результат)
|
||
2 => ["pipe", "w"] // stderr (читаем ошибки)
|
||
];
|
||
|
||
// Логируем команду перед её выполнением
|
||
file_put_contents(__DIR__ . '/logs/vectorizer_debug.log',
|
||
date('Y-m-d H:i:s') . " - Executing command: $command\n", FILE_APPEND);
|
||
|
||
$process = proc_open($command, $descriptors, $pipes);
|
||
|
||
if (!is_resource($process)) {
|
||
error_log("Ошибка запуска Python через proc_open: $command");
|
||
return [
|
||
"embedding_1024" => array_fill(0, 1024, 0.001),
|
||
"embedding_2048" => array_fill(0, 2048, 0.001)
|
||
];
|
||
}
|
||
|
||
// Передаем текст в stdin
|
||
fwrite($pipes[0], $text);
|
||
fclose($pipes[0]);
|
||
|
||
// Читаем результат из stdout
|
||
$output = stream_get_contents($pipes[1]);
|
||
fclose($pipes[1]);
|
||
|
||
// Читаем stderr (ошибки)
|
||
$errorOutput = stream_get_contents($pipes[2]);
|
||
fclose($pipes[2]);
|
||
|
||
proc_close($process);
|
||
|
||
// Логируем результат выполнения Python
|
||
file_put_contents(__DIR__ . '/logs/vectorizer_debug.log',
|
||
date('Y-m-d H:i:s') . " - Raw output: " . $output . "\n", FILE_APPEND);
|
||
|
||
if (!empty($errorOutput)) {
|
||
file_put_contents(__DIR__ . '/logs/vectorizer_debug.log',
|
||
date('Y-m-d H:i:s') . " - Python error: " . $errorOutput . "\n", FILE_APPEND);
|
||
return [
|
||
"embedding_1024" => array_fill(0, 1024, 0.001),
|
||
"embedding_2048" => array_fill(0, 2048, 0.001)
|
||
];
|
||
}
|
||
|
||
$decoded = json_decode($output, true);
|
||
|
||
return [
|
||
"embedding_1024" => $decoded["embedding_1024"] ?? array_fill(0, 1024, 0.001),
|
||
"embedding_2048" => $decoded["embedding_2048"] ?? array_fill(0, 2048, 0.001)
|
||
];
|
||
}
|
||
|
||
function logVectorStoreFiles($vectorStoreId) {
|
||
$url = OPENAI_VECTOR_STORES_API . '/' . $vectorStoreId . '/files';
|
||
|
||
$ch = curl_init();
|
||
curl_setopt_array($ch, [
|
||
CURLOPT_URL => $url,
|
||
CURLOPT_RETURNTRANSFER => true,
|
||
CURLOPT_HTTPHEADER => [
|
||
"Content-Type: application/json",
|
||
"Authorization: Bearer " . OPENAI_API_KEY,
|
||
"OpenAI-Beta: assistants=v2" // добавляем заголовок для использования Assistants v2
|
||
]
|
||
]);
|
||
|
||
$response = curl_exec($ch);
|
||
|
||
// Проверка ошибок cURL
|
||
if (curl_errno($ch)) {
|
||
logMessage("❌ Ошибка cURL: " . curl_error($ch));
|
||
curl_close($ch);
|
||
return;
|
||
}
|
||
curl_close($ch);
|
||
|
||
// Проверка на ошибки декодирования JSON
|
||
$data = json_decode($response, true);
|
||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||
logMessage("❌ Ошибка при декодировании JSON: " . json_last_error_msg());
|
||
return;
|
||
}
|
||
|
||
// Проверка, что данные о файлах действительно получены
|
||
if (isset($data['data'])) {
|
||
logMessage("📦 Содержимое Vector Store ($vectorStoreId):");
|
||
|
||
// Логируем данные по каждому файлу в Vector Store
|
||
foreach ($data['data'] as $file) {
|
||
$id = $file['id'] ?? '???';
|
||
$filename = $file['filename'] ?? 'без имени';
|
||
$bytes = $file['bytes'] ?? 0;
|
||
$status = $file['status'] ?? 'неизвестно';
|
||
|
||
// Логируем информацию о файле
|
||
logMessage("📄 [$id] $filename | Статус: $status | Размер: " . round($bytes / 1024, 1) . " КБ");
|
||
|
||
// Если файл проиндексирован, извлекаем первые 400 символов текста
|
||
if ($status === 'completed') {
|
||
$text = extractTextFromFile($filename); // извлекаем текст из файла
|
||
$fragment = mb_substr($text, 0, 400, 'UTF-8');
|
||
logMessage("📜 Фрагмент из $filename: $fragment...");
|
||
} else {
|
||
logMessage("⚠️ Файл не проиндексирован или текст не доступен: $filename");
|
||
}
|
||
}
|
||
} else {
|
||
logMessage("❌ Не удалось получить файлы из Vector Store ID: $vectorStoreId");
|
||
}
|
||
}
|
||
|
||
|
||
function checkFileStatus($vectorStoreId) {
|
||
// $url = "https://api.proxyapi.ru/openai/v1/vector_stores/$vectorStoreId/files";
|
||
$url = OPENAI_VECTOR_STORES_API . '/' . $vectorStoreId . '/files';
|
||
$ch = curl_init();
|
||
curl_setopt_array($ch, [
|
||
CURLOPT_URL => $url,
|
||
CURLOPT_RETURNTRANSFER => true,
|
||
CURLOPT_HTTPHEADER => [
|
||
"Content-Type: application/json",
|
||
"Authorization: Bearer " . OPENAI_API_KEY,
|
||
"OpenAI-Beta: assistants=v2" // Этот заголовок нужно добавить!
|
||
]
|
||
]);
|
||
|
||
$response = curl_exec($ch);
|
||
curl_close($ch);
|
||
|
||
$data = json_decode($response, true);
|
||
if (isset($data['data'])) {
|
||
foreach ($data['data'] as $file) {
|
||
$id = $file['id'] ?? '???';
|
||
$filename = $file['filename'] ?? 'без имени';
|
||
$status = $file['status'] ?? 'неизвестно';
|
||
logMessage("📄 Файл: $filename | Статус: $status");
|
||
}
|
||
} else {
|
||
logMessage("❌ Ошибка при получении статуса файлов из Vector Store.");
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
function getTextEmbedding($text) {
|
||
$command = "sudo -u fastuser /var/www/laws/legal/bin/python3 /var/www/laws/legal/vectorize.py";
|
||
|
||
$descriptors = [
|
||
0 => ["pipe", "r"],
|
||
1 => ["pipe", "w"],
|
||
2 => ["pipe", "w"]
|
||
];
|
||
|
||
$process = proc_open($command, $descriptors, $pipes);
|
||
|
||
if (!is_resource($process)) {
|
||
error_log("Ошибка запуска Python через proc_open: $command");
|
||
return [
|
||
"embedding_1024" => array_fill(0, 1024, 0.001),
|
||
"embedding_2048" => array_fill(0, 2048, 0.001)
|
||
];
|
||
}
|
||
|
||
fwrite($pipes[0], $text);
|
||
fclose($pipes[0]);
|
||
|
||
$output = stream_get_contents($pipes[1]);
|
||
fclose($pipes[1]);
|
||
|
||
$errorOutput = stream_get_contents($pipes[2]);
|
||
fclose($pipes[2]);
|
||
|
||
proc_close($process);
|
||
|
||
file_put_contents(__DIR__ . '/logs/vectorizer.log',
|
||
date('Y-m-d H:i:s') . " - Raw output: " . $output . "\n", FILE_APPEND);
|
||
|
||
if (!empty($errorOutput)) {
|
||
error_log("Ошибка Python: " . $errorOutput);
|
||
return [
|
||
"embedding_1024" => array_fill(0, 1024, 0.001),
|
||
"embedding_2048" => array_fill(0, 2048, 0.001)
|
||
];
|
||
}
|
||
|
||
$decoded = json_decode($output, true);
|
||
|
||
return [
|
||
"embedding_1024" => $decoded["embedding_1024"] ?? array_fill(0, 1024, 0.001),
|
||
"embedding_2048" => $decoded["embedding_2048"] ?? array_fill(0, 2048, 0.001)
|
||
];
|
||
}*/
|
||
?>
|