← LLMOps and agent observability: debugging the black box
06 / 07 · 50 min

The feedback loop: traces → eval sets → fixes

The LLMOps data flywheel: picking cases from production traces into datasets, a regression loop with a CI gate, linking prompt versions to traces, and a weekly review process.

Lesson content is currently available in Russian.

What you will learn

  • →Выстраивать цикл «трейсы → кейсы → датасет → эвал → фикс → деплой» как основной процесс качества.
  • →Отбирать и стратифицировать кейсы из продакшена без фикс-оверфита и утечек PII.
  • →Связывать версии промптов с трейсами и закрывать релизы CI-гейтом и канарейкой.

Замкнутый цикл: flywheel LLMOps

Линейная модель «написал промпт → потестировал руками → задеплоил → перешёл к следующей задаче» перестаёт работать в первый же месяц продакшена: система живёт в меняющемся мире — трафик дрейфует, провайдер обновляет модели, продукт добавляет фичи. Единственная устойчивая форма — замкнутый цикл: продакшен-трейсы → отбор проблемных и показательных кейсов → пополнение датасетов → эвалы → фикс → деплой → новые трейсы. Каждый оборот делает систему прочнее, потому что выученные ошибки не забываются, а оседают в eval-сете.

Полезная метафора — иммунная система: инцидент, прошедший полный цикл, оставляет «антитело» — регрессионный кейс, который сработает при следующей попытке той же болезни. Инцидент, закрытый быстрой правкой промпта без кейса, не оставляет ничего: через несколько релизов паттерн возвращается, и команда тратит те же часы на ту же диагностику.

Всё, что построено в предыдущих уроках, оказывается инфраструктурой этого цикла: инструментирование (урок 2) создаёт сырьё — трейсы; дашборды (урок 3) и фильтры паттернов (урок 4) показывают, где копать; алёрты (урок 5) запускают оборот не по расписанию, а по событию. Этот урок — про сам оборот: как кейс попадает из трейса в датасет, как датасет охраняет релизы и кто крутит колесо, чтобы оно не остановилось. Скорость оборота — от инцидента до защищающего кейса — и есть реальная метрика зрелости LLMOps в команде.

Отбор кейсов из трейсов в датасет

Источники кейсов, в порядке ценности: трейсы с негативным фидбэком и провалом судьи; находки еженедельного разбора (урок 4); трейсы из новых кластеров дрейфа (урок 5); пограничные успешные прогоны — случаи, где система справилась еле-еле. Механика проста: в Langfuse трейс добавляется в dataset как пара input/expected output, в LangSmith — «add to dataset» прямо из run-а.

Правила, которые отличают рабочий датасет от свалки:

  • Expected output пишет человек. Скопировать плохой продакшен-ответ как эталон — классическая ошибка; из трейса берётся вход и контекст, а ожидание формулируется заново: каким ответ должен был быть;
  • Стратификация против фикс-оверфита. Датасет только из фейлов заставляет оптимизировать промпт под ошибки и терять обычные сценарии; держите 30–50% нормальных кейсов как якорь;
  • Анонимизация до сохранения. Продакшен-вход содержит PII — имена, адреса, номера заказов заменяются реалистичными синтетическими до записи в датасет, который живёт дольше и доступнее трейсов;
  • Метаданные происхождения. У кейса — ссылка на исходный trace_id, категория отказа и дата: без этого через полгода никто не вспомнит, зачем кейс существует и можно ли его менять.

Ориентир темпа: 5–10 осмысленных кейсов в неделю. Через квартал это 100+ кейсов, выросших из реальных отказов вашей системы — такой датасет бьёт любой синтетический бенчмарк по релевантности.

Регрессионный контур и версии промптов

Датасет полезен ровно настолько, насколько регулярно он прогоняется. Контур из трёх частей:

Промпт — это код. Версия в git или в prompt management платформы, code review на изменения, changelog. Главное — метка версии прошивается в атрибуты каждого трейса (prompt_version, release): без неё невозможно связать сдвиг метрик с релизом, и разборы превращаются в гадание «что мы меняли во вторник?».

CI-гейт. PR, меняющий промпт или модель, автоматически гоняет эвал против датасета: быстрый smoke-набор (20–30 кейсов) на каждый PR, полный прогон — ночью. Гейт держит два условия: абсолютный порог (pass rate не ниже X%) и отсутствие регрессии (не хуже текущего main). Инструменты — promptfoo в GitHub Actions, эвалы LangSmith, dataset runs в Langfuse; выбор вторичен, обязательность гейта первична.

Канарейка. Эвал на фиксированном датасете не покрывает живое распределение, поэтому новая версия промпта раскатывается на 5–10% трафика, и online-скоры канарейки (судья, refusal rate, фидбэк из урока 5) сравниваются с контролем несколько часов или дней — в зависимости от объёма. Только после этого 100%.

Так замыкается защита: кейс из инцидента попадает в датасет, датасет охраняет каждый PR, канарейка страхует то, чего в датасете ещё нет. Инцидент, прошедший весь путь, больше не повторяется молча.

Процесс: кто и когда крутит петлю

Техника без процесса останавливается за месяц: датасет перестают пополнять, алёрты мьютят, разбор трейсов «переносится». Минимальный работающий ритуал для команды любого размера состоит из трёх элементов.

Еженедельный час трейсов. Вся команда — включая продакта — читает 20–30 трейсов из подготовленной выборки: негативный фидбэк, провалы судьи, новые кластеры, немного случайных. Формат: каждый читает свою пачку, записывает категории, последние 15 минут — сведение находок в таблицу и решения: какие кейсы — в датасет, какие фиксы — в бэклог. Этот час даёт больше общего понимания системы, чем любые отчёты.

Дежурный по качеству. Ротируемая роль на неделю: триаж алёртов качества, разметка аннотационной очереди, доведение кейсов до датасета. Без явного владельца петля — «общая ответственность», то есть ничья.

Метрики самой петли. Петля тоже нуждается в наблюдаемости: время от инцидента до кейса в eval-сете (цель — дни, не недели); доля фиксов, закрытых с регрессионным кейсом (цель — 100%); прирост датасета за неделю; возраст последнего полного прогона эвалов.

Антипаттерн, который убивает всё, — датасет-кладбище: 400 кейсов, собранных за квартал энтузиазма, ни разу не прогнанных за последний месяц. Датасет жив, только пока стоит в CI-гейте и еженедельном полном прогоне; мёртвый датасет хуже отсутствующего, потому что создаёт иллюзию защиты.

Practice

Один оборот петли

Прокрутите полный оборот на своём агенте: из трейсов уроков 4–5 отберите 10–15 кейсов в датасет (правила: человеческий expected output, 30–50% нормальных кейсов, ссылки на trace_id), настройте прогон эвала против датасета, внесите фикс одного паттерна из урока 4, прогоните эвал до и после и покажите разницу. Пропишите prompt_version в атрибуты трейсов.

Deliverable

Датасет с 10–15 кейсами и метаданными происхождения, два отчёта эвала (до и после фикса) с изменением pass rate и скриншот трейса с прошитым prompt_version.

Checkpoint

Опишите свой оборот петли: путь кейса от продакшен-инцидента до регрессионной защиты в CI.

  • ✓ Назван полный маршрут: трейс → отбор → датасет (с человеческим эталоном и стратификацией) → эвал → фикс → гейт.
  • ✓ Объяснено, зачем prompt_version в трейсах и как CI-гейт сочетается с канарейкой.
  • ✓ Приведены метрики самой петли и антипаттерн датасета-кладбища.

Check yourself

Почему expected output для кейса из плохого трейса пишет человек, а не копируется из ответа?

01Почему expected output для кейса из плохого трейса пишет человек, а не копируется из ответа?

Зачем в датасете держать 30–50% нормальных (успешных) кейсов?

02Зачем в датасете держать 30–50% нормальных (успешных) кейсов?

Зачем прошивать prompt_version в атрибуты каждого трейса?

03Зачем прошивать prompt_version в атрибуты каждого трейса?

Почему CI-гейт на датасете не отменяет канарейку?

04Почему CI-гейт на датасете не отменяет канарейку?

Что такое «датасет-кладбище» и почему он хуже отсутствия датасета?

05Что такое «датасет-кладбище» и почему он хуже отсутствия датасета?

Sources

The feedback loop: traces → eval sets → fixes · LLMOps and agent observability: debugging the black box · VORCL