Changes
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace App\Containers\Dashboard\Tasks;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class CallAiServiceForFileSelectionTask
|
||||
{
|
||||
/**
|
||||
* Отправляет фрагменты файлов в AI для определения основного файла
|
||||
*
|
||||
* @param array $fragments Массив фрагментов [['filename' => '...', 'text' => '...'], ...]
|
||||
* @return array|null Ответ AI с названием основного файла
|
||||
*/
|
||||
public function run(array $fragments): ?array
|
||||
{
|
||||
Log::info('[CallAiServiceForFileSelectionTask] Начало LLM запроса', [
|
||||
'fragments_count' => count($fragments),
|
||||
]);
|
||||
|
||||
$prompt = $this->buildPrompt($fragments);
|
||||
|
||||
Log::info('[CallAiServiceForFileSelectionTask] Отправка запроса к AI');
|
||||
|
||||
try {
|
||||
$response = Http::timeout(30) // Таймаут 30 секунд
|
||||
->withHeaders([
|
||||
'Authorization' => 'Bearer ' . env('QWEN_API_KEY'),
|
||||
'Content-Type' => 'application/json',
|
||||
])->post('https://routerai.ru/api/v1/chat/completions', [
|
||||
'model' => 'qwen/qwen3.5-flash-02-23',
|
||||
'messages' => [
|
||||
['role' => 'user', 'content' => $prompt],
|
||||
],
|
||||
'response_format' => ['type' => 'json_object'],
|
||||
'temperature' => 0,
|
||||
'max_tokens' => 500,
|
||||
]);
|
||||
|
||||
Log::info('[CallAiServiceForFileSelectionTask] Ответ от AI', [
|
||||
'status' => $response->status(),
|
||||
'successful' => $response->successful(),
|
||||
]);
|
||||
|
||||
if ($response->successful()) {
|
||||
$result = $response->json();
|
||||
$llmResponse = json_decode($result['choices'][0]['message']['content'], true);
|
||||
|
||||
Log::info('[CallAiServiceForFileSelectionTask] Распознан ответ', [
|
||||
'main_file' => $llmResponse['main_file'] ?? null,
|
||||
]);
|
||||
|
||||
return $llmResponse;
|
||||
} else {
|
||||
Log::error('[CallAiServiceForFileSelectionTask] Ошибка AI запроса', [
|
||||
'status' => $response->status(),
|
||||
'body' => $response->body(),
|
||||
]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('[CallAiServiceForFileSelectionTask] Исключение при запросе к AI', [
|
||||
'message' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
]);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Формирует промпт для AI
|
||||
*/
|
||||
private function buildPrompt(array $fragments): string
|
||||
{
|
||||
$filesInfo = "";
|
||||
foreach ($fragments as $index => $fragment) {
|
||||
$filesInfo .= "Файл #{$index}: {$fragment['filename']}\n";
|
||||
$filesInfo .= "Текст: {$fragment['text']}\n\n";
|
||||
}
|
||||
|
||||
return "Ты — ассистент для определения основного файла с новостью. " .
|
||||
"Тебе предоставлены фрагменты текста из нескольких DOCX файлов.\n\n" .
|
||||
"СПИСОК ФАЙЛОВ:\n{$filesInfo}\n" .
|
||||
"ЗАДАЧА: Определи, какой файл содержит основной текст новости (не приложение, не документ, а именно новость/статью).\n\n" .
|
||||
"ВЕРНИ СТРОГО JSON:\n" .
|
||||
"{\n" .
|
||||
' "main_file": "точное название файла с расширением .docx",' . "\n" .
|
||||
' "reason": "краткое объяснение выбора"' . "\n" .
|
||||
"}\n\n" .
|
||||
"Если не можешь определить — верни первый файл из списка.";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user