Telegram Web
Эксперименты

Метод валидируют на MUSE бенчмарке для забывания и датасетах NEWS (где нужно забыть новость) and BOOKS (забыть персонажей из Гарри Поттера). Какие модели используются, я не понял из текста. Кроме того, оценивают общие способности модели через MMLU, TruhtfulQA, TriviaQA, и энтропию n-грам на AlpacaEval.

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

Вывод

Факт забавный, хоть и в какой-то мере ожидаемый. Существует ли принципиальный способ заставить сеть забыть что-то увиденное? Техники снижения правдоподобия по всей видимости просто заметают это знание под ковер. Кажется, что требуется некая более глубокая хирургия с применением SAE и прочей модной лабуды.
👍5🔥3
The Super Weight in Large Language Models
Mengxia Yu, De Wang, Qi Shan, Colorado Reed, Alvin Wan
Статья: https://arxiv.org/abs/2411.07191
Код: https://github.com/mengxiayu/LLMSuperWeight

Очень прикольная работа про то, что внутри LLM можно найти один единственный вес, зануляя который мы обрушиваем качество работы модели в пропасть. Такие параметры авторы называют супер весами (super weights) и предлагают метод их нахождения за один forward pass.

Внутри обученных LLM находится группа весов-аутлаеров с большой магнитудой, они могут составлять порядка 0.01% от всех весов модели, что в случае миллиардных моделей всё равно сотни тысяч. Это было известно ранее. В текущей работе показывают, что внутри этой группы находится один единственный вес (тот самый super weight, SW), не обязательно самый большой, важность которого превышает суммарную важность тысяч других аутлаеров. Он необходим для качества, без него LLM не может генерить нормальный текст. Перплексия вырастает на несколько порядков, а точность на zero-shot задачах падает до рандома.

Ранее (https://arxiv.org/abs/2402.17762) были найдены супер-активации, критичные для качества. Они существуют в различных слоях, имеют константную магнитуду и всегда обнаруживаются в одинаковой позиции несмотря на вход. Текущая работа находит, что канал активации совпадает с оным для супер веса и сперва активация обнаруживается сразу после супер веса. Прунинг этого супер веса значительно уменьшает активацию, так что вероятно активация вызвана им, а не просто скоррелирована. Такие активации называются супер активациями (super activations, SA).

Предыдущая работа объясняла супер активации через bias terms, но не объясняла как они получаются и почему на одних и тех же местах. Сейчас авторы эмпирически нашли, что до down проекции (down_proj) произведение Адамара (Hadamard product) gate и up проекций (gate_proj, up_proj) создаёт относительно большую активацию. Супер вес далее усиливает её ещё и даёт супер активацию.

Напомню, что MLP блок в Ламе выглядит так:

out = down_proj( act_fn(gate_proj(input)) x up_proj(input) )

SW можно найти, анализируя спайки в распределениях входов и выходов down_proj. Для этого достаточен прямой проход с одним промптом. Авторы нашли супер веса для Llama (7B,13B,30B), Llama 2 (7B,13B), Mistral-7B, OLMo (1B,7B), Phi-3.

Провели эксперименты по обнулению SW, в том числе с восстановлением SA до исходного значения, чтобы проверить влияние SW на другие активации. Это восстанавливает 42% потери, то есть влияние SW на качество выше, чем просто через SA.

По анализу 500 различных промптов из Lambaba validation set видно, что при убирании SW вероятности стоп-слов сильно возрастают (а обычные слова соответственно занижаются). Для “the” это 2×, для “.” -- 5×, и для “,” -- 10×. То есть наличие SW как бы подавляет стоп-слова и позволяет генерировать осмысленный текст.

Другой интересный эксперимент скейлит супер веса с коэффициентами от 0 до 3 (где оригинальный режим работы соответствует значению 1) и оказывается, что при увеличении SW качество модели ещё немного возрастает. Это забавный результат.

Имея это знание, можно предложить специальный метод квантования: Super-outlier aware quantization. Стандартные механизмы квантизации могут быть недостаточно хорошими, так как аутлаеры искажают распределение, влияя на размер шага и увеличивая ошибки квантования. Здесь под super outliers подразумеваются и SW, и SA. Предложенные методы восстанавливают SW и SA после квантований с клиппингом и заменами на медианное значение. Это всё работает лучше дефолтных методов, главный вывод -- надо защищать супер веса. В статье есть подробный разбор экспериментов, кому интересно поглубже. Также новый метод меньше теряет в качестве с увеличением размера блока.

Прикольный результат в общем. Это всё несколько перекликается с темой про лотерейные билеты (https://www.tgoop.com/gonzo_ML/21), там внутри большой сети обнаруживалась сильно разреженная подсеть, обучая которую можно было достигать качества исходной сети (или даже выше). Интересно, входят ли супер-веса в лотерейный билет? Наверняка.
🔥163👀1
Классный обзор на классную статью)
👌3💯1
Pushing the Limits of Large Language Model Quantization via the Linearity Theorem
[Статья][PR в transformers]

SOTA векторные методы квантизации, такие как AQLM (+PV), QuIP#, QTIP, способны достигать умеренной просадки качества при сжатии в 2-3 бита, и почти без просадки (смотря на чем замерять) в 4 битах.

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

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

И коллеги @galqiwi и @black_samorez, совместно с корешами из IST, KAUST и MIT предложили новый, data-free (в большинстве сценариев) метод квантизации с переменной битностью слоев, который дает одновременно и хорошее качество в 3-4 бита и значительное ускорение.

Метод

State-of-the-art методы квантизации и прунинга для LLM по большей части оптимизируют ошибку на выходе линейного слоя, так как прямой учет лосса слишком затратен на масштабе.

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

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

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

Потому авторы применяют знакомые давним подписчикам канала Адамаровы вращения, которые убивают выбросы в весах и приводят распределение весов к нормальному i.i.d. А для нормального распределения существуют рассчитанные (численно) оптимальные решетки. Потому метод зовется Hadamard Incoherence and Gaussian MSE-optimal GridS (HIGGS). Причем рассматривается случай как скалярной, так и векторной квантизации. Векторная квантизация с 2-мерными кодбуками дает лучшее качество, чем скалярная, и при этом эффективно реализуется кернелами из библиотеки FLUTE.

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

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

Таким образом, задача нахождения оптимальных квантизованных весов сводится к нахождению коэффициентов важности каждого слоя и оптимальной квантизации для нормально распределенных i.i.d. весов.
👍93
Эксперименты

Метод валидируют в традиционном сетапе для сжатия LLM на Llama-3.1, Llama-3.2 и Qwen.

По качеству предложенный подход заметно опережает data-free AF, NF, HQQ (особенно при сжатии в 3.25 бит) даже при однородном сжатии. Чем больше размерность векторов в квантизацианной решетке - тем лучше качество, но p=2 (2-мерная) оптимальна точки зрения баланса между скоростью и качеством.

Неоднородная квантизация неплохо накидывает по сравнению с однородной.

HIGGS квантизация с FLUTE кернелами гораздо быстрее (на RTX 4090) навороченных векторных квантизаций (AQLM, QuIP#, QTIP) и даже быстрее, чем Marlin кернел для батчового инференса (для скалярной однородной квантизации).

По метрикам метод превосходит GPTQ/AWQ и немного уступает SOTA векторным квантизациям. Но просадка компенсируется куда большей производительностью с точки зрения практической привлекательности.

Линейная модель работает достаточно точно вплоть до сжатия в 2.5-3 бита.

Выводы

Классный результат от коллег. Ждем одобрения PR в transformers для выкатки на широкую публику. Интересно было бы еще протестировать на диффузионках а-ля FLUX.
🔥93
Switti: Designing Scale-Wise Transformers for Text-to-Image Synthesis
📖Статья 🖥Код 📑Сайт проекта 🤗Демка

Введение

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

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

Однако, этой весной команда исследователей из ByteDance в работе VAR (Visual Autoregressive Modeling: Scalable Image Generation via Next-Scale Prediction) предложила модификацию авторегрессионной парадигмы, где за один проход предсказывается не один патч, а все разрешение целиком. С помощью специальной аамодели - Residual Quantization VAE (вариационно кодировщика с остаточной квантизацией) - изображение разбивается на разные уровни: нижние уровни соответствуют общей семантике изображения, а верхние уровни - тонким деталям и текстурам. На нижних уровнях немного патчей, поэтому прогон модели на них дешев, и стоимость прогона возрастает с переходом на каждое следующее разрешение. На этапе генерации модель смотрит на все прошлые разрешения и генерируют текущее. Полученная картинка получается посредством суммирования всех разрешений.

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

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

Некоторое время спустя после выхода работы VAR вышли STAR и HART, которые адаптировали вышеупомянутый подход для генерации изображений по тексту. В этих работах удалось добиться сносного качества генерации и следования текстовому запросу, но все же далеко позади современных диффузионных генеративных моделей (таких, как SDXL, PixArt, Lumina).

Поэтому мы, исследователи из Yandex Research, решили обучить свою генеративную text-2-image модель.
10🔥3👍2
Метод

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

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

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

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

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

Полученную модель мы назвали Switti - Scale-wise transformer for text-to-image synthesis, так как она генерирует изображение по тексту разрешение за разрешением.
🔥2
Эксперименты и результаты

Мы обучили нашу модель на внутреннем большом датасете из множества картинок (~100M).

В качестве бейзлайнов мы берем Stable Diffusion XL, и ее ускоренные версии - SDXL-Turbo, SDXL-DMD2, SD3-Medium, Lumina-Next, а так же современные авторегрессионные модели LlamaGen и упомянутый HART.

Для оценки качества моделей мы использовали принятые и стандартные в литературе метрики (FID, CLIP, Pickscore, Image Reward, все знают, что они 💩, но этикет же надо соблюдать) а также пользовательские предпочтения на корзинке из 128 запросов (Parti Prompts).

Пользователи оценивали следующие аспекты изображения:
📝 Релевантность - соответствие текстовому запросу
👩‍🎨 Эстетичность - общая ‘красивость” изображения
🤖 Комплексность - количество деталей и сложность композиции
💔 Дефектность - отсутствие дефектов и артефактов в изображении

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

С диффузионными моделями мы добились паритета по качеству, но при этом Switti генерирует в 7 раз быстрее оригинальной SDXL-модели, и 2 раза быстрее ускоренных версий - SDXL-Turbo, SDXL-DMD2.

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

Вывод

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

Тем не менее, есть еще куда расти. На текущий момент Switti генерирует только в 512x512, и до нынешней SOTA (FLUX, Recraft, Ideogram v2, Midjourney 6.1), еще очень далеко. Но диффузионные модели уже давно полируются и улучшаются, а VAR-inspired парадигма зародилась совсем недавно 👼. И есть еще большой потенциал для роста 📈.
🔥191👍1
И картиночки)
8👍1
В процессе серфинга по тытрубе и подготовке к собственной защите наткнулся на защиту кандидатской диссертации Егор Захарова в Сколтехе.

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

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

В общем, рекомендую.
👍12
Хорошо мы успели залететь)

Авторы VAR (без первого, c которым вышла презанятная история) выкатили свою text-2-image модель под названием Infinity.

Обзорчик появится немного позднее)
👍10
Infinity∞: Scaling Bitwise AutoRegressive Modeling for High-Resolution Image Synthesis
[Статья] [Пока только ридми и картинки]

Только-только мы успели выпустить Switti, как создатели VAR, опубликовали собственную text-2-image модель, позиционирующую себя так же как конкурент моделей уровня SDXL/SD3 Medium.

Метод

Наиболее примечателен токенизатор.

В оригинальной статье по VAR использовался Residual VAE c общей кодовой книгой на все масштабы. Выход энкодера на данном масштабе заменяется на ближайший вектор из кодовой книги. На этом этапе возникает некоторая ошибка аппроксимации, и, по всей видимости, в это кроется причина, по которой VQ-VAE традиционно уступают непрерывным аналогам по качеству реконструкции.

Чем больше кодовая книга - тем потенциально меньше ошибка квантизации, но огромные кодовые книги (скажем, с 2^64 векторами) не влезут в память никакой машины.

Потому авторы предлагают параметризовать кодбуки бинарными векторами (специфичными для каждого масштаба k), и квантизация осуществляется просто взятием знака от непрерывного вектора z_k, соответствующему уровню k в иерархии c домножением на некоторый коэффициент. Рассматривают две опции - LFQ, BSQ, отличающиеся на коэффициент 1 / \sqrt{d} и берут в итоге второй вариант, так для него существует эффективное выражение для вычисления энтропийной регуляризации (используемой для более эффективного использования кодбука).

Благодаря такой бинарной квантизации можно расход памяти, требуемый на кодбук размера 2^d, уменьшается с O(2^d), до O(d), благодаря чему, можно хранить колоссальные кодовые книги.

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

Дабы поддерживать разные aspect ratio и размеры используют факторизованные 2d RoPE позиционные эмбеды.

В качестве текстового энкодера используют Flan-T5. Обусловливание на текст осуществляется как через self-attention, за счет добавления токенов промпта в prefix, так и cross attention между картиночными и текстовыми токенами.
👍6🔥1
Эксперименты и результаты

Данные для обучения собраны из отфильтрованных LAION, COYO, OpenImages датасетов. Сначала учат на 256x256 разрешении, потом на 512x512 и в конце переходят на 1024x1024. Токенизатор, как и в оригинальной статье, осуществляет 16x уменьшение по пространству.

Качество оценивают по FID на некотором внутреннем датасете из 40к изображений вместо стандартного MS COCO. Кроме того, замеряют качество на GenEval и DPG, и предпочтения пользователей на ImageReward/HPSv2.1 по аспектам релевантности (Prompt Following) и эстетичности (Visual Aesthetics).

На бенчмарках Infinity уверенно побеждает все прошлые авторегрессионные модели (Switti в сравнениях нет ввиду очень малого промежутка времени между выходом моделей). Опережают по качеству и диффузионки SDXL/SD3-Medium/PixArt-Sigma.

Модель хорошо умеет в рендеринг текста, если верить черрипикам.

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

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

Модель генерирует быстро - одно изображение в разрешении 1024x1024 за 0.8 секунд против 2.1 и 2.7 у SD3 Medium и SDXL, соответственно.

Вывод

Годное подтверждение жизнеспособности scale-wise парадигмы. Ключевой вклад данной работы сильно улучшенный токенизатор (который и является основным ограничителем качества в случае Switti). “Умная” токенизация в картиночных и видео моделях вообще очень горячая тема во второй половине текущего года. Ждем с нетерпением релиза моделей, чтобы поиграться и забрать к себе наработки)
👍8
Собственноручно проверил наличие супервеса (см. оригинальную статью и разбор от gonzo-обзоры ML статей) в Llama-3.2-1B.

Aномальный вес находится в позиции (400 - выходной канал, 1417 - входной канал) в model.layers.1.mlp.down_proj.

Не столь ярко выражен (перплексия на Wikitext-2 (8k context length) выросла с 8.375 до 8.625 при занулении данного веса), но все же очень много для всего одно веса.

[Google Colab для желающих поиграться]
🔥24
На днях наткнулся на канал в Youtube некоего Simon Oz.

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

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

1️⃣ Эффективный алгоритм редукции для нахождения максимума
2️⃣ Оптимизации доступов к памяти (coalescing)
3️⃣ Перенос части операций из shared memory в регистры GPU (которые еще быстрее)
4️⃣ Векторизация операций через float4
5️⃣ Однократная подгрузка данных для подсчета максимума и экспоненты вместо двухкратной

Красивое...
🔥297👍3❤‍🔥1💩1🤡1
Отныне, присно и во веки веков ведущий данного канала не просто балабол, а заслуженный балабол!

Спасибо Сколтеху, всем товарищам, коллегам и соавторам за эти замечательные и продуктивные 3 года, путь полный трудностей, открытий и приключений)

Это была славная охота.

Сам текст диссертации интересующиеся могут найти здесь.
👍50🔥424🎉1🍾1
О, это подарок в честь присуждения степени?)
😁14
Это математика с подвохом!

А вы тоже думали, что прибавление нуля к числу никогда ничего не меняет?
🤔8
PrefixQuant: Static Quantization Beats Dynamic through Prefixed Outliers in LLMs
[Статья] [Код]

Введение

Для получения максимального ускорения, особенно при инференсе большими глотками батчами, нужно квантизовать не только веса, но и активации. Однако, богомерзкие выбросы сильно затрудняют квантизацию, и в прошлых работах (QuaRot, SpinQuant, DuQuant) было предложено применять Адамаровы матрицы (или некоторые обучаемые), которые размазывают 🧈 выбросы по каналам.

Однако, выбросы встречают не только в отдельных каналах, но есть и токены, например <BOS> и иные разделители, отличающиеся большими значениями активаций, и их квантизация большими группами (per-tensor) с максимальным ускорением приводит к большим ошибкам. Поэтому в упонятых выше методах использовали per-token квантизацию с некоторым замедлением инференса.

В этой статье авторы предлагают вынести аутлаерные токены в префикс последовательности дабы упростить квантизацию.

Метод

Сам подход мотивирован идеями про attention sinks и Quantizable Transformers: Removing Outliers by Helping Attention Heads Do Nothing. Иногда трансформерному блоку не нужно ничего делать, и дабы реализовать почти тождественную операцию, приходится выбрасывать весь attention в токены с низкой семантикой.

Потому авторы предлагают просто найти все эти токены и положить в префикс последовательности.

Токены находят на основе некоторой калибровочной выборки смотря на выход down_proj в MLP. Отбирают токены, чья L_{\infty} норма сильно больше медианной по последовательности.

Сам процесс достаточно быстрый - занимает всего несколько минут. Таких токенов оказывается от 1 до 4 в рассмотренных моделях (Llama-2,3, Qwen, Mistral). Обычно это <BOS>, и еще символы переноса строки \n, артикли и знаки препинания.

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

Эксперименты

Метод валидидируют на 🦙-2,3 в режимах W8A8KV8, W4A8KV4, and W4A4KV4 квантизации (W - точность весов, A - активаций, KV - KV-кэшей).

Веса квантизуются поканально, кэши поголовно, активации потензорно.

Предложенный подход оказывается примерно на одном уровне с per-token квантизациями, чуть уступая лишь SpinQuant с дообучением матриц вращения каналов. При этом скорость инференса на 20-30% быстрее.

Поблочный файнтьюн немного накидывает.

Вывод

Простой и полезный трюк для квантизации. Тем не менее, кажется, что возможность делать ничего в блоке модели стоит закладывать изначально, и скорее всего, ввиду потребности в низко-битных моделях, сообщество до этого дойдет (через softmax+1 или иным образом).
🔥8👍4
ClosedAI назвали новую модельку o3, дабы обойти коллизию имен с o2 - британским оператором, но не учли, что o3 - это озон)
😁30🍌2
2025/07/12 09:56:55
Back to Top
HTML Embed Code: