← Все кейсы
Госсектор Техподдержка

Оператор городской транспортной системы

AI-поддержка водителей через email и Telegram. Каждый фильтр в системе появился после конкретного провала на реальных обращениях.

Задача

На вопрос «не могу войти в личный кабинет» модель сформировала ответ: «в системе наблюдается массовая техническая проблема, разработчик разбирается». Никакой проблемы не было. Если бы такой ответ ушёл водителю, тот решил бы, что платформа не работает, и не вышел на линию. Для транспортной системы с сотнями тысяч зарегистрированных водителей одна галлюцинация модели может обернуться реальным простоем.

Задача звучала стандартно: автоматизировать ответы на типовые обращения. Как получить идентификатор, как войти через госуслуги, почему не загружается фото с паспортом, что делать при смене телефона. Восемьдесят процентов вопросов повторяются, но каждый сформулирован по-своему. Сотрудник поддержки читает письмо и сразу понимает, о чём речь. Но чтобы найти нужный фрагмент в базе знаний, ему нужно перевести вопрос водителя на язык документации — и на этот перевод уходит основное время. Из пяти-десяти минут на обращение сам ответ занимает полминуты, остальное — поиск.

Что ломается на настоящих письмах

Прототип заработал за неделю: поиск по базе, генерация ответа, отправка по email. На тестовых данных всё выглядело убедительно, а потом пришли настоящие письма.

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

Второй провал — в самих ответах. На вопрос вроде «как обновить номер телефона» система могла найти фрагмент про управление аккаунтом и сгенерировать инструкцию: удалить аккаунт и создать новый. Формально по теме — и аккаунт, и телефон упоминаются. На практике водитель теряет все данные вместо обновления одного поля. Поиск не различал намерения внутри одной темы. Для этого появились шесть категорий намерений — система повышает оценку при совпадении категории вопроса и документа и снижает при несовпадении. Одну исключительную пару прописали руками: «загрузка документов» не штрафуется за пересечение с «редактированием профиля», потому что загрузка фото часто включает шаги по редактированию.

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

Между крупными ошибками — десятки мелких, и каждая оставила конкретное правило в системе. Модерация блокировала письма с деловой грубостью вроде «это безобразие!», принимая эмоции за токсичность. Бот просил водителя прислать скриншот, хотя не умеет обрабатывать ответы на свои вопросы. Короткие доменные запросы отсеивались как бессмысленные. Всего в системе набралось больше тридцати калиброванных параметров.

Все эти параметры складываются в формулу уверенности, которая определяет маршрут ответа. Высокая уверенность — ответ уходит водителю автоматически. Ниже порога — система честно передаёт обращение оператору без попытки угадать.

Как устроена формула уверенности — подробнее
ПРОХОД 1: КАЧЕСТВО ПОИСКА
насколько уверенно найден нужный документ
Отрыв лучшего результата margin
большой разрыв top-1/top-2 → уверенный выбор, маленький → случайное совпадение
Тип источника source prior
лучший результат — документ с проверенным ответом → дополнительный вес
ПРОХОД 2: КОРРЕКЦИЯ САМООЦЕНКИ МОДЕЛИ
модель систематически занижает уверенность
Floor-значения 3 уровня
самооценка 0.65 при верном ответе — отбрасывается без коррекции. Floor: top-1 → 0.88 · top-2 → 0.82 · top-3 → 0.75
ПРОХОД 3: ШТРАФЫ
каждый штраф появился после конкретного провала
Внешняя ссылка в ответе −0.1
модель любит выдумывать URL
Тема ответа ≠ тема вопроса −0.3
поиск нашёл похожий документ из другой категории
Бот просит скриншот или уточнение −0.5
самый тяжёлый штраф: бот не умеет обрабатывать ответ на свой же вопрос
итоговая формула →
p = 0.6 × качество_поиска + 0.4 × самооценка_модели − штрафы 60/40 в пользу поиска: ошибки чаще в модели, чем в поиске
Все параметры работают только вместе — изменение одного сдвигает распределение между автоответом и эскалацией.

Система подключена к почте на государственном домене и CRM заказчика — включая нестандартный сертификат российского удостоверяющего центра и собственный формат входящих писем, о которых нет внешней документации.

Инженерная карта системы
ОБРАЩЕНИЕ
email (IMAP, опрос каждые 10 мин, кастомный сертификат для госпочты) · Telegram (aiogram)
последовательно
ОЧИСТКА И МОДЕРАЦИЯ
отсечь мусор до дорогих операций поиска и генерации
Email cleanup LLM
вырезает подписи, шаблоны, цепочки ответов. Паттерны российских почтовых клиентов: «отправлено из mail.ru», «создано в яндекс.почте», «Get Outlook for iOS»
Спам-детектор regex
паттерны: кэшбэк, скидки, URL. Порог: 0.7
Токсичность словарь + LLM + safeguard
~40 записей (корни, фразы, транслит). Safeguard для делового тона: нет маркеров + confidence < 0.9 → понижение до «неинформативное»
BM25 bypass проба
сильное совпадение по ключевым словам → пропуск фильтра неинформативности. LLM confidence ≥ 0.9 → bypass игнорируется
параллельно
ПОИСК ПО КЛЮЧЕВЫМ СЛОВАМ
точные совпадения, <10мс
Индекс rank-bm25, pickle
русский токенайзер, дефисы внутри токенов
ПОИСК ПО СМЫСЛУ
перефразирования и семантическое сходство
Qdrant cosine, knowledge_ru
Qwen-3-Embedding-0.6B, batch halving при сбоях, автодетект float/base64
объединение и реранкинг →
нормализация обоих списков 0.7 × hybrid + 0.3 × cosine rerank intent detection: 6 категорий, boost/penalty
ГЕНЕРАЦИЯ ОТВЕТА Qwen 3 235B / DeepSeek через LiteLLM proxy
system prompt + top-K фрагментов + вопрос. Запрет на инцидентные формулировки без цитаты из контекстов
ответ из базы в top-1 → используется напрямую, модель не вызывается
ВАЛИДАЦИЯ
PII regex
телефоны → маскировка (кроме горячей линии). Длинные числа → маскировка
URL whitelist regex
три разрешённых домена. Остальные → удалены, штраф −0.1
Совпадение тем rules
тема вопроса ≠ тема ответа → штраф −0.3. Одна разрешённая пара: загрузка документов → редактирование профиля
Фильтр галлюцинаций hard filter
8 маркеров. Маркер в ответе, но не в найденных документах → блокировка
Запрос информации penalty
бот просит скриншот или уточнение → штраф −0.5
УВЕРЕННОСТЬ И МАРШРУТИЗАЦИЯ
base = 0.5 × top_score + 0.3 × margin(top1−top2) + 0.2 × source_prior
final = 0.6 × base + 0.4 × llm_confidence − penalties
ответ из базы без штрафов → floor 0.95
семантическое сходство > 0.8 → floor 0.85
≥ 0.95 автоответ
ответ уходит водителю без участия сотрудника поддержки
< 0.95 эскалация
письмо не отправляется, обращение передаётся оператору для ручной обработки
7 этапов · 2 поисковых индекса · 30+ параметров · 2 полосы маршрутизации
pydantic-ai · Qdrant · PostgreSQL · FastAPI · aiogram · LiteLLM proxy · Docker Swarm
Qwen 3 235B — генерация · Qwen-3-Embedding-0.6B — эмбеддинги

Результат

Система работает в продакшене на двух каналах: email и Telegram. Сотрудник поддержки больше не ищет ответы в базе знаний — он работает только с обращениями, где уверенности системы не хватает для автоответа.

Настройка продолжается, пока идут обращения, и система становится точнее с каждой неделей эксплуатации — без переобучения модели и без переписывания кода. Каждый новый класс ошибок превращается в конкретное правило, которое не даёт этой ошибке повториться.

письма водителей

Куда отправить: автоматически или оператору?

Пять реальных обращений. Попробуйте решить за систему — автоответ или эскалация?

1 / 5
Как получить постоянный идентификатор водителя?

Как система принимает эти решения за миллисекунды — в кейсе ниже

30+ параметров, калиброванных на реальных обращениях
8 маркеров для фильтра галлюцинаций
2 полосы маршрутизации по уверенности
30+ параметров, калиброванных на реальных обращениях
8 маркеров для фильтра галлюцинаций
2 полосы маршрутизации по уверенности

Модули платформы в этом проекте

Документы Qdrant

Двойной индекс: BM25 по ключевым словам и Qdrant по эмбеддингам. Intent-detection по шести категориям обращений водителей, boost при совпадении интента, штраф при кросс-категорийной ошибке

Инференс

Qwen 3 235B для генерации, модерации и реранкинга. Qwen-3-Embedding-0.6B для векторизации. Адаптивный batch split при сбоях провайдера, автодетект формата ответа (float / base64)

Guardrails

Морфологический токсик-фильтр с safeguard для делового тона, LLM-модерация с BM25 bypass для доменных запросов. На выходе: PII-маскирование, URL-whitelist, intent mismatch, фильтр галлюцинаций инцидентов

Evaluation

Трёхпроходная формула уверенности: retrieval geometry, LLM self-report с floor-коррекцией, penalties. Больше тридцати параметров, калиброванных на production-обращениях

LLM Router

LiteLLM proxy: маршрутизация Qwen / DeepSeek, fallback при сбоях, единый API для всех каналов поддержки

Расскажите, какой процесс хотите разобрать.

Ответим, подходит ли задача для AI-агентов, и если да, предложим конкретный план.

или напишите напрямую — ilya@manaraga.ai