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


Всем привет, меня зовут Иван Четвериков, я архитектор ИИ-направления в компании Raft, мы занимаемся внедрением передовых AI-технологий в процессы множества компаний во многих отраслях. Поделюсь нашим опытом внедрения нового подхода для классификации текста в чат-ботах. Сравним три подхода к реализации классификатора: классический ML-классификатор, LLM-классификатор и библиотеку semantic-router, но перед этим немного войдем в контекст проекта.

Выбор классификатора

В первую очередь определимся, какой классификатор выбрать, чтобы как можно скорее запустить mvp. Для этого мы провели небольшой анализа и выяснили, что у нас есть около 20 различных топиков, на которые нужно классифицировать запросы пользователя. Можно подумать, что для статичных топиков отлично подходит ML-классификатор, но его разработка может растянуться на несколько месяцев. Поэтому мы решили запускать MVP с LLM-классификатором, а после его разработки переезжать на ML-классификатор.

Преимущества LLM-классификатора:

  1. Нет необходимости в датасете: для разработки LLM-классификатора не требуется предварительно собирать и размечать большой объем данных. Достаточно написать промпт, что значительно ускоряет процесс.

  2. Быстрая разработка: время на разработку LLM-классификатора значительно меньше по сравнению с классическим ML-классификатором. Это позволяет быстрее запустить MVP и начать тестирование.

Недостатки LLM-классификатора:

  1. Ограниченная точность: без предварительно обученного датасета точность LLM-классификатора может быть ниже, чем у ML-классификатора.

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

Преимущества ML-классификатора:

  1. Высокая точность: при наличии хорошо размеченного датасета ML-классификатор может обеспечить высокую точность классификации.

  2. Автономность: ML-классификатор может быть развернут on-prem, что исключает зависимость от сторонних сервисов.

Недостатки ML-классификатора:

  1. Длительное время разработки: разработка и обучение ML-классификатора требует значительных временных и ресурсных затрат.

  2. Необходимость в датасете: для обучения ML-классификатора требуется большой объем размеченных данных, что может быть трудоемким процессом.

  3. Долгие процессы обновления: обновление модели занимает время и требует подключения ML-инженера.

Я обещал сравнить три подхода к реализации классификатора, но на текущем этапе внедрения наличие semantic-router еще не подразумевалось. Пока параллельно с LLM-классификатором началась разработка ML.

Этап 1: LLM-классификатор

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

  • Поиск информации об автомобиле по VIN-номеру;

  • Подбор автомобиля;

  • Информация из базы знаний компании (кредит, трейд-ин, рассрочка и т.п.);

  • Информация о работе офисов;

  • Вопросы с переключением на оператора.

Это было сделано для ускорения процесса разработки и облегчения размера промпта. Промпт написали с использованием паттерна few-shot (метод при котором нейросети предоставляется только несколько примеров), итоговый размер варьировался от 800 до 1000 токенов для целевой модели gpt-3.5-turbo. Стоимость одного запроса составляла примерно 0.002$ - 0.003$.

Исходя из этих данных, сравнивать LLM-классификатор с классификаторами ML и semantic-router было сложно, но мы всё же попробовали.

Его главный плюс — скорость реализации. У нас от старта проекта до создания рабочего DEV стенда прошло не больше одной-двух недель. Для стадий PoC или MVP это довольно быстро.

Для повышения точности мы использовали Few-Shot промптинг с 3-4 примерами для каждого из топиков. Также классификатор может послужить хорошей прослойкой для защиты от промпт-инъекций, так как он отбрасывает все сообщения, не относящиеся к целевым.

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

"""
You need to classify user input and return the best category that it match.
You must return exact name of the most appropriated category.
Only these categories are available:
"car-search-by-vin", "cars-search", "info", "office-info", "switch-to-operator"
Rules for categories:
Category "car-search-by-vin" - Any description
Category "cars-search" - Any description
Category "info" - Any description
Category "office-info" - Any description
Category "switch-to-operator" - Any
Examples of user input:
Ex. 1
Question: what's the mileage? how much does it cost?
VIN number: XXXXXXXXXXXXXXXXX
Expected category: "car-search-by-vin"
Ex. 2
Question: Any trade-in options?
Expected category: "info"
Ex. 3
Question: Need to discuss personal discount and car customization
Expected category: "switch-to-operator"
"""

Из метрик для LLM-классификатора мы рассчитывали только точность ответа на вопросы (precision) которая, к слову, была достаточно хорошей при дешевизне модели и составляла 75-80%. Также стоит отметить, что на все вопросы, которые бот не смог обработать, система автоматически переключалась на оператора.

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

Этап 2: ML-классификатор

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

На данном этапе проекта у нас был подготовленный датасет и определена модель (distilbert/distilbert-base-multilingual-cased) которую мы будем обучать.

Bert — это state-of-the-art модель от Google для классификации текстов. Кроме того, она мультиязычна, а значит подходит для русского языка и уже была обучена на нем. За счет дистилляции модель занимает меньше места, чем ее не дистиллированная версия. Она обучается быстрее при минимальной потере в качестве.

Топиков на этом этапе уже было не 5, как раньше, а все полноценные 20 штук. Размеченный датасет был собран в Excel-файл. Для наглядности ниже приведены примеры на некоторые из топиков:

clean_text

topic_name

topic

как можно с вами связаться?

Обратная связь

1

а авто в наличии?

Авто в наличии

2

авто за наличный расчёт продается?

Условия оплаты

3

в кредит можно?

Кредит

4

2.500.000 готов забрать

Торг и обсуждение цены

6

крашенные детали есть?

Состояние авто

7

можете прислать отчет по автомобилю?

Запрос диагностики

10

вин можно посмотреть?

Запрос VIN

19

После обучения на подготовленном и отфильтрованном датасете получился следующий результат. Отчет сформирован на основе библиотеки scikit-learn и подготовленном тестовом датасете:

Результаты ML-модели
Результаты ML-модели

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

Этап 3: Классификатор на базе semantic-router

Результаты semantic-router
Результаты semantic-router

Итак, мы подошли к моменту, когда стало понятно, что процесс обновления ML-модели достаточно долгий и трудоемкий. Это сильно замедляло все процессы работ по проекту. Поэтому мы решили искать альтернативу. Решения на основе pytorch или nltk нам не подошли из-за того, что создавали большую нагрузку в процессе развертывания приложения из-за разворачивания локальной модели, а также создавали большую нагрузку на CPU. Самым подходящим из существующих решений показался semantic-router. Так как нашей основой был Python и уже была реализована интеграция с OpenAI.

Библиотека semantic-router является "слоем для принятия решений", то есть классифицирует текст на темы. Работает она на основе LLM и Эмбеддинг-моделей с поддержкой локальных моделей, а также облачных: OpenAI и Cohere.

Для реализации версии бота с использованием semantic-router был использован тот же датасет, что и для ML-классификатора. Для хранения эмбеддингов взяли OpenAI и модель text-embedding-3-large (стоимость составляет $0.130 / 1M tokens).

Логика работы для запуска классификатора:

  1. Оптимизация исходного датасета.

    Здесь мы использовали метод K-средних, реализованный в библиотеке scikitlearn. Лучший результат был достигнут при следующих параметрах: размер батча данных = 1000, количество итоговых записей на один класс = 300, score threshold = 0.1.

  2. Загрузка оптимизированного датасета в эмбеддинги и создание класса для нашего классификатора.

    На этом этапе необходимо создать список маршрутов для наших эмбеддингов. Для этого мы использовали semantic_router.Route . Затем эти маршруты оборачиваются в semantic_router.layer.RouteLayer .

Пример для создания semantic-router классификатора загружен на github, с ним можно ознакомиться тут.

При запуске приложения стоимость загрузки датасета в эмбеддинг-модель составляет примерно 0.003$ на датасет из 5 000 записей (29 043 токенов). Один запрос для классификации расходует меньше 50 токенов (0.65$ на ~10k запросов).

Точность ответов (precision) с использованием данного подхода изначально составила 89%. После этого была произведена ручная оптимизация датасета для эмбеддингов, в рамках которой мы добавили больше примеров для некоторых топиков, точность которых в чатах с клиентами нас не устраивала. После оптимизации общая точность стала достигать 92-96%.

В итоге полученный отчет из scikit-learn выглядит следующим образом:

Результаты semantic-ro
Результаты semantic-router

Безопасность решений на классификаторах

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

Итоги

Безусловно, для данного кейса с определением тематик для автодилера, semantic-router показал самый лучший результат. Однако стоит отметить, что для получения высокой точности необходимо также вручную размечать датасет и подбирать параметры для перевода данных в эмбеддинги.

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

  • LLM-классификатор стоит использовать в случаях, когда нет подготовленного датасета, а также хочется запустить проект в кратчайшие сроки. Стоит отметить, что для большого количества сообщений данный классификатор может быть достаточно дорогим. При использовании облачных моделей latency тоже будет выше, чем у остальных решений.

  • ML-классификатор подойдет для развертывания on-prem или исходя из запрета использовать какие-либо сторонние сервисы на проекте (как OpenAI в нашем примере). Требует размеченный датасет, а также дополнительные ресурсы на сервере. Соответственно, все сообщения будут обработаны без дополнительной стоимости. Latency зависит от выделенных на классификатор ресурсов.

  • Классификатор на базе semantic-router также требует размеченный датасет, однако его развертывание можно произвести значительно быстрее, так как модель не нужно обучать, а только положить данные в эмбеддинги и обернуть в функционал данного фреймворка. Стоимость данного решения будет низкой, что позволяет увеличить пропускную способность и не платить как за LLM-классификатор. Latency в данном случае будет ближе к ML-классификатору, нежели к LLM, так как обращение к Эмбеддинг-модели происходит гораздо быстрее.

Стоимость решений:

  • LLM-классификатор: на OpenAI модели gpt-3.5-turbo-1106 0.002$ - 0.003$ за один запрос с промптом в 1000 токенов, 20-30$ за 10k запросов.

  • ML-классификатор: 0$ так как он работает на мощностях сервера.

  • semantic-router классификатор: на OpenaI модели text-embedding-3-large 0.003$ при каждом запуске приложения и ~0.65$ на 10k запросов.

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

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

Комментарии (0)