Автор: Александр Летуновский, Место работы — руководитель центра, Сбербанк страхование. Выпускник курса «Natural Language Processing»
Проблематика
Крупные организации сталкиваются с большим числом ИТ-инцидентов: иногда – с тысячами в месяц. Инциденты нередко повторяются, однако найти похожий случай в базе знаний или в системе регистрации непросто: стандартный поиск по ключевым словам часто неэффективен, а помнить детали всех инцидентов невозможно.
Здесь и возникает проблема: при поступлении нового инцидента инженеру трудно выяснить, был ли подобный инцидент раньше, и как его разрешили. Многие знания рассеиваются по прошлым тикетам и не используются вновь. В лучшем случае на помощь приходит опытный коллега, который вдруг вспоминает: «Да, в прошлом месяце у нас уже было нечто подобное по такой-то причине».
Эта ситуация натолкнула меня на мысль о создании системы, которая выступила бы искусственной «памятью» ИТ-команды: мгновенно просматривала бы все предыдущие инциденты и находила релевантную информацию в нужное время. Я хотел, чтобы при разборе нового инцидента система играла роль опытного инженера, видевшего все предыдущие проблемы, и подсказывала возможное решение.
Цель работы
Цель проекта – автоматизировать сопоставление новых инцидентов с решёнными ранее и предоставлять инженерам рекомендации по решению в виде комментария в тикете.
Я задался целью разработать помощника, который при каждом новом инциденте будет искать в базе знаний несколько самых похожих случаев и на основе описаний решений подсказывать причины проблемы и давать советы по способам её устранения. Такой подход, совмещающий поиск по базе знаний с генерацией текста, известен как «Retrieval-Augmented Generation» (RAG) – генерирация ответа с дополнением из внешней базы знаний.
Схема RAG
Мне предстояло реализовать минимально жизнеспособный прототип (MVP) и интегрировать его в промышленную среду системы Service Desk. Основные критерии успеха – ускорение анализа инцидентов (уменьшение времени на поиск решения) и увеличение частоты использования накопленных знаний об инцидентах.
Ограничения и особенности внедрения
Проект развёрнут и эксплуатируется в условиях существенных ограничений инфраструктуры.
I. Среда полностью офлайн. У меня не было возможности воспользоваться облачными сервисами вроде OpenAI API или управляемыми векторными базами. Ни база инцидентов, ни сервис генерации не имеют доступа к интернету или облачным API: все компоненты от моделей до баз данных должны быть размещены локально. Из-за офлайн-режима сложными вопросами становятся обновления и поддержки. Все обновления моделей (как эмбеддинг модели, так и LLM) требуют отдельной процедуры загрузки моделей в контур. Тем не менее, подобный автономный режим – частая ситуация в корпоративных внедрениях. И, как выяснилось позже, даже без доступа к облачным мощностям можно эффективно применять методы NLP на локальных ресурсах.
II. Отсутствие производительных графических процессоров (GPU) на этапе MVP. Сервер, на котором разворачивается решение, оснащён только CPU. Это повлияло на выбор моделей и инструментов: предпочтение отдавалось легковесным и оптимизированным вариантам.
Ход работы
Для решения поставленной задачи я спроектировал архитектуру RAG-агента. Архитектура включала в себя:
- интеграцию с системой Service Desk
- векторную базу данных для знаний об инцидентах
- использование большой языковой модели (LLM) для генерации подсказок.
Агент был реализован на Python. Ниже привожу схему логики работы разработанного агента.
Схема решения
Как показано на схеме, процесс состоит из семи шагов:
-
Получение инцидента: агент отслеживает появление нового инцидента в системе Service Desk и через API выгружает его описание в текстовом формате: HTML-разметка очищается до простого текста.
-
Дополнение описания: чтобы уточнить проблему, исходное описание инцидента при необходимости автоматически дополняется или переформулируется с помощью большой языковой модели. Например, извлечь ключевые симптомы, дополнить короткое описание, удалить лишние детали из описания.
-
Векторизация описания: текст инцидента (как в оригинале, так и переформулированный вариант) преобразуется в векторное представление – embedding – при помощи модели эмбеддинга.
-
Поиск похожих инцидентов: полученный вектор сравнивается с векторами ранее решённых инцидентов, хранящимися в векторной базе данных, с использованием метрики косинусного расстояния. В результате извлекаются несколько наиболее похожих описаний из базы (топ-5 по оригинальному тексту и топ-5 по переформулированному).
-
Генерация рекомендаций: собранная информация подаётся на вход большой языковой модели – формируется запрос (prompt), содержащий описание новой проблемы и сведения о найденных похожих инцидентах (описания и решения). LLM анализирует этот контекст и генерирует рекомендацию – комментарий с предположением причины проблемы и советом по её решению.
-
Обновление базы знаний: векторное представление нового инцидента сохраняется в векторной базе (вместе с текстом описания и решения после закрытия инцидента) для использования в будущем.
-
Публикация решения: сгенерированная LMM рекомендация и список ссылок на похожие инциденты автоматически отправляются в систему Service Desk в виде комментария к соответствующему тикету, где его видят инженеры.
Далее рассмотрены ключевые компоненты этой системы и принятые решения при её реализации.
Извлечение текста инцидентов из HTML
Первым шагом стало подключение к системе управления инцидентами (Service Desk) и извлечение необходимых данных. Интеграция реализована через REST API: агент периодически опрашивает систему на наличие новых тикетов или получает уведомление о них. Для каждого нового инцидента с помощью API вытягивается текст поля «Описание» (Description). Поскольку в Service Desk описания хранятся с разметкой HTML, этот контент приводится к простому тексту: удаляются HTML-теги, лишние символы, приводятся в порядок списки и форматирование. Разбор HTML выполняется с помощью библиотеки парсинга BeautifulSoup4. В результате на выходе получается связный текст, пригодный для последующей обработки.
Пример кода для очистки HTML от лишней информации:
def clean_html(html_content):
«»»Remove HTML tags from the content.»»»
if html_content is None:
return None
soup = BeautifulSoup(html_content, ‘html.parser’)
return soup.get_text(strip=True)
При извлечении текста описания агент также может получить связанные с инцидентом данные, например дату и время создания инцидента, категорию проблемы, затронутый сервис или компоненты. Эти сведения в текущей версии напрямую не используются для поиска, но в будущем могут помочь фильтровать результаты (например, ограничивать поиск схожих инцидентов тем же сервисом или близким временем). Пока же основным источником информации для поиска выступает текстовое описание симптомов инцидента.
Векторизация описаний инцидентов
Когда от нового инцидента получен текст описания, следующей задачей становится получение его векторного представления (embedding). Векторное представление – это набор чисел (координат векторов в многомерном пространстве), которые отражают смысл текста. Современные трансформерные модели способны превращать фразу или документ в такой числовой «отпечаток», близкий для похожих по содержанию текстов и далекий для непохожих. Иными словами, если два описания инцидентов описывают схожие проблемы, их векторы будут расположены близко друг к другу в пространстве; если же тематика разная – векторы будут далеко друг от друга. Важное свойство эмбеддингов (в отличие от простых хеш-функций) состоит в том, что концептуально схожий ввод приводит к близким векторным значениям, даже если тексты формально не совпадают по словам. Благодаря этому можно сравнивать семантическое сходство. То есть алгоритм обучается сравнивать «яблоки и апельсины» по смыслу, а не по буквальному совпадению.
Для вычисления степени близости векторов используется метрика косинусного расстояния (cosine similarity). Эта метрика возвращает значение от 0 до 1, отражающее степень сходства, и широко применяется для ранжирования похожести текстов. Чем меньше значение метрики, тем ближе по смыслу тексты.
Выбор модели эмбеддинга. В проекте были протестированы несколько предобученных моделей для векторизации текстов инцидентов. Основными критериями выбора были: качество семантического соответствия для русскоязычных и англоязычных текстов (другие языки не требовались), производительность и возможность локального запуска.
Среди протестированных моделей были:
-
all-MiniLM-L6-v2: компактная модель размерности 384, давала хорошую скорость, но уступала по качеству: в исторических данных пропускала релевантные случаи или ранжировала их ниже;
-
LaBSE-en-ru: «урезанная» модель от Google с размерностью вектора 768, содержащая только токены русского и английского языков. Модель очень хорошо справлялась с текстами инцидентов;
-
ru-en-RoSBERTa: русско-английская модель с размерностью векторов 1024, специально дообученная для работы с двуязычными текстами.
По итогам экспериментов победителем по качеству поиска схожих инцидентов стала модель ru-en-RoSBERTa: она показала наилучшее ранжирование и точность сопоставления, особенно при анализе инцидентов, содержащих технические термины, коды ошибок и смешанную лексику. В частности, она лучше других справлялась с короткими описаниями и контекстами без явных ключевых слов.
Использование модели для получения эмбеддингов текста. Пример кода:
# Загрузка модели
model = SentenceTransformer(‘ru-en-RoSBERTa’)
# Векторизация текста
vectors_description = model.encode(df[‘description’].tolist())
Переформулировка описаний с LLM. Особенностью подхода стало использование большой языковой модели (LLM) для улучшения качества векторизации. Как было сказано выше, иногда описания инцидентов бывают скудными или неочевидными, или наоборот слишком длинными. Например, тикет может содержать лишь фразу «Приложение не работает» или фрагмент лога, не коррелирующий напрямую с настоящей проблемой. В таких случаях даже хорошая модель эмбеддинга может не понять суть и «выдать» не самых релевантных соседей. Поэтому был реализован шаг дополнительной обработки описания с помощью LLM: перед векторизацией агент может отправить языковой модели запрос, чтобы та переформулировала, дополнила или сжала описание, подчеркнув ключевые детали. По сути LLM выступает как «улучшатель» запроса для поиска. Получив краткий текст ошибки, модель генерирует более развернутое описание проблемы (например, предполагает, что именно не работает и при каких условиях), которое затем тоже превращается в вектор. Далее поиск похожих инцидентов производится и по исходному, и по переформулированному описанию с выбором наиболее близких по смыслу инцидентов. Такой прием позволил в ряде случаев извлекать из базы инцидентов более точные совпадения.
Пример промта для LLM с целью переформулировки текстов инцидентов:
prompt_template = «»»
Вы являетесь ИТ-специалистом, который обрабатывает ИТ-инциденты.
Ваша задача — обработать описания ИТ-инцидентов, чтобы улучшить качество извлечения похожих текстов из векторного хранилища. Следуйте этим инструкциям:
Если запрос совсем короткий и недостаточно информативен, дополните его, добавив возможные причины, контекст или дополнительные детали.
Если запрос длинный и содержит много лишних деталей, в том числе повторяющихся — сократите его, оставив только ключевую информацию.
Уберите излишние подробности, но сохраните контекст, необходимый для понимания проблемы.
Верните только измененное описание инцидента, ничего больше.
Описание инцидента:
{query}
Ваш вариант:
«»»
Векторная база данных
Для хранения всех эмбеддингов прошлых инцидентов и выполнения поиска по ним понадобилась специализированная база данных, поддерживающая операции с векторами. Рассматривалось несколько вариантов векторных баз данных (Vector DB): интегрированные решения и отдельные движки. Среди популярных – полнофункциональные векторные хранилища Weaviate, Chroma, FAISS, а также расширения для классических СУБД, такие как PGVector для PostgreSQL.
PGVector добавляет тип данных «Vector», обеспечивая хранение эмбеддингов в виде векторов и поиск ближайших векторов по косинусному расстоянию, а также другими способами. Из достоинств такого решения – привычная работа с СУБД PostgreSQL и SQL запросами, надёжность, масштабируемость.
Взвесив все варианты, я выбрал именно PGVector
Пример SQL-кода для создания таблицы-хранилища с инцидентами:
#Создание таблицы с инцидентами
conn = psycopg2.connect(**DB_CONFIG)
cur = conn.cursor()
cur.execute(«»»
CREATE TABLE IF NOT EXISTS incidents (
id SERIAL PRIMARY KEY,
number INTEGER,
creation_date DATE,
report_text TEXT,
theme TEXT,
description TEXT,
service TEXT,
embedding_description vector(1024),
llm_response TEXT
);
«»»)
conn.commit()
cur.close()
conn.close()
В реализованной системе векторная база содержит таблицу, где для каждого ранее решённого инцидента хранится:
- идентификатор;
- время создания;
- ИТ-сервис, по которому зарегистрирован инцидент;
- текстовые поля (описание, решение и др.);
- векторное представление описания.
При поступлении нового инцидента выполняется SQL-запрос с оператором поиска ближайших соседей по вектору. В запросе указывается количество требуемых ближайших соседей k и условие по метрике (косинусной близости). Например, можно найти 5 наиболее похожих инцидентов по косинусному расстоянию, превышающему некоторый порог.
Пример SQL-кода для поиска похожих инцидентов:
# Функция для поиска похожих векторов по embedding
def search_similar_vectors(query, k=5, distance_threshold=0.5):
query_vector = model.encode([query])[0].tolist()
try:
cur.execute(«»»
SELECT id, number, creation_date, report_text, theme, description, service, embedding_combined,
(embedding_combined <=> %s::vector) AS distance
FROM incidents
WHERE embedding_combined <=> %s::vector < %s
ORDER BY distance
LIMIT %s
«»», (query_vector, query_vector, distance_threshold, k))
results = cur.fetchall()
return results
except Exception as e:
conn.rollback()
print(f»Ошибка при поиске векторов: {e}»)
return []
На практике порог пришлось откорректировать. Изначально допускались совпадения с близостью >0.5, но это приводило к попаданию нерелевантных случаев. После наблюдения за работой сервиса на протяжение пары недель порог был снижен до 0.15. Качество отбора существенно улучшилось – в список кандидатов стали попадать действительно только похожие тикеты. В дальнейшем можно будет настроить более тонкое ограничение: например, по категории услуги или по давности, чтобы сузить контекст поиска.
Найденные похожие инциденты извлекаются из БД вместе с их описаниями и решениями. Отбирается до 5 записей, которые передаются языковой модели на анализ. После создания рекомендации информация о новом инциденте заносится в базу; сохраняется эмбеддинг инцидента, чтобы будущие запросы находили и этот случай, и текст решения, связанный с данным описанием. Так база знаний постоянно пополняется новыми примерами, со временем качество подсказок будет расти.
Выбор и использование LLM: Ollama + Gemma 3
Важнейший компонент системы – большая языковая модель (LLM). Модель используется дважды: для улучшения описания и финальной генерации текста рекомендации. Поскольку проект развёртывается в офлайн-среде (без доступа к облачным API), выбор пал на модель с открытым исходным кодом, которую можно запускать локально на имеющемся оборудовании. Ограниченные ресурсы (отсутствие GPU) на этапе MVP накладывали в свою очередь на модель ограничения по числу параметров, иначе скорость ответа была бы неудовлетворительной. После тестирования нескольких моделей приемлемую скорость удалось получить на моделях размером не более 4В (4 млрд. параметров).
Были рассмотрены несколько современных открытых LLM. Среди них: Qwen 2.5, T-lite 1.0, YandexGPT-5-Lite, Gemma-3. В итоге для прототипа была выбрана модель Gemma 3-4b-instruct – LLM с 4 миллиардами параметров, обученная следовать инструкциям (instruct-tuned). Хотя 4 млрд параметров – это существенно меньше, чем у самых продвинутых моделей, она справилась с задачами проекта. Модель была загружена в квантованном виде (4-бит), что еще больше снизило требования к памяти (до нескольких гигабайт) при минимальной потере качества. Использование 4-битной квантованной модели позволило запускать инференс LLM на CPU достаточно быстро – создание рекомендации занимало примерно минуту.
Для простоты развёртывания модель Gemma 3b запускалась через инструмент Ollama – оптимизированный для LLM локальный сервис, который предоставляет простой API для генерации текста. Ollama облегчает использование моделей вроде Llama/Gemma: он берёт на себя загрузку модели в память, управление контекстом, ускорение за счёт квантования и так далее. Агент взаимодействует с Ollama по API, отправляет промпт и получает законченный ответ.
При работе я выявил некоторые проблемы со стабильностью Ollama – иногда мне не удавалось получить ответ от модели без видимых проблем в логах. В дальнейшем планирую постоянно обновлять версию Ollama, пока проблема со стабильностью не будет решена. В перспективе планирую полную замена Ollama на другой подобный инструмент: например VLLM (если появится сервер с GPU).
Качество ответов выбранной модели оказалось вполне приемлемым. Несмотря на небольшой размер, Gemma-3-4b в большинстве случаев формулировала корректные и уместные рекомендации для инцидентов. Модель редко «галлюцинировала», генерируя посторонний контент: все выводы действительно основывались на предоставленном контексте, как и требовалось. Очевидно, ограничение области знания только информацией об инцидентах компании (через примеры из базы) дисциплинирует даже небольшую LLM и помогает ей генерировать правдоподобные и целевые советы.
Применение LangChain и RAG
Для организации описанного взаимодействия компонентов использовался фреймворк LangChain, который предоставляет абстракции для построения цепочек вызовов LLM с дополнением из внешних источников. Сценарий работы RAG-агента был реализован как последовательность из нескольких шагов (Chain) с промежуточным хранением результатов. По сути, была сформирована связка «Retriever – Analyzer – Action»: сначала блок Retriever выполняет векторный поиск похожих случаев, затем блок Analyzer (LLM) на основе найденного анализирует ситуацию и формирует ответ, и наконец блок Action доставляет этот ответ обратно в систему, в нашем случае – публикует комментарий.
В LangChain предусмотрены компоненты для интеграции с векторными хранилищами (VectorStore). Однако прямой поддержки PGVector нет, поэтому обращение к базе PostgreSQL происходит через собственный запрос. Но концептуально это тот же retriever: агент получает на вход текст запроса (описание инцидента), обращается к векторному индексу и получает топ-N документов (описаний прошлых инцидентов) в качестве релевантного контекста. Далее формируется промт для LLM, содержащий описание нового инцидента и извлеченные описания прошлых.
Пример кода, реализующего запрос к LLM через LangChain:
#Обработка инцидента с помощью LLM
def get_llm_response (query, context):
# Настройка LangChain
llm = OllamaLLM(model=«gemma-3-4b-it.Q4_K_M:latest», base_url=«http://localhost:11434», num_ctx=8192)
# Создание промпта
prompt_template = «»»
Вы являетесь ИТ-специалистом, который обрабатывает ИТ-инциденты.
На основе предоставленной информации о ранее закрытых инцидентах, дайте заключение о том, как лучше решить текущий инцидент.
Ответ должен быть не более 3000 символов.
Не повторяйтесь.
Информация о ранее закрытых инцидентах:
{context}
Текущий инцидент:
{query}
Ваше заключение:
«»»
prompt = PromptTemplate(
input_variables=[«context», «incident»],
template=prompt_template
)
# Создание цепочки
chain = RunnableSequence(prompt | llm | StrOutputParser())
# Обработка результата с помощью LLM
llm_response = chain.invoke({«context»: context, «query»: query})
# Вывод результатов
return llm_response
После генерации текста LangChain-цепочка выполняет финальный шаг: передаёт полученный ответ обратно через API Service Desk, добавляя комментарий в тикет. Инженер, работающий с системой, видит новый комментарий от виртуального ассистента (агента) с рекомендацией и списком ссылок на похожие инциденты. Дальше он может следовать совету либо игнорировать его: решение всегда остается за человеком, агент лишь предоставляет информацию для поддержки решения.
Статистика внедрения и эффективность
Разработанный RAG-агент был развёрнут как MVP на части потока инцидентов для тестирования. На момент подготовки статьи система обработала около 500 инцидентов. Среднее время, затрачиваемое агентом на полный цикл (от получения данных до публикации комментария), составило 1–2 минуты на инцидент. Это время существенно меньше того, которое затратил бы инженер на ручной поиск похожих случаев и анализ.
Экономия составляет в среднем 10 минут на каждый инцидент. Таким образом, например при ~1000 инцидентах в месяц можно сэкономить около 167 человеко-часов, что эквивалентно работе примерно 1 инженера полной занятости.
Некоторые ключевые метрики и результаты внедрения MVP:
-
Сокращение времени анализа: ~10 минут экономии при анализе инцидента, более 80 часов в месяц экономии труда специалистов. Инженеры могут направить это время на более сложные задачи вместо поиска в документации.
-
Оптимизация штата: высвобождение эквивалента 0,5 инженера за счет автоматизации.
-
Снижение финансовых затрат: экономия фонда оплаты труда оценочно достигает 200-300 тыс. рублей в месяц за счёт автоматизации рутины, даже с учётом стоимости вычислительных ресурсов для работы агента.
-
Ускорение решения инцидентов: чем больше скорость поиска решение, тем меньше время простоя сервисов и сопутствующие убытки компании. Выгода от сокращения времени простоя может составлять до нескольких миллионов рублей в месяц для инцидентов, влияющих на продажи или критически важные процессы.
-
Затраты на поддержку решения: использование открытых моделей позволило избежать прямых расходов на лицензии. Стоимость инфраструктуры, поддержка и доработка совокупно обходится не более чем в 100 тыс. руб/мес. С учётом достигаемой экономии, окупаемость решения – порядка 1-2 месяцев. Первоначальные вложения (включая разработку) были невелики и тоже быстро окупились.
В целом, пилотное внедрение подтвердило ценность системы: агент экономит время и улучшает качество решения инцидентов.
Ниже приведены примеры комментариев, которые RAG-агент добавил в тикет, предложив вероятное решение на основе похожих случаев.
Выводы и дальнейшее развитие
Подход с использованием векторных представлений и больших языковых моделей может эффективно помочь в управлении инцидентами. По итогам работы MVP принято решение развивать проект дальше, расширять его охват и функциональность.
Качество рекомендаций. Анализ итогов работы MVP показал, что в большинстве ситуаций советы агента корректны и полезны. Инженеры подтвердили, что полученные рекомендации часто совпадают с их собственными выводами, соответствуют реальным причинам проблем и помогают выработать способы решения. Конечно, были и ситуации, когда агент мог предложить неподходящее решение: например, если в базе ещё нет похожего кейса или описания инцидента слишком размыты. Но даже в таких случаях наличие подсказки расширяет круг решений и может навести инженера на правильную мысль.
Проблемы и уроки
- Иногда алгоритм подбирал нерелевантные инциденты в качестве похожих инцидентов. Причина крылась в слишком мягких критериях сходства; ситуацию удалось улучшить с помощью настройки порога косинусной близости. В дальнейшем я планирую решать проблему с помощью фильтрации по услугам и времени.
- Качество исходных данных накладывает ограничения: если текст решения в прошлом инциденте был заполнен формально (например: «Исправлено» или «Решение применено»), то такой кейс принесёт мало пользы. Нужно улучшать качество закрытия инцидентов. Например, регламентировать заполнение поля «Решение» или автоматически проверять тексты решений инцидентов с помощью той же LLM.
- Обнаружилось, что для некоторых специфических услуг или систем даже семантический поиск не даёт результатов из-за малого числа примеров. Поэтому необходимо использовать и накапливать базу знаний по редким категориям: например, создавать отдельные векторные базы по каждому направлению, куда можно добавлять не только инциденты, но и связанные артефакты (документацию, FAQ) для повышения качества.
Планы развития
Следующими шагами в развитии системы станут:
- улучшение стабильности и производительности (в том числе перенос вычислений на GPU-сервер при появлении такового)
- качественное обновление LLM-модели и подключение полного потока инцидентов.
По мере накопления данных откроются новые возможности аналитики: автоматический анализ качества решений инцидентов, поиск скрытых закономерностей в причинах сбоев. В перспективе такой агент может эволюционировать в полноценного помощника SRE/DevOps-команды: не только подсказывать решения, но и проактивно уведомлять о повторяющихся проблемах, предлагать классификацию инцидентов, а возможно, и взаимодействовать с пользователями для сбора дополнительной информации.
Проект RAG-агента для инцидент-менеджмента показал, что современные методы NLP могут успешно применяться для интеллектуальной поддержки операционных процессов. Объединение методов семантического поиска и генерации позволяет извлекать ценность из корпоративной памяти, делает знания полезными и своевременными.
<!DOCTYPE html>
<html dir="ltr" lang="ru-RU">
<head>
<meta charset="UTF-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="profile" href="http://gmpg.org/xfn/11" />
<title>RAG-агент для автоматизации инцидент-менеджмента OTUS</title>
<!-- All in One SEO 4.5.2.1 - aioseo.com -->
<meta name="description" content="Автор: Александр Летуновский, Место работы - руководитель центра, Сбербанк страхование. Выпускник курса «Natural Language Processing» Проблематика Крупные организации сталкиваются с большим числом ИТ-инцидентов: иногда – с тысячами в месяц. Инциденты нередко повторяются, однако найти похожий случай в базе знаний или в системе регистрации непросто: стандартный поиск по ключевым словам часто неэффективен, а помнить детали всех инцидентов невозможно." />
<meta name="robots" content="max-image-preview:large" />
<link rel="canonical" href="https://otus.ru/journal/rag-agent-dlya-avtomatizacii-incident-menedzhmenta/" />
<meta name="generator" content="All in One SEO (AIOSEO) 4.5.2.1" />
<script type="application/ld+json" class="aioseo-schema">
{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/otus.ru\/journal\/rag-agent-dlya-avtomatizacii-incident-menedzhmenta\/#article","name":"RAG-\u0430\u0433\u0435\u043d\u0442 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u0446\u0438\u0434\u0435\u043d\u0442-\u043c\u0435\u043d\u0435\u0434\u0436\u043c\u0435\u043d\u0442\u0430 OTUS","headline":"RAG-\u0430\u0433\u0435\u043d\u0442 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u0446\u0438\u0434\u0435\u043d\u0442-\u043c\u0435\u043d\u0435\u0434\u0436\u043c\u0435\u043d\u0442\u0430","author":{"@id":"https:\/\/otus.ru\/journal\/author\/nick-alex\/#author"},"publisher":{"@id":"https:\/\/otus.ru\/journal\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXdIP15o2JPtTf6XQQO-X9i2jA7bH7GZ8P5nj_8E1EyHVXMvXjjmzyxDEgmbwxi1olfDXhuvmsEr0oOf__UAI-PELmqTlfkQEXcw8NSFCnHs8o0j8wlsWShNs3ljDNmnASl7JVW8HLClGc6EpmE89wM?key=N3Pb6Xo0scwE1yATXwqJXg","@id":"https:\/\/otus.ru\/journal\/rag-agent-dlya-avtomatizacii-incident-menedzhmenta\/#articleImage"},"datePublished":"2025-06-06T12:50:51+00:00","dateModified":"2025-06-06T12:50:53+00:00","inLanguage":"ru-RU","mainEntityOfPage":{"@id":"https:\/\/otus.ru\/journal\/rag-agent-dlya-avtomatizacii-incident-menedzhmenta\/#webpage"},"isPartOf":{"@id":"https:\/\/otus.ru\/journal\/rag-agent-dlya-avtomatizacii-incident-menedzhmenta\/#webpage"},"articleSection":"\u041f\u0440\u043e IT"},{"@type":"BreadcrumbList","@id":"https:\/\/otus.ru\/journal\/rag-agent-dlya-avtomatizacii-incident-menedzhmenta\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/otus.ru\/journal\/#listItem","position":1,"name":"\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430","item":"https:\/\/otus.ru\/journal\/","nextItem":"https:\/\/otus.ru\/journal\/rag-agent-dlya-avtomatizacii-incident-menedzhmenta\/#listItem"},{"@type":"ListItem","@id":"https:\/\/otus.ru\/journal\/rag-agent-dlya-avtomatizacii-incident-menedzhmenta\/#listItem","position":2,"name":"RAG-\u0430\u0433\u0435\u043d\u0442 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u0446\u0438\u0434\u0435\u043d\u0442-\u043c\u0435\u043d\u0435\u0434\u0436\u043c\u0435\u043d\u0442\u0430","previousItem":"https:\/\/otus.ru\/journal\/#listItem"}]},{"@type":"Organization","@id":"https:\/\/otus.ru\/journal\/#organization","name":"\u041e\u0442\u0443\u0441 \u043e\u043d\u043b\u0430\u0439\u043d-\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435","url":"https:\/\/otus.ru\/journal\/","sameAs":["https:\/\/www.youtube.com\/channel\/UCetgtvy93o3i3CvyGXKFU3g"],"contactPoint":{"@type":"ContactPoint","telephone":"+74999389202","contactType":"Customer Support"}},{"@type":"Person","@id":"https:\/\/otus.ru\/journal\/author\/nick-alex\/#author","url":"https:\/\/otus.ru\/journal\/author\/nick-alex\/","name":"Nicolay Alexandrov","image":{"@type":"ImageObject","@id":"https:\/\/otus.ru\/journal\/rag-agent-dlya-avtomatizacii-incident-menedzhmenta\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/309881a64338fdabd56efb59623d7c03?s=96&d=mm&r=g","width":96,"height":96,"caption":"Nicolay Alexandrov"}},{"@type":"WebPage","@id":"https:\/\/otus.ru\/journal\/rag-agent-dlya-avtomatizacii-incident-menedzhmenta\/#webpage","url":"https:\/\/otus.ru\/journal\/rag-agent-dlya-avtomatizacii-incident-menedzhmenta\/","name":"RAG-\u0430\u0433\u0435\u043d\u0442 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u0446\u0438\u0434\u0435\u043d\u0442-\u043c\u0435\u043d\u0435\u0434\u0436\u043c\u0435\u043d\u0442\u0430 OTUS","description":"\u0410\u0432\u0442\u043e\u0440: \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440 \u041b\u0435\u0442\u0443\u043d\u043e\u0432\u0441\u043a\u0438\u0439, \u041c\u0435\u0441\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u044b - \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u0446\u0435\u043d\u0442\u0440\u0430, \u0421\u0431\u0435\u0440\u0431\u0430\u043d\u043a \u0441\u0442\u0440\u0430\u0445\u043e\u0432\u0430\u043d\u0438\u0435. \u0412\u044b\u043f\u0443\u0441\u043a\u043d\u0438\u043a \u043a\u0443\u0440\u0441\u0430 \u00abNatural Language Processing\u00bb \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0442\u0438\u043a\u0430 \u041a\u0440\u0443\u043f\u043d\u044b\u0435 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u0447\u0438\u0441\u043b\u043e\u043c \u0418\u0422-\u0438\u043d\u0446\u0438\u0434\u0435\u043d\u0442\u043e\u0432: \u0438\u043d\u043e\u0433\u0434\u0430 \u2013 \u0441 \u0442\u044b\u0441\u044f\u0447\u0430\u043c\u0438 \u0432 \u043c\u0435\u0441\u044f\u0446. \u0418\u043d\u0446\u0438\u0434\u0435\u043d\u0442\u044b \u043d\u0435\u0440\u0435\u0434\u043a\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0442\u0441\u044f, \u043e\u0434\u043d\u0430\u043a\u043e \u043d\u0430\u0439\u0442\u0438 \u043f\u043e\u0445\u043e\u0436\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u0432 \u0431\u0430\u0437\u0435 \u0437\u043d\u0430\u043d\u0438\u0439 \u0438\u043b\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043d\u0435\u043f\u0440\u043e\u0441\u0442\u043e: \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u0441\u043b\u043e\u0432\u0430\u043c \u0447\u0430\u0441\u0442\u043e \u043d\u0435\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u0435\u043d, \u0430 \u043f\u043e\u043c\u043d\u0438\u0442\u044c \u0434\u0435\u0442\u0430\u043b\u0438 \u0432\u0441\u0435\u0445 \u0438\u043d\u0446\u0438\u0434\u0435\u043d\u0442\u043e\u0432 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e.","inLanguage":"ru-RU","isPartOf":{"@id":"https:\/\/otus.ru\/journal\/#website"},"breadcrumb":{"@id":"https:\/\/otus.ru\/journal\/rag-agent-dlya-avtomatizacii-incident-menedzhmenta\/#breadcrumblist"},"author":{"@id":"https:\/\/otus.ru\/journal\/author\/nick-alex\/#author"},"creator":{"@id":"https:\/\/otus.ru\/journal\/author\/nick-alex\/#author"},"datePublished":"2025-06-06T12:50:51+00:00","dateModified":"2025-06-06T12:50:53+00:00"},{"@type":"WebSite","@id":"https:\/\/otus.ru\/journal\/#website","url":"https:\/\/otus.ru\/journal\/","name":"OTUS JOURNAL","description":"Blog about IT","inLanguage":"ru-RU","publisher":{"@id":"https:\/\/otus.ru\/journal\/#organization"}}]}
</script>
<!-- All in One SEO -->
<link rel='dns-prefetch' href='//otus.ru' />
<link rel='dns-prefetch' href='//fonts.googleapis.com' />
<link rel='stylesheet' id='wp-block-library-css' href='https://otus.ru/journal/wp-includes/css/dist/block-library/style.min.css?ver=6.4.7' type='text/css' media='all' />
<style id='classic-theme-styles-inline-css' type='text/css'>
/*! This file is auto-generated */
.wp-block-button__link{color:#fff;background-color:#32373c;border-radius:9999px;box-shadow:none;text-decoration:none;padding:calc(.667em + 2px) calc(1.333em + 2px);font-size:1.125em}.wp-block-file__button{background:#32373c;color:#fff;text-decoration:none}
</style>
<style id='global-styles-inline-css' type='text/css'>
body{--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1);--wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1);}:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}body .is-layout-flex > *{margin: 0;}body .is-layout-grid{display: grid;}body .is-layout-grid > *{margin: 0;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}
.wp-block-navigation a:where(:not(.wp-element-button)){color: inherit;}
:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}
:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}
.wp-block-pullquote{font-size: 1.5em;line-height: 1.6;}
</style>
<link rel='stylesheet' id='wbcr-comments-plus-url-span-css' href='https://otus.ru/journal/wp-content/plugins/clearfy/components/comments-plus/assets/css/url-span.css?ver=2.2.0' type='text/css' media='all' />
<link rel='stylesheet' id='wpel-style-css' href='https://otus.ru/journal/wp-content/plugins/wp-external-links/public/css/wpel.css?ver=2.59' type='text/css' media='all' />
<link rel='stylesheet' id='ez-toc-css' href='https://otus.ru/journal/wp-content/plugins/easy-table-of-contents/assets/css/screen.min.css?ver=2.0.61' type='text/css' media='all' />
<style id='ez-toc-inline-css' type='text/css'>
div#ez-toc-container .ez-toc-title {font-size: 120%;}div#ez-toc-container .ez-toc-title {font-weight: 500;}div#ez-toc-container ul li {font-size: 95%;}div#ez-toc-container nav ul ul li {font-size: 90%;}
.ez-toc-container-direction {direction: ltr;}.ez-toc-counter ul{counter-reset: item ;}.ez-toc-counter nav ul li a::before {content: counters(item, ".", decimal) ". ";display: inline-block;counter-increment: item;flex-grow: 0;flex-shrink: 0;margin-right: .2em; float: left; }.ez-toc-widget-direction {direction: ltr;}.ez-toc-widget-container ul{counter-reset: item ;}.ez-toc-widget-container nav ul li a::before {content: counters(item, ".", decimal) ". ";display: inline-block;counter-increment: item;flex-grow: 0;flex-shrink: 0;margin-right: .2em; float: left; }
</style>
<link rel='stylesheet' id='contentberg-fonts-css' href='https://fonts.googleapis.com/css?family=Roboto%3A400%2C500%2C700%7CPT+Serif%3A400%2C400i%2C600%7CIBM+Plex+Serif%3A500' type='text/css' media='all' />
<link rel='stylesheet' id='contentberg-core-css' href='https://otus.ru/journal/wp-content/themes/contentberg/style.css?ver=1.8.3' type='text/css' media='all' />
<link rel='stylesheet' id='contentberg-lightbox-css' href='https://otus.ru/journal/wp-content/themes/contentberg/css/lightbox.css?ver=1.8.3' type='text/css' media='all' />
<link rel='stylesheet' id='font-awesome-css' href='https://otus.ru/journal/wp-content/themes/contentberg/css/fontawesome/css/font-awesome.min.css?ver=1.8.3' type='text/css' media='all' />
<script type="text/javascript" id="breeze-prefetch-js-extra">
/* <![CDATA[ */
var breeze_prefetch = {"local_url":"https:\/\/otus.ru\/journal","ignore_remote_prefetch":"1","ignore_list":["\/wp-admin\/"]};
/* ]]> */
</script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/plugins/breeze/assets/js/js-front-end/breeze-prefetch-links.min.js" id="breeze-prefetch-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-includes/js/jquery/jquery.min.js" id="jquery-core-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-includes/js/jquery/jquery-migrate.min.js" id="jquery-migrate-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/lazysizes.js" id="lazysizes-js"></script>
<link rel="https://api.w.org/" href="https://otus.ru/journal/wp-json/" /><link rel="alternate" type="application/json" href="https://otus.ru/journal/wp-json/wp/v2/posts/11537" /><link rel='shortlink' href='https://otus.ru/journal/?p=11537' />
<link rel="alternate" type="application/json+oembed" href="https://otus.ru/journal/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fotus.ru%2Fjournal%2Frag-agent-dlya-avtomatizacii-incident-menedzhmenta%2F" />
<link rel="alternate" type="text/xml+oembed" href="https://otus.ru/journal/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fotus.ru%2Fjournal%2Frag-agent-dlya-avtomatizacii-incident-menedzhmenta%2F&format=xml" />
<script>var Sphere_Plugin = {"ajaxurl":"https:\/\/otus.ru\/journal\/wp-admin\/admin-ajax.php"};</script><link rel="icon" href="https://otus.ru/journal/wp-content/uploads/2020/11/cropped-OTUS_logo_OTUS-COMP-LOGO-WHITE-1-32x32.png" sizes="32x32" />
<link rel="icon" href="https://otus.ru/journal/wp-content/uploads/2020/11/cropped-OTUS_logo_OTUS-COMP-LOGO-WHITE-1-192x192.png" sizes="192x192" />
<link rel="apple-touch-icon" href="https://otus.ru/journal/wp-content/uploads/2020/11/cropped-OTUS_logo_OTUS-COMP-LOGO-WHITE-1-180x180.png" />
<meta name="msapplication-TileImage" content="https://otus.ru/journal/wp-content/uploads/2020/11/cropped-OTUS_logo_OTUS-COMP-LOGO-WHITE-1-270x270.png" />
<style type="text/css" id="wp-custom-css">
#menu-item-10406 .wpel-icon {
display: none;
}
#menu-item-10407 .wpel-icon {
display: none;
}
.otus-login-site a .wpel-icon {
display: none;
}
.menu-menju-navykov-container a .wpel-icon {
display: none;
}
.otus-login-site a
{
background: #ffd709;
border-radius: 12px;
color: #0f0f10;
font-size: 14px;
font-weight: 700;
line-height: 20px;
display: block;
text-align: center;
padding: 8px 25px;
}
.main-footer.dark {
background: linear-gradient(90deg, #a64fc5, #4f54e6);
border-color: transparent;
}
.main-footer.bold .copyright {
color: #fff;
}
.main-footer.bold .to-top i {
color: #fff;
}
.main-footer.bold .back-to-top {
color: #fff;
}
.nav__scroll {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.scrollable-menu .menu {
display: flex;
}
.nav__scroll
{
background: linear-gradient(90deg, #a64fc5, #4f54e6);
}
.scrollable-menu .menu .menu-item {
flex: 0 0 auto;
padding: 15px 15px;
}
.scrollable-menu .menu .menu-item a {
color: #fff;
}
.nav__scroll::-webkit-scrollbar{background-color:#fff;height:5px;}
.nav__scroll::-webkit-scrollbar-thumb{background-color:#dcdcdc;}
.nav__scroll::-webkit-scrollbar-track{-webkit-border-radius:0;border-radius:0;background-color:#fff;}/
body {
min-width: 320px;
}
.banner-click img {
margin: 0 auto;
display: block;
}
.banner-click {
cursor: pointer;
}
.banner-footer-area {
margin-bottom: 20px;
}
.banner-left-area {
margin-top: 40px;
} </style>
<!--Start VDZ Yandex Metrika Plugin-->
<!-- Yandex.Metrika counter --><script type="text/javascript" >(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");ym(34531570, "init", {clickmap:true, trackLinks:true, accurateTrackBounce:true, webvisor:true, trackHash:true, ecommerce:"dataLayer"});</script>
<noscript><div><img src="https://mc.yandex.ru/watch/34531570" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter --><!--START ADD EVENTS FROM CF7--><script type='text/javascript'>document.addEventListener( 'wpcf7submit', function( event ) {
//event.detail.contactFormId;
if(ym){
//console.log(event.detail);
ym(34531570, 'reachGoal', 'VDZ_SEND_CONTACT_FORM_7');
ym(34531570, 'params', {
page_url: window.location.href,
status: event.detail.status,
locale: event.detail.contactFormLocale,
form_id: event.detail.contactFormId,
});
}
}, false );
</script><!--END ADD EVENTS FROM CF7-->
<!--End VDZ Yandex Metrika Plugin-->
</head>
<body class="post-template-default single single-post postid-11537 single-format-standard right-sidebar lazy-normal has-lb">
<div class="main-wrap">
<header id="main-head" class="main-head head-nav-below has-search-modal simple simple-boxed">
<div class="inner inner-head" data-sticky-bar="0">
<div class="wrap cf wrap-head">
<div class="left-contain">
<span class="mobile-nav"><i class="fa fa-bars"></i></span>
<div class="title">
<a href="https://otus.ru/journal/" title="OTUS JOURNAL" rel="home" data-wpel-link="internal">
<span class="text-logo"><img src="/journal/wp-content/themes/contentberg/img/logo_site.svg" alt="OTUS JOURNAL"></span>
</a>
</div>
</div>
<div class="navigation-wrap inline">
<nav class="navigation inline simple light" data-sticky-bar="0">
<div class="menu-rubriki-container"><ul id="menu-rubriki" class="menu"><li id="menu-item-109" class="menu-item menu-item-type-taxonomy menu-item-object-category current-post-ancestor current-menu-parent current-post-parent menu-cat-1 menu-item-109"><a href="https://otus.ru/journal/category/pro-it/" data-wpel-link="internal"><span>Про IT</span></a></li>
<li id="menu-item-113" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-cat-4 menu-item-113"><a href="https://otus.ru/journal/category/polza/" data-wpel-link="internal"><span>Полезное</span></a></li>
<li id="menu-item-114" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-cat-3 menu-item-114"><a href="https://otus.ru/journal/category/lifestyle/" data-wpel-link="internal"><span>Лайфстайл</span></a></li>
<li id="menu-item-10406" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10406"><a href="https://otus.ru/catalog/courses" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right"><span>Обучение</span><span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10407" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10407"><a href="https://otus.ru/about" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right"><span>Информация</span><span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
</ul></div> </nav>
</div>
<div class="actions">
<div class="otus-login-site">
<a href="https://otus.ru/login/" target="_blank" data-wpel-link="external" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Войти<span class="wpel-icon wpel-image wpel-icon-6"></span></a>
</div>
<a href="#" title="Search" class="search-link"><i class="fa fa-search"></i></a>
</div>
</div>
</div>
</header> <!-- .main-head -->
<div class="nav nav_disable nav_colored nav_transparent course-categories__nav nav__scroll ">
<div class="container wrap">
<div class="links inline simple light scrollable-menu">
<div class="menu-menju-navykov-container"><ul id="menu-menju-navykov" class="menu"><li id="menu-item-10413" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10413"><a href="https://otus.ru/categories/programming/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Программирование<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10414" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10414"><a href="https://otus.ru/categories/architecture/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Архитектура<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10415" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10415"><a href="https://otus.ru/categories/operations/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Инфраструктура<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10416" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10416"><a href="https://otus.ru/categories/information-security-courses/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Безопасность<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10417" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10417"><a href="https://otus.ru/categories/data-science/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Data Science<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10418" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10418"><a href="https://otus.ru/categories/gamedev/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">GameDev<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10419" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10419"><a href="https://otus.ru/categories/marketing-business/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Управление<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10420" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10420"><a href="https://otus.ru/categories/analytics/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Аналитика и анализ<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10421" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10421"><a href="https://otus.ru/categories/testing/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Тестирование<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
</ul></div> </div>
</div>
</div>
<div class="main wrap">
<div class="ts-row cf">
<div class="col-8 main-content cf">
<article id="post-11537" class="the-post post-11537 post type-post status-publish format-standard category-pro-it">
<header class="post-header the-post-header cf">
<div class="post-meta the-post-meta">
<span class="post-cat">
<a href="https://otus.ru/journal/category/pro-it/" class="category" data-wpel-link="internal">Про IT</a>
</span>
<h1 class="post-title">
RAG-агент для автоматизации инцидент-менеджмента
</h1>
<a href="https://otus.ru/journal/rag-agent-dlya-avtomatizacii-incident-menedzhmenta/" class="date-link" data-wpel-link="internal"><time class="post-date">6 июня, 2025</time></a>
</div>
<div class="featured">
</div>
</header><!-- .post-header -->
<div class="post-content description cf entry-content content-normal">
<p><strong>Автор:</strong> Александр Летуновский, Место работы — руководитель центра, Сбербанк страхование. Выпускник курса «<strong>Natural Language Processing»</strong></p>
<p><strong>Проблематика</strong></p>
<p>Крупные организации сталкиваются с большим числом ИТ-инцидентов: иногда – с тысячами в месяц. Инциденты нередко повторяются, однако найти похожий случай в базе знаний или в системе регистрации непросто: стандартный поиск по ключевым словам часто неэффективен, а помнить детали всех инцидентов невозможно.</p>
<p>Здесь и возникает проблема: при поступлении нового инцидента инженеру трудно выяснить, был ли подобный инцидент раньше, и как его разрешили. Многие знания рассеиваются по прошлым тикетам и не используются вновь. В лучшем случае на помощь приходит опытный коллега, который вдруг вспоминает: <em>«Да, в прошлом месяце у нас уже было нечто подобное по такой-то причине»</em>. </p>
<p>Эта ситуация натолкнула меня на мысль о создании системы, которая выступила бы <strong>искусственной «памятью»</strong> ИТ-команды: мгновенно просматривала бы все предыдущие инциденты и находила релевантную информацию в нужное время. Я хотел, чтобы при разборе нового инцидента система играла роль <strong>опытного инженера</strong>, видевшего все предыдущие проблемы, и подсказывала возможное решение.</p>
<p><strong>Цель работы</strong></p>
<p>Цель проекта – <strong>автоматизировать сопоставление новых инцидентов с решёнными ранее </strong>и предоставлять инженерам рекомендации по решению в виде комментария в тикете. </p>
<p>Я задался целью разработать помощника, который при каждом новом инциденте будет искать в базе знаний несколько самых похожих случаев и на основе описаний решений подсказывать причины проблемы и давать советы по способам её устранения. Такой подход, совмещающий поиск по базе знаний с генерацией текста, известен как «<strong>Retrieval-Augmented Generation» (RAG)</strong> – генерирация ответа с дополнением из внешней базы знаний. </p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdIP15o2JPtTf6XQQO-X9i2jA7bH7GZ8P5nj_8E1EyHVXMvXjjmzyxDEgmbwxi1olfDXhuvmsEr0oOf__UAI-PELmqTlfkQEXcw8NSFCnHs8o0j8wlsWShNs3ljDNmnASl7JVW8HLClGc6EpmE89wM?key=N3Pb6Xo0scwE1yATXwqJXg" alt="RAG-агент для автоматизации инцидент-менеджмента"/></figure>
<p><em>Схема RAG</em></p>
<p><br>Мне предстояло реализовать минимально жизнеспособный прототип (MVP) и интегрировать его в промышленную среду системы Service Desk. Основные критерии успеха – ускорение анализа инцидентов (уменьшение времени на поиск решения) и увеличение частоты использования накопленных знаний об инцидентах.</p>
<p><strong>Ограничения и особенности внедрения</strong></p>
<p>Проект развёрнут и эксплуатируется в условиях существенных ограничений инфраструктуры. </p>
<p>I. <strong>Среда полностью офлайн. </strong>У меня не было возможности воспользоваться облачными сервисами вроде OpenAI API или управляемыми векторными базами. Ни база инцидентов, ни сервис генерации не имеют доступа к интернету или облачным API: все компоненты от моделей до баз данных должны быть размещены <strong>локально</strong>. Из-за офлайн-режима сложными вопросами становятся обновления и поддержки. Все обновления моделей (как эмбеддинг модели, так и LLM) требуют отдельной процедуры загрузки моделей в контур. Тем не менее, подобный автономный режим – частая ситуация в корпоративных внедрениях. И, как выяснилось позже, даже без доступа к облачным мощностям можно эффективно применять методы NLP на локальных ресурсах.</p>
<p>II.<strong> Отсутствие производительных графических процессоров (GPU) на этапе MVP. </strong>Сервер, на котором разворачивается решение, оснащён только CPU. Это повлияло на выбор моделей и инструментов: предпочтение отдавалось легковесным и оптимизированным вариантам. </p>
<p><strong>Ход работы</strong></p>
<p>Для решения поставленной задачи я спроектировал архитектуру RAG-агента. Архитектура включала в себя:</p>
<ul>
<li>интеграцию с системой Service Desk</li>
<li>векторную базу данных для знаний об инцидентах</li>
<li>использование большой языковой модели (LLM) для генерации подсказок. </li>
</ul>
<p>Агент был реализован на Python. Ниже привожу схему логики работы разработанного агента.</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfbtVme9LdDkhlT5xOxl2jDecEHQLZUZkM4KP-Qu2mlUxxsZ88h0MOhZdMG_BeIPyeXfinoPM-qC4W9lfm8B8AAs817vXaA1T98LLajIhxFQ2Oxjh0hf8Z6IVWAYPm8w901xFN35a1QTNUItBFPDx4?key=N3Pb6Xo0scwE1yATXwqJXg" alt="RAG-агент для автоматизации инцидент-менеджмента"/></figure>
<p><em>Схема решения</em></p>
<p>Как показано на схеме, процесс состоит из семи шагов:</p>
<ol>
<li><strong>Получение инцидента:</strong> агент отслеживает появление нового инцидента в системе Service Desk и через API выгружает его описание в текстовом формате: HTML-разметка очищается до простого текста.</li>
<li><strong>Дополнение описания:</strong> чтобы уточнить проблему, исходное описание инцидента при необходимости автоматически дополняется или переформулируется с помощью большой языковой модели. Например, извлечь ключевые симптомы, дополнить короткое описание, удалить лишние детали из описания.</li>
<li><strong>Векторизация описания:</strong> текст инцидента (как в оригинале, так и переформулированный вариант) преобразуется в векторное представление – <strong>embedding –</strong> при помощи модели эмбеддинга.</li>
<li><strong>Поиск похожих инцидентов:</strong> полученный вектор сравнивается с векторами ранее решённых инцидентов, хранящимися в векторной базе данных, с использованием метрики косинусного расстояния. В результате извлекаются несколько наиболее похожих описаний из базы (топ-5 по оригинальному тексту и топ-5 по переформулированному).</li>
<li><strong>Генерация рекомендаций:</strong> собранная информация подаётся на вход большой языковой модели – формируется запрос (prompt), содержащий описание новой проблемы и сведения о найденных похожих инцидентах (описания и решения). LLM анализирует этот контекст и генерирует <strong>рекомендацию</strong> – комментарий с предположением причины проблемы и советом по её решению.</li>
<li><strong>Обновление базы знаний:</strong> векторное представление нового инцидента сохраняется в векторной базе (вместе с текстом описания и решения после закрытия инцидента) для использования в будущем.</li>
<li><strong>Публикация решения:</strong> сгенерированная LMM рекомендация и список ссылок на похожие инциденты автоматически отправляются в систему Service Desk в виде комментария к соответствующему тикету, где его видят инженеры.</li>
</ol>
<p>Далее рассмотрены ключевые компоненты этой системы и принятые решения при её реализации.</p>
<p><strong>Извлечение текста инцидентов из HTML</strong></p>
<p>Первым шагом стало подключение к системе управления инцидентами (Service Desk) и извлечение необходимых данных. Интеграция реализована через REST API: агент периодически опрашивает систему на наличие новых тикетов или получает уведомление о них. Для каждого нового инцидента с помощью API вытягивается текст поля «Описание» (Description). Поскольку в Service Desk описания хранятся с разметкой HTML, этот контент приводится к простому тексту: удаляются HTML-теги, лишние символы, приводятся в порядок списки и форматирование. Разбор HTML выполняется с помощью библиотеки парсинга BeautifulSoup4. В результате на выходе получается связный текст, пригодный для последующей обработки. </p>
<p>Пример кода для очистки HTML от лишней информации:</p>
<p><strong>def</strong> clean_html<strong>(</strong>html_content<strong>):</strong></p>
<p> «»»Remove HTML tags from the content.»»»</p>
<p> <strong>if</strong> html_content <strong>is</strong> <strong>None</strong><strong>:</strong></p>
<p> <strong>return</strong> <strong>None</strong></p>
<p> soup <strong>=</strong> BeautifulSoup<strong>(</strong>html_content<strong>,</strong> ‘html.parser’<strong>)</strong></p>
<p> <strong>return</strong> soup<strong>.</strong><em>get_text</em><strong>(</strong>strip<strong>=</strong><strong>True</strong><strong>)</strong></p>
<p>При извлечении текста описания агент также может получить связанные с инцидентом данные, например дату и время создания инцидента, категорию проблемы, затронутый сервис или компоненты. Эти сведения в текущей версии напрямую не используются для поиска, но в будущем могут помочь фильтровать результаты (например, ограничивать поиск схожих инцидентов тем же сервисом или близким временем). Пока же основным источником информации для поиска выступает текстовое описание симптомов инцидента.</p>
<p><strong>Векторизация описаний инцидентов</strong></p>
<p>Когда от нового инцидента получен текст описания, следующей задачей становится <strong>получение его векторного представления</strong> (embedding). Векторное представление – это набор чисел (координат векторов в многомерном пространстве), которые отражают смысл текста. Современные трансформерные модели способны превращать фразу или документ в такой числовой «отпечаток», близкий для похожих по содержанию текстов и далекий для непохожих. Иными словами, если два описания инцидентов описывают схожие проблемы, их векторы будут расположены близко друг к другу в пространстве; если же тематика разная – векторы будут далеко друг от друга. Важное свойство эмбеддингов (в отличие от простых хеш-функций) состоит в том, что <strong>концептуально схожий ввод приводит к близким векторным значениям</strong>, даже если тексты формально не совпадают по словам. Благодаря этому можно сравнивать семантическое сходство. То есть алгоритм обучается сравнивать «яблоки и апельсины» по смыслу, а не по буквальному совпадению. </p>
<p>Для вычисления степени близости векторов используется метрика косинусного расстояния (cosine similarity). Эта метрика возвращает значение от 0 до 1, отражающее степень сходства, и широко применяется для ранжирования похожести текстов. Чем меньше значение метрики, тем ближе по смыслу тексты. </p>
<p><strong>Выбор модели эмбеддинга.</strong> В проекте были протестированы несколько предобученных моделей для векторизации текстов инцидентов. Основными критериями выбора были: <strong>качество семантического соответствия для русскоязычных и англоязычных текстов</strong> (другие языки не требовались), производительность и возможность локального запуска.<br><br>Среди протестированных моделей были:</p>
<ul>
<li><strong>all-MiniLM-L6-v2</strong>: компактная модель размерности 384, давала хорошую скорость, но уступала по качеству: в исторических данных пропускала релевантные случаи или ранжировала их ниже;</li>
<li><strong>LaBSE-en-ru: «</strong>урезанная» модель от Google с размерностью вектора 768, содержащая только токены русского и английского языков. Модель очень хорошо справлялась с текстами инцидентов;</li>
<li><strong>ru-en-RoSBERTa</strong>: русско-английская модель с размерностью векторов 1024, специально дообученная для работы с двуязычными текстами.</li>
</ul>
<p>По итогам экспериментов <strong>победителем по качеству поиска схожих инцидентов стала модель ru-en-RoSBERTa</strong>: она показала наилучшее ранжирование и точность сопоставления, особенно при анализе инцидентов, содержащих технические термины, коды ошибок и смешанную лексику. В частности, она лучше других справлялась с короткими описаниями и контекстами без явных ключевых слов. </p>
<p>Использование модели для получения эмбеддингов текста. Пример кода:</p>
<p># Загрузка модели</p>
<p>model <strong>=</strong> SentenceTransformer<strong>(</strong>‘ru-en-RoSBERTa’<strong>)</strong></p>
<p># Векторизация текста</p>
<p>vectors_description <strong>=</strong> model<strong>.</strong><em>encode</em><strong>(</strong>df<strong>[</strong>‘description’<strong>].</strong><em>tolist</em><strong>())</strong></p>
<p><strong>Переформулировка описаний с LLM.</strong> Особенностью подхода стало использование большой языковой модели (LLM) для улучшения качества векторизации. Как было сказано выше, иногда описания инцидентов бывают скудными или неочевидными, или наоборот слишком длинными. Например, тикет может содержать лишь фразу «Приложение не работает» или фрагмент лога, не коррелирующий напрямую с настоящей проблемой. В таких случаях даже хорошая модель эмбеддинга может не понять суть и «выдать» не самых релевантных соседей. Поэтому был реализован шаг <strong>дополнительной обработки описания с помощью LLM</strong>: перед векторизацией агент может отправить языковой модели запрос, чтобы та переформулировала, дополнила или сжала описание, подчеркнув ключевые детали. По сути LLM выступает как «улучшатель» запроса для поиска. Получив краткий текст ошибки, модель генерирует более развернутое описание проблемы (например, предполагает, что именно не работает и при каких условиях), которое затем тоже превращается в вектор. Далее поиск похожих инцидентов производится <strong>и по исходному, и по переформулированному описанию </strong>с выбором наиболее близких по смыслу инцидентов. Такой прием позволил в ряде случаев извлекать из базы инцидентов более точные совпадения.</p>
<p>Пример промта для LLM с целью переформулировки текстов инцидентов:</p>
<p> prompt_template <strong>=</strong> «»»</p>
<p>Вы являетесь ИТ-специалистом, который обрабатывает ИТ-инциденты. </p>
<p>Ваша задача — обработать описания ИТ-инцидентов, чтобы улучшить качество извлечения похожих текстов из векторного хранилища. Следуйте этим инструкциям:</p>
<p>Если запрос совсем короткий и недостаточно информативен, дополните его, добавив возможные причины, контекст или дополнительные детали.</p>
<p>Если запрос длинный и содержит много лишних деталей, в том числе повторяющихся — сократите его, оставив только ключевую информацию.</p>
<p>Уберите излишние подробности, но сохраните контекст, необходимый для понимания проблемы.</p>
<p>Верните только измененное описание инцидента, ничего больше.</p>
<p>Описание инцидента:</p>
<p>{query}</p>
<p>Ваш вариант:</p>
<p>«»»</p>
<p><strong>Векторная база данных </strong></p>
<p>Для хранения всех эмбеддингов прошлых инцидентов и выполнения поиска по ним понадобилась специализированная база данных, поддерживающая операции с векторами. Рассматривалось несколько вариантов <strong>векторных баз данных</strong> (Vector DB): интегрированные решения и отдельные движки. Среди популярных – полнофункциональные векторные хранилища <strong>Weaviate</strong>, <strong>Chroma</strong>, <strong>FAISS</strong>, а также расширения для классических СУБД, такие как <strong>PGVector</strong> для <strong>PostgreSQL.</strong></p>
<p><strong>PGVector</strong> добавляет тип данных «Vector», обеспечивая хранение эмбеддингов в виде векторов и поиск ближайших векторов по косинусному расстоянию, а также <a href="https://github.com/pgvector/pgvector" target="_blank" rel="noopener nofollow external noreferrer" title="другими способами" data-wpel-link="external" class="wpel-icon-right">другими способами<span class="wpel-icon wpel-image wpel-icon-6"></span></a>. Из достоинств такого решения – привычная работа с СУБД PostgreSQL и SQL запросами, надёжность, масштабируемость. </p>
<p>Взвесив все варианты, я выбрал именно <strong>PGVector</strong></p>
<p>Пример SQL-кода для создания таблицы-хранилища с инцидентами:</p>
<p>#Создание таблицы с инцидентами</p>
<p>conn <strong>=</strong> psycopg2<strong>.</strong><em>connect</em><strong>(**</strong>DB_CONFIG<strong>)</strong></p>
<p>cur <strong>=</strong> conn<strong>.</strong><em>cursor</em><strong>()</strong></p>
<p>cur<strong>.</strong><em>execute</em><strong>(</strong>«»»</p>
<p> CREATE TABLE IF NOT EXISTS incidents (</p>
<p> id SERIAL PRIMARY KEY,</p>
<p> number INTEGER,</p>
<p> creation_date DATE,</p>
<p> report_text TEXT,</p>
<p> theme TEXT,</p>
<p> description TEXT,</p>
<p> service TEXT,</p>
<p> embedding_description vector(1024),</p>
<p> llm_response TEXT</p>
<p> );</p>
<p>«»»<strong>)</strong></p>
<p>conn<strong>.</strong><em>commit</em><strong>()</strong></p>
<p>cur<strong>.</strong><em>close</em><strong>()</strong></p>
<p>conn<strong>.</strong><em>close</em><strong>()</strong></p>
<p>В реализованной системе векторная база содержит таблицу, где для каждого ранее решённого инцидента хранится:</p>
<ul>
<li>идентификатор;</li>
<li>время создания;</li>
<li>ИТ-сервис, по которому зарегистрирован инцидент;</li>
<li>текстовые поля (описание, решение и др.);</li>
<li>векторное представление описания. </li>
</ul>
<p>При поступлении нового инцидента выполняется SQL-запрос с оператором поиска ближайших соседей по вектору. В запросе указывается количество требуемых ближайших соседей <em>k</em> и условие по метрике (косинусной близости). Например, можно найти <strong>5 наиболее похожих инцидентов</strong> по косинусному расстоянию, превышающему некоторый порог. </p>
<p>Пример SQL-кода для поиска похожих инцидентов:</p>
<p># Функция для поиска похожих векторов по embedding</p>
<p><strong>def</strong> search_similar_vectors<strong>(</strong>query<strong>,</strong> k<strong>=</strong>5<strong>,</strong> distance_threshold<strong>=</strong>0.5<strong>):</strong></p>
<p> query_vector <strong>=</strong> model<strong>.</strong><em>encode</em><strong>([</strong>query<strong>])[</strong>0<strong>].</strong><em>tolist</em><strong>()</strong></p>
<p> <strong>try</strong><strong>:</strong></p>
<p> cur<strong>.</strong><em>execute</em><strong>(</strong>«»»</p>
<p> SELECT id, number, creation_date, report_text, theme, description, service, embedding_combined,</p>
<p> (embedding_combined <=> %s::vector) AS distance</p>
<p> FROM incidents</p>
<p> WHERE embedding_combined <=> %s::vector < %s</p>
<p> ORDER BY distance</p>
<p> LIMIT %s</p>
<p> «»»<strong>,</strong> <strong>(</strong>query_vector<strong>,</strong> query_vector<strong>,</strong> distance_threshold<strong>,</strong> k<strong>))</strong></p>
<p> results <strong>=</strong> cur<strong>.</strong><em>fetchall</em><strong>()</strong></p>
<p> <strong>return</strong> results</p>
<p> <strong>except</strong> <strong>Exception</strong> <strong>as</strong> e<strong>:</strong></p>
<p> conn<strong>.</strong><em>rollback</em><strong>()</strong></p>
<p> <strong>print</strong><strong>(</strong>f»Ошибка при поиске векторов: {e}»<strong>)</strong></p>
<p> <strong>return</strong> <strong>[]</strong></p>
<p>На практике порог пришлось откорректировать. Изначально допускались совпадения с близостью >0.5, но это приводило к попаданию нерелевантных случаев. После наблюдения за работой сервиса на протяжение пары недель порог был снижен до 0.15. Качество отбора существенно улучшилось – в список кандидатов стали попадать действительно только похожие тикеты. В дальнейшем можно будет настроить более тонкое ограничение: например, по категории услуги или по давности, чтобы сузить контекст поиска. </p>
<p>Найденные похожие инциденты извлекаются из БД вместе с их описаниями и решениями. Отбирается до 5 записей, которые передаются языковой модели на анализ. После создания рекомендации информация о новом инциденте заносится в базу; сохраняется эмбеддинг инцидента, чтобы будущие запросы находили и этот случай, и текст решения, связанный с данным описанием. Так база знаний постоянно пополняется новыми примерами, со временем качество подсказок будет расти.</p>
<p><strong>Выбор и использование LLM: Ollama + Gemma 3</strong></p>
<p>Важнейший компонент системы – <strong>большая языковая модель</strong> (LLM). Модель используется дважды: для улучшения описания и финальной генерации текста рекомендации. Поскольку проект развёртывается в офлайн-среде (без доступа к облачным API), выбор пал на<strong> модель с открытым исходным кодом</strong>, которую можно запускать локально на имеющемся оборудовании. Ограниченные ресурсы (отсутствие GPU) на этапе MVP накладывали в свою очередь на модель ограничения по числу параметров, иначе скорость ответа была бы неудовлетворительной. После тестирования нескольких моделей приемлемую скорость удалось получить на моделях размером не более 4В (4 млрд. параметров).</p>
<p>Были рассмотрены несколько современных открытых LLM. Среди них: Qwen 2.5, T-lite 1.0, YandexGPT-5-Lite, Gemma-3. В итоге для прототипа была выбрана модель <strong>Gemma 3-4b-instruct</strong> – LLM с 4 миллиардами параметров, обученная следовать инструкциям (instruct-tuned). Хотя 4 млрд параметров – это существенно меньше, чем у самых продвинутых моделей, она справилась с задачами проекта. Модель была загружена в <strong>квантованном виде (4-бит)</strong>, что еще больше снизило требования к памяти (до нескольких гигабайт) при минимальной потере качества. Использование 4-битной квантованной модели позволило запускать инференс LLM на CPU достаточно быстро – создание рекомендации занимало примерно минуту. </p>
<p>Для простоты развёртывания модель Gemma 3b запускалась через инструмент <strong>Ollama</strong> – оптимизированный для LLM локальный сервис, который предоставляет простой API для генерации текста. Ollama облегчает использование моделей вроде Llama/Gemma: он берёт на себя загрузку модели в память, управление контекстом, ускорение за счёт квантования и так далее. Агент взаимодействует с Ollama по API, отправляет промпт и получает законченный ответ. </p>
<p>При работе я выявил некоторые <strong>проблемы со стабильностью Ollama</strong> – иногда мне не удавалось получить ответ от модели без видимых проблем в логах. В дальнейшем планирую постоянно обновлять версию Ollama, пока проблема со стабильностью не будет решена. В перспективе планирую полную замена Ollama на другой подобный инструмент: например VLLM (если появится сервер с GPU). </p>
<p>Качество ответов выбранной модели оказалось вполне приемлемым. Несмотря на небольшой размер, <strong>Gemma-3-4b</strong> в большинстве случаев формулировала корректные и уместные рекомендации для инцидентов. Модель редко «галлюцинировала», генерируя посторонний контент: все выводы действительно основывались на предоставленном контексте, как и требовалось. Очевидно, ограничение области знания только информацией об инцидентах компании (через примеры из базы) дисциплинирует даже небольшую LLM и помогает ей генерировать правдоподобные и целевые советы.</p>
<p><strong>Применение LangChain и RAG</strong></p>
<p>Для организации описанного взаимодействия компонентов использовался фреймворк <strong>LangChain</strong>, который предоставляет абстракции для построения цепочек вызовов LLM с дополнением из внешних источников. Сценарий работы RAG-агента был реализован как последовательность из нескольких шагов (Chain) с промежуточным хранением результатов. По сути, была сформирована связка «<em>Retriever – Analyzer – Action»</em>: сначала блок <strong>Retriever</strong> выполняет векторный поиск похожих случаев, затем блок <strong>Analyzer</strong> (LLM) на основе найденного анализирует ситуацию и формирует ответ, и наконец блок <strong>Action</strong> доставляет этот ответ обратно в систему, в нашем случае – публикует комментарий.</p>
<p>В LangChain предусмотрены компоненты для интеграции с векторными хранилищами (VectorStore). Однако прямой поддержки PGVector нет, поэтому обращение к базе PostgreSQL происходит через собственный запрос. Но концептуально это тот же retriever: агент получает на вход текст запроса (описание инцидента), обращается к векторному индексу и получает топ-N документов (описаний прошлых инцидентов) в качестве релевантного контекста. Далее формируется <strong>промт для LLM</strong>, содержащий описание нового инцидента и извлеченные описания прошлых. </p>
<p>Пример кода, реализующего запрос к LLM через LangChain:</p>
<p>#Обработка инцидента с помощью LLM</p>
<p><strong>def</strong> get_llm_response <strong>(</strong>query<strong>,</strong> context<strong>):</strong></p>
<p> # Настройка LangChain</p>
<p> llm <strong>=</strong> OllamaLLM<strong>(</strong>model<strong>=</strong>«gemma-3-4b-it.Q4_K_M:latest»<strong>,</strong> base_url<strong>=</strong>«http://localhost:11434»<strong>,</strong> num_ctx<strong>=</strong>8192<strong>)</strong></p>
<p> # Создание промпта</p>
<p> prompt_template <strong>=</strong> «»»</p>
<p> Вы являетесь ИТ-специалистом, который обрабатывает ИТ-инциденты.</p>
<p> На основе предоставленной информации о ранее закрытых инцидентах, дайте заключение о том, как лучше решить текущий инцидент.</p>
<p> Ответ должен быть не более 3000 символов.</p>
<p> Не повторяйтесь.</p>
<p> Информация о ранее закрытых инцидентах:</p>
<p> {context}</p>
<p> Текущий инцидент:</p>
<p> {query}</p>
<p> Ваше заключение:</p>
<p> «»»</p>
<p> prompt <strong>=</strong> PromptTemplate<strong>(</strong></p>
<p> input_variables<strong>=[</strong>«context»<strong>,</strong> «incident»<strong>],</strong></p>
<p> template<strong>=</strong>prompt_template</p>
<p> <strong>)</strong></p>
<p> # Создание цепочки</p>
<p> chain <strong>=</strong> RunnableSequence<strong>(</strong>prompt <strong>|</strong> llm <strong>|</strong> StrOutputParser<strong>())</strong></p>
<p> # Обработка результата с помощью LLM</p>
<p> llm_response <strong>=</strong> chain<strong>.</strong><em>invoke</em><strong>({</strong>«context»<strong>:</strong> context<strong>,</strong> «query»<strong>:</strong> query<strong>})</strong></p>
<p> # Вывод результатов</p>
<p> <strong>return</strong> llm_response</p>
<p>После генерации текста LangChain-цепочка выполняет финальный шаг: передаёт полученный ответ обратно через API Service Desk, добавляя комментарий в тикет. Инженер, работающий с системой, видит новый комментарий от виртуального ассистента (агента) с рекомендацией и списком ссылок на похожие инциденты. Дальше он может следовать совету либо игнорировать его: решение всегда остается за человеком, агент лишь предоставляет информацию для поддержки решения.</p>
<p><strong>Статистика внедрения и эффективность</strong></p>
<p>Разработанный RAG-агент был развёрнут как MVP <strong>на части потока инцидентов</strong> для тестирования. На момент подготовки статьи система обработала около <strong>500 инцидентов</strong>. Среднее время, затрачиваемое агентом на полный цикл (от получения данных до публикации комментария), составило <strong>1–2 минуты на инцидент</strong>. Это время существенно меньше того, которое затратил бы инженер на ручной поиск похожих случаев и анализ.<br>Э<strong>кономия составляет в среднем 10 минут</strong> на каждый инцидент. Таким образом, например при ~1000 инцидентах в месяц можно сэкономить около <strong>167 человеко-часов</strong>, что эквивалентно работе примерно <strong>1 инженера</strong> полной занятости.</p>
<p> Некоторые ключевые метрики и результаты внедрения MVP:</p>
<ul>
<li><strong>Сокращение времени анализа:</strong> ~10 минут экономии при анализе инцидента, более 80 часов в месяц экономии труда специалистов. Инженеры могут направить это время на более сложные задачи вместо поиска в документации.</li>
<li><strong>Оптимизация штата:</strong> высвобождение эквивалента 0,5 инженера за счет автоматизации.</li>
<li><strong>Снижение финансовых затрат:</strong> экономия фонда оплаты труда оценочно достигает <strong>200-300 тыс. рублей в месяц</strong> за счёт автоматизации рутины, даже с учётом стоимости вычислительных ресурсов для работы агента.</li>
<li><strong>Ускорение решения инцидентов:</strong> чем больше скорость поиска решение, тем меньше время простоя сервисов и сопутствующие убытки компании. Выгода от сокращения времени простоя может составлять <strong>до нескольких миллионов рублей в месяц</strong> для инцидентов, влияющих на продажи или критически важные процессы.</li>
<li><strong>Затраты на поддержку решения:</strong> использование открытых моделей позволило избежать прямых расходов на лицензии. Стоимость инфраструктуры, поддержка и доработка совокупно обходится не более чем в <strong>100 тыс. руб/мес</strong>. С учётом достигаемой экономии, <strong>окупаемость</strong> решения – порядка <strong>1-2 месяцев. </strong>Первоначальные вложения (включая разработку) были невелики и тоже быстро окупились.</li>
</ul>
<p>В целом, пилотное внедрение подтвердило ценность системы: агент экономит время и улучшает качество решения инцидентов. </p>
<p>Ниже приведены примеры комментариев, которые RAG-агент добавил в тикет, предложив вероятное решение на основе похожих случаев. </p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdPsWVoa6yD7gkYqBgm4l2PvGJokaT7K17p63UexcdTlWrsFb_lCY4nzBxFc3-u71ECWd7gxrDjX3YE5sNeXTgybxOckUwKpz8NLUCzDXPOoYn255LF6WqPaTkcsKF6ap_hDRwoVFgDEkvzRdAZBtw?key=N3Pb6Xo0scwE1yATXwqJXg" alt="RAG-агент для автоматизации инцидент-менеджмента"/></figure>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdd2YfsjvBtGfU9gcgyy8xavpN82P4dPbWeKVG_MYvtodJRf5qEbQEH0d_eJkLuvO-Yj_QyZM0exXrwCg3xtVKSGxydm9uujwIxVuab08_BzWfUrAzVtHqHxWlqkpaP0yD1NSa5Rgms5CPmIr0GjUo?key=N3Pb6Xo0scwE1yATXwqJXg" alt="RAG-агент для автоматизации инцидент-менеджмента"/></figure>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfAfMEpogQMEaYjKQ6qSTJXhl-PKBmRg80NHP8Y_pFCIQD1IoS4gL_8lHZcv0t1imvOCLyYkQuC3ssZN6BlXJPvi0GAb02P1jav5IB_1_ChKuJ1mlEtryDDWTvh6PuMeeO3WAteTtMhz7lc3xQiKxA?key=N3Pb6Xo0scwE1yATXwqJXg" alt="RAG-агент для автоматизации инцидент-менеджмента"/></figure>
<p><strong>Выводы и дальнейшее развитие</strong></p>
<p>Подход с использованием векторных представлений и больших языковых моделей может эффективно помочь в управлении инцидентами. По итогам работы MVP принято решение развивать проект дальше, расширять его охват и функциональность. </p>
<p><strong>Качество рекомендаций.</strong> Анализ итогов работы MVP показал, что в большинстве ситуаций советы агента корректны и полезны. Инженеры подтвердили, что полученные рекомендации часто совпадают с их собственными выводами, соответствуют реальным причинам проблем и помогают выработать способы решения. Конечно, были и ситуации, когда агент мог предложить неподходящее решение: например, если в базе ещё нет похожего кейса или описания инцидента слишком размыты. Но даже в таких случаях наличие подсказки расширяет круг решений и может навести инженера на правильную мысль.</p>
<p><strong>Проблемы и уроки</strong></p>
<ol>
<li>Иногда алгоритм подбирал нерелевантные инциденты в качестве похожих инцидентов. Причина крылась в слишком мягких критериях сходства; ситуацию удалось улучшить с помощью настройки порога косинусной близости. В дальнейшем я планирую решать проблему с помощью фильтрации по услугам и времени. </li>
<li>Качество исходных данных накладывает ограничения: если текст решения в прошлом инциденте был заполнен формально (например: «Исправлено» или «Решение применено»), то такой кейс принесёт мало пользы. Нужно <strong>улучшать качество закрытия инцидентов</strong>. Например, регламентировать заполнение поля «Решение» или автоматически проверять тексты решений инцидентов с помощью той же LLM. </li>
<li>Обнаружилось, что для некоторых специфических услуг или систем даже семантический поиск не даёт результатов из-за малого числа примеров. Поэтому необходимо использовать и накапливать <strong>базу знаний</strong> по редким категориям: например, создавать отдельные векторные базы по каждому направлению, куда можно добавлять не только инциденты, но и связанные артефакты (документацию, FAQ) для повышения качества. </li>
</ol>
<p><strong>Планы развития</strong></p>
<p>Следующими шагами в развитии системы станут: </p>
<ul>
<li>улучшение стабильности и производительности (в том числе перенос вычислений на GPU-сервер при появлении такового)</li>
<li>качественное обновление LLM-модели и подключение полного потока инцидентов.</li>
</ul>
<p>По мере накопления данных откроются новые возможности аналитики: автоматический анализ качества решений инцидентов, поиск скрытых закономерностей в причинах сбоев. В перспективе такой агент может эволюционировать в полноценного помощника SRE/DevOps-команды: не только подсказывать решения, но и проактивно уведомлять о повторяющихся проблемах, предлагать классификацию инцидентов, а возможно, и взаимодействовать с пользователями для сбора дополнительной информации.</p>
<p>Проект <strong>RAG-агента для инцидент-менеджмента</strong> показал, что современные методы NLP могут успешно применяться для интеллектуальной поддержки операционных процессов. Объединение методов семантического поиска и генерации позволяет извлекать ценность из корпоративной памяти, делает знания полезными и своевременными. </p>
</div><!-- .post-content -->
<div class="the-post-foot cf">
<div class="tag-share cf">
<div class="post-share">
<div class="post-share-icons cf">
<span class="counters">
</span>
<a href="https://www.facebook.com/sharer.php?u=https%3A%2F%2Fotus.ru%2Fjournal%2Frag-agent-dlya-avtomatizacii-incident-menedzhmenta%2F" class="link facebook wpel-icon-right" target="_blank" title="Share on Facebook" data-wpel-link="external" rel="nofollow external noopener noreferrer"><i class="fa fa-facebook"></i><span class="wpel-icon wpel-image wpel-icon-6"></span></a>
<a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fotus.ru%2Fjournal%2Frag-agent-dlya-avtomatizacii-incident-menedzhmenta%2F&text=RAG-%D0%B0%D0%B3%D0%B5%D0%BD%D1%82%20%D0%B4%D0%BB%D1%8F%20%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8%20%D0%B8%D0%BD%D1%86%D0%B8%D0%B4%D0%B5%D0%BD%D1%82-%D0%BC%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%BC%D0%B5%D0%BD%D1%82%D0%B0" class="link twitter wpel-icon-right" target="_blank" title="Share on Twitter" data-wpel-link="external" rel="nofollow external noopener noreferrer"><i class="fa fa-twitter"></i><span class="wpel-icon wpel-image wpel-icon-6"></span></a>
<a href="https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fotus.ru%2Fjournal%2Frag-agent-dlya-avtomatizacii-incident-menedzhmenta%2F" class="link linkedin wpel-icon-right" target="_blank" title="LinkedIn" data-wpel-link="external" rel="nofollow external noopener noreferrer"><i class="fa fa-linkedin"></i><span class="wpel-icon wpel-image wpel-icon-6"></span></a>
<a href="https://pinterest.com/pin/create/button/?url=https%3A%2F%2Fotus.ru%2Fjournal%2Frag-agent-dlya-avtomatizacii-incident-menedzhmenta%2F&media=&description=RAG-%D0%B0%D0%B3%D0%B5%D0%BD%D1%82%20%D0%B4%D0%BB%D1%8F%20%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8%20%D0%B8%D0%BD%D1%86%D0%B8%D0%B4%D0%B5%D0%BD%D1%82-%D0%BC%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%BC%D0%B5%D0%BD%D1%82%D0%B0" class="link pinterest wpel-icon-right" target="_blank" title="Pinterest" data-wpel-link="external" rel="nofollow external noopener noreferrer"><i class="fa fa-pinterest-p"></i><span class="wpel-icon wpel-image wpel-icon-6"></span></a>
</div>
</div>
</div>
</div>
<div class="post-nav">
<div class="post previous cf">
<a href="https://otus.ru/journal/kogortnyj-analiz-ltv-i-rfm-v-sql/" title="Prev Post" class="nav-icon" data-wpel-link="internal">
<i class="fa fa-angle-left"></i>
</a>
<span class="content">
<a href="https://otus.ru/journal/kogortnyj-analiz-ltv-i-rfm-v-sql/" class="image-link" rel="previous" data-wpel-link="internal">
</a>
<div class="post-meta">
<span class="label">Prev Post</span>
<div class="post-meta post-meta-b">
<h2 class="post-title">
<a href="https://otus.ru/journal/kogortnyj-analiz-ltv-i-rfm-v-sql/" data-wpel-link="internal">Когортный анализ, LTV и RFM в SQL</a>
</h2>
<div class="below">
<a href="https://otus.ru/journal/kogortnyj-analiz-ltv-i-rfm-v-sql/" class="meta-item date-link" data-wpel-link="internal"><time class="post-date" datetime="2025-04-24T09:08:37+00:00">24 апреля, 2025</time></a>
<span class="meta-sep"></span>
<span class="meta-item read-time">3 Mins Read</span>
</div>
</div> </div>
</span>
</div>
<div class="post next cf">
<a href="https://otus.ru/journal/kak-obuchenie-v-otus-pomoglo-specialistu-iz-nii-uluchshit-infrastrukturu-kompanii/" title="Next Post" class="nav-icon" data-wpel-link="internal">
<i class="fa fa-angle-right"></i>
</a>
<span class="content">
<a href="https://otus.ru/journal/kak-obuchenie-v-otus-pomoglo-specialistu-iz-nii-uluchshit-infrastrukturu-kompanii/" class="image-link" rel="next" data-wpel-link="internal">
<img width="150" height="106" src="data:image/svg+xml,%3Csvg%20viewBox%3D%270%200%20150%20106%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3C%2Fsvg%3E" class="attachment-thumbnail size-thumbnail lazyload wp-post-image" alt="Как обучение в OTUS помогло специалисту из НИИ улучшить инфраструктуру компании" decoding="async" data-srcset="https://otus.ru/journal/wp-content/uploads/2025/07/oj-1080x720-kopiya-150x106.png 150w, https://otus.ru/journal/wp-content/uploads/2025/07/oj-1080x720-kopiya-300x212.png 300w, https://otus.ru/journal/wp-content/uploads/2025/07/oj-1080x720-kopiya-1024x724.png 1024w, https://otus.ru/journal/wp-content/uploads/2025/07/oj-1080x720-kopiya-768x543.png 768w, https://otus.ru/journal/wp-content/uploads/2025/07/oj-1080x720-kopiya-1536x1086.png 1536w" data-src="https://otus.ru/journal/wp-content/uploads/2025/07/oj-1080x720-kopiya-150x106.png" data-sizes="(max-width: 150px) 100vw, 150px" title="Как обучение в OTUS помогло специалисту из НИИ улучшить инфраструктуру компании" /> </a>
<div class="post-meta">
<span class="label">Next Post</span>
<div class="post-meta post-meta-b">
<h2 class="post-title">
<a href="https://otus.ru/journal/kak-obuchenie-v-otus-pomoglo-specialistu-iz-nii-uluchshit-infrastrukturu-kompanii/" data-wpel-link="internal">Как обучение в OTUS помогло специалисту из НИИ улучшить инфраструктуру компании</a>
</h2>
<div class="below">
<a href="https://otus.ru/journal/kak-obuchenie-v-otus-pomoglo-specialistu-iz-nii-uluchshit-infrastrukturu-kompanii/" class="meta-item date-link" data-wpel-link="internal"><time class="post-date" datetime="2025-07-03T15:23:54+00:00">3 июля, 2025</time></a>
<span class="meta-sep"></span>
<span class="meta-item read-time">3 Mins Read</span>
</div>
</div> </div>
</span>
</div>
</div>
<section class="related-posts grid-3">
<h4 class="section-head"><span class="title">Читать ещё</span></h4>
<div class="ts-row posts cf">
<article class="post col-4">
<a href="https://otus.ru/journal/proekt-tg-autoposter-na-nest-js/" title="Проект «TG Autoposter на Nest.JS»" class="image-link" data-wpel-link="internal">
</a>
<div class="content">
<h3 class="post-title"><a href="https://otus.ru/journal/proekt-tg-autoposter-na-nest-js/" class="post-link" data-wpel-link="internal">Проект «TG Autoposter на Nest.JS»</a></h3>
<div class="post-meta">
<time class="post-date" datetime="2025-12-23T00:44:53+00:00">23 декабря, 2025</time>
</div>
</div>
</article >
<article class="post col-4">
<a href="https://otus.ru/journal/langtrainee-razrabotka-mvp-ai-platformy-dlya-personalizirovannogo-izucheniya-yazykov/" title="LangTrainee: разработка MVP AI-платформы для персонализированного изучения языков" class="image-link" data-wpel-link="internal">
</a>
<div class="content">
<h3 class="post-title"><a href="https://otus.ru/journal/langtrainee-razrabotka-mvp-ai-platformy-dlya-personalizirovannogo-izucheniya-yazykov/" class="post-link" data-wpel-link="internal">LangTrainee: разработка MVP AI-платформы для персонализированного изучения языков</a></h3>
<div class="post-meta">
<time class="post-date" datetime="2025-11-12T04:39:47+00:00">12 ноября, 2025</time>
</div>
</div>
</article >
<article class="post col-4">
<a href="https://otus.ru/journal/pochemu-my-ne-uhodim-iz-it-dazhe-kogda-hochetsya/" title="Почему мы не уходим из IT даже когда хочется" class="image-link" data-wpel-link="internal">
<img width="270" height="180" src="data:image/svg+xml,%3Csvg%20viewBox%3D%270%200%20270%20180%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3C%2Fsvg%3E" class="image lazyload wp-post-image" alt="Почему мы не уходим из IT даже когда хочется" title="Почему мы не уходим из IT даже когда хочется" decoding="async" data-srcset="https://otus.ru/journal/wp-content/uploads/2025/11/oj-1080x720-kopiya-1-270x180.jpg 270w, https://otus.ru/journal/wp-content/uploads/2025/11/oj-1080x720-kopiya-1-770x515.jpg 770w, https://otus.ru/journal/wp-content/uploads/2025/11/oj-1080x720-kopiya-1-370x245.jpg 370w" data-src="https://otus.ru/journal/wp-content/uploads/2025/11/oj-1080x720-kopiya-1-270x180.jpg" data-sizes="(max-width: 270px) 100vw, 270px" /> </a>
<div class="content">
<h3 class="post-title"><a href="https://otus.ru/journal/pochemu-my-ne-uhodim-iz-it-dazhe-kogda-hochetsya/" class="post-link" data-wpel-link="internal">Почему мы не уходим из IT даже когда хочется</a></h3>
<div class="post-meta">
<time class="post-date" datetime="2025-11-04T12:29:53+00:00">4 ноября, 2025</time>
</div>
</div>
</article >
</div>
</section>
</article> <!-- .the-post -->
</div>
<aside class="col-4 sidebar">
<div class="inner">
<ul>
<li id="search-2" class="widget widget_search"><h5 class="widget-title"><span>Поиск по блогу</span></h5>
<form method="get" class="search-form" action="https://otus.ru/journal/">
<label>
<span class="screen-reader-text">Search for:</span>
<input type="search" class="search-field" placeholder="Введите запрос и нажмите Enter" value="" name="s" title="Search for:" />
</label>
<button type="submit" class="search-submit"><i class="fa fa-search"></i></button>
</form>
</li>
<li id="tag_cloud-5" class="widget widget_tag_cloud"><h5 class="widget-title"><span>Метки</span></h5><div class="tagcloud"><a href="https://otus.ru/journal/tag/android-2/" class="tag-cloud-link tag-link-74 tag-link-position-1" style="font-size: 12.472222222222pt;" aria-label="Android (34 элемента)" data-wpel-link="internal">Android</a>
<a href="https://otus.ru/journal/tag/c-3/" class="tag-cloud-link tag-link-91 tag-link-position-2" style="font-size: 10.916666666667pt;" aria-label="C (23 элемента)" data-wpel-link="internal">C</a>
<a href="https://otus.ru/journal/tag/c-2/" class="tag-cloud-link tag-link-81 tag-link-position-3" style="font-size: 12.666666666667pt;" aria-label="C# (35 элементов)" data-wpel-link="internal">C#</a>
<a href="https://otus.ru/journal/tag/c/" class="tag-cloud-link tag-link-20 tag-link-position-4" style="font-size: 12.472222222222pt;" aria-label="c++ (34 элемента)" data-wpel-link="internal">c++</a>
<a href="https://otus.ru/journal/tag/computer-science/" class="tag-cloud-link tag-link-209 tag-link-position-5" style="font-size: 15.972222222222pt;" aria-label="computer science (78 элементов)" data-wpel-link="internal">computer science</a>
<a href="https://otus.ru/journal/tag/css/" class="tag-cloud-link tag-link-288 tag-link-position-6" style="font-size: 8.6805555555556pt;" aria-label="CSS (13 элементов)" data-wpel-link="internal">CSS</a>
<a href="https://otus.ru/journal/tag/data-science/" class="tag-cloud-link tag-link-151 tag-link-position-7" style="font-size: 8pt;" aria-label="Data Science (11 элементов)" data-wpel-link="internal">Data Science</a>
<a href="https://otus.ru/journal/tag/devops/" class="tag-cloud-link tag-link-98 tag-link-position-8" style="font-size: 10.138888888889pt;" aria-label="devops (19 элементов)" data-wpel-link="internal">devops</a>
<a href="https://otus.ru/journal/tag/docker/" class="tag-cloud-link tag-link-143 tag-link-position-9" style="font-size: 8.2916666666667pt;" aria-label="Docker (12 элементов)" data-wpel-link="internal">Docker</a>
<a href="https://otus.ru/journal/tag/gamedev/" class="tag-cloud-link tag-link-25 tag-link-position-10" style="font-size: 11.694444444444pt;" aria-label="gamedev (28 элементов)" data-wpel-link="internal">gamedev</a>
<a href="https://otus.ru/journal/tag/hr/" class="tag-cloud-link tag-link-103 tag-link-position-11" style="font-size: 8pt;" aria-label="hr (11 элементов)" data-wpel-link="internal">hr</a>
<a href="https://otus.ru/journal/tag/html/" class="tag-cloud-link tag-link-217 tag-link-position-12" style="font-size: 11.208333333333pt;" aria-label="HTML (25 элементов)" data-wpel-link="internal">HTML</a>
<a href="https://otus.ru/journal/tag/ios/" class="tag-cloud-link tag-link-101 tag-link-position-13" style="font-size: 8.9722222222222pt;" aria-label="iOS (14 элементов)" data-wpel-link="internal">iOS</a>
<a href="https://otus.ru/journal/tag/it/" class="tag-cloud-link tag-link-50 tag-link-position-14" style="font-size: 10.527777777778pt;" aria-label="IT (21 элемент)" data-wpel-link="internal">IT</a>
<a href="https://otus.ru/journal/tag/java/" class="tag-cloud-link tag-link-75 tag-link-position-15" style="font-size: 15.680555555556pt;" aria-label="Java (73 элемента)" data-wpel-link="internal">Java</a>
<a href="https://otus.ru/journal/tag/javascript/" class="tag-cloud-link tag-link-83 tag-link-position-16" style="font-size: 14.319444444444pt;" aria-label="JavaScript (53 элемента)" data-wpel-link="internal">JavaScript</a>
<a href="https://otus.ru/journal/tag/linux/" class="tag-cloud-link tag-link-141 tag-link-position-17" style="font-size: 11.888888888889pt;" aria-label="Linux (29 элементов)" data-wpel-link="internal">Linux</a>
<a href="https://otus.ru/journal/tag/machine-learning/" class="tag-cloud-link tag-link-167 tag-link-position-18" style="font-size: 8.6805555555556pt;" aria-label="Machine Learning (13 элементов)" data-wpel-link="internal">Machine Learning</a>
<a href="https://otus.ru/journal/tag/otus-book/" class="tag-cloud-link tag-link-261 tag-link-position-19" style="font-size: 9.9444444444444pt;" aria-label="otus book (18 элементов)" data-wpel-link="internal">otus book</a>
<a href="https://otus.ru/journal/tag/php/" class="tag-cloud-link tag-link-45 tag-link-position-20" style="font-size: 10.527777777778pt;" aria-label="PHP (21 элемент)" data-wpel-link="internal">PHP</a>
<a href="https://otus.ru/journal/tag/python/" class="tag-cloud-link tag-link-27 tag-link-position-21" style="font-size: 16.944444444444pt;" aria-label="Python (99 элементов)" data-wpel-link="internal">Python</a>
<a href="https://otus.ru/journal/tag/qa/" class="tag-cloud-link tag-link-155 tag-link-position-22" style="font-size: 11.402777777778pt;" aria-label="qa (26 элементов)" data-wpel-link="internal">qa</a>
<a href="https://otus.ru/journal/tag/sql/" class="tag-cloud-link tag-link-38 tag-link-position-23" style="font-size: 12.861111111111pt;" aria-label="SQL (37 элементов)" data-wpel-link="internal">SQL</a>
<a href="https://otus.ru/journal/tag/team-lead/" class="tag-cloud-link tag-link-364 tag-link-position-24" style="font-size: 9.9444444444444pt;" aria-label="team lead (18 элементов)" data-wpel-link="internal">team lead</a>
<a href="https://otus.ru/journal/tag/unity/" class="tag-cloud-link tag-link-24 tag-link-position-25" style="font-size: 8pt;" aria-label="unity (11 элементов)" data-wpel-link="internal">unity</a>
<a href="https://otus.ru/journal/tag/algoritmy/" class="tag-cloud-link tag-link-30 tag-link-position-26" style="font-size: 9.9444444444444pt;" aria-label="Алгоритмы (18 элементов)" data-wpel-link="internal">Алгоритмы</a>
<a href="https://otus.ru/journal/tag/bazy-dannyh/" class="tag-cloud-link tag-link-40 tag-link-position-27" style="font-size: 10.138888888889pt;" aria-label="Базы данных (19 элементов)" data-wpel-link="internal">Базы данных</a>
<a href="https://otus.ru/journal/tag/matematika/" class="tag-cloud-link tag-link-44 tag-link-position-28" style="font-size: 10.916666666667pt;" aria-label="Математика (23 элемента)" data-wpel-link="internal">Математика</a>
<a href="https://otus.ru/journal/tag/arhitektura-po/" class="tag-cloud-link tag-link-10 tag-link-position-29" style="font-size: 9.4583333333333pt;" aria-label="архитектура ПО (16 элементов)" data-wpel-link="internal">архитектура ПО</a>
<a href="https://otus.ru/journal/tag/bazy-dannyh-2/" class="tag-cloud-link tag-link-251 tag-link-position-30" style="font-size: 10.138888888889pt;" aria-label="базы данных (19 элементов)" data-wpel-link="internal">базы данных</a>
<a href="https://otus.ru/journal/tag/vebinar/" class="tag-cloud-link tag-link-201 tag-link-position-31" style="font-size: 13.930555555556pt;" aria-label="вебинар (48 элементов)" data-wpel-link="internal">вебинар</a>
<a href="https://otus.ru/journal/tag/dajdzhest/" class="tag-cloud-link tag-link-308 tag-link-position-32" style="font-size: 10.722222222222pt;" aria-label="дайджест (22 элемента)" data-wpel-link="internal">дайджест</a>
<a href="https://otus.ru/journal/tag/zapis-vebinara/" class="tag-cloud-link tag-link-226 tag-link-position-33" style="font-size: 14.902777777778pt;" aria-label="запись вебинара (61 элемент)" data-wpel-link="internal">запись вебинара</a>
<a href="https://otus.ru/journal/tag/zapis-uroka/" class="tag-cloud-link tag-link-272 tag-link-position-34" style="font-size: 16.069444444444pt;" aria-label="запись урока (80 элементов)" data-wpel-link="internal">запись урока</a>
<a href="https://otus.ru/journal/tag/informacionnaya-bezopasnost/" class="tag-cloud-link tag-link-232 tag-link-position-35" style="font-size: 10.138888888889pt;" aria-label="информационная безопасность (19 элементов)" data-wpel-link="internal">информационная безопасность</a>
<a href="https://otus.ru/journal/tag/karera-v-it/" class="tag-cloud-link tag-link-292 tag-link-position-36" style="font-size: 9.9444444444444pt;" aria-label="карьера в IT (18 элементов)" data-wpel-link="internal">карьера в IT</a>
<a href="https://otus.ru/journal/tag/podborka/" class="tag-cloud-link tag-link-7 tag-link-position-37" style="font-size: 12.666666666667pt;" aria-label="подборка (35 элементов)" data-wpel-link="internal">подборка</a>
<a href="https://otus.ru/journal/tag/podborka-statej/" class="tag-cloud-link tag-link-219 tag-link-position-38" style="font-size: 15.777777777778pt;" aria-label="подборка статей (75 элементов)" data-wpel-link="internal">подборка статей</a>
<a href="https://otus.ru/journal/tag/programmirovanie/" class="tag-cloud-link tag-link-65 tag-link-position-39" style="font-size: 22pt;" aria-label="программирование (332 элемента)" data-wpel-link="internal">программирование</a>
<a href="https://otus.ru/journal/tag/proekt/" class="tag-cloud-link tag-link-321 tag-link-position-40" style="font-size: 11.888888888889pt;" aria-label="проект (29 элементов)" data-wpel-link="internal">проект</a>
<a href="https://otus.ru/journal/tag/proektnaya-rabota/" class="tag-cloud-link tag-link-310 tag-link-position-41" style="font-size: 11.597222222222pt;" aria-label="проектная работа (27 элементов)" data-wpel-link="internal">проектная работа</a>
<a href="https://otus.ru/journal/tag/seti/" class="tag-cloud-link tag-link-181 tag-link-position-42" style="font-size: 12.958333333333pt;" aria-label="сети (38 элементов)" data-wpel-link="internal">сети</a>
<a href="https://otus.ru/journal/tag/testirovanie/" class="tag-cloud-link tag-link-69 tag-link-position-43" style="font-size: 13.930555555556pt;" aria-label="тестирование (48 элементов)" data-wpel-link="internal">тестирование</a>
<a href="https://otus.ru/journal/tag/upravlenie-komandoj/" class="tag-cloud-link tag-link-63 tag-link-position-44" style="font-size: 11.694444444444pt;" aria-label="управление командой (28 элементов)" data-wpel-link="internal">управление командой</a>
<a href="https://otus.ru/journal/tag/habr-2/" class="tag-cloud-link tag-link-203 tag-link-position-45" style="font-size: 13.930555555556pt;" aria-label="хабр (48 элементов)" data-wpel-link="internal">хабр</a></div>
</li>
</ul>
</div>
</aside>
</div> <!-- .ts-row -->
</div> <!-- .main -->
<footer class="main-footer dark bold">
<section class="lower-footer cf">
<div class="wrap">
<div class="links">
<div class="menu-menju-navykov-container"><ul id="menu-menju-navykov-1" class="menu"><li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10413"><a href="https://otus.ru/categories/programming/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Программирование<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10414"><a href="https://otus.ru/categories/architecture/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Архитектура<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10415"><a href="https://otus.ru/categories/operations/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Инфраструктура<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10416"><a href="https://otus.ru/categories/information-security-courses/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Безопасность<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10417"><a href="https://otus.ru/categories/data-science/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Data Science<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10418"><a href="https://otus.ru/categories/gamedev/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">GameDev<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10419"><a href="https://otus.ru/categories/marketing-business/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Управление<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10420"><a href="https://otus.ru/categories/analytics/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Аналитика и анализ<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10421"><a href="https://otus.ru/categories/testing/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Тестирование<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
</ul></div> </div>
<p class="copyright"> © 2015-2026 OTUS </p>
<div class="to-top">
<a href="#" class="back-to-top"><i class="fa fa-angle-up"></i> Top</a>
</div>
</div>
</section>
</footer>
</div> <!-- .main-wrap -->
<div class="mobile-menu-container off-canvas" id="mobile-menu">
<a href="#" class="close"><i class="fa fa-times"></i></a>
<div class="logo">
</div>
<ul class="mobile-menu"></ul>
</div>
<div class="search-modal-wrap">
<div class="search-modal-box" role="dialog" aria-modal="true">
<form method="get" class="search-form" action="https://otus.ru/journal/">
<input type="search" class="search-field" name="s" placeholder="Search..." value="" required />
<button type="submit" class="search-submit visuallyhidden">Submit</button>
<p class="message">
Type above and press <em>Enter</em> to search. Press <em>Esc</em> to cancel. </p>
</form>
</div>
</div>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/plugins/clearfy/components/comments-plus/assets/js/url-span.js" id="wbcr-comments-plus-url-span-js"></script>
<script type="text/javascript" id="ez-toc-scroll-scriptjs-js-extra">
/* <![CDATA[ */
var eztoc_smooth_local = {"scroll_offset":"0"};
/* ]]> */
</script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/plugins/easy-table-of-contents/assets/js/smooth_scroll.min.js" id="ez-toc-scroll-scriptjs-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/plugins/easy-table-of-contents/vendor/js-cookie/js.cookie.min.js" id="ez-toc-js-cookie-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/plugins/easy-table-of-contents/vendor/sticky-kit/jquery.sticky-kit.min.js" id="ez-toc-jquery-sticky-kit-js"></script>
<script type="text/javascript" id="ez-toc-js-js-extra">
/* <![CDATA[ */
var ezTOC = {"smooth_scroll":"1","visibility_hide_by_default":"","scroll_offset":"0","fallbackIcon":"<span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span>"};
/* ]]> */
</script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/plugins/easy-table-of-contents/assets/js/front.min.js" id="ez-toc-js-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/custom-script.js" id="custom-script-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/magnific-popup.js" id="magnific-popup-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/jquery.fitvids.js" id="jquery-fitvids-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-includes/js/imagesloaded.min.js" id="imagesloaded-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/object-fit-images.js" id="object-fit-images-js"></script>
<script type="text/javascript" id="contentberg-theme-js-extra">
/* <![CDATA[ */
var Bunyad = {"custom_ajax_url":"\/journal\/rag-agent-dlya-avtomatizacii-incident-menedzhmenta\/"};
/* ]]> */
</script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/theme.js" id="contentberg-theme-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/theia-sticky-sidebar.js" id="theia-sticky-sidebar-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/jquery.slick.js" id="jquery-slick-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/jarallax.js" id="jarallax-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-includes/js/masonry.min.js" id="masonry-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-includes/js/jquery/jquery.masonry.min.js" id="jquery-masonry-js"></script>
</body>
</html>
<!-- Cache served by breeze CACHE - Last modified: Tue, 10 Mar 2026 15:19:42 GMT -->