̶с̶а̶м̶̶о̶изолента мёбиуса
2.39K subscribers
13 photos
2 videos
1 file
184 links
Костыли и технологии для обработки естественных языков. Обзоры статей и личный опыт. by @cointegrated
Download Telegram
Я на созвоне неделю назад обещал скинуть примеры заданий на собеседовании в FAANG.
Делать такие примеры самому оказалось очень влом, поэтому поделюсь постом Айры на эту же тему: https://www.instagram.com/p/ChrWkHXgUNr/?igshid=MWQ2ODkyMjM=
До этого лета я не занимался машинным переводом вообще. А в июле, в промежутке между Сколтехом и новой работой, я решил потренироваться и сделать переводчик для языка, с которым никогда раньше не работал – и вообще работал мало кто. Это эрзянь кель, один из языков Мордовии. На весь пайплайн – сбор текстов, выравнивание их с русским, обучение моделей – ушло две недели; обучал модели на в колабе и на собственном ноутбуке. Качество получилось пока очень такое себе, но сам факт, что можно быстро и дёшево сделать машинный перевод для нового языка, меня вдохновляет.

Вчера я описал свои приключения на Хабре; приглашаю к прочтению.
̶с̶а̶м̶̶о̶изолента мёбиуса
Вы рабов продоёте? Нет, только показываем. Возникла идея создания ещё одного канала+чата, где любой может вывесить вакансию или проект для кожаного мешка, специализирующегося где-то около NLP, или, наоборот, выложить своё NLPшное резюме на всеобщее оборзение.…
Меня регулярно зовут на какую-нибудь NLPшную работу или подработку.
А ещё мне время от времени пишут люди, которые такую работу ищут.
Я таки решил попробовать начать соединять одних с другими автоматически, и завел под это дело канал @nlp_jobs
Он пока совсем пустой, но, возможно, мы его сможем потихоньку наполнить.
Если вы можете оказаться на рынке NLP-вакансий (как со стороны спроса, так и предложения) - добро пожаловать в канал.
Если вам интересно поучаствовать в его администрации - пишите об этом мне.
Последние три дня (в пятницу был выходной) занимался машинным переводом, но не для работы.

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

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

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

С одной стороны, конечно, я сам дурак; если уж полез играть со Сбером, надо было играть по его правилам и не выпендриваться. С другой – оно всё-таки того стоило, ведь если бы команда "Slava Ukraini" победила в Сберовском конкурсе, это было бы как минимум весело)

Ну а нормальный машинный перевод с эвенкийского языка мы ещё сделаем.

P.S. Большой респект организаторам соревнования за то, что его вообще придумали: идея – огонь!
Последние несколько месяцев я активно ковырял галлюцинации в машинном переводе, и сегодня мы с коллегами выложили статью про это:
Detecting and Mitigating Hallucinations in Machine Translation: Model Internal Workings Alone Do Well, Sentence Similarity Even Better.

Что такое «галлюцинация»? В широком смысле, в NLP принято так называть любой сгенерированный текст, который нас чем-то не устраивает. В более узком смысле мы под галлюцинациями понимаем переводы, в которых модель фантазирует нечто, вообще не имеющее к входному тексту отношения. Нейросетки так делают относительно часто, особенно если входной текст чем-то не похож на те тексты, на которых они обучались.

Можно ли такие патологии детектировать автоматически? В более ранней статье Guerreiro et al, 2022 ответ был скорее пессимистичный: если не генерировать галлюцинации искусственно, то никакие из предлагавшихся в литературе способов не позволяют выявлять галлюцинации лучше, чем простая сортировка переводов по их log loss’у из модели, а этот метод плохо отличает галлюцинации от менее критичных ошибок и от просто сложных переводов. Но мы предложили три другие способа, которые вроде бы работают лучше:

1) Просто сравнить LaBSE эмбеддинги исходного текста и перевода. Этот способ кажется очевидным, ибо LaBSE как раз и обучалась сопоставлять одинаковые по смыслу тексты на разных языках, но почему-то для детекции плохих переводов его раньше не применяли.

2) Засунуть исходный и переведенный тексты в мультиязычную модель для NLI и перемножить предсказанные моделью вероятности, что один текст логически следует из другого. Я уже показывал, что это хорошо коррелирует с человеческими оценками похожести текстов в рамках одного языка – и вот оказывается, что между языками оно тоже работает.

3) Самое интересное: средний вклад токенов исходного текста в представления токенов выходного текста, посчитанный той же самой моделью, которая и переводила текст. Да, оказывается, что модель сама «понимает», когда она галлюцинирует, и нужно у неё только правильно «спросить». Для этого я использовал метод ALTI+ (Ferrando et al, 2022), который хитро агрегирует активации разных слоев трансформера, чтобы вычислить процентный вклад каждого входного токена энкодера и декодера в каждое предсказание декодера. Усреднив эти вклады, можно понять, что при генерации данного перевода модель, скажем, в среднем 30% своего внимания обращала на исходный текст, а 70% – на уже сгенерированный её же префикс. И по таким пропорциям хорошо детектируются самые жесткие случаи галлюцинации, когда весь перевод имеет мало отношения к исходному тексту.

Окей, галлюцинации мы детектировать можем, а как их лечить? В работе Guerreiro предлагают рабоче-крестьянский метод: сгенерировать десяток разнообразных гипотез перевода, и выбрать лучшую согласно всё тем же автоматическим метрикам. Это сокращает долю галлюцинаций в 2-3 раза, но не лечит их полностью. Так что работать ещё есть над чем.
Как вы знаете, я обожаю энкодеры предложений, особенно многоязычные.
Как-нибудь в ближайшем будущем я напишу про LASER, ибо с него вообще всё началось.
А сегодня я репостну сюда свой ответ про обучение LaBSE, который не хочется потерять в пучинах умирающего Слака ODS.

Итак, вопрос: как воспроизвести обучение LaBSE (статья, веса) – BERTовой модели, вычисляющий сопоставимые эмбеддинги предложений для 100 языков?

Ответ: обучение очень похоже на рекомендуемый пайплайн от sentence-transformers, на одних только положительных примерах (парах предложений с одинаковым смыслом на разных языках). Отрицательными примерами будут все остальные тексты в текущем батче. Это достигается функцией потерь вроде MultipleNegativesRankingLoss с параметром scale=1 и с дополнительным вычитанием магического числа margin=0.3 из диагонали матрицы сходства предложений.

Вот моя имплементация этого лосса:
def get_contrastive_loss(embs1, embs2, margin=0.3):
bs = embs1.shape[0]
d = embs1.device
embs1 = torch.nn.functional.normalize(embs1)
embs2 = torch.nn.functional.normalize(embs2)
all_scores = torch.matmul(embs1, embs2.T)
# print(all_scores)
if margin:
all_scores = all_scores - torch.eye(bs, device=d) * margin
loss_fn = torch.nn.CrossEntropyLoss()
diag_ids = torch.arange(bs, device=d)
return loss_fn(all_scores, diag_ids) + loss_fn(all_scores.T, diag_ids)
Соответственно, training loop для обучения модели будет выглядеть примерно так:
for step in trange(n_steps):
x_texts, y_texts = get_next_batch()
x_embs = model(tokenizer(x_texts)).pooler_output
y_embs = model(tokenizer(y_texts)).pooler_output
get_contrastive_loss(x_embs, y_embs).backward()
optimizer.step()
optimizer.zero_grad()

Здесь tokenizer – это обычный BertTokenizer, но обученный сразу на всех 100 языках, которые хочется поддержать.
А model - это, опять же, обычная BertModel , которую можно инициализировать из берта, предобученного на MLM на этих языках, а можно и просто с нуля.
Функция get_next_batch() должна сэмплить два списка предложений, такие, что i-тые предложения в обоих списках обозначают одно и то же, но на разных языках. Параллельный корпус, на котором обучали LaBSE, в открытый доступ не выложен, но можно взять любой другой - например, корпус NLLB+CCMatrix.

Этот же лосс, кстати можно использовать, чтобы дообучить уже имеющийся LaBSE какому-нибудь новому языку, используя двуязычный корпус – как я в прошлом году делал для эрзянского.
С докером я работаю давно, но Dockerfile'ы почти всегда копипащу из одного проекта в другой с минимальными изменениями.
Сегодня ради разнообразия решил написать докерфайл с нуля.
Результат: часа два ебался с тем, почему мой докер не печатает мне логи.

Выяснилось, что всё решает формат финальной команды: CMD ["python", "main.py] работает нормально, а вот при CMD python main.py весь stdout улетает в какую-то другую вселенную, хотя всё остальное работает нормально.

Есть ли у этого какое-то внятное объяснение?
Forwarded from New Yorko Times (Yury Kashnitsky)
Пет-проекты и менторство
#career #ml #petproject

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

Тут стоит упомянуть менторскую инициативу, запущенную в Singularis.ai Айрой Монгуш @aira_mo & Co. Вот описание программы, там же список менторов. Список годный, к некоторым из этих людей я бы сам сходил как менти. Хватайте! Можно будет и ко мне постучаться, но я скорее всего забит, фрухпут выделил – 1 менти за раз.

Вот какие идеи сейчас на уме (помимо умного поиска по мемам, про который уже писал), в порядке от более простых и хорошо формулированных к менее тривиальным и прописанным:

1) Валидация sciBERT-лонгформера на нескольких датасетах, техрепорт. Я как-то опубликовал расширенную версию SciBERT, поддерживающие тексты до 4096 токенов (делаются такие штуки по тьюториалу от HF, там суть в том, что позиционные эмбеддинги расширяются с 512 до 4096 простым копированием). Но я толком не валидировал выхлоп с этого дела. Можно взять несколько датасетов с длинными научными текстами (будь до классификация статей или QA для страниц Википедии, полно бенчмарков в статье Меты про Galactica) и сравниться с обычным SciBERT и лонгформером на базе роберты (не дообученной на научный контент). Из этого можно сделать техрепорт, опубликовать на архиве;

2) Удивительно, но для того же научного домена я не нашел легковесной модельки а-ля DistilBERT. Можно взять SciBERT, дистилировать его в модельку размера DistilBERT, опубликовать на HF и прославиться. Также опубликовать техрепорт. В целом можно следовать статье Давида Дале @izolenta_mebiusa про малького шустрого Берта на русском. Там Давид аж о 8-ми лоссах дистиллирует. То есть можно взять не только одного SciBERT как teacher и не только logloss, но также Galactica и более хитрые лоссы а-ля выравнивание CLS-эмбеддингов моделей учителя и ученика;

3) Ассистент на вопросах-ответах Stackoverflow. Там уже полно ранжированных ответов, с кодом. Возможно, никакой RLHF не нужен с таким датасетом. А самому StackOverflow, на мой взгляд, нет смысла обучать такого бота – им нужны кожаные мешки на сайте. Пока я это придумывал, 🤗 уже собрал датасет (узнал из поста Игоря Котенкова), ну идея в воздухе висела в принципе. Дальше можно повалидироваться с chatGPT, Codex и прочими ассистентами, с лету лучше вряд ли получится, но опыт интересный. Умеренные LLM в целом уже научились файнтюнить за разумное время даже на одной GPU, вот пример от инженера HF;

4) Распознавалка ребенка по мере его роста. Самый размыто формулированный пет – про CV и для тех, кто ждет ребенка, т.е. самый нишевый вариант из перечисленных. Суть: дите растет, модель ошибается, нужен continual learning. Тут сплошной дата дрифт и сходу вообще не понятно как подступиться. По крайней мере, алгоритмы Apple ошибаются, мне в галерее айфона показывает несколько инстансов моей дочери.

По поводу первых двух – можно мне писать, я готов подключиться к написанию репорта. Правда, я учусь делегировать (больно) и воздержусь от ковыряния в коде своими руками, буду чистый “Data Scientist ртом”. Со статьей при этом готов активно помогать. Лучше в коментах писать, кто что готов взять, можно скоординироваться и между собой.
Я обещал давеча рассказать про эмбеддинги LASER.

Первая их версия вышла в 2018 году (статья), и была довольно прорывной штукой. Идея такова: совместно обучить две LSTM-модели, энкодер и декодер. Энкодер читает предложения на 93 разных языках и превращает их в векторы фиксированной размерности, а декодер получает на вход эти векторы и по ним генерирует перевод исходных предложений на английский язык. Потом декодер мы выкидываем (ибо как переводчик он не очень хорош), а энкодер зато теперь может собирать предложения с 93 разных языков в общее семантическое пространство, в котором можно, например, искать ближайших соседей и таким образом майнить параллельные корпусы для машинного перевода. Ну или можно обучать классификатор поверх этих эмбеддингов на одном языке, а потом применять его на других.

Выложенный код LASER оказался не очень удобным, но сообщество быстро соорудило пакет laserembeddings и активно им пользовалось. Потом появились и другие мультиязычные энкодеры предложений (USE, LaBSE, мультиязычные sentence-transformers), и LASER немного утратил актуальность. Но в прошлом году вышла статья No Language Left Behind, и вместе с ней выложили энкодеры предложений для 200 языков, названные LASER-3 (LASERом-2 было обновление исходного пространства эмбеддингов, вышедшее чуть раньше без большой шумихи). Так что если вам нужны эмбеддинги предложений, скажем, для мальтийского языка, то кроме LASER-3 (либо обучения вашей собственной модели) выбора сегодня особо и нету.

Если хотите потыкать LASER-2/3 самостоятельно, можно или залезть в официальный репо, или, если у вас аллергия на bash-скрипты, начать с моего блокнота, в котором их нет.

Ну и напоследок: в прошлом году появились энкодеры speechLASER для ~20 европейских языков, кодирующие аудио в то же пространство, что и LASER-2 и LASER-3. Так что можно, например, обучить классификатор на английских текстах, а потом применять его к речи на этих 20 языках, минуя этап speech recognition. Модели, правда, очень жирные, так что на практике их применять сложновато, но таки оно работает.

Ну и в будущем, я полагаю, какие-нибудь ещё интересные новые LASERы будут появляться.
Так сложилось, что прошлой зимой и весной я чуть-чуть имел дело с башкирским.
Айгиз, которого вы можете знать, делает большой проект по оцифровке своего языка, и я помогал ему с двумя задачами – автоматическим исправлением орфографии и чисткой параллельного корпуса предложений.
Результаты этих моих изысканий могут оказаться полезны кому-то ещё, поэтому вот пост про них.

Несколько отдельных небезынтересных выводов:

1) Для задач, где нужно вносить в текст маленькие точечные правки (в моём случае это было исправление ошибок OCR), хорошо работают маленькие нейросетки с посимвольными токенами на входе (ещё и предварительно разбавленными другими символами) и с CTC лоссом на выходе. Как тут. Почему неплохо? Потому что в отличие от seq2seq моделей, у них почти нет возможности галлюцинировать или пропускать большие куски инпута.

2) В задачах, где нужно сравнивать пары текстов (в моём случае - удаление некорректных пар из русско-башкирского параллельного корпуса), кросс-энкодеры (модели, делающие оценку сходства по сконкатенированной паре предложений) работают чуть качественнее, чем би-энкодеры (модели, которые эмбеддят каждое предложение отдельно, и потом сравнивают эмбеддинги). Но это преимущество достигается, только если повозиться со сложными отрицательными примерами – создавать их, внося мутации в положительные пары предложений. Примерно как тут.

3) Публичные большие параллельные корпусы для не самых попсовых языков могут едва ли не наполовину состоять из мусора. Поэтому если вы собираетесь (до-)обучать на них что-либо, эта самая фильтрация, кажется, необходима.

Если решите попробовать мои рецепты для другого языка или другой задачи – не стесняйтесь писать мне, чтобы я подготовил их в более удобном виде.
Я обновил рейтинг русскоязычных энкодеров предложений github.com/avidale/encodechka, по просьбам трудящихся (и благодаря помощи @dealerAI, нашедшего баг в моих расчетах и настойчиво о нем напоминавшего).

Напомню, что это бенчмарк из 8 задач на эмбеддинги предложений (и еще 2 дополнительные- на эмбеддинги токенов).
В каждой задаче эмбеддинги из модели берутся "как есть" (для BERT-подобных моделей я беру наилучший из двух: эмбеддинг первого токена либо средний эмбеддинг всех токенов), и применяются в качестве фичей для конечной задачи (косинусная близость, либо классификация с помощью логрега или knn).
Дальше я усредняю метрики качества по 8 основным задачам (они разные, но все между 0 и 1), и отмечаю модели, оптимально балансирующие это качество и размер либо скорость.

Что изменилось:
1) Некоторые скоры подвинулись вверх (но не очень сильно, в основном на 1-2%), благодаря исправленной опечатке в формуле усреднения эмбеддингов токенов.
2) Добавилось несколько новых моделей, включая:
- нового лидера Multilingual-E5-large, взявшего сразу 5 медалей в задачах семантической близости, анализа тональности, и классификации интентов;
- эмбеддинги от OpenAI text-embedding-ada-002, которые, несмотря на большую размерность, не особо себя проявили;
- symanto/sn-xlm-roberta-base-snli-mnli-anli-xnli, ожидаемо (и не очень честно) победившую в NLI задаче;
- deepvk/deberta-v1-base, победившую в разряде "детекция токсичности" (aka "одноклассники");
- энкодер от ai-forever/FRED-T5-large, победивший в детекции неполиткорректных текстов.
3) Добавил в лидерборд столбец с размерностью модели, так что теперь например видно, что одинаково перформят 1536-мерные эмбеддинги от OpenAI и 384-мерные из MiniLM-L12.

Если вы хотели бы видеть в бенчмарке какие-нибудь ещё энкодеры – пишите, добавлю!
̶с̶а̶м̶̶о̶изолента мёбиуса
Я обновил рейтинг русскоязычных энкодеров предложений github.com/avidale/encodechka, по просьбам трудящихся (и благодаря помощи @dealerAI, нашедшего баг в моих расчетах и настойчиво о нем напоминавшего). Напомню, что это бенчмарк из 8 задач на эмбеддинги…
Кстати, какие таски, по-вашему, стоит ещё добавить в бенчмарк encodechka, чтобы сделать его более информативным?

Думаю добавить каких-нибудь retrieval задач (типа miracl или mr-tydi, где вроде есть русскоязычное подмножество) и задач на логическую связь между текстами, типа RuFacts, headline_cause, или даже seahorse_summarization_evaluation (предсказывать оценки attribution и main ideas). Ну и еще пару задач классификации - например, спам или тематику коротких историй.

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

Мои коллеги по Мете обучили ещё одно семейство эмбеддингов - SONAR (код, статья). Название намекает, что они работают не только с текстом, но и со звуком: в настоящий момент опубликован текстовый мультиязычный энкодер предложений на 200 языков, и 37 одноязычных энкодеров предложений для устной речи. И все эти энкодеры для всех языков работают в общем семантическом пространстве.

Более того, выложен декодер из этого пространства обратно в текст на 200 языков (на основе модели NLLB, как вы могли заподозрить). Примерно как я делал год назад с LaBSE, только сильно более масштабно 🙂 А это значит, что соединив энкодер с декодером, мы можем переводить текст (200 языков) и речь (37 языков) на любой из 200 текстовых языков.

Ну и да, на основе этих эмбеддингов мы намайнили море параллельных данных, на которых обучили большую seq2seq модель SeamlessM4T переводить уже речь-в-речь для 100 языков на входе и 36 языков на выходе (плюс разные комбинации с текстом). Но про это и так сегодня напишут, так что я ограничусь ссылкой на блог.

Расскажу лишь про свой вклад в эту статью - небольшая моделька поверх эмбеддингов SONAR, которую мы обозвали BLASER 2.0 (первый BLASER тут), которую можно использовать для оценки качества машинного перевода и других семантических сравнений. Первая, blaser-2.0-qe, сравнивает перевод с исходным предложением, а вторая, blaser-2.0-ref - ещё и с переводом-референсом.
Примерно как COMET или BLEURT, только мультимодальное и более мультиязычное 🙃
Знакомые организуют Workshop on Advancing Neural Network Training (WANT): Computational Efficiency, Scalability, and Resource Optimization – в общем, про то, как обучать нейронки вычислительно эффективнее.

Если вы этим занимаетесь, до 29 сентября к ним можно засабмтить свою статью.
Сегодня в этот канал пришло довольно много новых подписчиков.
Любопытно: откуда вы пришли и о чём бы хотели здесь читать? 🙂
Ну а пока я расскажу про статью Belebele от своих мультиязычных коллег по Мете.

Они взяли датасет FLORES-200, задали к его текстам вопросы разной сложности с 4 вариантами ответа, и аккуратно перевели их на 115 языков (122, если считать разные варианты письменности). Получился, кажется, самый мультиязычный бенчмарк по question answering.

Вопросы в открытой форме не стали задавать, чтобы сфокусировать бенчмарк чисто на понимании текста, а не на его генерации (и не на знаниях о мире). В результате датасет оказался не очень сложный: сами авторы верно ответили на 97% английских вопросов, модели типа Llama2 и GPT3.5 - на 90%. Но в среднем по всем языкам у GPT-подобных моделей вышла только 50% точность (что не очень много; 25% - точность случайного угадывания). А мультиязычные BERT-подобные модели (XLM-R и пара её модификаций), обученные на английской тренировочной выборке, выбили 80% на английском и 56% в среднем по языкам, а при переводе обучающей выборки на все языки - 60%.

Выводы из этого я бы сделал такие (в основном совпадающие с выводами авторов):
- Простая задача, ответ на вопросы по тексту, для 100 крупнейших языков пока скорее не решена, чем решена.
- LLM без дообучение обобщаются на новые языки на удивление неплохо (на ~40% языков выбили больше 50% правильных ответов), но таки очень далеко от точности, ожидаемой для применения (условно как для английского).
- Дообучение encoder-only моделей всё ещё кажется практичным решением для задач понимания текста; многие из них дообучены на более сбалансированном распределении языков, чем LLMs, и потому дообучаются качественно.

Впрочем, подождем, пока появится LLM, предобученная на сбалансированной смеси сотни языков, и тогда ещё раз сравним 🙃
По просьбе в комментариях, собрал примерный рейтинг самых залайканных постов в этом канале (помимо чисто лулзовых):

1. Первый переводчик для эрзянского
2. обновление Энкодечки
3. обзор SeamlessM4T and Sonar
4. статья про галлюцинации в переводе
5. обзор LASER
6. опечаточник и фильтрация параллельного корпуса для башкирского
7. бенчмарк Энкодечка и rubert-tiny2
8. восстановление предложений из эмбеддингов LaBSE

Кроме этого, вот список других постов с полезными моими поделиями, в основном из тех времен, когда в Телеге еще не было лайков:

- Сжатие эмбеддингов fasttext в 100 раз
- поиск контекстно похожих слов (ответ на stackoverlow)
- парафразер на правилах (почти без ml)
- как выкидывать ненужные токены из mT5
- первый rubert-tiny
- обзор парафразеров для русского
- ресурсы по NLI, включая мои модели для русского
- мультизадачный T5 для русского
- детоксификация текстов без параллельных данных
- обзор метрик семантического сходства коротких английских текстов
Собрал тьюториал по дообучению NLLB-200 для перевода на новые языки, на примере русско-тувинского перевода.

В комплекте:
- предобработка текстов (неочевидная)
- добавление токенов для нового языка (муторное)
- собственно training loop (очевидный)
- докеризованное приложение для инференса (не оптимизированное, зато простое)

Если вам интересно добавить собственный язык в NLLB, или поделиться опытом того, как вы это уже сделали - пишите!
Хороший мини-курс по лингвистике для NLPшников недавно выпустила Лиза Былинина: bylinina.github.io/ling_course.

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

Поэтому - рекомендую.