7 760 статей
arXiv:2611.02416 84 2 нояб. 2026 г. FREE

Historical Frequency Profiling (EOB): защита LLM от ложных тревог при поиске причин сбоев

КЛЮЧЕВАЯ СУТЬ
Обнаружено: при разборе аварий LLM слепо обвиняет тот сервис, у которого в логах самая большая цифра выброса, даже если секунду назад по графу доказала вину другого узла. Метод Historical Frequency Profiling позволяет находить реальную первопричину сбоя по логам и метрикам без ложных тревог на фоновый шум. Фишка: к каждой аномалии дописывается базовая частота шума в норме (r%), а в примерах промпта реальные имена сервисов скрываются под масками.
Адаптировать под запрос
⚡

TL;DR

Historical Frequency Profiling (профилирование исторической частоты) — техника подготовки данных и промпта для диагностики инцидентов, которая добавляет к каждому аномальному сигналу его базовую частоту срабатывания в штатном режиме (Expected Outlier Baseline, r). Вместо того чтобы скармливать модели голые пики метрик и ошибки из логов, метод показывает, как часто этот же сигнал «фонит», когда система полностью здорова.

Когда в системе случается сбой, нейросеть видит десятки алертов и почти всегда обвиняет тот сервис, у которого самая большая цифра отклонения в метриках, даже если абзацем выше в собственных рассуждениях доказала, что проблема пришла от другого узла по цепочке вызовов. Причина в слепоте к базовой норме: фоновые процессы (например, плановая очистка памяти или пересчёт кэша) постоянно дают резкие скачки и ключевые слова error в логах. Без пометки о том, что для конкретного сервиса такой всплеск — обычная рутина, модель путает громкий фоновый шум с первопричиной аварии.

Метод решает проблему в два шага на уровне данных и промпта: сначала считает статистику отклонений по длительному безаварийному периоду (а не за пять минут до сбоя), а затем дописывает к каждой метрике и строке лога в промпте процент r — в скольких процентах спокойных окон этот сигнал тоже пробивал порог. Дополнительно при использовании обучающих few-shot примеров (примеров правильного разбора в промпте) из них маскируют реальные названия сервисов, чтобы модель перенимала логику проверки графа зависимостей, а не копировала имя виновника из образца.


🔬

Схема метода

ШАГ 1 (Офлайн / подготовка данных): Замер метрик, логов и трейсов в спокойные периоды → расчёт базовой частоты шума r (%) для каждого сигнала
ШАГ 2 (В промпте инцидента): Подача аномалий в формате [Сервис / Сигнал · отклонение z · частота в норме r%] + граф зависимостей → диагноз по редким в норме сигналам и цепочке вызовов
ШАГ 3 (Если в промпте есть few-shot пример): Замена реальных имён сервисов в примере на нейтральные маски (Service_A, Service_B) → защита от слепого копирования ответа

Шаги 2 и 3 выполняются внутри одного промпта при разборе инцидента; шаг 1 рассчитывается заранее по историческим логам или мониторингу.


🚀

Пример применения

Задача: В финтех-сервисе оплаты заказов (аналог СБП-шлюза и корзины в крупном российском маркетплейсе) в пятницу вечером начали отваливаться платежи. Дежурный инженер собирает выгрузку из мониторинга (Prometheus/Grafana и логи) и отдаёт LLM-ассистенту, чтобы быстро найти виновный микросервис и не перезапускать вслепую здоровые узлы.

Промпт:

Ты — инженер диагностики распределённых систем. В кластере оформления заказов маркетплейса произошёл сбой в окне 19:00–19:30. Найди компонент-первопричину (root cause) и тип сбоя.

Граф вызовов (кто кого вызывает):
Frontend → Checkout → [CartService, PaymentGateway, BonusEngine]
CartService → RedisCluster
BonusEngine → PostgresLoyalty

Аномальные сигналы в окне инцидента (z — сила выброса в сигмах, r — как часто этот сигнал превышает порог в спокойные дни без сбоев):

Метрики:
- BonusEngine / jvm_heap_used: z = 28.4 · r = 94.0%
- BonusEngine / gc_pause_ms: z = 19.1 · r = 89.5%
- PaymentGateway / upstream_timeout_rate: z = 14.2 · r = 0.2%
- Checkout / http_5xx_count: z = 31.0 · r = 0.4%

Логи:
- BonusEngine ×14: "[GC (Allocation Failure) PSYoungGen]" · r = 86.0%
- PaymentGateway ×4: "Connection pool exhausted while waiting for acquirer socket" · r = 0.0%
- Checkout ×22: "Upstream request failed: PaymentGateway timeout" · r = 0.3%

Трейсы:
- PaymentGateway: latency ×8.4 vs normal
- Checkout: latency ×7.9 vs normal
- BonusEngine: latency ×1.1 vs normal

Инструкция разбора:
1. Отсей сигналы с высокой базовой частотой в норме (r > 20%) — это рутинный фоновый шум компонента, даже если у них огромный z.
2. По графу вызовов проследи направление распространения ошибки от нижних сервисов к верхним (от вызываемого к вызывающему).
3. Перед финальным ответом проверь: совпадает ли выбранный компонент с самой нижней точкой зарождения редкой аномалии в графе вызовов, и не приписал ли ты ему метрику соседнего сервиса.

Результат: Модель не поведётся на огромные значения z = 28.4 и 14 записей Allocation Failure у сервиса BonusEngine, потому что увидит метку r = 86–94% (штатная сборка мусора). Далее по графу вызовов она свяжет ошибки Checkout (z = 31.0) с таймаутами нижестоящего PaymentGateway (r = 0.0% в логах и рост задержки в 8.4 раза) и точно назовёт первопричиной исчерпание пула соединений в PaymentGateway, не противореча собственному разбору цепочки зависимостей.


🧠

Почему это работает

У языковых моделей — особенно компактных, которые компании разворачивают локально ради приватности логов — есть сильное смещение к самым громким числам. Даже когда модель в блоке рассуждений (Chain-of-Thought) правильно выписывает граф зависимостей и замечает, что сбой идёт снизу вверх от базы данных или шлюза, в финальной строчке ответа она всё равно срывается и называет тот сервис, у которого в промпте написано самое большое число z или больше всего строк со словом error.

При этом сама модель отлично умеет сопоставлять контекст редкости события и причинно-следственные связи в графе, если дать ей точку отсчёта. Когда рядом с грозным выбросом z = 30 явно написано r = 97% (сигнал шумит почти в каждом десятом окне без всяких аварий), числовой якорь теряет свою магическую силу. Модель переключает внимание на сигналы, где r близок к нулю — то есть на события, которые действительно случаются только во время аварий.

Второй критический механизм связан с тем, как LLM используют few-shot примеры (образцы прошлых разборов) в промпте. Вместо того чтобы копировать алгоритм рассуждений, модель часто цепляется за конкретные названия сервисов из примера и вставляет их в ответ к новому инциденту. Маскирование имён компонентов в обучающем примере (Component_A, Component_B) убирает этот соблазн и заставляет модель опираться только на структуру анализа.

Рычаги управления промптом: - Окно расчёта базовой нормы (r) → считай среднее и разброс по нескольким дням штатной работы, а не за 5 минут до аварии (короткое окно не захватывает периодические циклы вроде очистки памяти и даёт сплошные ложные срабатывания). - Имена в few-shot примерах → всегда заменяй реальные названия таблиц, подов и сервисов в примерах промпта на абстрактные метки (Node_1, Service_X), иначе модель будет угадывать старого виновника. - Финальная сверка с графом → требуй от модели явно выписать цепочку Источник → Жертва перед словом Ответ:, чтобы заблокировать скачок к максимальному z в последней строке.


📋

Шаблон промпта

Контекст системы: в системе {название_системы} зафиксирован инцидент в интервале {окно_времени}.
Задача: определить компонент-первопричину, тип сбоя и время начала.

Граф зависимостей компонентов:
{граф_вызовов}

Аномальные сигналы в окне инцидента (z — отклонение от нормы, r — доля безаварийных окон, в которых сигнал также превышает порог):

[Метрики]
{список_метрик_с_z_и_r}

[Логи]
{список_логов_с_количеством_и_r}

[Трейсы]
{список_трейсов_с_кратностью_задержки_к_норме}

Пример правильного хода рассуждений (имена компонентов замаскированы):
- Кандидат Service_A имеет высокий z, но r > 80% — это рутинное колебание в штатном режиме.
- Кандидат Service_B зависит от Service_C. У обоих редкие аномалии (r < 2%), но по графу вызовов сбой в Service_C вызывает каскадную задержку в Service_B.
- Вывод: первопричина — Service_C.

Выполни диагностику строго по шагам:
1. Раздели кандидатов на фоновый шум (высокий r) и реальные улики сбоя (низкий r).
2. Проанализируй распространение сбоя по графу зависимостей среди кандидатов с низким r.
3. Проверь, что все названные тобой метрики действительно принадлежат выбранному компоненту, а финальный ответ совпадает с корнем цепочки распространения.

Что подставлять в плейсхолдеры: - {название_системы} и {окно_времени} — контур и таймслот аварии. - {граф_вызовов} — список связей вида Сервис А → Сервис Б. - {список_метрик_с_z_и_r}, {список_логов_с_количеством_и_r}, {список_трейсов_с_кратностью_задержки_к_норме} — отфильтрованные сигналы с добавленной исторической частотой r в спокойные периоды.

🚀 Быстрый старт — вставь в чат:

Вот шаблон Historical Frequency Profiling для поиска первопричины сбоя по логам и метрикам. Адаптируй под мою задачу: [твоя задача]. 
Задавай вопросы, чтобы заполнить поля.

[вставить шаблон выше]

LLM спросит, какие компоненты входят в твою систему, кто кого вызывает и какие метрики у тебя обычно «фонят» по расписанию (кроны, бэкапы, сборка мусора) — потому что без разделения штатных периодических пиков и редких аномалий модель выберет самый шумный сервис вместо реального источника аварии.


⚠️

Ограничения

⚠️ Необходимость предрасчёта базовой статистики: Промпт не узнает сам, как ведёт себя система без аварий. Чтобы передать параметр r и кратность задержки трейсов к норме, нужно заранее посчитать статистику срабатываний алертов на архивных безаварийных окнах.

⚠️ Потолок обычного промптинга на малых моделях: На компактных локальных моделях (около 4B параметров) одно лишь добавление инструкций и контекста в промпт не убирает до конца привычку выбирать максимальный z-балл вопреки собственному анализу графа. В исследовании для полного устранения этого разрыва потребовалось дополнительное обучение модели методом Biased-Decision Correction (DPO) на парах её собственных ответов, где начало рассуждений совпадало, а финальный вердикт расходился.

⚠️ Уязвимость к неmasked few-shot примерам: Если вставить в промпт реальный пример прошлого постмортема с настоящими названиями сервисов, а новая авария произошла в другом узле, точность диагностики резко падает (ниже, чем вообще без примера), так как модель начинает копировать имя старого виновника.


🔍

Как исследовали

Команда из университета Ханьян (Южная Корея) решила выяснить, почему локальные малые модели (SLM до 20B параметров вроде Qwen3-4B и Gemma 3) на задачах диагностики микросервисов OpenRCA выдают точность полного совпадения меньше 4%, а флагманы вроде Claude Opus 5 и GPT-5.6 Sol — около 10.5–10.6% (при стоимости до \$42 за 1000 инцидентов). Сначала авторы проверили сам входной промпт на банковском датасете Bank (10 дней телеметрии, 136 инцидентов) и обнаружили поразительный факт: из-за того, что стандартные системы считают норму по коротким 5-минутным окнам перед аварией, плановая сборка мусора JVM в Tomcat01 пробивает порог $3\sigma$ в 97% абсолютно здоровых окон, GC-логи помечаются как ошибки в 82–87% здоровых окон, а трейсы IG01/IG02 — в 97–98%. В результате настоящий виновник аварии присутствует среди кандидатов в 99% случаев, но имеет максимальный балл аномалии всего в 8% инцидентов! Переход на расчёт среднего и дисперсии по всему безаварийному периоду сразу снизил долю ложных тревог по памяти JVM с 97% до 4%.

Затем исследователи собрали 640 траекторий рассуждений модели Qwen3-4B (по 8 на каждый из 80 инцидентов) и разметили их с помощью двух независимых судей на базе Claude Opus 5. Оказалось, что в 100% случаев модель честно проверяет несколько кандидатов и анализирует граф распространения сбоя, но при выборе финального ответа в 76% траекторий ссылается просто на большой балл аномалии, в 68% случаев противоречит собственному выводу о распространении сбоя, а в 66% — приписывает выбранному сервису чужую метрику! Когда в промпт добавили эталонный few-shot разбор от DeepSeek-R1, вскрылась ещё одна ловушка: если в примере был тот же виновник, точность Top-1 взлетала с 16% до 56%, но если виновник в примере отличался, точность проваливалась с 16% до 9%, потому что в 44% ответов модель тупо копировала имя сервиса из примера (а при маскировании имён в примере точность честно росла до 21%). Объединив профилирование частоты в норме (Historical Frequency Profiling) и дообучение на точках ветвления решений (Biased-Decision Correction через DPO), авторы подняли точность 4B-модели на датасете Bank до 48.7% против 18.5% у 14-миллиардной OpsAgent-14B и обошли конкурентов на 8 датасетах (включая перенос на новые системы без переобучения).


💡

Адаптации и экстраполяции

🔧 Техника: Пометка базовой частоты r% в бизнес-аналитике и мониторинге рекламы → защита от паники на регулярных колебаниях

Приём Expected Outlier Baseline отлично переносится из DevOps в регулярные промпты для анализа продаж, рекламных кабинетов (Яндекс.Директ, VK Реклама) или продуктовых воронок. Если подавать LLM таблицу с падением конверсии или ростом CPA, добавляй к каждой метрике колонку Доля таких отклонений в обычные дни (r%):

Кампания: Ретаргетинг_Корзина | Рост CPA за час: +45% (z = 3.4) | Частота таких скачков в обычные дни: r = 78% (каждый вечер после 22:00)
Кампания: Поиск_Бренд | Падение CTR за час: -38% (z = 4.1) | Частота таких скачков в обычные дни: r = 0.5%

Это мгновенно отучает модель бить тревогу из-за суточной сезонности и фокусирует разбор на реальных поломках (например, слетевшей посадочной странице).


🔗

Ресурсы

[Fault-Free Profiles and Decision-Level Training for Root Cause Analysis via Small Language Models] [arXiv:2611.02416v2, OpenRCA benchmark] [Kyoohyun Lee, Woohyeok Park, Taeyoon Kim, Sungyong Baik, Kyungyong Lee — Hanyang University, Republic of Korea]


📋 Дайджест исследования

Ключевая суть

Обнаружено: при разборе аварий LLM слепо обвиняет тот сервис, у которого в логах самая большая цифра выброса, даже если секунду назад по графу доказала вину другого узла. Метод Historical Frequency Profiling позволяет находить реальную первопричину сбоя по логам и метрикам без ложных тревог на фоновый шум. Фишка: к каждой аномалии дописывается базовая частота шума в норме (r%), а в примерах промпта реальные имена сервисов скрываются под масками.

Принцип работы

Фоновые задачи вроде очистки памяти или сборки мусора постоянно дают дикие скачки метрик в полностью здоровой системе. Без ориентира модель ведётся на самую громкую цифру как сорока на блестящее. Добавь к силе выброса z процент r — как часто сигнал шумит в спокойные дни. Когда рядом с грозным выбросом z = 28.4 написано r = 94%, магия большой цифры пропадает. Модель отсеивает рутину и ищет узлы, где r близок к нулю.

Почему работает

Даже когда компактная модель правильно строит цепочку вызовов в рассуждениях, в последней строчке ответа её срывает на максимальное число z в промпте. А если дать в промпте пример прошлого разбора с реальными именами микросервисов, точность падает ещё ниже: модель тупо копирует имя старого виновника. Связка метки частоты r по безаварийным дням и маскирования имён (Service_A) убирает оба перекоса и заставляет идти строго по графу зависимостей.

Когда применять

Диагностика сбоев и DevOps → конкретно для поиска первопричины аварий (Root Cause Analysis) по метрикам, логам и трейсам, особенно когда в кластере десятки микросервисов с шумными фоновыми задачами по расписанию. НЕ подходит без предварительного замера архивной статистики за несколько спокойных дней (пятиминутного окна до сбоя мало).

Мини-рецепт

1. Посчитай норму заранее: по архиву безаварийных дней вычисли r% — в какой доле спокойных окон каждый сигнал пробивал порог.
2. Подай сигналы парой: в промпте инцидента пиши метрики и логи в формате Сервис / Сигнал: z = 28.4 · r = 94.0%.
3. Замаскируй примеры: в образцах разбора (few-shot) замени все реальные имена узлов на Service_A, Service_B, Service_C.
4. Введи фильтр шума: первым шагом прикажи отсеять кандидатов с высоким r (например, выше 20%) как штатную рутину.
5. Заблокируй срыв в финале: потребуй перед ответом выписать цепочку Источник → Жертва по графу вызовов среди узлов с низким r.

Примеры

[ПЛОХО] : Найди причину сбоя по метрикам: BonusEngine jvm_heap z=28.4, PaymentGateway timeout z=14.2, Checkout 5xx z=31.0
[ХОРОШО] : Граф: Checkout -> [PaymentGateway, BonusEngine]. Сигналы (z — выброс, r — частота в спокойные дни): BonusEngine jvm_heap z=28.4 · r=94.0%; PaymentGateway timeout z=14.2 · r=0.2%; Checkout 5xx z=31.0 · r=0.4%. 1) Отсей шум с r>20%. 2) Найди корень сбоя с низким r по графу вызовов.
Источник: Fault-Free Profiles and Decision-Level Training for Root Cause Analysis via Small Language Models
ArXiv ID: 2611.02416 | Сгенерировано: 2026-11-09 08:52

Проблемы LLM

ПроблемаСутьКак обойти
Модель выбирает виновником сбоя самый шумный компонент вопреки собственной логикеПодаёшь в промпт метрики и логи аварии вместе с графом вызовов сервисов. Модель в рассуждениях верно находит источник проблемы внизу цепочки. Но в финальной строке ответа срывается и называет сервис с самым большим числом отклонения или числом ошибокДопиши к каждой метрике и строке лога процент её срабатывания в спокойные дни (r%). В инструкции потребуй отсеять сигналы с частым фоновым шумом (r > 20%) и сверить ответ с корнем графа вызовов
Модель копирует имя виновника из примера в промпте вместо логики разбораДобавляешь в промпт образец разбора прошлой аварии с настоящими именами сервисов. Когда случается сбой в другом узле, модель цепляется за знакомое имя из примера. Точность падает ниже, чем вообще без примераЗамени все реальные названия сервисов, таблиц и узлов в примерах промпта на нейтральные маски (Service_A, Service_B). Тогда модель перенимает только схему проверки зависимостей

Методы

МетодСуть
Добавление базовой частоты фонового шума к метрикам в промптеЗаранее посчитай по архиву спокойных дней, как часто каждый сигнал пробивает порог без всяких аварий (r%). В промпте подавай каждую аномалию в связке: [Сервис / Сигнал · сила выброса z · частота в норме r%]. Потребуй сначала отбросить привычный шум (r > 20%), а затем искать первопричину по графу вызовов среди редких сигналов (r < 2%). Почему работает: без точки отсчёта крупное число выброса притягивает внимание модели сильнее причинно-следственных связей. Явная пометка r = 90% гасит ложный числовой якорь. Когда применять: поиск причин аварий, анализ логов, мониторинг и разбор алертов. Когда не работает: нет архива штатной работы для расчёта базовой частоты
Маскирование имён компонентов в обучающих примерах промптаВ блоке примеров правильного разбора замени все настоящие имена сервисов на абстрактные метки (Component_A, Component_B). В конце инструкции добавь обязательный шаг: выписать цепочку Источник -> Жертва перед финальным ответом. Почему работает: модель перестаёт угадывать ответ по знакомым словам из образца и вынуждена следовать структуре графа зависимостей. Когда применять: любые промпты с примерами для диагностики, классификации узлов и поиска виновника в связанных системах. Когда не работает: пример не содержит названий конкретных объектов

Тезисы

ТезисКомментарий
Показатель редкости события перебивает слепую тягу модели к большим числамУ моделей (особенно малых) есть сильное смещение к максимальным цифрам в тексте. Если сервис регулярно даёт резкие скачки из-за фоновой очистки памяти, модель всегда обвинит его. Но если рядом с огромным пиком указать, что в норме он случается в 90% окон, модель легко переключается на действительно редкие сбои. Применяй: рядом с любой резкой метрикой в запросе пиши её обычную частоту в штатном режиме
Настоящие имена объектов в примерах промпта ломают диагностику новых случаевКогда в промпте есть пример с реальными названиями элементов системы, модель запоминает само название как правильный ответ. На новой задаче она подставляет старого виновника. Обезличивание имён в примере полностью убирает эту привязку. Применяй: всегда заменяй реальные имена в примерах промпта на Объект_1, Объект_2
📖 Простыми словами

Fault-Free Profiles and Decision-Level Training for Root Cause Analysis via SmallLanguageModels

arXiv: 2611.02416

Диагностика сбоев в IT через нейронки сейчас работает криво, потому что модели ведут себя как паникёры. Когда в системе что-то ломается, мониторинг вываливает кучу ошибок, и маленькие локальные LLM просто срываются на самый громкий крик. Если у одного сервиса в логах сто ошибок, а у другого — пять, модель ткнет пальцем в первый, даже если эти сто ошибок для него — нормальный ежедневный фон, а те пять у второго — признак того, что база данных сейчас сгорит. Исследователи предложили лечить это через Historical Frequency Profiling: теперь мы даем модели не просто список аномалий, а контекст того, как часто эта фигня происходит, когда всё работает нормально.

Это как если бы ты пришел к врачу с жалобой на пульс 100 ударов в минуту. Обычная модель сразу закричит: «О боже, у него тахикардия, срочно в реанимацию!». Но метод Expected Outlier Baseline добавляет важную деталь: этот парень — марафонец, и для него пульс 100 во время легкой пробежки — это вообще норма. Без понимания того, что является базовым шумом системы, нейронка превращается в бесполезного дежурного, который при любом шорохе жмет на красную кнопку и перезагружает всё подряд, лишь бы не разбираться.

В реальности это работает так: к каждому сигналу об ошибке приклеивается коэффициент r — частота, с которой этот баг вылезает «на холодную». Если в твоем платежном шлюзе в пятницу вечером всегда летит 500 тайм-аутов из-за нагрузки, модель увидит это в профиле и не будет делать из этого трагедию. Вместо этого она сфокусируется на реальной аномалии, которая раньше тонула в общем потоке. Метод заставляет модель сравнивать текущий хаос с «идеальным» состоянием системы, отсекая мусор на уровне логики, а не просто считая количество строк со словом error.

Тестировали это на микросервисах, но принцип универсален для любого анализа данных, где есть шум. Будь то мониторинг завода, финтех-транзакции или даже анализ рекламных кампаний — везде, где нужно отличить «штатный облом» от катастрофы. SEO для логов уходит в прошлое, теперь мы учим модели понимать контекст через сравнение с нормой. Это позволяет использовать маленькие и дешевые модели там, где раньше лажали даже гиганты вроде GPT-4, потому что дело не в размере мозгов, а в правильной подаче фактов.

Короче, хватит кормить нейронки голыми цифрами и ждать чуда. Если не давать модели базовый уровень шума, она всегда будет ошибаться в пользу самого «яркого» события, а не самого важного. Внедрение Decision-Level Training и профилей нормального состояния превращает бестолковую читалку логов в адекватного инженера. Либо ты учишь модель отличать фон от сигнала, либо продолжаешь чинить то, что не ломалось, пока реальная причина сбоя добивает твой бизнес.

Работа с исследованием

Адаптируйте исследование под ваши задачи или создайте готовый промпт на основе техник из исследования.

0 / 2000
~0.5-2 N-токенов ~10-30с
~0.3-1 N-токенов ~5-15с