Files
crm.clientright.ru/aiassist/gptAssistant2.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

521 lines
20 KiB
PHP
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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/gptAssistant.php
require_once 'config.php';
require_once 'logger.php';
function createNewThread() {
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => OPENAI_THREADS_API,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . OPENAI_API_KEY,
'OpenAI-Beta: assistants=v2'
]
]);
$response = curl_exec($curl);
$decoded = json_decode($response, true);
curl_close($curl);
if (isset($decoded['id'])) {
logMessage("🔄 Создан новый thread_id: " . $decoded['id']);
return $decoded['id'];
} else {
logMessage("❌ Ошибка создания нового треда: " . json_encode($decoded));
return null;
}
}
function extractCaseDetailsWithGPT($threadId, $assistantId, $fileId, $content) {
logMessage("\ud83d\udccc Формируем текст запроса для GPT-4 (анализ + проверка заказчика и суммы).");
$userMessage = <<<PROMPT
🔹 **Анализ обращения + проверка загруженных документов**
Проанализируй файлы и выдели ключевые параметры дела.
---
### **1⃣ Модерация документов**
- Перечисли все загруженные файлы.
- Проверь, содержат ли изображения текст.
- Если изображение **без текста**, опиши, что на нём изображено.
- Укажи, если в файле есть **ненормативная лексика**, сцены насилия, запрещённая символика.
- Если требуется **ручная проверка**, напиши `"⚠️ Требуется ручная проверка: [название файла]"`.
---
### **2⃣ Проверка заказчика (истца) в заявлении и документах**
- Определи **ФИО или название компании заказчика в заявлении**.
- Определи **ФИО или название компании в документах (договорах, платежах, актах)**.
- Если есть **расхождения**, напиши: `"⚠️ Заказчик в заявлении и документах различается! Проверьте соответствие."`
---
### **3⃣ Проверка суммы договора**
- Найди сумму, указанную **в заявлении**.
- Найди сумму, указанную **в платежных документах**.
- Если суммы **не совпадают**, напиши: `"⚠️ Сумма в заявлении (___ руб.) не совпадает с платежами (___ руб.). Проверьте!"`
---
### **4⃣ Краткий анализ спора**
- **Истец:** (ФИО или название компании)
- **Ответчик:** (ФИО или название компании)
- **Суть спора:** (Опиши проблему)
- **Основные аргументы сторон:** (Что заявляет истец и какие возражения у ответчика)
---
### **📌 Верни два блока ответа:**
✅ **1⃣ JSON-формат для Elasticsearch:**
```json
{
"category": "",
"articles": [""],
"facts": "",
"claim_amount": "",
"document_type": "",
"applicant_name": "",
"document_client_name": "",
"discrepancy_alert": "",
"stated_amount": "",
"document_amount": ""
}
✅ 2⃣ Читаемый текст для CRM:
🔹 Краткий анализ: ...
🔹 Заказчик: ...
🔹 Сумма договора: ...
PROMPT;
**Файлы:** $fileId
**Содержимое:** $content
PROMPT;
logMessage("\ud83d\udce1 Отправляем запрос в GPT-4: " . $userMessage);
$payload = [
"assistant_id" => $assistantId,
"thread" => [
"messages" => [
["role" => "user", "content" => $userMessage]
]
],
"stream" => true
];
$payloadJson = json_encode($payload, JSON_UNESCAPED_UNICODE);
$finalMessage = "";
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => OPENAI_THREADS_API . "/runs",
CURLOPT_RETURNTRANSFER => false,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payloadJson,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . OPENAI_API_KEY,
'OpenAI-Beta: assistants=v2'
],
CURLOPT_WRITEFUNCTION => function($ch, $data) use (&$finalMessage) {
$finalMessage .= $data;
return strlen($data);
}
]);
curl_exec($curl);
$curlError = curl_error($curl);
if ($curlError) {
logMessage("\u274c Ошибка cURL в extractCaseDetailsWithGPT: " . $curlError);
curl_close($curl);
return null;
}
curl_close($curl);
logMessage("\ud83d\udcc2 Сырой потоковый ответ от GPT-4:\n" . $finalMessage);
$parsedMessage = "";
$lines = explode("\n", $finalMessage);
foreach ($lines as $line) {
$line = trim($line);
if (strpos($line, "data: ") === 0) {
$dataPart = substr($line, 6);
if ($dataPart === "[DONE]") {
break;
}
$json = json_decode($dataPart, true);
if (is_array($json) && isset($json['delta']['content'])) {
$contentPiece = "";
foreach ($json['delta']['content'] as $segment) {
if (isset($segment['text']['value'])) {
$contentPiece .= $segment['text']['value'];
}
}
$parsedMessage .= $contentPiece;
}
}
}
if (empty(trim($parsedMessage))) {
logMessage("\u26a0\ufe0f Парсинг не дал результата, используем сырой ответ.");
$parsedMessage = $finalMessage;
}
logMessage("\u2705 Итоговый ответ от GPT-4:\n" . $parsedMessage);
$structuredData = json_decode($parsedMessage, true);
if (!$structuredData) {
logMessage("\u274c Ошибка парсинга JSON, возвращаем сырой ответ.");
return ["error" => "Ошибка обработки данных"];
}
return $structuredData;
}
/*function extractCaseDetailsWithGPT($threadId, $assistantId, $fileId, $content) {
logMessage("📌 Предварительный анализ обращения через GPT-4 (stream): thread_id=$threadId, fileId=$fileId");
$userMessage = "🔹 Разбери обращение и выдели ключевые параметры:
1⃣ **Категория дела**:
Определи, к какому типу спора относится это обращение.
2⃣ **Применимые статьи закона**:
Выяви, какие нормы права могут быть применимы.
3⃣ **Основные обстоятельства дела**:
Выдели важные факты из обращения и приложенных документов.
4⃣ **Сумма требований (если указана)**:
Извлеки сумму требований, если она присутствует.
5⃣ **Тип запрашиваемого документа**:
Определи, нужно ли составлять иск, претензию, жалобу или ходатайство.
6⃣ **Оценка вероятности выигрыша**:
Оцени шансы на положительное решение (в %).
🔹 **Формат ответа (JSON)**:
{
\"category\": \"\",
\"articles\": [\"\"],
\"facts\": \"\",
\"claim_amount\": \"\",
\"document_type\": \"\",
\"win_probability\": \"\"
}
📌 Файлы: " . $fileId . "\n
📌 Содержимое для анализа:\n" . $content;
logMessage("📌 Формируем запрос к GPT-4: " . $userMessage);
$payload = [
"assistant_id" => $assistantId,
"thread" => [
"messages" => [
["role" => "user", "content" => $userMessage]
]
],
"stream" => true
];
$payloadJson = json_encode($payload, JSON_UNESCAPED_UNICODE);
logMessage("🔹 Отправляем запрос в GPT-4 (Payload):\n" . $payloadJson);
$finalMessage = "";
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => OPENAI_THREADS_API . "/runs",
CURLOPT_RETURNTRANSFER => false,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payloadJson,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . OPENAI_API_KEY,
'OpenAI-Beta: assistants=v2'
],
CURLOPT_WRITEFUNCTION => function($ch, $data) use (&$finalMessage) {
$finalMessage .= $data;
return strlen($data);
}
]);
curl_exec($curl);
$curlError = curl_error($curl);
if ($curlError) {
logMessage("❌ Ошибка cURL в extractCaseDetailsWithGPT: " . $curlError);
curl_close($curl);
return null;
}
curl_close($curl);
logMessage("📌 Сырой потоковый ответ (raw stream):\n" . $finalMessage);
$parsedMessage = "";
$lines = explode("\n", $finalMessage);
foreach ($lines as $line) {
$line = trim($line);
if (strpos($line, "data: ") === 0) {
$dataPart = substr($line, 6);
if ($dataPart === "[DONE]") {
break;
}
$json = json_decode($dataPart, true);
logMessage("🔹 DEBUG: Распарсенный фрагмент: " . print_r($json, true));
if (is_array($json) && isset($json['delta']['content'])) {
$contentPiece = "";
foreach ($json['delta']['content'] as $segment) {
if (isset($segment['text']['value'])) {
$contentPiece .= $segment['text']['value'];
}
}
$parsedMessage .= $contentPiece;
}
}
}
if (empty(trim($parsedMessage))) {
logMessage("❌ Парсинг не дал результата, используем сырой ответ.");
$parsedMessage = $finalMessage;
}
logMessage("✅ Итоговый ответ от GPT-4 (stream):\n" . $parsedMessage);
$structuredData = json_decode($parsedMessage, true);
if (!$structuredData) {
logMessage("❌ Ошибка парсинга JSON, возвращаем сырой ответ.");
return ["error" => "Ошибка обработки данных"];
}
return $structuredData;
}
*/
function analyzeDocumentWithAssistantStream($threadId, $assistantId, $fileId, $content, $foundCases) {
logMessage("🔹 Анализ документа через GPT-4 (stream) + судебные решения: thread_id=$threadId, fileId=$fileId");
$casesSummary = "";
foreach ($foundCases as $index => $case) {
$caseId = $case["case_id"] ?? "Неизвестный ID";
$court = $case["court"] ?? "Неизвестный суд";
$decision = mb_substr($case["court_decision"] ?? "Текст отсутствует", 0, 1000, "UTF-8");
$casesSummary .= "📌 Дело #".($index + 1)." (ID: $caseId, Суд: $court):\n$decision\n\n";
}
$userMessage = <<<PROMPT
🔹 **Анализ юридического обращения**
Текст обращения: "$content"
📌 **Найденные судебные решения в базе:**
$casesSummary
📢 **Задача для GPT-4:**
1⃣ Проанализируй найденные судебные дела и их исходы.
2⃣ Определи вероятность успеха аналогичного иска.
3⃣ Выяви основные аргументы, на которые можно опираться.
4⃣ Укажи возможные риски и слабые места в иске.
Файлы пользователя: $fileId
PROMPT;
logMessage("📢 Промпт для GPT-4:\n" . $userMessage);
$payload = [
"assistant_id" => $assistantId,
"thread" => [
"messages" => [
["role" => "user", "content" => $userMessage]
]
],
"stream" => true
];
$payloadJson = json_encode($payload, JSON_UNESCAPED_UNICODE);
logMessage("📡 Отправка запроса в GPT-4: " . $payloadJson);
$finalMessage = "";
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => OPENAI_THREADS_API . "/runs",
CURLOPT_RETURNTRANSFER => false,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payloadJson,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . OPENAI_API_KEY,
'OpenAI-Beta: assistants=v2'
],
CURLOPT_WRITEFUNCTION => function($ch, $data) use (&$finalMessage) {
$finalMessage .= $data;
return strlen($data);
}
]);
curl_exec($curl);
$curlError = curl_error($curl);
if ($curlError) {
logMessage("❌ Ошибка cURL в analyzeDocumentWithAssistantStream: " . $curlError);
curl_close($curl);
return null;
}
curl_close($curl);
logMessage("📥 Сырой потоковый ответ от GPT-4:\n" . $finalMessage);
$parsedMessage = "";
$lines = explode("\n", $finalMessage);
foreach ($lines as $line) {
$line = trim($line);
if (strpos($line, "data: ") === 0) {
$dataPart = substr($line, 6);
if ($dataPart === "[DONE]") {
break;
}
$json = json_decode($dataPart, true);
if (is_array($json) && isset($json['delta']['content'])) {
$contentPiece = "";
foreach ($json['delta']['content'] as $segment) {
if (isset($segment['text']['value'])) {
$contentPiece .= $segment['text']['value'];
}
}
$parsedMessage .= $contentPiece;
}
}
}
if (empty(trim($parsedMessage))) {
logMessage("⚠️ Парсинг не дал результата, используем сырой ответ.");
$parsedMessage = $finalMessage;
}
logMessage("✅ Итоговый анализ от GPT-4:\n" . $parsedMessage);
return [
"status" => "complete",
"content" => $parsedMessage
];
}
/*function analyzeDocumentWithAssistantStream($threadId, $assistantId, $fileId, $content, $foundCases, $prelimResponse = null) {
logMessage("🔹 Анализ документа через GPT-4 (stream) + судебные решения: thread_id=$threadId, fileId=$fileId");
$casesSummary = "";
foreach ($foundCases as $index => $case) {
$caseId = $case["case_id"] ?? "Неизвестный ID";
$court = $case["court"] ?? "Неизвестный суд";
$decision = mb_substr($case["court_decision"] ?? "Текст отсутствует", 0, 1000, "UTF-8");
$casesSummary .= "📌 Дело #".($index + 1)." (ID: $caseId, Суд: $court):\n$decision\n\n";
}
// Если предварительный анализ был выполнен, включаем его полностью
$prevAnalysisText = "";
if ($prelimResponse) {
// Можно форматировать предварительный ответ как JSON или, если он уже строка, использовать напрямую
if (is_array($prelimResponse)) {
$prevAnalysisText = json_encode($prelimResponse, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
} else {
$prevAnalysisText = $prelimResponse;
}
}
// Формируем финальный промпт, включающий первоначальный текст обращения, предварительный анализ и контекст судебных решений
$userMessage = <<<PROMPT
🔹 **Анализ юридического обращения**
Текст обращения: "$content"
📌 **Найденные судебные решения в базе:**
$casesSummary
📢 **Задача для GPT-4:**
1⃣ Проанализируй найденные судебные дела и их исходы.
2⃣ Определи вероятность успеха аналогичного иска, основанного на данных из обращения. Укажи
3⃣ Выяви основные аргументы, на которые можно опираться.
4⃣ Укажи возможные риски и слабые места в иске.
Файлы пользователя: $fileId
PROMPT;
logMessage("📢 Промпт для GPT-4:\n" . $userMessage);
$payload = [
"assistant_id" => $assistantId,
"thread" => [
"messages" => [
["role" => "user", "content" => $userMessage]
]
],
"stream" => true
];
$payloadJson = json_encode($payload, JSON_UNESCAPED_UNICODE);
logMessage("📡 Отправка запроса в GPT-4: " . $payloadJson);
$finalMessage = "";
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => OPENAI_THREADS_API . "/runs",
CURLOPT_RETURNTRANSFER => false,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payloadJson,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . OPENAI_API_KEY,
'OpenAI-Beta: assistants=v2'
],
CURLOPT_WRITEFUNCTION => function($ch, $data) use (&$finalMessage) {
$finalMessage .= $data;
return strlen($data);
}
]);
curl_exec($curl);
$curlError = curl_error($curl);
if ($curlError) {
logMessage("❌ Ошибка cURL в analyzeDocumentWithAssistantStream: " . $curlError);
curl_close($curl);
return null;
}
curl_close($curl);
logMessage("📥 Сырой потоковый ответ от GPT-4:\n" . $finalMessage);
$parsedMessage = "";
$lines = explode("\n", $finalMessage);
foreach ($lines as $line) {
$line = trim($line);
if (strpos($line, "data: ") === 0) {
$dataPart = substr($line, 6);
if ($dataPart === "[DONE]") {
break;
}
$json = json_decode($dataPart, true);
if (is_array($json) && isset($json['delta']['content'])) {
$contentPiece = "";
foreach ($json['delta']['content'] as $segment) {
if (isset($segment['text']['value'])) {
$contentPiece .= $segment['text']['value'];
}
}
$parsedMessage .= $contentPiece;
}
}
}
if (empty(trim($parsedMessage))) {
logMessage("⚠️ Парсинг не дал результата, используем сырой ответ.");
$parsedMessage = $finalMessage;
}
logMessage("✅ Итоговый анализ от GPT-4:\n" . $parsedMessage);
return [
"status" => "complete",
"content" => $parsedMessage
];
}
*/
?>