Найти тему
Pavel Zloi

Перевод на разные языки используя модель NLLB

Оглавление

Приветствую тебя, мой уважаемый читатель!

Последние пару дней изучаю возможности проекта NLLB (анг. No Language Left Behind, что пафосно переводится как: ни один язык не остался позади), изучаю я его потому как мне нужно в рамках одного небольшо прототипа проекта RAG-системы интегрировать модуль перевода текста.

Сгенерировано при помощи Яндекс Шедеврум
Сгенерировано при помощи Яндекс Шедеврум

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

Краткий обзор

Изучение этой темы начал тривиально, с прочтения постов на HuggingFace про NLLB и NLLB-MoE, затем прочёл работу No Language Left Behind: Scaling Human-Centered Machine Translation (2207.04672) на arXiv и после этого полез изучать документацию к репозиторию на GitHub.

Если коротко, то модель NLLB создана инженерами из F**k, представляет из себя мультиязыковую модель для выполнения задачи машинного перевода типа: sequence-to-sequence, то есть предложение в предложение.

Есть два основных варианта реализации модели:

Различия между Dense и MoE вариациями модели
Различия между Dense и MoE вариациями модели
  • Dense (можно перевести как: компактный) - похожа на обычную трансформерную GPT модель, навроде LLaMA или ruGPT, ей передаётся какой-то текст на входе и какой-то текст ожидается на выходе. Указание языка на который осуществлять перевод происходит при помощи токена следующего сразу за bos_token_id, в данном случае модель работать как эдакая всезнайка, она компактнее и быстрее чем MoE версия, но имеет чуть меньшую точность;
  • Dense Distilled - Тоже что и предыдущая, только из неё убраны слои и веса которые не сильно влияют на качество перевода, при этом дистилированные модели весят намного меньше.
  • MoE (Mixture of Expert, то бишь: смесь экспертов) - указанная версия несколько сложнее чем Dense вариант, одна из особенностей в том, что в ней при помощи шлюзов (MoE Gating) реализована маршрутизация нескольких внутренних моделей работающих с разными группами языков. Этот подход в разы увеличивает размер модели, однако, увеличивается и качество перевода, скорость само-собой у MoE модели тоже чуть ниже чем у Dense, но если важна точность то эти недостатки не критичны.

На HuggingFace можно найти следующие вариации модели:

А вот тут можно изучить все их метрики.

Пример использования

Принцип работы модели NLLB плюс-минус похож на обычные трансформерные GPT'шки и, как говаривал классик, суть такова:

  • сначала мы инициализируем токенизатор, явно указав с какого языка происходит перевод (если не указать то будет выбран eng_Latn), скажем мы хотим перевести с русского (тогда пишем rus_Cyr), передаём на вход токенизатора некий текст, после чего получаем массив из токенов;
  • далее на вход модели передаются указанные токены, но самое любопытное, что сразу после токена bos_token_id (анг. Begin of String, то есть: начало строки) под капотом передаётся токен идентификатора языка, на который необходимо выполнить перевод;
Содержимое файла tokenizer.json
Содержимое файла tokenizer.json
  • модель шебуршит шестерёнками и возвращает токены перевода на нужный язык, после чего выполняется обратная токенизация, которая восстанавливает переведённый текст.

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

А вот пример кода, который позволяет выполнить перевод с русского на английский:

Пример перевода с русского на английский
Пример перевода с русского на английский

Исходники тут.

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

Версия переводчика в формате класа
Версия переводчика в формате класа

Исходный код указанного класса можно посмотреть тут.

В методе detect взывается функция get_language_long из локального пакета nllb_languages, давайте рассмотрим код этого пакета:

Верхняя часть пакета
Верхняя часть пакета

Дальше идёт несколько десятков строк с перечислением языков.

А вот тут завершающая часть пакета и функции
А вот тут завершающая часть пакета и функции

Исходный код пакета находится тут.

В массиве LANGUAGES перечислены не совсем все языки, полный список можно найти в тексте публикации No Language Left Behind: Scaling Human-Centered Machine Translation (2207.04672) в главе №3 на 12й странице.

Как видно из исходного кода пакет nllb_languages при импорте класса происходит подготовка переменных SHORT_TO_LONG и LONG_TO_SHORT для ускорения процесса поиска нужного языка. Далее имеется два метода для получения короткого названия языка по длинной версии и обратная функция.

А вот так можно данным классом пользоваться:

Пример запуска класса
Пример запуска класса

Завершение

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

Не забывайте следить за обновлениями, ведь в мире технологий всегда происходит что-то новое и удивительное. И, конечно же, если вам понравилась эта публикация, не забудьте подписаться на мой Telegram-канал, где я делюсь своими мыслями, новостями и экспериментами. Ваша поддержка и интерес вдохновляют меня на новые исследования и публикации!

К тому же, если вы хотите поддержать мои усилия то можете сделать пожертвование на CloudTips. Ваша поддержка поможет мне продолжать свою работу и делиться новыми открытиями с вами.

Спасибо за ваше внимание и до новых встреч!