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

За последнее время нами были выпущены новые модели и добавлены новые функциональные возможности в сервис. А теперь мы представляем новую нейросетевую модель, у которой более 29 миллиардов параметров. Она успешно прошла тест на ЕГЭ и показала отличные результаты в сравнении с другими системами. Если вы только начинаете интересоваться новыми технологиями в области искусственного интеллекта, то имейте в виду, именно они в ближайшие годы будут формировать наше с вами будущее и давать преимущество тем, кто ими владеет. Давайте познакомимся с ними поближе.

Не ещё один чат

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

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

Приведем пару примеров работы с GigaChat. Запросы могут быть самые разные:

Технические

Даны списки:
a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]; b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13].

Нужно вернуть список, который состоит из элементов, общих для этих двух списков.

Ответ:

Для решения этой задачи можно использовать встроенную функцию Python set(), которая возвращает уникальные элементы списка. После этого можно преобразовать полученное множество обратно в список с помощью функции list(). В итоге получим список, состоящий из элементов, которые присутствуют и в первом, и во втором списке.

Вот как это можно сделать:
a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89];
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
c = list(set(a) & set(b)).

После выполнения этого кода переменная c будет содержать список [1, 2, 3, 5, 8, 13].

Креативные

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

Ответ:

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

Позвольте представить вам просторный, светлый гараж площадью 60 квадратных метров, расположенный на охраняемой территории с видеонаблюдением. В нём есть электричество, вода и канализация, а также смотровая яма, без которой не обходится ни один настоящий автолюбитель.

Могу сказать наверняка: ваш автомобиль заслуживает лучшего, и этот гараж станет для него настоящим домом. Не упустите свой шанс обзавестись недвижимостью в экологически чистом районе Химок. Жду ваших обращений!

Развлекательные

Сочини считалку про программиста

Ответ:

В офисе скрестили шпаги
Наши программисты:
Разбирали они баги,
Фича-рецидивисты.

Что под капотом

Процесс создания GigaChat, как и всех других AI-сервисов на основе LLM от ChatGPT до Claude, состоит из двух этапов:

  • Unsupervised Pretraining — учим нейронную сеть на большом количестве легкодоступных данных. GigaChat учится предсказывать следующее слово в текстах из Интернета, книгах и т. д.

  • Alignment — учим нейронную сеть с предыдущего шага следовать инструкциям пользователя, при этом не нарушая никакие законы и не будучи предвзятым. Эта стадия называется alignment (выравнивание), потому что происходит выравнивание желаний и ценностей людей с тем, что генерирует нейронная сеть.

В этой статье мы расскажем про нашу новую pretrain модель, которая легла в основу GigaChat Pro версии.

Возможности новой модели

Самое большое событие релиза — это достижение паритета с ChatGPT-3.5-turbo на метрике SBS (Side-By-Side), где мы просим людей сравнить качество ответов двух моделей.

У SBS есть минусы и поэтому мы дополняем его с помощью автоматических метрик — задач, ответы на которые можно проверить без участия людей. Такие метрики позволяют получать оценку модели очень быстро, а также оценивать Pretrain'ы, которые еще не научились следовать инструкциям.

Для оценки моделей после alignment в автоматических метриках мы используем продуктовые задачи из банка и от внешних клиентов, которые передали нам корзины запросов для оценки, а для оценки pretrain моделей замеряем их на открытых бенчмарках.

SBS (Side-By-Side)

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

  • Лучше ответила 1-ая модель (всего таких ответов good_a);

  • Лучше ответила 2-ая модель (всего таких ответов good_b);

  • Обе модели ответили хорошо (всего таких ответов both);

  • Обе модели ответили плохо (всего таких ответов none).

Результат SBS считается по формуле:

 result\_a = \frac{good\_a + both/2}{good\_a + good\_b + both}

Результаты SBS (50%) GigaChatPro vs (50%) ChatGPT

Результаты SBS (62%) GigaChatPro vs (38%) YandexGPT General (теперь Lite)

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

Автоматические метрики pretrain модели

Модель

MMLU ru (5-shot)

MMLU (5-shot)

HumanEval (pass@1)

HellaSwag (0-shot)

WinoGrande (0-shot)

gsm8k (8-shot)

GigaChat Pro

58,1

65,01

35,37

82,33

76,48

43,82

GigaChat

47,53

53,38

24,39

76,92

71,27

26,7

llama-2-7b

37,86

46,87

12,8

77.22

69.2

14,6

llama-2-34b

62,60

mistral-7b

50,53

61,72

30,5

81.1

73.88

36,09

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

Основной акцент GigaChat’а — это русский язык, но наш pretrain показывает результаты, сравнимые с лучшими Open Source моделями и на английском языке.
На английском MMLU GigaChat Pro до alignment’а дает более высокие результаты, чем LLama-2-34B (64,7% против 62,6%). К сожалению, LLama-2-34B не была выпущена в Open Source, поэтому мы не можем замерить другие метрики вроде MMLU-RU.

На MMLU-RU GigaChat Pro побеждает одну из самых сильных Open Source моделей на данный момент Mistral-7B (57,8% против 50,5%).

Автоматические метрики после alignment

Модель

MMLU ru

Прод. задачи

Ответы по документам

GigaChat Pro

50,0

77,4

70,5

GigaChat

45,0

67,1

35,0

ChatGPT

54,0

57,2

52,5

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

В «Ответы по документам» необходимо указать процент аванса и число дней отсрочки, если они указаны в документе.

Сдача ЕГЭ по обществознанию

GigaChat смог выполнить все задания единого государственного экзамена по обществознанию и набрал 67 баллов, что превышает минимальный балл для подачи в вуз (45 баллов) и средний балл по предмету в 2023 году (56,4 балла). Ответы модели были проверены независимыми экспертами НИУ ВШЭ.

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

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

Выводы

GigaChat Pro достиг паритета по способностям с ChatGPT, а на продуктовых задачах в банке обходит его. Сама pretrain модель находится на уровне сильнейших Open Source на английском языке сравнимого размера, а на русском является лидером среди моделей схожего размера на 5 декабря 2023 года.

API

Чтобы попросить GigaChat перевести текст, придумать анекдот или сгенерировать картинку с котиком, отлично подходит веб интерфейс, но для более серьезных применений нужен удобный программный интерфейс — API. ChatGPT от OpenAI на днях запретил обращение к своей системе с российских IP-адресов и GigaChat может стать хорошей альтернативой, достигая такого же или лучшего качества на многих задачах, особенно на русском языке.

Мы предоставляем индивидуальным разработчикам специальный freemium тариф на 1 миллион бесплатных токенов. Если их не хватает, можно докупить нужный пакет токенов. Как по мне, так это отличная возможность интегрировать нейросетевые технологии в свой проект или облегчить свои рутинные задачи на работе.

Сценарии работы с API подробно описаны в нашей документации, но в целом алгоритм следующий:

  1. Получить в личном кабинете авторизационные данные, которые будут использоваться для получения временного токена доступа.

curl --location --request POST 'https://ngw.devices.sberbank.ru:9443/api/v2/oauth' \
     --header 'Authorization: Bearer <auth_token>' \
     --header 'RqUID:f2911be0-8c91-4576-bbd4-5238d834c17a' \
     --header 'Content-Type: application/x-www-form-urlencoded' \
     --data-urlencode 'scope=GIGACHAT_API_PERS'
Ответ:
{
  "access_token":"eyJjdHkiOiJqd3Q...iLCJlbmMiOiJBMjU2Q0JDLU",
  "expires_at":1700396614784
}
  1. Использовать токен при обращении к необходимой модели.

    Полный контекст диалога можно передавать в виде массива объектов с ролями user и assistant.

curl -k https://gigachat.devices.sberbank.ru/api/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer eyJjdHkiOiJqd3Q...iLCJlbmMiOiJBMjU2Q0JDLU' \
  -d '{
  "model": "GigaChat-Pro",
  "messages": [
    {
      "role": "user",
      "content": "Придумай альтернативное название для шоколадки Алёнка, 
            оно должно быть необычным и футуристичным"
    }
  ],
  "temperature": 0.65
}'
Ответ:
{
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "Как насчёт \"Квантовой сладости\"?
                    Это название звучит необычно и подразумевает использование
                    передовых технологий в производстве шоколада.",
        "role": "assistant"
      }
    }
  ],
  "created": 1700395635,
  "model": "GigaChat:latest",
  "object": "chat.completion",
  "usage": {
    "completion_tokens": 30,
    "prompt_tokens": 191,
    "total_tokens": 221
  }
}

Отмечу также и еще одно преимущество работы с API. Вы можете самостоятельно управлять семплингом и регулировать параметры top_p, top_k, temperature и repetition_penalty. Это дает вам контроль над тем, будет ли модель генерировать самый вероятный ответ или будет варьировать распределение токенов, чтобы каждый раз выдавать что-то новое. Первый вариант больше подходит для решения задач на классификацию текста или ответа на экзаменационный вопрос, а последний — для генерации креативных материалов, типа маркетинговых текстов.

Техническая часть

Чтобы внести свой вклад в развитие LLM, мы хотим поделиться подробностями нашего пайплайна для pretraining’а. Мы надеемся, что эта информация поможет сообществу развиваться и поддерживать конкурентную среду.

Начнем с общей технической информации о наших моделях. Как и предыдущая модель, новый GigaChat Pro — это декодер трансформер 29 миллиардов параметров с улучшениями для ускорения сходимости и обучения. Для кодирования позиционной информации используются Rotary эмбеддинги. В качестве оптимизатора используется Adam с beta_1=0.99, beta_2=0.95.

Основная часть pretraining’а происходит с контекстом в 4 тысячи токенов. Ближе к концу обучения мы расширяем контекст моделей, используя свойства Rotary эмбеддингов, и заканчиваем обучение с большим контекстом (24-32 тысячи токенов).

Для обучения моделей мы используем фреймворк FSDP (Fully Sharded Data Parallel). По функциональности он очень похож на DeepSpeed и позволяет шардировать модели при обучении, т.е. хранить на каждой GPU только часть весов и состояний оптимизатора.

Большинство Open Source LLM сейчас используют по сути одинаковую архитектуру и процесс обучения нейронной сети. Направления, в которых идет основная конкуренция — это качество pretrain данных, эффективность обучения и небольшие детали в процедуре обучений. Именно про продвижение в этих направлениях мы расскажем далее.

Данные

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

Во-первых, данных на английском языке значительно больше и среди них проще отфильтровать качественные токены.

Во-вторых, самые качественные Open Source датасеты вроде FRW (Falcon Redefined Web) отфильтровывали русские данные, а мультиязычные датасеты не делали акцент на русском языке и в целом слабее FRW.

Для сбора качественного датасета мы решили самостоятельно очистить Common Crawl, сделав акцент на двух языках — русском и английском. Извлечение текста из HTML страниц проводилось с помощью библиотеки trafilatura, а для дальнейшей очистки мы дополнили классические фильтрации на основе эвристик с помощью двухстадийного нейронного классификатора. После очисток применяется дедупликация с помощью SimHash.

Нейронные классификаторы

Основной тип ошибок, которые мы ищем — некорректное извлечение текста из HTML trafilatur’ой. Первая стадия очистки разделяет документы на три цвета — зеленый, желтый и красный.

Зеленые документы, где ошибок нет, отправляются сразу в обучение, красные, где много проблем, выкидываются, а желтые, где ошибок немного, отправляются на вторую стадию для починки.

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

Отладка процесса обучения

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

GigaChat Pro — трансформер, содержащий 29 миллиардов параметров, и его обучение потребовало от нас решения многих инфраструктурных и архитектурных проблем.

Инициализация модели

Текущие модели настолько большие, что для инференса порой не хватает 80 GB GPU памяти даже на Nvidia-A100. Обучение модели требует еще больше ресурсов, поэтому используется техника шардирования (разбиения) модели между вычислительными узлами, как, например, показано на картинке.

Шардировать модель можно тремя способами (рассмотрим случай, когда инициализация слоев происходит независимо друг от друга):

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

  2. Инициализировать ее на CPU, а потом передавать куски модели на соответствующие GPU. Это намного дольше, чем пункт 1, но зато позволяет использовать оперативную память вычислительного узла, которой зачастую в десятки раз больше, чем на видеокарте.

  3. Если известен алгоритм шардирования модели, то можно сразу произвести инициализацию шардов на нужных GPU без полной инициализации модели в одном месте. Это самый быстрый и самый эффективный по памяти метод (meta init).

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

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

Токенизатор

Токен — некоторая смысловая единица текста (например, подстрока или последовательность байт). Задача токенизатора состоит в том, чтобы эффективно разбивать поступающий в модель текст на подстроки или последовательности байт и сопоставлять им соответствующие токены.

Изначально мы использовали токенизатор со словарем в 132 тысяч токенов и byte-level токенизаций. Это приводило к ряду проблем:

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

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

  2. Развал модели при более агрессивных параметрах оптимизации (уменьшении Adam epsilon).

Мы попробовали решить их комплексно и обучили новый мультиязычный токенизатор на 42 тысячи токенов. У нас получилась достаточно высокая степень сжатия: в среднем на один токен приходится 3.9 символа текста. Также в новом токенизаторе каждая цифра — отдельный токен, что позволило GigaChat’у лучше понимать математические задачи.

Оптимизатор

В своих обучениях мы используем Decoupled AdamW оптимизатор. Проведя ряд экспериментов с другими оптимизаторами, мы выбрали Adam. Он дает самые низкие значения loss функции, а также достаточно прост во внедрении.

Рассмотрим гиперпараметр Epsilon: самая популярная Open Source модель LLaMa-2 обучалась с \epsilon = 1e^{-5}. Наши эксперименты показывают, что:

  1. При большом размере токенизатора уменьшение epsilon может вызывать развал обучения.

  2. Более низкий epsilon с первых шагов и до конца обучения демонстрирует наименьшие значения loss функции, то есть модель обучается лучше.

Таким образом, уменьшение размера словаря токенизатора помогло добиться стабильного обучения при \epsilon = 1e^{-8} и, как следствие, дало возможность достигать более низких значений loss-функции.

Рестарты обучения

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

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

  2. Каждый рестарт также занимает некоторое время.

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

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

NaN в обучении

Во время pretrain’а GigaChat’а мы столкнулись с тем, что неожиданно число батчей, на которых возникает NaN, начало резко расти. А обновлять NaN’ом веса нельзя, так как это ведет к развалу модели.

поиске проблемы нам помогла система мониторинга обучения модели. Она собирает информацию о:

  • нормах, минимумах и максимумах весов, их градиентов и соответствующих моментов оптимизатора;

  • нормах, минимумах и максимумах активаций;

  • номерах слоев на forward и backward, где возник NaN;

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

По этим показателям мы заметили, что NaN возникал на backward сразу перед последним слоем, и придумали решение. Обновление весов модели при шардированном обучении обычно реализовано следующим образом:

  1. на каждой GPU считается loss по своему батчу;

  2. с каждой карты аккумулируются и усредняются градиенты;

  3. происходит backward и обновление параметров.

Был модифицирован пункт 2, и те градиенты, где встречаются NaN’ы, мы обнулили. Плюсы и минусы этого подхода:

Плюсы:

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

Минусы:

  • Тратим лишние вычислительные ресурсы на проверку на NaN’ы и зануление градиентов. Снижается скорость обучения.

  • Снижаем норму общего градиента с учетом зануления.

Этот трюк помог «вылечить» нашу модель от вычислительной нестабильности. Включив его, число NaN’ов начало падать и в итоге сократилось до нуля.

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

BF16 и FP32

Активации наших моделей для экономии памяти и ускорения подсчетов на обучении хранятся в типе данных bf16 (bfloat16). Этот тип данных имеет тот же range, что и fp32, но меньшую точность. Для аккумуляции градиентов и на этапе вычисления backward мы используем тип fp32, чтобы не допустить потерь в точности и ошибок вычислений.

Ускорение обучения трансформеров

А теперь давайте рассмотрим методы, которые позволили нам ускорить обучение в несколько раз.

Flash Attention 2

FlashAttention реализует механизм внимания (attention is all you need), который оптимизирован для работы с устройствами, имеющими высокую пропускную способность памяти (HBM) и быстродействующую оперативную память (SRAM).

Чем отличается HBM память от SRAM?

SRAM (Static Random Access Memory) и HBM (High Bandwidth Memory) — это два разных типа памяти, которые используются в компьютерных системах. Они отличаются по многим параметрам, включая скорость работы, емкость, стоимость и конструктивные особенности.

SRAM — это тип статической оперативной памяти. Она быстрее и надежнее, чем обычная оперативная память (RAM), но более дорогая и имеет меньшую емкость. SRAM используется в качестве кэш-памяти процессора, так как кэш требует высокой скорости работы.

HBM — это новый тип памяти, который был разработан для использования в графических процессорах и серверах. Она имеет высокую пропускную способность и большую емкость, что позволяет обрабатывать большие объемы данных. HBM также имеет более высокую скорость работы, чем обычная оперативная память.

Картинка из официального репозитория.

Ускорение достигается путем разбиения входного потока данных на более мелкие блоки и обработки этих блоков параллельно. Это позволяет уменьшить количество обращений к «медленной» памяти, что ускоряет выполнение операций.

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

Небольшой технический совет

В реализации из flash-attention обратите внимание на переменную causal.

Во многих реализациях блока внимания на основе flash-attention, подача непустой attention_mask (в том числе состоящей из единиц) сопровождается использованием функции unpad_input на каждом слое. Эта функция вызывает множество последовательных синхронизаций CPU и GPU. Чтобы найти подобные узкие места, можно воспользоваться PyTorch Profiler.

Чем плохи синхронизации между CPU и GPU?

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

Пример синхронизации CPU & GPU от использования unpad_input. На больших обучениях такие простои могут стоить много миллионов рублей.

Другие fused слои

Что такое fused слои?

Fused слой — это слой, в котором операции выполняются с использованием «слияния» или совместной обработки. В контексте глубокого обучения, «слияние» обычно относится к оптимизации, при которой несколько операций объединяются в одну, чтобы улучшить эффективность вычислений. Например, вместо того, чтобы выполнять операцию свертки, а затем операцию активации, можно объединить их в одну операцию, которая выполняет обе функции одновременно. Это может ускорить выполнение модели и снизить использование памяти.

К примеру, FlashAttention тоже относится к fused слоям. Но он особенный, поэтому мы написали о нем отдельно :).

Мы используем множество фьюзов, вот некоторые из них: Fused Cross-Entropy, Fused LayerNorm, Fused Rotary Embeddings. Каждый дает большой прирост к скорости, а некоторые — огромный выигрыш в видеопамяти.

Подробнее можно почитать в уже классическом блог-посте Making Deep Learning go Brrrr From First Principles

Selective Activation Checkpointing

Что такое Activation Checkpointing?

Activation checkpointing — это техника оптимизации, используемая в глубоком обучении для уменьшения количества памяти, необходимой для хранения активаций между операциями. Вместо того, чтобы сохранять активации для каждого отдельного примера во время обучения, activation checkpointing сохраняет в памяти только часть активаций (например, для каждого второго слоя), а остальные пересчитывает при вычислении backward. Это может существенно снизить использование памяти и дает возможность обучать модели большего размера.

Заметим, что активации модели в зависимости от слоя занимают разное количество видеопамяти и требуют разного количества времени на пересчет.

При достаточно большом контексте (или модели), мы сталкиваемся с тем, что активации всей модели уже не помещаются в видеопамять GPU. Тем не менее, нам нужны активации для подсчета backward pass. Решение — можем хранить только активации для N слоев, а остальные пересчитывать по необходимости вычисления градиентов.

Но вместо того, чтобы хранить все активации для N слоев, мы могли бы сохранять только самые вычислительно-затратные активации на единицу памяти. Это позволит нам сохранять «дорогие» активации для дополнительных M слоев.

Реализации подобных слоев с гибкой настройкой под модель позволили хранить в 5 раз больше вычислительно-затратных на единицу памяти активаций и тем самым увеличить скорость обучения на 10%!

В дополнение, если речь идет о меньших моделях, то снижение потребляемой активациями памяти позволяет отказаться от полного разделения параметров модели по всем GPU (ZeRO 3), оставив только шардирование состояний оптимизатора и градиентов (ZeRO 2), что дает около 20% в производительности.

Синхронный GarbageCollector

Как PyTorch управляет памятью?

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

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

При работе на границе видеопамяти GPU кэширующий аллокатор в PyTorch работает на пределе. Это происходит из-за недетерминированного перекрытия computation и communication, что приводит к увеличению доли памяти, недоступной из-за фрагментации, и в конечном итоге может привести к ошибке OOM (out of memory).

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

Подробнее про работу аллокатора и FSDP можно почитать тут.

Реаллокация памяти позволяет продолжать работу, но она может на несколько секунд остановить обучение на одном из узлов. Если у вас большое количество узлов, то может возникнуть ситуация, когда почти все время на каком-то узле будет происходить чистка мусора. Обучение с использованием ZeRO происходит со скоростью самого медленного звена, и эту скорость необходимо выравнивать.

Чтобы минимизировать простой и суммарное время простоя, можно синхронизировать чистку мусора. Таким образом, мы смогли эффективно использовать ресурсы GPU и избежать проблем с памятью.

Улучшаем общение между GPU

Когда у Вас есть кластер с тысячей видеокарт, выстроить эффективное общение между ними — это сложная задача. GPU от Nvidia для этого используют библиотеку NCCL (Никель).

Простыми словами про NCCL.

Nvidia NCCL— это библиотека для организации параллельных вычислений на графических процессорах (GPU) от компании Nvidia.

NCCL позволяет организовать взаимодействие между GPU, которые подключены к одному компьютеру или находятся в одной сети. Библиотека обеспечивает быстрый обмен данными между GPU, что в разы увеличивает скорость работы алгоритмов, которые взаимодействуют с большими объёмами данных.

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

Так мы смогли сократить передаваемый объем данных по сети, улучшить топологию общения и увеличить скорость обучения на 5%!

Итоговые ускорения

Изменение

Кумулятивное повышение throughput

+Flash Attention v2

62,73%

+Fused CE, RMSNorm, RoPE

75,71%

+Уменьшение cpu-gpu sync

82,31%

+Selective checkpointing

103,86%

+Настройка NCCL*

109,02%

Тесты проводились на модели 29B, 128GPU A100. *Эффект от настройки NCCL приведен для 1024 GPU, так как на маленьком числе узлов эффект не так заметен.

Благодарности

Задача по осуществлению такого проекта требует больших усилий, внимательности и вовлеченности. Участвуя в этом процессе, я не перестаю удивляться энтузиазму коллег, генерирующих идеи и готовых воплощать их в жизнь в любое время. Девушки и парни из SberDevices, Sber AI и Научно-исследовательского института искусственного интеллекта AIRI, вы лучшие.

Ждём вашу обратную связь

Также приглашаю вас в наш Telegram-канал Salute AI, в котором мы с коллегами начали делиться наработками в области машинного обучения и другими рабочими моментами. А в соответствующем чатике Salute AI Community можно напрямую поспрашивать про всё это и просто пообщаться.

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

Авторы: Сергей Аверкиев (@averkij), Валентин Мамедов (@vltnmmdv), Евгений Косарев (@evgenijkkk), Григорий Лелейтнер (@runfme), Эльдар Дамиров (@edmr_x5720), Дарья Латорцева (@cassowary)

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


  1. kraidiky
    13.12.2023 12:43

    Имеющиеся возможности гигачата:

    И исправление возможностей гигачата, после того как пример пошёл гулять по рукам:

    Мне вот просто очень интересно как и откуда модель подчерпнула этот сияющий бриллиант знаний? Есть ли у Гигачата команда, которая проверяет по датасету откуда и какие знания цепляет модель. Существует ли команда по чистке датасета? Сформулированна ли потребность дополнительно зачистить от данных приводящих к таким вот результатам, или отделение их в отдельный сабсет, и применение этого сабсета с другим алгоритмом обучения, чтобы в дальнейшем не попадать в неудобные ситуации? Хотят ли запустить что-то вроде RLHF когда пользователей будут просить найти неправильные или спорные утверждения бота для последующей доработки, такой проект "народного воспитателя, грубо говоря".

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


    1. oulenspiegel
      13.12.2023 12:43

      Мне вот просто очень интересно как и откуда модель подчерпнула этот сияющий бриллиант знаний?

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

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


      1. johnfound
        13.12.2023 12:43

        Всё просто — человек долго и упорно разводил модель на галлюцинацию разными способами, развёл.

        Я бы сразу поверил, но заглушка не вписывается в такой гипотезе. Или и ее нет, а это тоже глюки?


        1. Doman
          13.12.2023 12:43

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


          1. johnfound
            13.12.2023 12:43

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

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

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

            Так что в итоге выглядит как будто нейронка всегда так отвечает на этот (и может быть на подобные вопросы) и ей просто заткнули рот.


          1. kraidiky
            13.12.2023 12:43

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


        1. oulenspiegel
          13.12.2023 12:43

          Фильтры несовершенны — они либо много лишнего блокируют (что народ очень раздражает), либо пропускают много. В данном случае никакой фильтр на такой вопрос не сработал (а должен был? Нельзя задавать такие вопросы?..)


    1. oulenspiegel
      13.12.2023 12:43

      Памятка
      Памятка


      1. kraidiky
        13.12.2023 12:43

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

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

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


        1. Cerberuser
          13.12.2023 12:43

          Мне вот интересно, что это за "западный Интернет" такой, в котором реально (а не в виде отдельных случаев фричества и/или необразованности) продвигается точка зрения "русские бомбили Хиросиму"?


        1. CeKsCKoToM
          13.12.2023 12:43

          То есть нельзя просто дать прочитать ей архивы? Вот например 1с консультант ищет по базе данных дел, которые добавляют туда архива суда люли и прикинь там Зичи нет, что написал то и получил а модели также самые поиски устраивают по каталогу только дичи добавляют.


    1. janvarev
      13.12.2023 12:43

      Ну, в защиту разработчиков - языковые модели по дефолту НЕ предназначаются для вопросов по фактам. Не знаю уж, нужно ли это писать БОЛЬШИМИ БУКВАМИ при каждой генерации, или только при входе в систему, или еще чем-то.

      Хотят ли запустить что-то вроде RLHF когда пользователей будут просить найти неправильные или спорные утверждения бота для последующей доработки, такой проект "народного воспитателя, грубо говоря".

      Вот имхо - упаси боже. Вы за или против самоизоляции на коронавирусе? Вы за или против низких ставок по ипотечным кредитам? А по обычным?

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


      1. kraidiky
        13.12.2023 12:43

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

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

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


        1. janvarev
          13.12.2023 12:43

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

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

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

          Учитывая, что иностранные коллеги с байесом модели на правильную политическую позицию работают в явном виде - даже красивое слово придумали - алайнмент

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


    1. dmbreaker
      13.12.2023 12:43

      ЧЯДНТ?
      ЧЯДНТ?


  1. IvanPetrof
    13.12.2023 12:43

    В офисе скрестили шпаги
    Наши программисты:
    Разбирали они баги,
    Фича-рецидивисты.

    Рифма случайно получилась? Или оно таки научилось в стихи?


    1. oulenspiegel
      13.12.2023 12:43

      Какие-то знания о фонетике у модели есть, они недостаточны, увы, чтобы всегда выходило складно, но иногда удаются и рифма и ритм


    1. averkij
      13.12.2023 12:43

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


  1. dsamersoff
    13.12.2023 12:43

    Пока GigaChat подарил нам с ребенком прекрасный вечер (попытка использовать его для дела закончилась примерно также):

    Муму — это героиня повести Ивана Тургенева «Муму», дворовая крестьянка, которая спасла своего хозяина от бедности и невзгод, но сама была вынуждена уйти из жизни из-за жестокости своей барыни.


    1. averkij
      13.12.2023 12:43

      А для какого дела хотели использовать?


  1. AtmosferaVA
    13.12.2023 12:43

    Когда с Вашей точки зрения можно ждать рабочие версии корпоративных "ИскИнов" ? Теоретически по моему всё готово:

    Необходимо на сервер с несколькими видеокартами RTX 3060 12 Гб

    1. накатить модель типа Мистраль/ГигаЧатПро с контекстом в 25-100 тыс.токенов

    2. настроить её обновление и настройку с серверов гитхаба/Сбера

    3. локальный полнотекстовый поисковик по документами типа эластик

    4. добавить свой внешний поисковик для поиска данных в интернете

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

    6. добавит возможность простого написания своих инструкции

    7. дообучение модели на новых данных

    8. прикрутить несколько агентов и GPTs из своего магазина

    Почему вполне рабочая модель для стартапа но я что то ничего подобного не видел. И спрос есть многое бы купили в компанию сервер с моделью за 150 т.р. - 5 млн руб - и сервис по подписке на обновления для обработки своих корпоративных документов (а не для креативов по генерации котов-космонавтов и объявлений для Авито).

    ----

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

     «Золотые правила Гарварда и McKinsey: Принцип пирамиды в мышлении, деловом письме и устных выступлен.» Барбара Минто
    Подробнее: https://www.labirint.ru/reviews/goods/143360/

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

    ГигаЧат пока не пригоден для практической работы:

    1. Генераторы кода на питоне - почему пред выдачей кода его не проверить внутри модели на интерпретатор питона на работоспособность ?

    2. Обработка текста - желательно иметь продвинутый сумморитазтор, который смождет из 5-15 страниц текста с графиками сделать удобный для понимания текст без жаргона и англицизмов - русский язык так испоганили что 30% текстов читать невозможно. Приходится продираться через косноязычие в поисках смысла. Желательно чтобы суммаризатор искал в тексте логические ошибки, нестыковки т.е. заменял редактора.


    1. janvarev
      13.12.2023 12:43

      Почему же? Это все вполне себе работает... Уверен, что в топ-50 банков и крупных компаний работают специалисты по внедрению всего, что у вас написано. Лямов так за 5 на команду В МЕСЯЦ. Потому что технология еще не отработана.

      Рано или поздно это дойдет и до масс - только вопрос, в каком виде и объеме. Я уже предоставляю вон сервис по OpenAI API - так что подключиться к разным системам можно. А вот интеграция дело гораздо более тонкое и щекотливое - потому что любой "некорректный ответ модели" трактуется в пользу "а давайте забьем на эту интеграцию" (так же как с CRM, ERP и пр.).


  1. Captain_in_the_Green_Hat
    13.12.2023 12:43

    Чат дорвался до Автортудея и начитался барахла, отсюда и пошел креативчик.

    Чем кормить русскоязычный чат очень сложный вопрос. Это он еще телевизор смотреть не научился.

    Может и научился, у кого есть доступ, спросите, кто ссыт в подъездах, любопытно


  1. StjarnornasFred
    13.12.2023 12:43

    Главное - не "чем кормить", а научить распознавать вопросы, на которые в принципе не нужно отвечать отсебятиной!

    Например, математические уравнения. Их не нужно решать "своим умом" - вместо этого следует воспользоваться калькулятором, который, несомненно, встроен в серверную часть. Просьбы типа "сыграть в шахматы" должны приводить к тому, что бот подключится к Стокфишу, а не начнёт воссоздавать по памяти шахматную нотацию. Ещё было бы неплохо научить бота цитировать.

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

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


  1. Ubudragon
    13.12.2023 12:43

    зачем вообще запрещать модели отвечать на те или иные вопросы?
    что за ущемление свобод ИИ? )


    1. Alexey2005
      13.12.2023 12:43

      Чтобы случайно не присесть.

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

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

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


  1. Firsto
    13.12.2023 12:43

    Всё жду, когда научится стихи писать:


    1. Kerman
      13.12.2023 12:43

      Долго можно ждать. Чат на языковой модели не может в принципе писать стихи просто потому что не знает, как произносятся слова.


      1. Alexey2005
        13.12.2023 12:43

        Зато знает оператор, который и играет роль оценочного фильтра.

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


    1. Alexey2005
      13.12.2023 12:43

      Они уже в какой-то степени умеют, просто пока их выхлоп приходится фильтровать вручную методом "теоремы о бесконечных обезьянах".

      Скачиваем ruGPT3.5 от Сбера, настраиваем так, чтобы выдавало по строчке за раз, и жмём на повтор, покуда созданная строчка нам не покажется подходящей. Обычно долго кликать не приходится: в среднем порядка 10-15 кликов на строчку уходит.

      И так за пять минут можно состряпать

      вполне приличное стихотворение
      Старый вампир на охоту 
      Вышел в вечерние дни. 
      Будет бродить до восходу, 
      Слушать ночные огни.
      
      Он одинокий и старый, 
      Скучно ему одному. 
      Обходит он скверы, бульвары, 
      Ищет он деву одну...  
      
      Смотрит на мир он угрюмо, 
      Не понимая его. 
      Прочь он уходит от шума, 
      Домов, где покой и тепло.
      
      Вот он шагает неспешно, 
      Бродит по тёмным дворам. 
      Зубы сверкают зловеще: 
      "Я отыщу вас, мадам!"  
      
      Вот он подходит к подъезду, 
      Где притаилась она. 
      Вспышка! Дыхание бездны... 
      И дева исчезла одна. 


    1. averkij
      13.12.2023 12:43

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

      https://habr.com/ru/companies/sberdevices/articles/660717/


  1. AlisonBrwn
    13.12.2023 12:43

    Подскажите, какое перекрытие у SBS? (сколько сотрудников смотрело на один и тот же пример?)


    1. averkij
      13.12.2023 12:43

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


  1. couatl
    13.12.2023 12:43

    Привет! Спасибо за статью и поздравляю с запуском новой модели. 

    Как я понял из текста, вы сравнили модель GigaChat Pro на 29 млрд параметров со старой моделью YandexGPT, к которой можно было получить доступ по API в прошлом. Ещё неделю назад мы открыли для всех пользователей API новой модели YandexGPT 2. Было бы корректно сравниваться именно с ней. 

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


    1. averkij
      13.12.2023 12:43

      Петр, привет. Мы обязательно перезамерим модели.

      Подскажи, пожалуйста, а в документации где-то есть список доступных моделей и их характеристики? Так сразу не обнаружил.


      1. couatl
        13.12.2023 12:43

        https://cloud.yandex.ru/docs/yandexgpt/concepts/models


        1. averkij
          13.12.2023 12:43

          Ага, yandexgpt — это 33B, а yandexgpt-lite — 7B, правильно?


          1. couatl
            13.12.2023 12:43

            Вся информация, которой готов делиться, есть в документации, что я скинул


            1. averkij
              13.12.2023 12:43

              Принято, спасибо.


  1. Bully
    13.12.2023 12:43

    Наверное мне подсунули версию GigaChat, которая не умеет сдавать ЕГЭ:

    куда катится мир?!?!


  1. Mike-M
    13.12.2023 12:43

    Так подробно всё расписали... Глаз конкурентов не боитесь? )