08 окт. 2024 г.·7 мин чтения

До того как строить агента, дообучите небольшой классификатор

Узнайте, когда дообучение небольшого классификатора выгоднее, чем более крупный агент, для маршрутизации и тегирования — через узкие метки, дешёвые проверки и простой план запуска.

До того как строить агента, дообучите небольшой классификатор

Начните с реального решения

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

Когда вы дообучаете небольшой классификатор, сформулируйте решение как один простой вопрос. Он должен быть настолько понятным, чтобы два человека чаще всего отвечали на него одинаково. «Нужно ли отправить это сообщение в engineering, sales или billing?» — понятно. «Что нам делать с этим клиентом?» — нет.

Держите первую версию привязанной к одному процессу. Выберите один inbox, одну очередь или одну форму. Узкая модель для классификации по меткам обучается быстрее, когда каждая метка относится к одной ежедневной задаче, а не к нескольким слабо связанным сценариям.

Прежде чем собирать примеры, запишите цену неправильного ответа. Это быстро проясняет метки. Если платёжный вопрос уйдёт в sales, вы потеряете, возможно, 10 минут. Если отчёт о проблеме безопасности попадёт в общий support, вы потеряете день и разозлите отправителя. Эти потери подсказывают, где нужны более точные метки, больше примеров или шаг ручной проверки.

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

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

Это можно дешёво проверить ещё до создания чего-то сложного. Возьмите от 50 до 100 реальных примеров, разметьте их вручную и посмотрите, где модель не согласуется с людьми. Пять повторяющихся ошибок научат вас большему, чем отполированный демо-сценарий, в котором агент один раз ответил правильно.

Если классификатор не может чётко маршрутизировать запросы, более крупный агент будет ошибаться только дороже.

Почему маленький классификатор часто выигрывает первым

Небольшой классификатор часто оказывается лучшим первым шагом, когда задача простая: отправить вход в одну из нескольких понятных категорий. Если support-сообщению достаточно попасть в «billing», «bug» или «sales», фиксированный набор меток обычно работает лучше, чем полноценный агент. Он отвечает быстрее, стоит дешевле и ошибается так, что команда может быстро это заметить.

Разница в стоимости быстро становится заметной. Вызов инструментов часто требует дополнительных проходов модели, более длинных промптов и повторных попыток, если модель выбрала неправильное действие. Классификатору обычно нужен один короткий запрос. Если вы обрабатываете 50 000 запросов в день, даже небольшое снижение стоимости на один запрос заметно к концу месяца.

Скорость не менее важна. Пользователи замечают паузу. И ещё больше замечают, когда система останавливается, чтобы подумать, выбирает инструмент, задаёт ещё один вопрос и только потом делает простейший выбор маршрута. Измеряйте время ответа на реальном трафике, а не на аккуратном демо-наборе. Модель, которая маршрутизирует большинство запросов за 300 миллисекунд, часто полезнее агента, которому нужно 2–3 секунды, чтобы прийти к тому же ответу.

Фиксированные метки ещё и делают задачу честной. При небольшом наборе решений можно писать примеры вокруг границы и запускать дешёвые проверки. Можно задавать простые вопросы: попал ли «refund request» в billing, а «app crashes on login» — в bug? Это гораздо проще, чем оценивать длинную цепочку скрытых решений внутри агента.

Вызовы инструментов лучше оставлять для действий, а не для первичной сортировки. Используйте инструменты, когда системе нужно сделать что-то реальное: создать тикет, найти заказ или обновить запись. Сначала пусть классификатор решит, куда относится запрос. А потом нужный workflow возьмёт задачу на себя.

Такое разделение хорошо работает в продакшене. Команды, которые начинают с дообучения небольшого классификатора, обычно учатся быстрее, тратят меньше и позже избегают множества сложных отладок.

Выбирайте метки, которые остаются понятными

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

Используйте слова, которые ваша команда уже произносит вслух. «Billing issue» лучше, чем «commercial inquiry». «Bug report» лучше, чем «technical product concern». Простые метки ускоряют разметку и позже помогают легче замечать ошибки.

Главная ловушка — пересечения. Команды часто создают пары вроде «sales question» и «pricing question» или «bug» и «broken workflow». Если обе метки отправляют сообщение одному и тому же человеку или запускают один и тот же следующий шаг, объедините их. Большее число меток не делает систему умнее. Обычно оно лишь распыляет тренировочные данные и ухудшает границу.

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

Старайтесь связывать каждый пример с одной меткой, если только вам действительно не нужно несколько выходов. Одна метка на пример проще для проверки, проще для тестирования и проще для маршрутизации. Сообщение вроде «Мне нужен счёт и ещё приложение падает при входе» содержит две проблемы, но модели маршрутизации всё равно нужен один следующий шаг. Выберите метку, которая соответствует первому владельцу или первой очереди.

Перед разметкой тысяч примеров помогает быстрый тест. Новый сотрудник должен уметь размечать 20 примеров почти без вопросов. Каждая метка должна соответствовать одному действию. Пограничные случаи должны попадать в «other», а не искажать настоящий класс. И после чтения реальных сообщений у вас не должно возникать желания переименовать половину меток.

Это особенно важно, когда вы дообучаете небольшой классификатор. Понятные метки позволяют быстро сравнивать версии и точно видеть, где граница начинает съезжать.

Собирайте примеры, которые учат границе

Модель учится границе между метками на примерах, а не на названиях меток. Если примеры чистые, узкие и реальные, обучение становится гораздо проще.

Начните с сообщений, с которыми ваша команда уже работает. Тикеты, чат-логи, цепочки писем, формы поддержки, формы для сбора лидов и внутренние заметки по triage обычно дают более полезные данные, чем примеры, написанные с нуля.

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

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

Следите, чтобы количество примеров по меткам было достаточно близким, и сравнение оставалось честным. Совпадать идеально не нужно, но сильного перекоса быть не должно. Если у одной метки 500 примеров, а у другой 25, слабый результат может объясняться не плохой меткой, а слишком скудными данными.

Пограничные случаи тоже нужны намеренно. Добавляйте сообщения, в которых есть два намерения сразу, короткие заметки без контекста, сообщения с неправильными словами для правильной проблемы, редкие, но дорогие случаи и почти одинаковые примеры, которые относятся к разным меткам.

Представьте небольшой SaaS inbox с метками вроде «billing issue», «bug report» и «feature request». Сообщение вроде «Меня списали дважды, и ещё страница счёта падает» полезнее десяти простых bug report, потому что заставляет решить, какой маршрут должен быть главным.

Очистите данные до обучения. Уберите имена, email-адреса, номера телефонов, номера счетов, номера заказов и всё, что может идентифицировать человека или компанию. Если на метку влияют личные данные, замените их простыми плейсхолдерами, чтобы смысл сохранился.

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

Обучайте и проверяйте по шагам

Запускайтесь без лишнего усложнения
Настройте одну очередь, один набор меток и один безопасный первый запуск.

Классификатор заслуживает доверия, когда он лучше простого правила на данных, которых ещё не видел. Разделите размеченные примеры на три части: train, test и holdout. Train учит модель. Test помогает сравнивать запуски во время настройки. Holdout не трогают до конца, чтобы в финале получить честную проверку.

Прежде чем дообучать небольшой классификатор, сделайте baseline, который кажется почти слишком простым. Достаточно keyword rules, поиска по похожим прошлым примерам или даже варианта «всегда выбирай самый частый класс». Если модель не может уверенно обойти такой baseline, остановитесь и посмотрите на данные. Чаще всего метки расплывчаты или примеры плохо показывают границу.

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

Не доверяйте одной средней метрике. Модель маршрутизации может выглядеть хорошо в целом и при этом проваливаться на самой важной метке. Проверяйте precision, recall и confusion matrix для каждой метки отдельно.

Потом вручную читайте неверные предсказания по одному. Это медленно, но именно так экономится больше всего времени позже. Обычно паттерн становится заметен быстро: две метки пересекаются, одной метке нужна более точная формулировка или несколько обучающих примеров ведут в неверную сторону.

Небольшой пример делает это очевидным. Допустим, вы маршрутизируете сообщения в «sales», «bug» и «account». Если модель постоянно отправляет billing complaints в «bug», исправление может быть таким простым, как переименование «account» в «billing and account» и добавление 20 более удачных примеров. Это лучше, чем слишком рано добавлять инструменты, агентов или дополнительные промпты.

Простой пример маршрутизации

Небольшой SaaS-команде не нужен агент, чтобы сортировать входящие сообщения. В большинстве случаев ей нужно одно понятное решение: куда отправить это сообщение дальше?

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

Именно здесь дообучение небольшого классификатора приносит пользу. Вы даёте ему узкий набор меток, оставляете правила простыми и принимаете одно решение на одно сообщение. Для этой команды метками могут быть billing, bug report и human review.

Сообщение вроде «Меня списали дважды, и мне нужен возврат» должно уйти в finance. Записка вроде «Кнопка экспорта бесконечно крутится после выбора CSV» должна попасть в product или engineering. Если кто-то пишет: «Ваше приложение не работает, и я раздражён», модели может не хватить деталей. Такой случай должен сразу уйти человеку.

Низкая уверенность важнее умной автоматизации. Если классификатор уверен только на 55%, отправить сообщение человеку обычно дешевле, чем отправить его не в ту команду и создать второй круг triage. Одна плохая передача может стоить больше, чем десять ручных проверок.

Команде также стоит раз в неделю разбирать промахи. Храните короткий список сообщений, которые попали не туда, и тех, что ушли на human review, хотя задним числом выглядели очевидными. Потом задавайте простые вопросы: имел ли смысл набор меток, пересекались ли две метки или примеры не покрывают распространённую формулировку?

После нескольких итераций классификатор обычно становится точнее. В billing-сообщениях часто встречаются слова вроде «invoice», «refund» или «card declined». В bug report часто упоминаются экран, шаг и ошибка. Этого достаточно, чтобы решить задачу маршрутизации и тегирования для небольшой команды без вызова инструментов, длинных промптов и лишних частей системы.

Это лучшее начало, чем строить агента, который пытается одновременно читать, рассуждать, выбирать инструмент и отвечать.

Ошибки, которые создают лишнюю работу

Сначала наладьте передачу задачи
Схематично разберите, что происходит после каждой метки, чтобы неверная маршрутизация не создавала лишней работы.

Больше всего времени уходит на попытки сделать модель умной до того, как задача стабилизировалась. Классификатор лучше всего работает, когда решение простое, меток немного, а пограничные случаи видны.

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

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

Ещё одна дорогая ошибка — пытаться насильно отнести любой вход к какой-то метке. Это скрывает неопределённость вместо того, чтобы управлять ею. Если уверенность низкая, отправляйте элемент на проверку, задавайте уточняющий вопрос или помещайте его в bucket «unclear». Один дополнительный шаг дешевле, чем тихая неверная маршрутизация.

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

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

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

Проверки перед добавлением инструментов

Проверьте метки на прочность
Проверьте свои метки, пограничные случаи и путь на ручную проверку с опытным Fractional CTO.

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

Начните с самих меток. Поместите все метки на одну страницу с простым описанием и одним коротким примером. Если эта страница выглядит перегруженной или две метки звучат почти одинаково, модели тоже будет тяжело.

Потом проверьте метки людьми, а не только моделью. Дайте двум людям одни и те же 20–30 примеров и попросите их разметить их самостоятельно. Если они часто не совпадают, проблема пока не в модели. Граница всё ещё расплывчата.

Перед тем как давать доступ к инструментам, убедитесь, что вы можете объяснить каждую метку одним предложением, что два человека чаще всего размечают один и тот же пример одинаково, что модель обходит простые правила на небольшом тестовом срезе, что неправильная метка наносит меньше вреда, чем неправильное действие, и что вы успеваете пересматривать промахи менее чем за 30 минут в неделю.

Третий пункт важнее, чем кажется. Если несколько keyword rules уже сравнимы с моделью, пока оставьте rules. Классификатор должен заслужить своё место, ловя случаи, которые правила пропускают, или сокращая объём ручной проверки.

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

Используйте небольшой регулярный review. Раз в неделю собирайте ошибки, просматривайте их и задавайте один вопрос: модель ошиблась или ошиблись метки? Если на это уходит 20–30 минут, значит, у вас есть система, которую реально можно поддерживать.

Следующие шаги без лишнего разрастания

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

Большинство команд добавляют инструменты слишком рано. Если дообучение небольшого классификатора уже сортирует запросы по нужным категориям, пусть сначала делает только эту одну работу. Вам не нужны вызовы инструментов, память и цепочки действий, чтобы решить, относится ли сообщение к billing, product feedback или bug report.

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

Держите первую версию простой. Пропустите одну очередь через классификатор и логируйте каждый прогноз. Настройте оповещение, если уверенность падает ниже выбранного порога. Следите, не начинает ли одна метка резко расти выше своей обычной доли. Раз в неделю разбирайте промахи и отмечайте новый паттерн, а не только старую метку.

Метки не фиксированы навсегда. Появляется новый способ формулировать запросы, изменения в продукте создают новые категории, а пограничные случаи перестают быть пограничными. Когда одна и та же путаница повторяется несколько раз, обновляйте метки или делите перегруженную метку на две.

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

Если перед большим запуском вам нужен второй взгляд, Oleg Sotnikov на oleg.is работает со стартапами и небольшими командами как Fractional CTO и startup advisor. Он часто помогает командам выстраивать практичные AI-процессы, оценивать компромиссы и держать автоматизацию лёгкой, вместо того чтобы превращать простую задачу маршрутизации в дорогой агентный проект.

Часто задаваемые вопросы

Что мне автоматизировать первым с помощью классификатора?

Начните с одного решения о маршрутизации, которое ваша команда уже принимает каждый день. Хорошая первая задача звучит так: «Отправить это в billing, bug report или sales?». Свяжите первую версию с одним inbox, формой или очередью, чтобы быстро увидеть, что работает, а что нет.

Когда небольшой классификатор лучше, чем агент?

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

Сколько меток стоит выбрать на старте?

Начинайте с минимального числа меток. Для первой версии часто достаточно трёх–пяти. Если две метки отправляют работу одному и тому же человеку или запускают один и тот же следующий шаг, лучше объединить их, чем оставлять обе.

Нужно ли добавлять метку other или human review?

Да, в большинстве случаев стоит. Метка «other» или «human review» даёт модели безопасное место для пограничных случаев, смешанных намерений и неясных сообщений. Так странные примеры не будут портить реальные классы.

Сколько примеров нужно, чтобы протестировать это?

Для дешёвой первой проверки вручную разметьте 50–100 реальных примеров и сравните ответы модели. Обычно этого уже хватает, чтобы быстро увидеть повторяющиеся ошибки. А для обучения собирайте больше данных, когда поймёте, что метки действительно имеют смысл.

Откуда брать обучающие примеры?

Берите примеры из того места, где решение уже принимается. Inbox службы поддержки, чаты, формы и triage-заметки обычно дают модели больше пользы, чем примеры, написанные с нуля. Реальные сообщения несут в себе тот самый живой, неровный язык, с которым модель столкнётся потом.

Что делать, если одно сообщение подходит сразу под две метки?

Выбирайте метку, которая соответствует первому владельцу или первой очереди. Даже если сообщение описывает две проблемы, вашей системе маршрутизации всё равно нужен один следующий шаг. Если никто не может согласиться, какой именно, отправьте сообщение на human review, а не навешивайте сомнительную метку.

Как понять, что классификатор действительно достаточно хорош?

Сначала проверьте его на простом базовом варианте — например, на keyword rules или на самом частом классе. Потом смотрите не только на средний результат, но и на показатели по каждой метке отдельно, а затем по одному просматривайте неверные ответы. Если модель обходит baseline и ошибки выглядят исправимыми, это уже полезное решение.

Когда можно разрешить системе вызывать инструменты или выполнять действия?

Подождите, пока маршрутизация не станет стабильной, и только потом добавляйте доступ к инструментам. Если классификатор всё ещё путает метки, вызовы инструментов лишь спрячут проблему и сделают ошибки дороже. Сначала пусть модель выбирает направление, а потом человек или отдельный workflow выполняет действие.

Как поддерживать классификатор после запуска?

Раз в неделю пересматривайте ошибки и следите за смещением меток. Пользователи меняют формулировки, команды переименовывают категории, а новые продукты создают новые шаблоны. Если люди постоянно исправляют одну и ту же метку или одна категория начинает резко расти, обновляйте метки и добавляйте свежие примеры.