- BrainTools - https://www.braintools.ru -

Как я делал свою языковую модель: история эксперимента

Уже больше года назад у меня зародилась идея создать свою архитектуру языковой модели. Традиционные модели, “думающие” на уровне токенов мне решительно не нравились. Колоссальный вычислительный бюджет на то, чтобы просто предсказать один токен. Логичным мне казалось оторвать мышление [1] модели от токенов, перенеся его в латентное пространство. Примерно полгода назад я начал первые практические эксперименты и сейчас получил первые практические результаты. Поскольку уровень подготовки читателей очень сильно различается, в статье не будет глубоких технических разборов, а скорее история эксперимента.

Для того, чтобы реализовать эту идею логично [2] было разделить модель на три части:

  1. Энкодер — переводит текст из пространства токенов в латентное.

  2. Декодер — делает обратное: из латентов восстанавливает текст.

  3. Ядро — остаётся “внутри” и непосредственно думает, генерируя латентную последовательность.

Плюсом подхода было то, что каждую часть модели можно тренировать отдельно, экономя ресурсы и не используя огромные объемы VRAM. Кроме того, можно экспериментировать с архитектурами и параметрами каждой субмодели. Главным было сохранить единым латентный “язык”.

Создание и обучение [3] собственного энкодера – задача весьма непростая и требует больших вычислительных мощностей. Поэтому для упрощения я решил взять готовый энкодер с достаточно большой семантикой и специализацией на русском языке. Выбор пал на USER2-bge-m3 [4] с размерностью эмбеддинга 1024. Кто-то наверняка скажет, что классический энкодер осуществляет сжатие с потерями, неизбежно теряет часть информации и не заточен под восстановление исходного текста. Да, теряет, да, не заточен. Но, эксперименты показали, что тексты не очень большой длины (до 20-30 токенов) можно восстанавливать практически без потерь. На более длинных последовательностях потери уже ощутимы, но, что более важно — сохраняется семантика, мы не теряем смысл. Да и для эксперимента это было не так важно, куда важнее было убедиться в работоспособности подхода. Поэтому задача была нарезать исходный текст на относительно небольшие части и, что не менее важно, семантически однородные, чтобы в эмбеддинге не происходило смешения “смыслов”. Т.е. один эмбеддинг должен быть сформирован семантически единым фрагментом текста, без шума и мусора. Например, если берем описание города из Википедии, то оно содержит разные фрагменты: информация о населении, истории, культуре, архитектуре, общественном транспорте и так далее. В идеале нужно разделить этот целый текст на отдельные семантически не пересекающиеся фрагменты, создать своего рода семантический токен, но не в дискретном пространстве токенов, а в непрерывном латентном.

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

Латенты: что это такое в данной модели

После сегментации каждый сегмент с помощью энкодера превращается в вектор фиксированной размерности — латент. Для проекта это ключевая “валюта”: всё самое интересное происходит именно с этими векторами. На них “думает” ядро модели. А целый текст превращается в последовательность латентов.

> текст → сегменты → латенты: [L1, L2, L3, …]

Почему последовательность? Удобнее:

  • её можно продолжать (это пригодится для обучения ядра),

  • можно брать окно контекста,

  • можно независимо обучать компоненты и проверять гипотезы.

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

Кратко о данных

Как известно, данные решают. Конечно у меня нет в распоряжении кластера на 8xH100 на месяц, ресурсы скромные и ограниченные. Всего одна 5090 на 32Гб – кто сталкивался с обучением LLM, понимает, насколько это мало. Поэтому рассчитывать на полноценное обучение на терабайтах токенов я конечно не мог. Но эксперимент на то и эксперимент, что должен показать хоть какой-то результат. В итоге было сформировано два небольших датасета. Первый на 2 млрд. токенов для претрейна и еще один на 1 млрд. токенов для инструктивного обучения.

Датасеты: как готовились данные

1) Датасет для декодера (latents → text)

Это базовая задача “обратного преобразования”: по латентам восстановить текст.

Каждая запись — это по сути “одна история” (статья или кусок диалога):

  • список сегментов,

  • список латентов для каждого сегмента,

  • полный исходный текст – это удобно для проверки качества.

Датасет строится просто: берём исходный корпус, сегментируем, кодируем сегменты энкодером и сохраняем всё в удобном формате (parquet‑шарды). Дальше на этом можно учить декодер “говорить” по латентам, а ядро – прогнозировать следующий латент в последовательности

2) Инструктивный датасет (Q/A) для обучения поведения [5]

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

Инструктивный датасет сразу сделал универсальным, чтобы можно было обучать как ядро(латенты как “смысл”), так и декодер (текст как “речь”).

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

Ядро: “мышление” на уровне латентов

Ядро – это часть, ради которой весь этот эксперимент и затевался. Оно учится на последовательностях латентов и предсказывает следующий латент. По смыслу это похоже на классическую языковую модель, только вместо токенов у нее смысловые векторы.

Зачем это нужно:

  • ядро учится продолжать смысл без привязки к конкретным словам,

  • можно делать “планирование” в латентном пространстве,

  • сформированная последовательность латентов переводится в текст через декодер.

Декодер: речь по латентам

Декодер — это речевая часть модели. Он берёт латенты и превращает их обратно в последовательность токенов, то есть в читаемый текст.

Ограниченность датасета сыграла свою роль – “дожать” декодер до хороших результатов не получилось, он неизбежно сваливался в переобучение.

Какие итоги эксперимента?

1) Получилось построить пайплайн:

семантическая сегментация → латенты → ядро (латентное продолжение) → декодер (текст)

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

2) Получилась модель “двухуровневой” генерации:

  • на уровне латентов создается смысл,

  • на уровне токенов – форма и язык.

Именно это разделение и было изначальной целью: не “сделать ещё одну LLM”, а сделать систему, где смысл и форма — два разных уровня, которые можно развивать независимо.

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

You> как найти хорошую работу?

Bot> Лучший способ найти работу в сфере предпринимательства — это изучить потенциальных работодателей и их квалификацию. Подумайте о том, чтобы пройти курсы или стажировки, на которых вы можете быть в курсе последних тенденций и технологий. Кроме того, рассмотрите возможность посещения занятий в компании или университете, которые могут дать совет о вакансиях. Наконец, не забудьте включить в свое резюме сопроводительное письмо и другие документы, подтверждающие ваши навыки и опыт [6].

You> какой язык программирования ты посоветуешь для новичка?

Bot> Самый популярный язык программирования для изучения — Python. Python — это язык программирования, который можно использовать для написания программ, отладки кода и создания пользовательских интерфейсов. Он имеет ряд преимуществ перед другими языками программирования, такими как Java и C++.

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

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

Не бойтесь экспериментировать с языком и инструментами.

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

Что дальше?

Дальше идей много, но если коротко, самые очевидные направления такие:

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

  • улучшать устойчивость модели сегментации на “грязных” текстах,

  • делать более богатые инструктивные режимы (диалоговые форматы, многоходовые ответы),

  • наращивать качество декодера через архитектуру/данные без потери стабильности,

  • создать долговременную память [7] модели на латентах.

Буду благодарен за обратную связь и отвечу на возникшие вопросы.

Автор: aka352

Источник [8]


Сайт-источник BrainTools: https://www.braintools.ru

Путь до страницы источника: https://www.braintools.ru/article/24337

URLs in this post:

[1] мышление: http://www.braintools.ru/thinking

[2] логично: http://www.braintools.ru/article/7640

[3] обучение: http://www.braintools.ru/article/5125

[4] USER2-bge-m3: https://huggingface.co/deepvk/USER-bge-m3

[5] поведения: http://www.braintools.ru/article/9372

[6] опыт: http://www.braintools.ru/article/6952

[7] долговременную память: http://www.braintools.ru/article/9500

[8] Источник: https://habr.com/ru/articles/985496/?utm_source=habrahabr&utm_medium=rss&utm_campaign=985496

www.BrainTools.ru

Rambler's Top100