Передача дежурства с RAG: собираем хронологию инцидента с источниками
Вечерний дежурный видит длинный чат, несколько графиков и тикет с обновлениями. Ему нужно понять, что произошло с сервисом, что уже пробовали и какое действие остаётся следующим. Краткое резюме LLM экономит чтение только тогда, когда сохраняет порядок событий и позволяет открыть их источники. Иначе новый инженер начнёт повторять уже неудачную проверку.
Для такого ассистента полезно готовить контекст по номеру инцидента. Семантический поиск помогает найти обсуждения похожего симптома, но рабочая передача требует полного журнала выбранного инцидента. Запрос «последние похожие сообщения» может потерять ранний эксперимент, который объясняет текущее решение. Сначала выберите инцидент, затем соберите связанные события из тикета, чата и журнала изменений.
Разделите событие и объяснение
Событие — это наблюдение с временем: «в 09:12 доля ошибок выросла». Гипотеза — объяснение: «возможно, виноват новый пул соединений». Их стоит хранить в разных полях. Даже совпадение релиза и роста ошибок ещё не доказывает причину. В передаче дежурства читатель должен понимать, что подтверждено графиком, а что предложено участником обсуждения.
У каждого события сохраните время самого действия, время поступления в систему и ссылку на исходник. Поздно пересланное сообщение не должно оказаться в конце хронологии как новое действие. Для источников из разных часовых поясов используйте время со смещением. При одинаковом времени стабильный идентификатор обеспечит воспроизводимый порядок.
Соберите пакет передачи
Пример работает с синтетическими событиями и не подключается к системе мониторинга. Он сводит вход из разных каналов, удаляет повтор одного event_id и строит открытые действия по устойчивому action_id. Завершение проверки связывается с началом через ID, а не через похожую формулировку. В конце получаем вход для модели: упорядоченные факты и список незавершённых действий.
Запустите код на Python 3.11 или новее. В реальном адаптере повтор одного ID с другим содержимым нужно отдельно фиксировать как конфликт источников. В примере такая ситуация останавливает сборку. Это удобнее, чем молча выбрать последнюю копию сообщения и спрятать расхождение.
from datetime import datetime
events = [
{"id":"e3", "at":"2026-10-28T12:20:00+03:00", "kind":"done", "action":"a1", "text":"Откат завершён, ошибки сохраняются", "source":"ticket/42#3"},
{"id":"e1", "at":"2026-10-28T09:12:00+00:00", "kind":"observation", "text":"Рост HTTP 503", "source":"metrics/42"},
{"id":"e2", "at":"2026-10-28T12:15:00+03:00", "kind":"start", "action":"a1", "text":"Откат приложения", "source":"ticket/42#2"},
{"id":"e4", "at":"2026-10-28T12:25:00+03:00", "kind":"start", "action":"a2", "text":"Проверить пул соединений", "source":"ticket/42#4"}]
events.append(events[0].copy())
unique = {}
for event in events:
if event["id"] in unique and unique[event["id"]] != event:
raise ValueError("Conflicting event: " + event["id"])
unique[event["id"]] = event
timeline = sorted(unique.values(), key=lambda e: (datetime.fromisoformat(e["at"]), e["id"]))
open_actions = {}
for event in timeline:
if event["kind"] == "start":
open_actions[event["action"]] = event["text"]
elif event["kind"] == "done":
open_actions.pop(event["action"], None)
assert [e["id"] for e in timeline] == ["e1", "e2", "e3", "e4"]
assert open_actions == {"a2":"Проверить пул соединений"}
for e in timeline:
print(e["id"], e["text"], e["source"])
print("OPEN", open_actions)
Передайте модели хронологию с конкретным заданием
Запрос пользователя: «Передаю инцидент 42 следующей смене. Что известно и что делать дальше?» В контекст добавьте timeline и open_actions, полученные скриптом, а также момент сборки. Модель превращает этот пакет в короткую передачу; получившийся текст инженер читает перед сменой.
Составь передачу дежурства по приложенному JSON. Верни sections: observed_state, completed_checks, open_actions. Каждый пункт содержит text и event_ids. Используй только входные события. Гипотезы помечай как гипотезы. Не превращай следующую проверку в установленную причину. Сохрани action_id у незавершённых действий. Если исход неизвестен, так и напиши.
Проверяемые ожидания: упомянут рост HTTP 503, откат отмечен завершённым без устранения ошибок, a2 остаётся открытым. Утверждение «пул соединений вызвал сбой» недопустимо: такого наблюдения во входе нет. Сначала проверьте эти случаи на сохранённом пакете, затем подключайте чтение живых журналов.
Как получить полезный текст передачи
Попросите модель составить три части: текущее наблюдаемое состояние, уже выполненные проверки с результатами и открытые действия. Для каждого факта требуется event_id. Технически неизвестная причина должна остаться неизвестной. В нашем входе нет доказательства, что пул соединений действительно вызвал сбой; есть только следующее действие a2.
Перед показом инженеру приложение проверяет, что все упомянутые ID существуют в пакете. Затем человек сверяет смысл важных утверждений с источниками. Тест «ID существует» ловит выдуманную ссылку, но не утверждение, которое источник не подтверждает. Для допуска пилота полезно вручную разметить несколько реальных передач и проверить, что ни одна незавершённая проверка не исчезла из итогового текста.
Когда обновлять передачу
Сохраняйте границу сборки: например, события до 12:30. Новые сообщения должны порождать новую редакцию пакета. В интерфейсе покажите момент актуальности рядом с резюме. Если откат отменили после сборки, дежурный увидит возраст данных и откроет свежий тикет вместо выполнения устаревшего шага.
Подключите runbook и инструменты дежурного
Когда пакет событий уже собирается, можно добавить поиск по runbook и связать его с текущим состоянием инцидента. На курсе вы соберёте RAG по документам с цитатами, подключите инструменты и перейдёте к явным workflow в LangGraph. Блоки по тайм-аутам, метрикам и стоимости пригодятся, чтобы передача дежурства работала как сервис с API и интерфейсом. Откройте программу платного курса «LangChain 1.0.x: c нуля до продакшн LLM-приложений».
Продолжить на практике
- LangChain 1.0.x: c нуля до продакшн LLM-приложений ↗
Практический курс по LangChain. Соберёте продакшн LLM-бота: RAG по PDF с цитатами, веб-поиск и трекинг заказов, многошаговый агент для анализа CSV и финальное веб-приложение (UI + API). Плюс профессиональные блоки: PromptOps и версионирование промптов, метрики качества RAG, гибридный поиск с реранком, observability/стоимость, надёжность (ретраи, таймауты), guardrails и отдельный модуль по LangGraph для устойчивых workflow. P.S. Полностью обновили материалы на актуальную версию LangChain
