Вы уже считаете количество ошибок в логах. Но что, если нейросеть сможет не просто посчитать, а понять, что происходит в вашем доме? В этой статье мы:
- Настроим локальную нейросеть Qwen 2.5 7B (GGUF) на Linux
- Напишем PHP-скрипт, который анализирует логи Zigbee-устройств
- Сделаем красивую HTML-панель для отображения результатов
- Настроим автоматический сбор и анализ логов
1. Установка нейросети на Linux
Мы будем использовать llama.cpp — это самый производительный движок для запуска GGUF-моделей на видеокартах NVIDIA.
1.1 Устанавливаем llama.cpp с поддержкой CUDA
# Клонируем репозиторий
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
# Собираем с поддержкой CUDA (для вашей RTX 5060)
LLAMA_CUDA=1 make -j4
# Проверяем, что сборка прошла
./llama-cli -h
1.2 Скачиваем модель Qwen 2.5 7B (Q4_K_M)
Для вашей видеокарты с 8 ГБ памяти идеально подходит версия Q4_K_M — около 4.3 ГБ.
# Скачиваем через huggingface-cli (рекомендуется)
pip install -U "huggingface_hub[cli]"
huggingface-cli download tensorblock/Qwen2.5-7B-Instruct-GGUF \
--include "Qwen2.5-7B-Instruct-Q4_K_M.gguf" \
--local-dir ./models/qwen
paultimothymooney/Qwen2.5-7B-Instruct-Q4_K_M-GGUF.
1.3 Запускаем модель как сервер (API)
Для интеграции с PHP удобнее всего запустить модель в режиме сервера. Он будет висеть в фоне и ждать запросов.
# Запускаем сервер на порту 8080
./llama-server -m ./models/qwen/Qwen2.5-7B-Instruct-Q4_K_M.gguf \
-c 4096 \
-ngl 999 \
--flash-attn \
--port 8080
-c 4096 — размер контекста (для логов хватит)-ngl 999 — загрузить все слои в видеопамять--flash-attn — экономия памяти
2. Архитектура агента: сбор логов → анализ → вывод
Вот как будет работать вся система:
Zigbee-устройства → логи → PHP-агент → Qwen (API) → анализ → HTML-панель
📥 Сбор логов
Ваш Zigbee-контроллер (например, zigbee2mqtt) пишет логи в файл /var/log/zigbee.log.
🧠 Анализ
PHP-скрипт читает логи, формирует промпт и отправляет запрос к нейросети.
📊 Результат
Нейросеть возвращает структурированный ответ с рекомендациями и критическими событиями.
🖥️ Панель
HTML-страница с карточками, графиками и статусами — всё в реальном времени.
3. PHP-агент для анализа логов
Этот скрипт читает логи, выделяет ошибки, предупреждения и отправляет их в нейросеть. Результат кешируется, чтобы не нагружать видеокарту.
3.1 Класс для работы с API нейросети
<?php
// agent.php — ядро аналитики
class QwenAgent {
private $apiUrl = 'http://localhost:8080/v1/chat/completions';
private $cacheFile = '/tmp/agent_cache.json';
private $cacheTTL = 300; // 5 минут
public function analyzeLogs($logText) {
// Проверяем кеш
if ($this->getCache($logText)) {
return $this->getCache($logText);
}
// Формируем системный промпт
$systemPrompt = "Ты — эксперт по умному дому. Анализируй логи Zigbee-устройств.
Выдели критичные ошибки, нестабильные устройства и дай рекомендации.
В ответе используй JSON-структуру:
{
\"critical\": [\"список критических событий\"],
\"warnings\": [\"список предупреждений\"],
\"summary\": \"краткое резюме\",
\"devices_offline\": [\"устройства, которые не отвечают\"]
}";
$payload = [
'messages' => [
['role' => 'system', 'content' => $systemPrompt],
['role' => 'user', 'content' => "Проанализируй эти логи:\n" . $logText]
],
'temperature' => 0.2,
'max_tokens' => 1024
];
$ch = curl_init($this->apiUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
$response = curl_exec($ch);
curl_close($ch);
if (!$response) {
return ['error' => 'Нейросеть не отвечает'];
}
$data = json_decode($response, true);
$result = $data['choices'][0]['message']['content'] ?? '';
// Сохраняем в кеш
$this->setCache($logText, $result);
return $result;
}
private function getCache($text) {
if (!file_exists($this->cacheFile)) return false;
$cache = json_decode(file_get_contents($this->cacheFile), true);
if (!$cache) return false;
if (time() - $cache['time'] > $this->cacheTTL) return false;
if (md5($text) !== $cache['hash']) return false;
return $cache['data'];
}
private function setCache($text, $data) {
file_put_contents($this->cacheFile, json_encode([
'hash' => md5($text),
'data' => $data,
'time' => time()
]));
}
}
// Использование:
$agent = new QwenAgent();
$logs = file_get_contents('/var/log/zigbee.log'); // последние 1000 строк
$analysis = $agent->analyzeLogs($logs);
echo $analysis;
?>
3.2 Скрипт для сбора статистики по ключевым словам (без нейросети)
Если нейросеть ещё не установлена, можно использовать «упрощённый» анализатор. Он считает ключевые слова и подготавливает данные для нейросети.
<?php
// stat_collector.php — собирает статистику по ключевым словам
function collectStats($logPath) {
$keywords = ['error' => 0, 'warning' => 0, 'failed' => 0, 'offline' => 0];
$lines = file($logPath, FILE_IGNORE_NEW_LINES);
$lines = array_slice($lines, -200); // последние 200 строк
foreach ($lines as $line) {
$lower = strtolower($line);
foreach ($keywords as $key => &$count) {
if (strpos($lower, $key) !== false) {
$count++;
}
}
}
// Формируем текст для нейросети
$logText = implode("\n", $lines);
return [
'stats' => $keywords,
'log_text' => $logText,
'total_lines' => count($lines)
];
}
// Сохраняем статистику в JSON для панели
$data = collectStats('/var/log/zigbee.log');
file_put_contents('/var/www/html/stats.json', json_encode($data));
?>
4. HTML-панель для отображения результатов
Вот готовая страница, которая показывает статистику ошибок, результат анализа нейросети и статус устройств. Обновляется автоматически каждые 30 секунд.
4.1 Полный HTML-код панели
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🏠 Умный дом — AI-аналитика</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Segoe UI', system-ui, sans-serif;
background: #f0f4f8;
padding: 2rem 1rem;
color: #1e293b;
}
.dashboard {
max-width: 1200px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 1.5rem;
}
.card {
background: white;
border-radius: 24px;
padding: 1.5rem;
box-shadow: 0 4px 16px rgba(0,0,0,0.06);
border: 1px solid #e2e8f0;
}
.card-full { grid-column: 1 / -1; }
.card h3 {
font-size: 1rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: #64748b;
margin-bottom: 0.75rem;
}
.stat-number {
font-size: 2.6rem;
font-weight: 700;
color: #0f172a;
}
.stat-label { color: #475569; font-size: 0.95rem; }
.badge-error { background: #fef2f2; color: #b91c1c; padding: 0.2rem 0.8rem; border-radius: 30px; font-size: 0.8rem; }
.badge-warning { background: #fffbeb; color: #92400e; padding: 0.2rem 0.8rem; border-radius: 30px; font-size: 0.8rem; }
.badge-ok { background: #ecfdf5; color: #065f46; padding: 0.2rem 0.8rem; border-radius: 30px; font-size: 0.8rem; }
.ai-response {
background: #f8fafc;
padding: 1.2rem;
border-radius: 16px;
margin-top: 0.8rem;
white-space: pre-wrap;
font-size: 0.95rem;
border-left: 4px solid #3b82f6;
}
.device-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem;
margin-top: 0.5rem;
}
.device-item {
background: #f8fafc;
padding: 0.6rem 1rem;
border-radius: 12px;
display: flex;
justify-content: space-between;
}
.footer { margin-top: 2rem; text-align: center; color: #94a3b8; font-size: 0.85rem; }
@media (max-width: 800px) {
.dashboard { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="dashboard" id="dashboard">
<!-- Карточка ошибок -->
<div class="card">
<h3>🔴 Ошибки (error)</h3>
<div class="stat-number" id="errorCount">--</div>
<div class="stat-label">за последние 200 строк</div>
</div>
<!-- Карточка предупреждений -->
<div class="card">
<h3>🟡 Предупреждения (warning)</h3>
<div class="stat-number" id="warningCount">--</div>
<div class="stat-label">за последние 200 строк</div>
</div>
<!-- Карточка офлайн-устройств -->
<div class="card">
<h3>📡 Офлайн устройства</h3>
<div class="stat-number" id="offlineCount">--</div>
<div class="stat-label">не отвечают</div>
</div>
<!-- Анализ нейросети (полная ширина) -->
<div class="card card-full">
<h3>🧠 Анализ нейросети (Qwen 2.5)</h3>
<div class="ai-response" id="aiAnalysis">
⏳ Ожидание данных...
</div>
<div style="margin-top: 0.8rem; font-size: 0.85rem; color: #64748b;">
Последнее обновление: <span id="updateTime">--</span>
</div>
</div>
<!-- Устройства (пример) -->
<div class="card card-full">
<h3>🔌 Состояние устройств Zigbee</h3>
<div class="device-grid" id="deviceGrid">
<div class="device-item"><span>Датчик двери (спальня)</span> <span class="badge-ok">Онлайн</span></div>
<div class="device-item"><span>Датчик движения (кухня)</span> <span class="badge-ok">Онлайн</span></div>
<div class="device-item"><span>Умная розетка (гостиная)</span> <span class="badge-warning">Нестабильно</span></div>
<div class="device-item"><span>Датчик температуры (ванна)</span> <span class="badge-error">Офлайн</span></div>
</div>
</div>
</div>
<div class="footer">
🤖 Локальная нейросеть Qwen 2.5 7B · Обновление каждые 30 секунд
</div>
<script>
// Обновление панели через AJAX
async function updateDashboard() {
try {
const response = await fetch('stats.json?t=' + Date.now());
const data = await response.json();
document.getElementById('errorCount').textContent = data.stats?.error || 0;
document.getElementById('warningCount').textContent = data.stats?.warning || 0;
document.getElementById('offlineCount').textContent = data.stats?.offline || 0;
// Если есть анализ от нейросети (кэшируется в файле)
const aiResponse = await fetch('ai_result.json?t=' + Date.now()).catch(() => null);
if (aiResponse && aiResponse.ok) {
const aiData = await aiResponse.json();
if (aiData.analysis) {
document.getElementById('aiAnalysis').textContent = aiData.analysis;
}
}
document.getElementById('updateTime').textContent = new Date().toLocaleTimeString();
} catch (e) {
console.warn('Ошибка обновления:', e);
}
}
updateDashboard();
setInterval(updateDashboard, 30000); // каждые 30 секунд
</script>
</body>
</html>
5. Настройка Cron для автоматического анализа
Добавьте задачу в crontab, чтобы логи анализировались каждые 15 минут, а результат сохранялся в JSON для панели.
# Открываем crontab
crontab -e
# Добавляем две задачи:
*/15 * * * * /usr/bin/php /var/www/html/stat_collector.php
*/15 * * * * /usr/bin/php /var/www/html/agent.php > /var/www/html/ai_result.json
🎯 Итог: что у нас получилось
✅ Собрали логи
PHP-скрипт читает последние 200 строк из /var/log/zigbee.log.
✅ Проанализировали нейросетью
Qwen 2.5 выдаёт структурированный ответ с критическими событиями.
✅ Отобразили в панели
HTML-страница с карточками, статистикой и AI-блоком обновляется каждые 30 секунд.
✅ Автоматизировали
Cron запускает анализ каждые 15 минут — вы всегда в курсе.
• Добавить Telegram-бота для уведомлений о критических ошибках
• Настроить анализ истории (тренды ошибок по дням)
• Интегрировать с Home Assistant через REST API
Комментарии
Пока нет комментариев. Будьте первым!