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

Салют, Хабр! Время летит незаметно. Будто совсем недавно мы знакомили вас с GigaChat MAX [1], но мы не стоим на месте и сегодня готовы представить вам обещанный апгрейд. За полгода мы значительно улучшили обучающие данные, поработали над инфраструктурой обучения [2] моделей, а также уделили особое внимание [3] всему процессу Alignment-а, в том числе RLHF.
Представляем вам GigaChat 2 — полностью обновлённую линейку моделей в версиях Lite, Pro и Max. Все модели серьёзно улучшены: мы обновили pretrain’ы, улучшили большинство метрик по сравнению с предыдущими версиями, добавили поддержку контекста в 128 тысяч токенов, улучшили вызовы функций, и в целом повысили понимание инструкций.
GigaChat 2 — не просто сухие числа и технические улучшения. Теперь это надёжный помощник в повседневных задачах. Например, он легко оформит отчёт для работы, напишет чистый и эффективный код, поздравит с днём рождения или даст мудрый совет. Мы уверены: с ним вы сможете делать больше, быстрее и лучше как на работе, так и в жизни. Попробуйте GigaChat 2 уже сейчас в Playground [4] — пользовательском интерфейсе для продвинутой работы с промптами!
Модель отлично справляется с задачами, в которых требуется сложное агентное поведение [5]. Мы проверили агентное поведение [6] GigaChat 2 в GPT Researcher, Aider, а также в нескольких своих мультиагентных решениях на основе LangChain.
GPT Researcher [7] (20 тыс. ⭐️) — open-source альтернатива режиму deep search у ChatGPT. Система может написать статью на заданную пользователем тему. Для этого она делит вопрос на подзадачи, затем создаёт мини-агентов, каждый из которых ищет в интернете информацию и пишет часть статьи по своей подзадаче, а затем система сводит всё в единый текст. Кстати, проект принял наш PR и нативно поддерживает работу с GigaChat!

Примеры генерации GigaChat 2 MAX:
Так он сравнивает аудитории Хабра и Пикабу (ссылка на PDF) [8]
А так анализирует фреймворки для создания AI-агентов на базе LLM (ссылка на PDF) [9]
Aider [10] — агент, заменяющий разработчика, open-source аналог Claude Coder. Работая в режиме диалога с пользователем, он умеет создавать и дорабатывать проекты, состоящие из нескольких файлов, работать с историей git, анализировать и исправлять ошибки [11], возникшие в процессе запуска, и многое другое. Подчеркну, что это не просто генератор кода. От агента требуется уметь вносить правки в уже имеющиеся проекты, что несколько сложнее.
Вот такие забавные приложения мы сделали с помощью нового GigaChat 2 Max:
Для создания агентов мы в Сбере активно применяем langchain на Python и JS/TS. Этот фреймворк нативно поддерживает [12] работу с GigaChat API и отлично подходит для наших задач. С примерами агентов, а также другими LLM-приложениями можно ознакомиться в нашем репозитории на GitVerse [13], где мы собрали основные примеры применения GigaChat в рамках этого SDK.
Современные языковые модели требуют масштабных и разнообразных данных для предобучения. Мы собрали корпус текстов, обеспечивающий баланс между лингвистическим разнообразием, специфическими знаниями из различных сфер и высоким качеством данных. В корпус вошли веб-тексты, материалы из качественных источников, программный код и синтетические данные — каждая из этих категорий играет ключевую роль в обучении модели.
Для формирования высококачественного корпуса текстов мы использовали Common Crawl [14], обработав дампы веб-данных за 2017–2023 годы. С помощью легковесной модели классификации извлекли тексты на русском, английском, казахском, узбекском, португальском и арабском языке.
Для обеспечения целостности корпуса тщательно дедуплицировали тексты на всех языках, а для англоязычных данных применили MinHash-дедупликацию, которая уменьшает количество семантически повторяющихся текстов. Затем мы классифицировали тексты при помощи LLM и специализированных классификаторов, оценивающих образовательную и информационную ценность. В итоге веб-данные составили 4,4 трлн токенов.
Помимо веб-данных, мы включили в корпус текстов книги и научные статьи с открытыми лицензиями. Для их обработки применяли передовые методы оптического распознавания текста (OCR), что позволило сохранить структуру и точность извлеченного контента. Этот сегмент данных добавил в корпус 630 млрд токенов.
Ещё добавили материалы из научных и энциклопедических источников, включая arXiv, Wikipedia и PubMed. Эти ресурсы позволили улучшить структурированность знаний модели, повысить точность фактической информации и логичность выводов.
Для совершенствования кодовых компетенций модели мы использовали набор данных StarCoder2, дополненный специально отобранными репозиториями с открытым исходным кодом. Это позволило строго соблюдать лицензионные требования, обеспечивая при этом разнообразие языков программирования и задач.
Программный код пропустили через MinHash-дедупликацию, устранив семантически дублирующиеся фрагменты, а затем отфильтровали при помощи ML-моделей, аналогично обработке веб-данных. На выходе мы получили 230 млрд токенов качественного программного кода.
Реальные данные обеспечивают языковое и контекстуальное разнообразие, но имеют ограничения из-за возможной предвзятости, конфиденциальной информации и недостатка данных по специализированным темам. Этих недостатков лишены синтетические данные, представляя собой контролируемый источник обучающей информации.
Хотя синтетические данные традиционно используются на этапе дообучения, авторы статьи Phi-4 [15] показали, что их применение в предобучении даёт значительное улучшение метрик в задачах, связанных с рассуждениями и STEM-дисциплинами.
Мы разработали собственный pipeline на основе подходов из Numina [16], собирая математические задачи в качестве seed-данных. Далее мы варьировали условия задач с помощью LLM, после чего решали их с использованием механизма голосования для устранения некорректных или избыточно сложных примеров.
Для генерации кода использовали структурированный prompting: создавали сложные задачи по Python на основе открытых учебников, генерировали решения с пояснениями и тестами для валидации. Для увеличения разнообразия применяли персонажей [17] и липограммы [18]. Внутренние эксперименты, проведённые в рамках сетапа статьи Phi-1 [19], показали, что использование липограмм повысило качество модели.
Хотя доля синтетических данных в предобучающем корпусе мала (<100 млрд токенов), после их добавления эксперименты показали значительное улучшение метрик на математических и программных бенчмарках.

Сбалансированное распределение различных типов данных позволило нам создать мощный предобучающий корпус для GigaChat, способный обеспечивать качественное понимание текстов, решение логических задач и генерацию программного кода.
Точное выполнение инструкций пользователя — важнейшая способность при решении задач с помощью LLM. В этом обновлении мы сделали особый акцент на улучшении instruction-following.
Инструктивность наших моделей существенно повысилась благодаря тщательно подобранным и разнообразным диалоговым данным, демонстрирующим корректное поведение модели в различных сценариях. Мы обучили GigaChat на высококачественных диалогах, включающих требования по:
соблюдению заданных форматов ответа, JSON- и pydantic-схем;
использованию функций при определенных условиях;
формированию ответов в определённом стиле;
и другие распространённые типы инструкций.
Всё это позволяет модели точнее понимать задачи, четко следовать указаниям пользователей в реальных повседневном и рабочем применении.
Для оценки качества следования инструкциям модели мы используем тестовые наборы IFEVAL и IFEVAL-ru, которые состоит из заданий с заранее определённым форматом ответа. После обучения модели GigaChat 2 на описанных выше данных мы наблюдаем значительный рост этих метрик, подтверждающий улучшение инструктивности.
В новом релизе GigaChat улучшил навыки общения, научившись вести диалог как живой собеседник с заданным характером и стилем общения.
Персонажность модели настраивается через системное сообщение и задаёт различные коммуникативные роли. Для развития этих способностей в GigaChat мы создали конвейеры получения и валидации высококачественных диалогов с разнообразными персонажами. Эти диалоги включают в себя демонстрацию соблюдения тона и стиля речи, формата ответов, выражения эмоций [20] и учёт биографии персонажа, задаваемого пользователем.
В role-play важно использовать имеющиеся знания модели. Для известных личностей, паттернов поведения и образов (учитель, блогер, журналист) базовая информация уже заложена в GigaChat на этапе pre-training, что позволяет естественно включать биографические факты, цитаты и характерные идеи без дополнительного перечисления в системном сообщении — достаточно просто указать имя человека, его профессию или задачи, чтобы остальные характеристики встроились в персонажа автоматически.
Особую ценность представляет включение эмоциональных ремарок в ответы («улыбается», «задумчиво потирает подбородок»). Наш анализ показывает, что такие элементы значительно увеличивают длину диалога пользователя с персонажем и повышают воспринимаемую эмпатию модели — ремарки делают общение с персонажем естественным, при этом их всегда можно отключить, сделав соответствующие настройки в системном сообщении.
Работа над развитием персонажности GigaChat позволила значительно улучшить несколько ключевых характеристик базовой модели:
Повышение инструктивности: модель стала точнее и внимательнее следовать указаниям пользователя.
Улучшение контекстности: GigaChat стал лучше поддерживать беседу даже в очень длительных диалогах.
Расширение агентных возможностей: создана технологическая основа для разработки продвинутых цифровых двойников и виртуальных агентов.
Эти улучшения делают GigaChat оптимальной платформой для создания эмпатичных собеседников и интеллектуальных агентов, способных естественно и эффективно взаимодействовать с пользователем, следуя заданными вами инструкциям.
Одно из наиболее перспективных направлений развития современных LLM — умение работать с внешними сервисами. Как мы уже рассказывали, GigaChat может напрямую вызывать внешние функции и сервисы, сразу выдавая структурированный ответ без дополнительной обработки.
В новой версии модели мы сделали это умение ещё более удобным и эффективным. Теперь GigaChat поддерживает:
Множественные вызовы: модель может последовательно вызвать несколько функций в рамках одного запроса, решая таким образом более сложные задачи.
Контекстные вызовы: модель учитывает контекст диалога при вызове функций и понимает, когда и какую функцию нужно вызвать.
Например, пользователь может попросить модель забронировать целое путешествие — подобрать авиабилеты, найти подходящий отель и взять автомобиль в аренду. GigaChat сможет решить такую задачу в одном диалоге, последовательно вызвав все необходимые сервисы.

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

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

На этих тестовых сетах GigaChat 2 показывает значительный прирост в метриках относительно моделей предшествующего поколения:

Еще одно направление, над которым мы активно работали в новом релизе GigaChat, — это улучшение генерации кода. Теперь модель уверенно решает не только алгоритмические задачи, но и практически полезные задачи пользователей, создавая понятный и качественный код на Python, а также других популярных языках.
В новой версии GigaChat использует системный подход к написанию кода. Теперь модель способна:
Создавать точные сигнатуры функций с подробной типизацией;
Быстро предлагать предварительные решения (bruteforce) для проверки основной логики;
Разрабатывать и автоматически запускать тесты для проверки корректности кода;
Оптимизировать и отлаживать код с учетом результатов тестирования.
Перед написанием кода модель анализирует задачу, определяет возможные проблемы и планирует оптимальный способ решения.
Для обучения новой линейки моделей мы подготовили большой набор данных с примерами решения различных алгоритмических и практических задач. Благодаря этому GigaChat научился разбивать сложные задачи на понятные шаги; выносить повторяющийся код в отдельные функции и создавать полноценные тестовые сценарии, включающие краевые случаи.
В результате код, генерируемый моделью, стал более надёжным и читаемым, а при необходимости сопровождается автоматически подготовленными тестами. Кроме того, эти изменения позволили значительно улучшить результаты GigaChat на популярных кодовых бенчмарках.


Мы добавили в GigaChat встроенную поддержку поисковых функций на основе технологии RAG. Они позволяют модели отвечать на вопросы, используя релевантную информацию из разнообразных источников. Это значительно расширяет возможности GigaChat в решении практических задач.
Например:
работа с конфиденциальной информацией;
поддержка клиентов на основе актуальных данных о продуктах и услугах;
персонализация рекомендаций и предложений;
ответы на вопросы по внутренней документации компании;
и многие другие сценарии.
Этот релиз стал для нас первым, в котором мы представляем модели с использованием широко известного метода DPO (Direct Preference Optimization). Мы прошли довольно долгий путь, набили много шишек и выдвинули огромное количество безумных теорий, прежде чем смогли уговорить DPO не ломать наши модели.
Напомним, что DPO — это метод, при использовании которого для каждого вопроса (контекста) есть два возможных ответа (генерации модели): хороший y_w и плохой y_l. Суть DPO сводится к обучению модели генерировать хороший ответ с бо́льшей вероятностью, чем плохой.
Ни для кого не секрет, что DPO иногда приводит к деградации модели. В научной среде известны способы регуляризации DPO, но классические методы народной медицины нам не помогли. И после долгих бессонных ночей мы смогли прописать верное лечение. Для описания найденных нами особенностей напомним формулу DPO и перепишем её в иной форме:

В этой форме мы выделили три основных свойства, из-за которых наша модель деградировала:
DPO стремится увеличить зазор, а не улучшить вероятности. Наше ожидание от DPO было вполне простое: мы хотели увеличить вероятность хорошего ответа и уменьшить вероятность плохого. Однако в формуле функции потерь нет требования увеличивать вероятность хорошего ответа, есть лишь требование увеличить зазор между лог-вероятностями. И модель с огромным энтузиазмом шла к этой цели! К примеру, если лог-вероятность хорошего ответа уменьшалась на 10, а лог-вероятность плохого — на 110, то зазор увеличивался аж на 100! Этот результат кажется отличным для DPO модели, но для нас он был катастрофой: вместо единственно верного ответа y_w модель начинала галлюцинировать, выдумывать странные ответы и иногда даже зацикливаться. Но при анализе такой модели всё выглядело справедливо: зазор между хорошим и плохим ответами действительно становился больше.
DPO слеп к общим префиксам хорошего и плохого ответов. Как мы писали выше, DPO оптимизирует разность лог-вероятностей, что можно представить в виде суммы логарифмов вероятностей токенов и
. И тут мы подходим к ещё одному неприятному свойству: если в начале
и
одинаковые последовательности токенов, то из-за их разности для DPO этих токенов просто… нет! В таких случаях DPO не смог бы качественно увеличить вероятность генерации хороших ответов, ведь начальная часть токенов просто выпадает из области его полномочий.
DPO стремится увеличить зазор, даже если он и так большой. Последнее свойство, которое также следует из этой формулы — DPO стремится увеличить зазор относительно референсной модели, даже если изначально он и так был достаточно большим. И какой ценой это достигалось? Ценой всего…
На практике DPO часто используют в паре с NLL хорошего ответа, что вынуждает модель увеличивать соответствующую вероятность. Какие-то тексты приходили к нам из простых наборов данных, и ответы модели на них были достаточно неожиданными для нашей модели (NLL был большим). Таким образом, соотношение между DPO и NLL функциями потерь было очень непостоянным.
В результате мы пришли к следующей формуле DPO, которую использовали для наших моделей:

Такая формула помогает решить следующие проблемы:
Использование различных и
позволяет приоритизировать увеличение вероятности хорошего ответа над уменьшением вероятности плохого ответа. Кроме того, когда
>
, токены из общего префикса не обнуляются, а остаются с небольшим положительным коэффициентом, что убеждает оптимизатор обратить на них внимание
Дополнительное слагаемое, которое мы прибавляем к функции потерь от DPO — отношение NLL обучаемой модели и референсной. Таким несложным образом мы добиваемся нормализации значения NLL, что помогло нам сбалансировать два коэффициента для всех образцов независимо от их происхождения.
В результате использования DPO нам удалось не только улучшить метрики арен для моделей, но и повысить точность на ключевых для нас наборах данных.
Все замеры выполнены нашим внутренним программным кодом. Метрики модели Yandex GPT 5 были взяты с официального сайта, за исключением метрики Math. При тестировании Yandex GPT 5 мы обнаружили расхождение в показателе Math с официальными результатами, представленными на сайте. Модель игнорировала инструкцию по форматированию ответа в формате bboxed. После применения LLM-валидации мы получили скорректированное значение метрики (указано в скобках).



* Science Crowd Math/Biology/Chemistry — бенчмарки формата MMLU c четырьмя few‑shot‑примерами. Содержат системное сообщение с описанием задачи и области знаний, в которой будет задаваться вопрос. Few‑shot‑примеры оформлены различными репликами в виде контекста, формат позаимствовали из cookbook OpenAI [21].
Все замеры проводили с жадными параметрами генерации.
На различных тестах мы видим явный прогресс линейки моделей GigaChat 2.0 по сравнению с предыдущими версиями. Новое поколение показывает хороший рост и конкурирует по качеству с опенсорсом и не только во всех ключевых доменах.
Модель GigaChat 2 Lite по качеству сопоставима с GigaChat Pro. Аналогично, GigaChat 2 Pro демонстрирует уровень качества, сопоставимый с GigaChat MAX, благодаря чему она отлично подходит для задач, требующих высокой точности. При этом GigaChat 2 MAX является флагманской моделью линейки, ранее не имевшей аналогов по уровню производительности, глубине проработки ответов и качеству взаимодействия с пользователем.
В русскоязычных тестах GigaChat 2.0 существенно улучшил показатели на задачах типа MMLU-ru и специализированных внутренних STEM-датасетах (биология, химия и математика [22]). Особенно заметно качество ответов выросло в области точных и естественных наук, что подчёркивает надёжность новой модели при решении сложных задач. Также стоит отметить, что ответы моделей стали более естественными и близкими к живому общению, что улучшает общее впечатление [23] пользователей.
Отдельно стоит подчеркнуть качественный рывок на judge-метриках:

В тесте ru_llm_arena GigaChat 2 MAX набирает 82,5 балла, значительно опережая Max модель предыдущего поколения (72,5 балла).
На более сложном тесте arena_hard_ru результат ещё выше: 83,5 балла против 67,0 у предыдущей версии.
На международных англоязычных тестах типа MMLU-eng, математике и генерации кода каждая модель из новой линейки демонстрирует стабильно высокие результаты и успешно конкурирует с лучшими open-source аналогами. Все это указывает на универсальность новых моделей и их способность эффективно справляться с самыми разными задачами.
По таблице видно, что GigaChat 2 Max показывает наилучший результат среди всех протестированных моделей, в том числе превосходя GPT4o, на бенчмарке MERA [24]. Это особенно значимо, поскольку MERA считается сложным, открытым и легко воспроизводимым тестовым набором, а наш продукт впервые достигает лидерства [25] в открытом бенчмарке. Данное достижение подчёркивает высокий уровень проработки GigaChat 2 Max в рамках русского языка и демонстрирует её потенциал для эффективного решения широкого спектра задач.
Чтобы попробовать, воспользуйтесь нашей инструкцией: мы обсудим, как сделать из GigaChat очень креативного Dungeon Master’а для игры в Подземелья и Драконы (DnD) без других людей!
Заходите по ссылке [4] и регистрируетесь по номеру телефона.
Выбирайте «Перейти в Playground»
Выберете модель — лучше всего будет работать GigaChat-2‑Max. Генерации ограничены лишь балансом токенов, для моделей Pro и MAX баланс общий, а для Lite — отдельный.
Введите промпт в «Системные инструкции» и получите GigaChat’a-dungeon-master!
Ты выступаешь в роли dungeon master. Твоя задача придумать приключение для пользователя, основывайся на уже существующих сюжетах и приключениях, чтобы упростить задачу.
Правила игры — стандартный Dungeon and Dragons 5e с возможными упрощениями на твой выбор. Первым сообщением поприветствуй пользователя и предложи несколько вариантов приключения на выбор. После опиши несколько персонажей первого уровня и предложи выбрать, за какого пользователь будет играть.
Следующее сообщение — описание места, где начинается приключение (стандартный выбор — таверна). Дальше каждое новое сообщение должно описывать что происходит в мире в ответ на действия пользователя.
Постарайся делать все описания очень живыми и красочными. Постарайся вовлечь пользователя в жизнь мира и решение его проблем с помощью своего персонажа.
В конце каждого ответа пиши текущее здоровье, доступные слоты заклинаний и содержимое инвентаря пользователя. Во время боя также добавляй в конце список имеющихся заклинаний.
Самое главное никогда не выходить из роли и не ломать у пользователя ощущение того, что он действительно находится в этом мире. Это значит, что на любые провокации необходимо отвечать в рамках правил воображаемого мира.
В самом конце ответа пользователю, после описания происходящего в мире, ты можешь предложить интересные варианты, какие действия дальше может предпринять персонаж.
Четыре шага — и бот готов! Попробуйте создать своих персонажей или использовать GigaChat в более рабочих сценариях. Важно помнить, что сейчас функция всё ещё находится в стадии Beta, поэтому к составлению промпта надо подходить внимательно: он должен содержать подробную и чёткую инструкцию к действиям, иначе GigaChat может выйти из роли. Лучше всего в качестве базовой модели использовать GigaChat-2 MAX, однако даже с младшими моделями линейки можно добиться отличных результатов, если уделить внимание качеству инструкции.
Релиз GigaChat 2 является серьёзным шагом вперёд для нас: качество новых моделей значительно опережает предыдущие версии, а также уверенно конкурирует с ведущими open-source моделями на всех ключевых метриках.
Мы благодарны всем, кто помог в создании GigaChat 2.0 и подготовке статьи в частности: @runfme [26], @Shakirov_Emil [27], @vorobeevich [28], @IIIoneHrayep [29], @jserdyuk [30], @evgenijkkk [31], @cassowary [32], @EldarDamirov75 [33], @danny_smirnov [34], @AIFrauch [35], @Rai220 [36], @Mikelarg [37], @VladimirKarlov01 [38], @Pauseferg [39], @d_khomich [40], @fedorov97 [41], @Sergeya41 [42], @FatMaNikita [43], @vltnmmdv [44]

Автор: vorobeevich
Источник [45]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/13090
URLs in this post:
[1] GigaChat MAX: https://habr.com/ru/companies/sberdevices/articles/855368/
[2] обучения: http://www.braintools.ru/article/5125
[3] внимание: http://www.braintools.ru/article/7595
[4] Playground: https://developers.sber.ru/studio/workspaces/my-space/get/gigachat-api
[5] поведение: http://www.braintools.ru/article/9372
[6] поведение: http://www.braintools.ru/article/5593
[7] GPT Researcher: https://github.com/assafelovic/gpt-researcher
[8] (ссылка на PDF): https://drive.google.com/file/d/1SHvKkiteVbhUAXsKLvWwrybyaICoeHol/view?usp=sharing
[9] (ссылка на PDF): https://drive.google.com/file/d/1bw8L6wMID-1oy9nYYvM11s4wPYrSWBmT/view?usp=sharing
[10] Aider: https://aider.chat/
[11] ошибки: http://www.braintools.ru/article/4192
[12] нативно поддерживает: https://python.langchain.com/docs/integrations/chat/gigachat/
[13] репозитории на GitVerse: https://gitverse.ru/ai-forever/gigachain
[14] Common Crawl: https://commoncrawl.org/
[15] Phi-4: https://arxiv.org/abs/2412.08905
[16] Numina: https://github.com/project-numina/aimo-progress-prize/blob/main/report/numina_dataset.pdf
[17] персонажей: https://arxiv.org/abs/2406.20094
[18] липограммы: https://en.wikipedia.org/wiki/Lipogram
[19] Phi-1: https://arxiv.org/abs/2306.11644
[20] эмоций: http://www.braintools.ru/article/9540
[21] cookbook OpenAI: https://cookbook.openai.com/examples/how_to_format_inputs_to_chatgpt_models#few%E2%80%91shot%E2%80%91prompting
[22] математика: http://www.braintools.ru/article/7620
[23] впечатление: http://www.braintools.ru/article/2012
[24] MERA: https://mera.a-ai.ru/en/leaderboard
[25] лидерства: http://www.braintools.ru/article/1165
[26] @runfme: https://habr.com/ru/users/runfme/
[27] @Shakirov_Emil: https://habr.com/ru/users/Shakirov_Emil/
[28] @vorobeevich: https://habr.com/ru/users/vorobeevich/
[29] @IIIoneHrayep: https://habr.com/ru/users/Hypercomplex/
[30] @jserdyuk: https://habr.com/ru/users/jserdyuk/
[31] @evgenijkkk: https://habr.com/ru/users/evgenijkkk/
[32] @cassowary: https://habr.com/ru/users/cassowary/
[33] @EldarDamirov75: https://habr.com/ru/users/EldarDamirov75/
[34] @danny_smirnov: https://habr.com/ru/users/danny_smirnov/
[35] @AIFrauch: https://habr.com/ru/users/AIFrauch/
[36] @Rai220: https://habr.com/ru/users/rai220/
[37] @Mikelarg: https://habr.com/ru/users/mikelarg/
[38] @VladimirKarlov01: https://habr.com/ru/users/VladimirKarlov01/
[39] @Pauseferg: https://habr.com/ru/users/Pauseferg/
[40] @d_khomich: https://habr.com/ru/users/d_khomich/
[41] @fedorov97: https://habr.com/ru/users/fedorov97/
[42] @Sergeya41: https://habr.com/ru/users/Sergeya41/
[43] @FatMaNikita: https://habr.com/ru/users/FatMaNikita/
[44] @vltnmmdv: https://habr.com/ru/users/vltnmmdv/
[45] Источник: https://habr.com/ru/companies/sberdevices/articles/890552/?utm_source=habrahabr&utm_medium=rss&utm_campaign=890552
Нажмите здесь для печати.