💡 Предисловие: «Пока модели нормальной не нашел, тупые ядра на этом Xeon. Тормозит жутко.
На новом Core i7 в 20 раз быстрее, но это с использованием инструкций AVX.
Надо подобрать правильную модель для Xeon.»
В этой статье я покажу, как мы с нуля развернули локальную нейросеть на обычном сервере без GPU,
написали агента на PHP для анализа логов и заставили их работать вместе.
⚡ Итог: работающий прототип за 1 день, бюджет — 0 ₽
1. Почему локальная нейросеть, а не ChatGPT?
Отправлять логи сервера в облачные API — плохая идея. Это безопасность, задержки, цена.
А если интернет упал? Мы хотели получить автономного агента, который:
Работает без доступа к интернету
Не отправляет данные наружу
Отвечает быстро (ну, почти)
Не требует видеокарты (только CPU и RAM)
✅ Наш выбор: Qwen2.5-14B (квантизация Q4_K_M) — 9 ГБ, запускается на процессоре,
даёт короткие и точные ответы.
Виртуальный сервер на Xeon с 44 ядрами оказался медленнее, чем обычный Core i7 с 4 ядрами.
Причина — в использовании инструкций AVX2, которые llama.cpp задействует на полную,
а Ollama на виртуалке — нет. Поэтому мы выбрали связку:
llama.cpp — запуск модели на вашем компьютере
Qwen2.5-14B — модель с хорошим балансом скорости и качества
4. Двухкнопочный агент на PHP
Мы написали агента, который работает в два клика:
«Забрать ошибки» — читает последние 100 строк из логов, находит ошибки и показывает их.
«Отправить на анализ» — отправляет собранные ошибки в нейросеть и возвращает структурированный ответ.
Вот финальный код агента/usr/share/zabbix/ai_log_analyzer.php:
<?php
/**
* AI Log Analyzer - двухкнопочный агент для анализа логов
*/define('OLLAMA_HOST', 'http://192.168.1.133:8080');
define('MODEL_NAME', 'C:\\Users\\sdgfdsagdsgfds\\.cache\\huggingface\\hub\\models--bartowski--Qwen2.5-14B-Instruct-GGUF\\snapshots\\05244aa5d871cs23432415d3bce44714d068d\\Qwen2.5-14B-Instruct-Q4_K_M.gguf');
define('LOG_FILES', [
'/var/log/syslog',
'/var/log/auth.log',
'/var/log/nginx/error.log',
'/var/log/zabbix/zabbix_server.log',
]);
define('ERROR_KEYWORDS', ['error', 'fatal', 'panic', 'critical', 'failed', 'failure', 'exception', 'timeout', 'out of memory', 'segmentation fault', 'connection refused']);
/**
* Собирает последние ошибки из логов
*/functiongetRecentErrors() {
$all_errors = [];
foreach (LOG_FILES as$file) {
if (!file_exists($file)) continue;
$lines = shell_exec("tail -100 $file 2>/dev/null");
if (empty($lines)) continue;
$lines = explode("\n", $lines);
$file_errors = [];
foreach ($linesas$line) {
$lower = strtolower($line);
foreach (ERROR_KEYWORDS as$kw) {
if (strpos($lower, $kw) !== false) {
$file_errors[] = trim($line);
break;
}
}
}
if (!empty($file_errors)) {
$all_errors[] = "📁 " . basename($file) . ":";
$all_errors = array_merge($all_errors, array_slice($file_errors, 0, 5));
}
}
if (empty($all_errors)) {
return"⚠️ Ошибок в логах не найдено за последнее время.";
}
returnimplode("\n", $all_errors);
}
/**
* Отправляет текст на анализ в нейросеть
*/functionanalyzeWithAI($text) {
if (empty($text) || $text === "⚠️ Ошибок в логах не найдено за последнее время.") {
return"⚠️ Нет ошибок для анализа.";
}
$url = OLLAMA_HOST . '/completion';
$prompt = "Проанализируй эти ошибки из системных логов и дай ЧЁТКИЙ СТРУКТУРИРОВАННЫЙ ОТВЕТ (максимум 5 предложений).
Обязательно укажи:
• ГЛАВНАЯ ПРОБЛЕМА: что сломалось?
• ГДЕ: в каком файле/сервисе?
• ЧТО ДЕЛАТЬ: конкретные шаги для исправления (не более 3 пунктов)
Вот ошибки:
" . $text;
$data = [
'prompt' => $prompt,
'temperature' => 0.1,
'max_tokens' => 150,
'stream' => false
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) return"⚠️ Ошибка соединения: " . $error;
if ($httpCode !== 200) return"⚠️ Ошибка API (HTTP $httpCode)";
$decoded = json_decode($response, true);
$answer = $decoded['content'] ?? '';
returnempty($answer) ? "⚠️ Нейросеть вернула пустой ответ" : trim($answer);
}
// Дальше идёт HTML-интерфейс с двумя кнопками
?>
5. Как это работает
📥 Шаг 1: «Забрать ошибки»
Скрипт читает последние 100 строк из каждого лога, фильтрует строки с ключевыми словами
error, fatal, panic, critical, failed,
exception, timeout и другими. Показывает до 5 ошибок из каждого файла.
🧠 Шаг 2: «Отправить на анализ»
Собранный текст отправляется в нейросеть на 192.168.1.33:8080.
Модель Qwen2.5-14B анализирует ошибки и возвращает структурированный ответ:
ГЛАВНАЯ ПРОБЛЕМА — что сломалось
ГДЕ — в каком файле/сервисе
ЧТО ДЕЛАТЬ — конкретные шаги (не более 3 пунктов)
6. Проблемы и решения
🔴 Медленная генерация на Xeon
Виртуальный сервер на Xeon с 44 ядрами работал медленнее, чем Core i7 на 4 ядрах.
Решение — использовать llama.cpp на компьютере с поддержкой AVX2.
🔴 Таймауты при отправке
Скрипт не успевал получить ответ за 60 секунд. Решение — увеличить
CURLOPT_TIMEOUT до 120 секунд.
🔴 Нейросеть возвращала пустой ответ
Модель сначала «думала» (поле thinking), а потом отвечала.
Мы переключились на llama.cpp с эндпоинтом /completion,
где ответ сразу приходит в поле content.
🔴 PHP не читал логи
Пользователь www-data не имел прав на чтение логов.
Решение — добавить пользователя в группу adm:
sudo usermod -a -G adm www-data
7. Результат
Мы получили работающего AI-агента с удобным веб-интерфейсом:
📄 Собирает ошибки из 4 логов: syslog, auth.log, nginx, zabbix_server
ГЛАВНАЯ ПРОБЛЕМА: Система не может аутентифицировать пользователя mazzick при использовании sudo.
ГДЕ: Ошибки в auth.log и error.log.
ЧТО ДЕЛАТЬ:
1. Проверить пароль пользователя mazzick.
2. Проверить доступность сокета PHP-FPM.
3. Увеличить таймауты в настройках nginx.
Комментарии
Пока нет комментариев. Будьте первым!