Files
crm.clientright.ru/aiassist/vectorgpt.php
Fedor ac7467f0b4 Major CRM updates: AI Assistant, Court Status API, S3 integration improvements, and extensive file storage system
- 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.
2025-10-16 11:17:21 +03:00

386 lines
14 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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)
];
}*/
?>