С ростом числа обращений в Service Desk классические ML-решения перестали покрывать все сценарии. Что же с этим делать?
Привет, Хабр! Я — Дмитрий Терентьев, ведущий специалист по науке о данных в Центре компетенций сопровождения IT-продуктов. Работаю с данными больше восьми лет, последние четыре — в Лемана Тех. В этой статье по мотивам доклада с AiConf я расскажу об эволюции моделей машинного обучения в поддержке и как удалось дополнить экосистему поддержки LLM с RAG для человекообразных ответов по Wiki и интеллектуальной эскалации к живым специалистам.

Мы разберем:
архитектуру эволюции: от классических ML-моделей (бустинги) и других ML-алгоритмов до гибридной системы с LLM;
стратегию внедрения: зачем RAG для работы с документацией и где классические алгоритмы остаются эффективнее;
подводные камни: баланс между автоматизацией (статьи, шаблоны) и «очеловечиванием» ответов, контроль галлюцинаций;
перспективы: интеграция с Problem&Quality Management и кастомизация LLM под домен;
опыт удачных и неудачных подходов.
Контекст
Чтобы понимать, с чем работают наши продукты, нужно осознавать масштаб. У нас в Лемана Тех задействовано более 40 тысяч сотрудников, 11 дарксторов, 6 РЦ, 112 магазинов, более 500 бизнес-систем, свыше 2500 сервисных операций и 100 000 обращений в поддержку от сотрудников в месяц.
Обращения бывают совершенно разноплановые — код сломался, или мы видим, что кто-то не может пользоваться принтером, ломается фискальник, нет доступа к каким-то информационным системам. Весь процесс обращения управляется инцидент-менеджментом.

Управление инцидентами для самых маленьких
Цель управления инцидентами — максимально быстрое восстановление IT-услуг с минимальными потерями для бизнеса.

В ITSM-системе используются два типа обращений:
Инциденты — незапланированные прерывания или снижение качества услуг
Здесь нужно провести анализ, разобраться с причинами и как можно быстрее устранить их. Желательно еще устранить первопричины, чтобы избежать рецидивов.
Запросы на обслуживание — запросы пользователей на информацию, консультации, доступ или стандартные изменения
Это плановое/внеплановое обслуживание — ничего анализировать не надо, они просто проводятся.
Всё это живёт в ITSM (IT Service Management) — это подход к организации управления IT-услугами, направленный на удовлетворение потребностей бизнеса.
Путь обращений в поддержке Лемана Тех
У нас четыре линии поддержки, различающиеся по времени реакции и по стоимости для компании от L1 до L4 (самые дорогие специалисты). Это сотрудники продуктовых команд, которые разрабатывают продукты и поддерживают их — естественно, они дороже всех.

Здесь стоит обратить внимание на время реакции. Согласно регламентам, мы можем себе позволить 20 минут ничего не делать с обращением, а по некоторым обращениям даже до 60 минут. То есть вы написали, что у вас что-то сломалось, и час ничего не происходит. По крайней мере, так было раньше. Это регламент для живых людей.
Обычный путь обращения в нашей поддержке выглядит следующим образом:
Весьма мудрёная схема, непросто в ней разобраться. Потому есть цифровой путь обращения:

У нас есть каналы поступления — это почта, портал самообслуживания, система ITSM. Также пользователь может оставить обращение по телефону. После того, как обращение зарегистрировано, оно поступает в наш классификатор нулевого уровня и классификатор первого уровня. Классификатор нулевого уровня определяет, какая это бизнес-система. При успешной классификации мы переходим к классификатору первого уровня, который может подсказать, что это за операция.
Затем — классификатор автоматических решений. Как это работает? У нас есть некий набор инструкций и статей, пользуясь которыми пользователь может самостоятельно решить своё обращение, удовлетворить свои цифровые потребности и обращение закрыть. Все довольны — и мы, и пользователь. Классификатор автоматических решений тоже состоит из двух классификаторов. На нулевом уровне определяется, можно ли решить данное обращение инструкцией/статьёй или нет, а на первом уровне работаем по перечню статей/ инструкций.
Важно: сначала идёт классификатор и некоторые классы, которые сообщаются с RAG-конвейером. Открывается чат, обращение пользователя попадает туда. Если оно не было классифицировано как для автоматизированного решения, то пользователю отвечает наш умный бот, к которому прикручен RAG, по нашей технической документации. Это происходит далеко не для всех классов, а только для тех, где это действительно нужно.
Эволюция и подходы в моделях поддержки в Лемана Тех
Пробежимся по эволюции, а потом рассмотрим всё это более детально.
Подход с бустингами

Как и многие, мы начинали с бустингов, рассмотрели и XGBoost, и CatBoost, остановились на Light GBM (Gradient Boosting Machine). По своим вычислительным запросам он не требует так много памяти, как XGBoost, и CatBoost, и при этом работает достаточно точно для нас.
В рамках подготовки данных для него мы предобрабатываем текстовую часть обращения пользователя, удаляем стоп-слова и прочие шероховатости автора, проводим стемминг, всё приводим к одному корню и превращаем в вектора при помощи tf-idf.
У нас есть ещё one-hot фичи: время и день поступления обращения, должность сотрудника и место, где он работает. Эти фичи мы предобрабатываем в one-hot encoder, кладём в бустинг, получаем метрику f1 макро = 0,86. Весьма недурно.
Какие были наши следующие итерации в попытках развивать наши LLM-модели?
Во время бума рекуренток мы, конечно, обязаны были их попробовать.
Подход с LSTM

Это был подход с LSTM. Мы использовали классические ячейки LSTM, GRU-ячейки как более быстрые, пробовали Sequence-to-Sequence (Seq2Seq) — это когда с одной стороны sequence текст обращения пользователя, а со второй — комбинаторика из бизнес-системы и операция. Напоминаю, что у нас более 500 классов и 2 500 субклассов. Задача очень нетривиальная для классификатора. Метрика получилась, к сожалению, ниже при значительных вычислительных затратах. Несколько суток на nvidia tesla v100, всё это пыхтит, пытаясь хорошо научить — в итоге хуже, чем бустинг. В прод не пошёл.
Далее в эпоху модных трансформеров попробовали Bert, Roberta, Rubert, Electra, различные наши локализованные «Берты» по мере того, как энтузиасты и различные организации выпускали их.
Подход трансформерами

Текст предобрабатывали по-прежнему регулярками, но проводили уже не стемминг, а нормализацию, чтоб не потерять смысл. Не чистили совсем — попробовали разные стратегии, дабы хорошо определялась пунктуация и проставлялись специальные символы для трансформера. Лучший результат — 0,85. При трёх эпохах на nvidia tesla A100 несколько суток машинного времени — очень долго. Мы не получили профит, а каждая цифра для бизнеса — это деньги.
У нас достаточно большой дата-дрифт, и, если стоять на месте и не делать ничего, метрики быстро опустятся вниз.
Когда у коллег из Яндекса был бесплатный период обучения классификатора с их foundation models, грех было не воспользоваться.
Подход с yandex foundation models

Но у них было ограничение на датасет — максимум 50 000 строк в дата-сете, максимум 100 классов. Ну, что ж, датасет мы переработали. Взяли самые частотные классы, по которым больше всего обращений в месяц (99 штук), остальные бросили в «Другое», и так каскадом, пока не исчерпали все наши классы. Но нельзя сказать, что релевантный эксперимент. Мы понимаем, что не могли накормить всеми данными, что у нас есть. Нам метрика такая не зашла — двинулись дальше.
Опробовали большие языковые модели.
Подход lora sft, обучаем адаптеры

Мы воспользовались подходом lora: обучили несколько адаптеров к открытым версиям llama 2, llama 3 и sayga-gemma. К тому времени были в моде открытые сети, и sayga-gemma зашла лучше всех. Датасет формировался непосредственно как промпт запроса: «Найди взаимосвязь между этим обращением, классом и операцией». Подавали всё это в промптах, получили метрику 081. Для эксперимента хорошо, для бизнеса — так себе.
Что имеем на данный момент
Для понимания вернитесь к схеме чуть выше с цифровым путём обращения в поддержке. Ещё раз посмотрим, чем мы кормим модель, на примере.
Чем кормим модель
На вход классификатора подаётся последовательность токенов, полученная после предобработки текста обращений (удалений html разметки, стоп слов, удаление автора).
А также категориальные признаки, а именно:
- “Место работы”
- “Должность”
- Временные признаки
- “Время регистрации обращения”
- “День недели регистрации обращения”
- Временные признаки преобразуются посредством функций sin и cos
- Категориальные признаки посредством one hot encoding

Здесь есть номер обращения пользователя, текст обращения и дополнительные фичи (должность, откуда обрабатываем, временные фичи с синусом и косинусом — то есть время дня и день недели). Должность и офис — это one hot фичи.
Мы дошли до трансформера с дополнительными признаками для классификации обращений:

Мы берём выход из BERT Pooling output и при помощи additive attention кормим его нашими дополнительными фичами. Так как это additive attention, получаем зависимость между текстовой частью обращения и непосредственно этими фичами.
Архитектура модели
Здесь стоит упомянуть о выходе BERT (pooled_output из последнего слоя). После применения внимания к дополнительным признакам, мы объединяем их с выходным представлением BERT.
Additive attention позволяет модели учитывать взаимосвязи между двумя последовательностями. В нашем случае, мы используем его для того, чтобы модель учитывала взаимосвязь между pooled_output (выход BERT) и features_processed (предобработанными признаками). Такая архитектура позволяет модели учитывать как семантику текста, так и контекстные метаданные.
Additive attention
Addictive attention — это механизм нейросетей, позволяющий модели динамически определять релевантность отдельных компонентов вводных данных.
В нашей архитектуре он выполняет кросс-модальное взаимодействие между текстовыми представлениями (выход BERT), структурированными признаками (метаданные обращений). Механизм имитирует когнитивное внимание человека — текстовые паттерны. Аналогично тому, как мозг выделяет значимые детали в потоке информации.
Среди практических преимуществ — автоматический feature engineering, устойчивость к шуму и кросс-модальные взаимодействия.
Что мы на самом деле делаем?

Мы берём проекцию выхода BERT, делаем проекцию наших фичей, выравниваем их по длине. После этого складываем всё это в тангенс и получаем некий importance. После этого мы можем эту важность домножить на наши фичи, и это всё суммируется с оригинальным выходом BERT.
Получается действительно кросс-модальное взаимодействие, где мы понимаем, что у сотрудника из центрального офиса не может поломаться фискальник, просто потому что он ничего там не продаёт, явно тут что-то не то написано. Это не будет, грубо говоря, бизнес-система, там фискальный принтер.
Классификатор авторешений
Рассмотрим более подробно классификатор авторешений.

Казалось бы, забавная модель в наше время — это обычная логистическая регрессия. Мы говорим про первый уровень. Да и второй не намного сложнее по ML-составляющей: 0 — мы решаем, что не будем давать статью, 1 — даём. Но есть нюанс, о нём чуть позже.
Ранее в ходе исследования выяснилось, что порядка 10% обращений мы можем решать, вообще не привлекая никаких людей — просто автоматически. Это было бы всё равно так, но мы не смогли бы собрать такие данные. Если бы у нас не было предыдущих механизмов (всех предыдущих классификаторов), мы не могли бы понимать, какой это класс, бизнес-система и операция.
Как мы готовим данные для классификатора авторешений:
Отсекаем низкочастотные операции, то есть выбрасываем все данные из обучения, которые в классе операции повторялись мало. Условно, если больше 50 — подходит, берём эту операцию и все данные из неё.
Векторизуем все обращения при помощи больших векторов spacy (там есть большая версия), трансформерных векторов из rubert и e5.
Кластеризуем все вектора по косинусному расстоянию.
Отбрасываем кластеры, в которых получилось слишком малое количество.
Интересный момент: казалось бы, шаблоны, по которым можем давать авторешения, мы нашли, но как понять, пользователь может решить свой вопрос самостоятельно или нужна помощь сотрудника поддержки? Например: «Я сбросил пароль и выслал вам инструкцию, как завести новый». Казалось бы, этот шаблон повторяется тысячи раз в месяц, но клиент не сможет решить это обращение без сотрудника.
Рассмотрим другой пример, когда нужно заполнить форму для получения допуска в спортзал. Там сотрудник поддержки говорит: «Заполните форму по этому URL», и клиент может сам перейти и заполнить. Он закрыл своё обращение, компания в плюсе.
Как мы поймём, что клиент не может справиться без помощи сотрудника поддержки? Естественно, натравим большую языковую модель. В данном случае мы используем qwen2.5 на 14 млрд параметров запроса: может ли пользователь самостоятельно, следуя этому шаблону, решить обращение. Эта штука работает! Действительно, мы можем отбросить обращения, которые пользователь не может решить без сотрудника поддержки. Там немного мудрёный промпт. Эти данные мы уже и правда можем использовать в датасете авторешений и научить наши модели машинного обучения логистической регрессии, понимая, что эти обращения могут быть решены.
Какие плюсы? Механизм поиска шаблонных запросов (с использованием большой языковой модели qwen2.5-14b), которые пользователь может решить сам с помощью статьи или инструкции, запускается, условно, с периодичностью раз в месяц, и при этом модель логистической регрессии, обученная на найденных данных шаблонов, работает всё время. Она быстро обучается, на инференсе она тоже быстра. Даже как-то был эксперимент: мы конвертировали её в ONNX и ещё быстрее стало. То есть мы основные ресурсы на инференсе практически не тратим.
Наш умный бот
У нас открылась платформа MLOPS — её поддерживали достаточно дорогие специалисты (MLE, DS). Это не просто сотрудник поддержки, который картридж меняет, а действительно дорогой для компании специалист. Целью было разгрузить их от рутинных вопросов по Kubeflow/Jenkins. В нашей доменной специфике всё-таки есть нюансы. По крайней мере, я не смог, открыв изначальную документацию по Kubeflow, с ходу написать и прогнать какой-то pipeline.
Как это работает — наглядно:
[Обращение] →[Чат]→ [Классификатор] → [RAG] → {Ответ?} → Да → [Готово]
↓ Нет → [Автотикет в Tracker]
Классификатор маршрутизирует запросы класса «MLOps_support». Далее включается RAG (Qwen2.5 8B + кастомный эмбеддер) и ищет ответ в базе знаний. Если RAG не справился, тикет автоматически уходит эксперту вообще без всякого ожидания. Мы помним, что у нас в нормативах целых 60 минут, а здесь тикет уйдёт сразу — явный плюс.
Техническая реализация
Начнём со стека:
LLM: Qwen2.5 8B (квантованная версия для CPU для экономии ресурсов).
Ответ на обращение занимает 60 секунд при том, что мы в Кубере доверили ему 16 ядер. Но он очень редко их все трогает.
Поиск: кастомный эмбеддер с Triplet Loss (точность 92% Hit@3 по релевантным запросам).
Интеграция: Loop API (наш внутренний мессенджер) + автосоздание тикетов при провале.
Критерии эскалации:
Низкий confidence score (<0,7), если мы не уверены, что это верно;
Пользователь нажал /switch_to_human или /not_helpful.
Пример ответа RAG:
«Для деплоя модели в Kubeflow: 1) Соберите Docker-образ... [см. док]».
Если просто /switch_to_human — мы его запишем в чёрную тетрадку, потому что он не даёт нам собрать статистику. Мы не понимаем: ему ответ не помог, или он просто хочет с человеком живым общаться. Конечно, для нас /not_helpful — это гораздо более практичный ответ, на основании которого мы можем собрать статистику и дальше дообучать наш эмбеддер или адаптер к qwen-у.
Итог: быстро, точно, без блокировок
Во-первых, чат не замедляет процесс (всего 60 сек и только по заданным классам) при норме на реакцию сотрудника техподдержки от 20 до 60 минут в зависимости от приоритета.
То есть, мы не бежим по всем 500 бизнес-системам, а потом умножаем это на 2 500 операций — только заданные классы, по которым у нас подготовлены векторные базы. Профит от применения этого на первой линии, кажется, не сильно велик. Сотрудники реагируют за 20—60 минут, а тут всего 60 секунд.
Во-вторых, он разгружает дорогих L4, но не мешает им работать. В-третьих — пользователь всегда может мгновенно перейти к эксперту. Это даже выгоднее, чем просто написать обращение.
Обучение кастомного эмбеддера (Triplet Loss)
Цель — научить модель понимать доменные термины (Kubeflow/Jenkins/MLOps).
В качестве основы архитектуры выбрали multilingual-e5-large (поддержка русского/английского) и дообучение на Triplet Loss с margin=1.0.
Учили его нашему домену знаний в платформе MLOps. За основу взяли многоязычную е5. Сделали такой Triplet Loss, где у нас косинусное расстояние между якорным вопросом, релевантным ответом и нерелевантным.

Данные — 10k+ триплетов (anchor=вопрос, positive=релевантный чанк, negative=нерелевантный).
Пример:
Anchor: «как дебажить run pipelina в kubflow?»
Positive: чанк с логами и шагами диагностики
Negative: инструкция по настройке PVC
Процесс обучения и результаты
Мы взяли следующие параметры: 3 эпохи, lr=1e-5, batch_size=1 (из-за длинных текстов), GPU NVIDIA RTX 4090Ti(A100).
По ресурсам это всего три эпохи на локальный 4090. На А 100 будет примерно так же.
По метрикам имеем следующую картину:
Hit Rate@3: 92% (против 68% у базовой e5-large).
Время инференса: 0.15 сек. запрос.
Пример работы:
query = «Ошибка ImagePullBackOff в Kubeflow»
doc = «Решение: 1) Проверьте registry creds... 2) Убедитесь...»
similarity = 0.87 # (было 0.52 до обучения)
Итоги
Суммируем все вышесказанное. Что у нас было:
tf-idf, one-hot encoding и бустинги — метрика 0,86, по ресурсам 5 часов на nvidia tesla v100.
Рекурентки — очень долго и, увы, метрики нет.
BERT— метрика меньше 0,85 и 25 часов на NVIDIA.
Трансформеры с допслоями — F1 макро (0,89), 12 часов на NVIDIA Tesla A100
Надо сказать, что для нас действительно порядка 5 000 обращений — неплохие цифры, а 12 часов на A100 далеко не самый большой BERT.
Обученный e5-large — 10 часов на rtx4090ti.
Технология | Метрики | Ресурсная нагрузка на обучение модели |
tf-idf+ohe+boostings | f1 = 0.86 | 5 часов nvidia tesla v100 |
рекурентные сети | f1 = 0.83 | 25 часов nvidia tesla v100 |
bert large, roberta, electra | f1 <= 0.85 | до 25 часов nvidia tesla A100 |
трансформер с допслоями и вниманием для фич | f1 = 0.89 | 12 часов nvidia tesla A100 |
обученный e5-large | Hit Rate@3: 92% | 10 часов rtx4090ti |
К чему мы пришли:
От модели с бустингами и обработкой 55% обращений мы пришли к 76% автоматизированной классификации, увеличили точность классификации до 92% с учётом порогов.
Увеличили скорость решения обращений более чем в 20 раз для успешных авторешений и ответов чат-бота.
Вывод:
Для каждой задачи есть своя более успешная технология. Использовать везде LLM, как сейчас модно, не стоит — большие языковые модели я бы точно не рекомендовал. Где-то успешно справляется логистическая регрессия, как мы видели на примере.
А чтобы узнать еще больше полезного материала, приходите на прикладную техническую конференцию по Data Science AIConf 2026. Мероприятие состоится 20 апреля в Москве, но принять участие можно и онлайн. Вас ждет новый формат — конференция становится инструментом решения задач, а не потребления контента. Пройдите квиз и получите доступ к топ-видеозаписям AIConf 2025!
