← Назад к блогу

Окно контекста: как прорубить окно в Европу при работе с промышленными логами

AILLMPythonYandexGPTArchitectureData Processing

Двух- и трёхэтапная подготовка данных, progressive disclosure и техники экономии токенов. Реальные примеры агрегации логов SCADA.AI перед подачей в YandexGPT 5.1.

Проблема в цифрах

Контекстное окно LLM — строгий ресурс. У YandexGPT 5.1 это 32 768 токенов, что эквивалентно ~1500 сырых тегам SCADA за сессию. Промышленные системы генерируют непрерывно:

  • 5 параметров × 1 измерение/мин = 7200 точек/сутки
  • Системный лог: 50 000 — 500 000 строк/сутки
  • Журнал аварий: 100 — 5000 событий/сутки

Данные в 10-100 раз превышают контекст. Попытка скормить сырой лог приводит к обрезке, потере 98% информации и галлюцинациям. Решение: детерминированная подготовка данных до вызова LLM.

Метод 1: Двухэтапная обработка (основной паттерн)

Этап 1: Pre-aggregation (Python)

Агрегируем, фильтруем и структурируем на бэкенде.

async def aggregate_logs_for_llm(limit: int = 500) -> dict:
    raw_logs = await read_log_file(limit)
    
    categories = {
        "critical": [], "warning": [], "info": [], "debug": []
    }
    for entry in raw_logs:
        level = entry.get("level", "info").lower()
        if level in categories:
            categories[level].append({
                "timestamp": entry["timestamp"],
                "message": entry["message"][:200]
            })

    stats = {
        "total_events": len(raw_logs),
        "by_category": {k: len(v) for k, v in categories.items()},
        "time_range": {
            "from": raw_logs[0]["timestamp"] if raw_logs else None,
            "to": raw_logs[-1]["timestamp"] if raw_logs else None
        }
    }

    top_events = {
        "critical": categories["critical"][:20],
        "warning": categories["warning"][:30],
        "info": categories["info"][:10],
        "debug": []
    }

    anomalies = detect_anomalies(raw_logs)
    return {
        "stats": stats, "top_events": top_events, "anomalies": anomalies,
        "raw_sample": raw_logs[:5]
    }

Этап 2: LLM analysis (YandexGPT)

Модель работает только с подготовленной структурой.

async def analyze_with_llm(aggregated_data: dict) -> str:
    prompt = f"""Проанализируй системный лог SCADA.AI.
## Статистика
- Всего событий: {aggregated_data['stats']['total_events']}
- Критических: {aggregated_data['stats']['by_category']['critical']}
- Предупреждений: {aggregated_data['stats']['by_category']['warning']}
- Период: {aggregated_data['stats']['time_range']['from']}{aggregated_data['stats']['time_range']['to']}

## Топ критических событий
{format_events(aggregated_data['top_events']['critical'])}

## Обнаруженные аномалии
{format_anomalies(aggregated_data['anomalies'])}

Дай отчёт в Markdown:
1. ## Общая оценка
2. ## Критические проблемы
3. ## Аномалии и причины
4. ## Рекомендации (3-5 пунктов)
"""
    response = await call_yandexgpt(
        messages=[{"role": "user", "text": prompt}],
        temperature=0.3
    )
    return response.get("text", "Анализ недоступен")

Итог: 500 000 строк → агрегация → ~3000 токенов → качественный отчёт за 3-5 секунд.

Метод 2: Трёхэтапная обработка

Когда агрегация не влезает:

  1. Chunking: разбиваем по 500-1000 записей.
  2. Parallel LLM calls: каждый чанк анализируется отдельно.
  3. Meta-analysis: финальная LLM склеивает мини-отчёты.
async def three_stage_analysis(logs: list, chunk_size: int = 500) -> str:
    chunks = [logs[i:i+chunk_size] for i in range(0, len(logs), chunk_size)]
    mini_reports = await asyncio.gather(*[
        analyze_chunk(chunk, i) for i, chunk in enumerate(chunks)
    ])
    final_prompt = f"""У тебя есть {len(mini_reports)} мини-отчётов.
{chr(10).join([f"## Часть {i+1}{chr(10)}{report}" for i, report in enumerate(mini_reports)])}
Склей в единый отчёт, выдели паттерны, убей дубликаты."""
    return await call_yandexgpt(messages=[{"role": "user", "text": final_prompt}])

Метод 3: Progressive disclosure

Не вываливаем всё сразу. Пользователь углубляется постепенно:

  1. «проанализируй лог» → краткий summary
  2. «расскажи подробнее про критические» → деталь по critical
  3. «что с аномалиями в 14:30?» → deep dive

Tool возвращает available_deep_dives, модель предлагает направление, сохраняя session_id.

Грабли из production-опыта

  1. Сырой лог напрямую → обрезка до 32 768 токенов → потеря 98% → галлюцинации. Решение: агрегация ДО LLM.
  2. Слишком агрессивная агрегация → только статистика, без паттернов. Решение: топ-N событий + поиск аномалий.
  3. Один промпт на всё → модель путается. Решение: чёткая структура с разделами.
  4. Игнор стоимости → 3+ запроса на анализ. Решение: кэш агрегации, двухэтапная схема где возможно.
  5. Модель «забывает» контекст. Решение: сохранять session_id + последние N агрегированных данных.

Техники экономии токенов

ТехникаЭкономияКогда использовать
Обрезать строки до 200 символов30-50%Всегда
Не передавать DEBUG40-60%Если не нужен
Группировать одинаковые события80-90%При повторах
Передавать только delta70-80%Временные ряды
Сокращения в system prompt20-30%Длинные инструкции
Few-shot: 2-3 примера50-70%Строгий формат вывода

Когда какой метод использовать

  • Двухэтапная: стандартный анализ, дашборды, до 500K записей
  • Трёхэтапная: аудит за месяц, архивы, forensic-анализ
  • Progressive disclosure: интерактивные чаты, диагностика в реальном времени

Итог

Контекстное окно — ресурс, который нужно оптимизировать. 80% работы происходит до вызова модели: фильтрация, агрегация, структурирование. Python берёт детерминированную обработку, YandexGPT — интерпретацию.

Соблюдайте границы, кэшируйте результаты и давайте пользователю контроль над глубиной анализа.