Skip to content

Русскоязычная QA система обернутая в Telegram-бот

License

Notifications You must be signed in to change notification settings

MilyaushaShamsutdinova/ru_qa_system

Repository files navigation

Русскоязычная QA система обернутая в Telegram-бот

Описание задачи

Необходимо было разработать русскоязычную систему для извлечения ответов на вопросы (Extractive QA). Основная цель – найти и извлечь ответ в виде стартовых и конечных токенов из текста вопроса, где содержится контекст.

Выбор подхода к решению задачи

Для реализации extractive QA наилучшим подходом оказалось использование моделей с поиском start/end токенов. Такие модели обеспечивает высокую точность и скорость, что делает его оптимальным для задач, где ответ уже присутствует в контексте (как и требуется в данной задаче). Полный анализ различных методов представлен в ноутбуке.

Поскольку задача заключалась в создании русскоязычной QA-системы, выбор моделей был ограничен многоязычными и специализированными русскоязычными моделями. Одними из лучших вариантов оказались multilingual DistilBERT и RuBERT, результаты экспериментов с которыми можно найти в ноутбуках.

Для обучения был выбран датасет Sberquad, поскольку этот датасет специально разработан для русскоязычных QA-задач, что полностью соответствует требованиям проекта. Система была развернута в виде Telegram-бота для удобства интеграции и тестирования.

Детали реализации задачи

Структура проекта

ru_qa_system/
├── bot/
│   ├── __init__.py
│   ├── bot.py
│   └── main.py
├── model/
│   ├── __init__.py
│   ├── train.py
│   ├── inference.py
│   ├── dataset.py
│   ├── input_preprocessing.py
│   └── utils.py
├── trained_models/
│   └── rubert-v3/
│       └── (модель)
└── notebooks/
    └── (ноутбуки с модальными экспериментами)

Взаимодействие между модулями из папок bot и model организовано следующим образом:

  • bot использует модули из model для выполнения ключевых задач, таких как предобработка текста и выполнение запросов к модели. В частности, он импортирует класс TextSplitter из model.input_preprocessing, который отвечает за разделение входного текста (как сообщение пользователя) на вопрос и контекст.
  • bot обращается к классу QAModel из model.inference для получения ответов на вопросы пользователей, основываясь на обученной модели.
  • Внутри модуля model файл train.py использует класс QADataset из dataset для работы с данными.

Обработка данных для обучения модели

Класс QADataset загружает и предобрабатывает датасет. После загрузки данных применяется метод предобработки данных preprocess_data, который токенизирует вопросы и контексты и формирует метки для начальных и конечных позиций ответов. Затем создаются DataLoader’ы для тренировочного и валидационного наборов. Класс предоставляет методы для получения исходного датасета, предобработанных тренировочного и валидационного датасетов, а также соответствующих DataLoader'ов для удобного взаимодействия с данными.

Выбор модели на основании экспериментов

В ходе экспериментов были протестированы две предобученные модели: многоязычный DistilBERT и RuBERT. Для каждой из моделей были попробованы различные параметры обучения, включая различные значения скорости обучения, количество эпох и оптимизаторы. Но лучшие результаты для обеих моделей были показаны при использовании оптимизатора AdamW c темпом обучения равным 3е-5. Результаты метрик для каждой модели представлены в таблицах ниже.

Многоязычный DistilBERT

Эпоха Exact (%) F1 (%)
1 53.06 73.12
2 54.77 74.41

RuBERT

Эпоха Exact (%) F1 (%)
1 62.49 82.10

В случае многоязычного DistilBERT наилучшие результаты были достигнуты после двух эпох обучения, с улучшением метрик во второй эпохе. RuBERT, с другой стороны, продемонстрировала более высокие показатели уже после первой эпохи, однако дальнейшее обучение привело к ухудшению метрик, что указывает на возможное переобучение модели.

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

В результате эксперимента, было решено обучать RuBERT для данной задачи.

Обучение модели

Для обучения модели RuBERT были использованы следующие параметры обучения:

Параметр Значение
Оптимизатор AdamW
Планировщик Линейный
Ускоритель Accelerator
Точность обучения fp16
Размер батча 16
Темп обучения 3e-5
Количество эпох 1

Тестирование и валидация модели

В процессе тренировки модели проводилась регулярная валидация модели на валидационном датасете по окончании каждой эпохи обучения. Ключевыми метриками для оценки качества модели были Exact Match, отражающая процент правильно предсказанных ответов, и F1-score, показывающая баланс между точностью и полнотой. Но также немаловажную роль играет время выполнения запроса, это было оценено на практике при запуске бота.

Также можно визуально сравнить результаты работы на тренированной модели DistilBERT и RuBERT в ноутубке.

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

Метрика Значение
Exact match 62.49
F1-score 82.10
Average inference time 0.4 сек
Max inference time 1 сек

Предобработка входного сообщения для подачи в модель

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

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

Преимущества и недостатки реализованного решения

Приемущества:

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

  • Точность ответов: Модель всегда извлекает ответ непосредственно из предоставленного контекста, что гарантирует высокую точность результатов.

Недостатки:

  • Строгий формат входных данных: Решение требует, чтобы входные данные были строго оформлены, например, наличие вопросительного знака в вопросе (и только в вопросе). Это ограничивает гибкость системы и может привести к непредсказуемому поведению, если формат данных не соблюдается.

  • Ограниченность в понимании контекста: Модели, основанные на поиске start/end токенов, не справляются с более сложными вопросами, требующими глубокого анализа смысла контекста.

Как пользоваться ботом, не запуская код

Телеграм-бот доступен по ссылке (если лимиты бесплатного тарифа еще не исчерпаны). Для хостинга я использовала платформу Railway. Однако при развертывании модели на Railway время выполения запроса возросло до почти минуты. Вероятно, Railway предоставляет ограниченные ресурсы для бесплатных проектов, что может влиять на скорость инференса.

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

Как запустить бота локально, используя Docker

  1. Клонируйте репозиторий

    git clone https://github.com/MilyaushaShamsutdinova/ru_qa_system.git
    cd ru_qa_system
    
  2. Откомментируйте 17-ую строку в Dockerfile и 16-ую строку в input_preprocessing.py

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

  3. Создайте файл .env

    В файле .env укажите токен для бота:

    • BOT_TOKEN — токен для вашего бота, который можно получить в BotFather в Телеграме.
  4. Соберите и запустите контейнер

    docker-compose up --build
    

    Возможно после запуска контейнера необходимо подождать минуту-две, прежде чем тестировать.

    Теперь бот работает, можно использовать!

    Чтобы отключить бота, остановите контейнер:

    docker-compose down
    

Примеры работы системы

Контекст + один вопрос

alt text

Контекст + несколько вопросов

alt text

Только контекст

alt text

Только вопрос

alt text

Нерелевантный контекст + вопрос

alt text

Модель на Hugging Face

Вы также можете скачать обученную QA модель с платформы Hugging Face и использовать в своих целях.

About

Русскоязычная QA система обернутая в Telegram-бот

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published