Inquirer‘Parents responsible for protecting kids online, not just government’ESPN Deportes¿Podría Ryan Flournoy darles a los Cowboys un tercer receptor de 1,000 yardas?RTP DesportoEuropeus de atletismo. Joana Pontes no top 10 da maratona em marcha com recorde nacionalוואלהחיזבאללה קורא לממשלת לבנון להפסיק את המו"מ עם ישראל ומאיימת בתגובהThe Jerusalem PostWATCH: Funnel cloud seen in Golan Heights amid widespread thunderstorm, flash flood warningsSky TG24Ceuta, la polizia disperde i migranti diretti in SpagnaIl Sole 24 OreTroppo caldo, stop allo sci estivo sul ghiacciaio dello StelvioBBC News BrasilTerremoto de magnitude 7,7 mata ao menos 47 pessoas na IndonésiaSportstarF1 remains the dream, eyeing strong finish to F2 season: Kush MainiRai NewsCinque anni dal ritorno dei Talebani: l’Afghanistan ha cancellato le donne, solo il 7% lavoraLa TerceraConductor en estado de ebriedad atropella a tres bomberos que atendían accidente en ChiguayanteRTL BoulevardSchrijver Peter Andriesse (85) overleden
The Daily Newsstand · Free, Always
Saturday, August 15, 2026

3 бита вместо 16: разбираем TurboQuant и когда его реально стоит включать

Translate

В марте 2026 года Google публикует пост про алгоритм сжатия памяти для языковых моделей. Звучит скучно, правда? Но акции Micron, SanDisk, Samsung, SK Hynix и других производителей памяти за неделю теряют суммарно почти $90 млрд капитализации. Инвесторы паникуют: если модели начнут тратить в разы меньше памяти, то зачем столько железа?

Алгоритм, который навел весь этот шум, называется TurboQuant — герой этой статьи.

Я не буду говорить, что это «революция» или «переворот в индустрии» — это было бы явное преувеличение. Но штука действительно интересная, и уже есть рабочие реализации. Если вы деплоите LLM в продакшн или просто прогоняете модели локально, то вам 100% будет полезно об этом узнать. Разберем, что из заявленного правда, а что преувеличение, и главное — как это попробовать прямо сейчас.

Главная уязвимость LLM: в чем проблема с KV-кэшем

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

Когда LLM генерирует текст, на каждом шаге она учитывает все предыдущие токены. Чтобы не пересчитывать их заново, модель сохраняет промежуточные вычисления в памяти. Это и есть KV-кэш (Key-Value cache). Штука достаточно полезная: без нее инференс был бы в разы медленнее и дороже — это обусловлено самим устройством слоев внимания.

Но есть проблема: KV-кэш растет линейно с длиной контекста (чем длиннее текст мы генерируем, тем больше данных нужно хранить).

Вот конкретные числа, чтобы прочувствовать масштаб: у модели Llama 3.1 70B при контексте 128K токенов KV-кэш в формате BF16 занимает около 40 ГБ (при использовании Grouped Query Attention с 8 KV-головами). Сама модель в BF16 весит порядка 140 ГБ. В итоге один запрос требует 180 ГБ памяти, из-за чего он не помещается на ускоритель H100 (80 ГБ) даже в одиночку. Если же нужно параллельно обслуживать четырех пользователей на контексте в 128K, только под KV-кэш уйдет 160 ГБ — а это уже больше, чем весят сами параметры модели.

Где это критично

Проблема KV-кэша становится критической в трех сценариях. При RAG-подходе с большими документами попытка загрузить в контекст кодовую базу или длинный PDF забивает всю VRAM еще до отправки первого запроса. 

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

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

Решение

Проблему пытались решать по-разному. Метод GQA, например, уменьшает количество KV-голов, отлично работает и активно используется еще со времен Llama 2, Qwen2 и других моделей.

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

MLA у DeepSeek — это уже архитектурное решение: оно сжимает KV до латентных векторов и убирает около 93% кэша.

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

TurboQuant хорош как раз тем, что предлагает другой подход — просто сжать то, что уже есть, без изменения архитектуры, калибровки и файн-тюнинга. Вы просто берете модель, включаете метод, и KV-кэш сжимается в 5–6 раз.

Как работает TurboQuant 

Скажу сразу — TurboQuant содержит большую и взрослую математику. Но чтобы понять суть метода и начать его использовать, зарываться в формулы не обязательно. Мы сейчас пропустим сухую теорию и просто поверим, что умные люди все проверили (ICLR 2026 принял, значит доверять можно) и разберемся на пальцах, почему это вообще работает.

Если вы любите хардкор, три теоремы, доказательства near-optimal distortion rate, бета-распределения, информационно-теоретические нижние границы — вам прямая дорога  к полному исследованию.  Это фундаментальный труд, и тем, кому интересно погрузиться, лучше начинать с него, но сразу готовьте несколько дней или недель жизни на это (в общем — приятного чтения).

Квантизация KV-кэша — идея, прямо скажем, не новая: взять float16-значения и упаковать их в меньшее количество бит. Проблема в том, что наивная квантизация (равномерная сетка) работает плохо: значения в KV-кэше распределены неравномерно, и большинство традиционных методов либо теряют качество, либо требуют калибровочных данных под конкретную модель.

TurboQuant решает это с помощью двух идей.

Идея первая — случайное вращение. Перед квантизацией вектор умножается на случайную ортогональную матрицу. Звучит странно: зачем крутить данные перед тем как их сжимать? 

А вот зачем: после такого вращения компоненты вектора становятся почти независимыми и распределены предсказуемо. Из произвольного и сложного распределения получаем что-то близкое к нормальному, а с этим уже гораздо приятнее работать.

Идея вторая — оптимальный квантизатор для известного распределения. Если мы знаем, как распределены данные, то можно заранее просчитать оптимальную сетку квантизации (это называется Lloyd-Max квантизатор). Не равномерную, а такую, где ошибка минимальна именно для этого распределения: кодбук считается один раз, хранится статично и не требует никакой калибровки под конкретную модель.

Комбинация этих двух идей и дает результат: алгоритм доказуемо находится в пределах ~2,7× от теоретического минимума ошибки квантизации. Это называется near-optimal, и, как вы понимаете, довольно интересно.

На самом деле есть еще и третий компонент —  QJL-коррекция остатка. Теоретически он красиво описан и обоснован, но на практике сообщество выяснило: в наивной реализации через стандартный attention softmax экспоненциально усиливает дисперсию от 1-bit коррекции, и результат становится хуже, а не лучше. 

В vLLM PR #38479 проблему решили через norm correction (варианты с суффиксом _nc), в llama.cpp форках QJL чаще всего просто отключают или упрощают. 

Главное, что нужно запомнить: алгоритм data-oblivious. Ему не нужны калибровочные данные, не нужен файн-тюнинг — он сразу работает на любой трансформерной модели. Берете модель, которая у вас уже есть, и просто включаете (ну почти): на момент написания статьи Google еще не выложила официальный код. Все, что есть и что можем попробовать, —  это реализации от комьюнити.

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

8x и «zero loss»

Давайте поговорим о цифрах. Google заявляет: «up to 8x speedup on H100 GPUs». И нет, к сожалению, ваш инференс не станет в восемь раз быстрее (в 99% случаев). Восьмикратный рост измерен относительно FP32, который никто не использует в продакшене. Относительно реально рабочего FP16-бейзлайна это будет примерно 4x.

И это еще не все. Четырехкратный рост — это ускорение только attention, не end-to-end инференса. В реальном пайплайне attention — лишь часть времени, а есть же еще линейные слои, sampling, IO. 

Реального wall-clock времени от токена до токена в предложенной методике нет — есть только ускорение attention, а это лишь часть пайплайна. А еще сообщество намерило overhead на префил порядка 21–27 мс на квантизацию (не катастрофа, но и не бесплатно).

Все, тогда расходимся, нас всех оверхайпнули? На самом деле нет, потому что реальная ценность TurboQuant не в скорости, а в памяти. Сжать KV-кэш в пять раз — это значит впихнуть в одну GPU контекст, который раньше не влезал. Например, на Llama 3.1 70B это разница между ~109K токенов и ~536K токенов на 34 ГБ VRAM. Вот это реально полезно.

«Zero accuracy loss» с оговорками

Продолжим идти по цифрам — на бенчмарках LongBench и Needle-in-a-Haystack результаты действительно впечатляют: модель Llama-3.1-8B-Instruct при квантовании до 3,5 бит набирает 50,06 балла на LongBench (ровно столько же, сколько в оригинальном FP16), а на Needle держит показатель 0,997 на контексте вплоть до 104K токенов. 

Если коротко — на длинном контексте качество не разваливается, и это главное.

Однако с практической точки зрения картина уже не такая радужная: все замеры проводились на небольших моделях до ~12B параметров (Llama-3.1-8B, Mistral-7B, Gemma). Данных для архитектур масштаба 70B+ в исследовании нет вовсе, и это риск — переносимость на крупные модели остается открытым вопросом.

Спасает то, что комьюнити уже провело самостоятельные тесты, и первые результаты обнадеживают: на модели 104B с пресетом turbo3 прирост перплексии (PPL) составил всего +3,6%. Однако «мы тут сами проверили, вроде работает» — это не замена нормального бенчмарка.

Отдельно в исследовании режет глаз отсутствие классической базы. Метрики WikiText-2 perplexity, MMLU — это тот минимум, без которого нормально сравнить метод с конкурентами в одной системе координат не получится.

Кроме того, есть еще один нюанс: ключи и значения в KV-кэше — это не одно и то же. У Qwen2.5, например, нормы ключей на порядки больше норм значений. 

Отсюда вывод: симметричная квантизация с одинаковой разрядностью для K и V — это костыль, ключам по-хорошему нужно больше бит. Асимметричные пресеты вроде K8V4, которые появились в vLLM и в форках llama.cpp, — тому доказательство.

ИИ‑роутер — доступ к 300+ моделям из одной панели

Подключите OpenAI‑совместимый шлюз по единому API‑ключу. Настраивайте сквозную аналитику, отслеживайте лимиты и квотируйте ресурсы.

Запустить ИИ‑роутер →

А что конкуренты

TurboQuant — далеко не единственный метод сжатия KV-кэша и даже не обязательно лучший для вашего конкретного сценария.

Метод KVTC строится на совершенно иной философии. Если TurboQuant работает по принципу «повернул и квантизовал», то KVTC — это своего рода аналог JPEG для KV-кэша. Разработчики заявляют о сжатии вплоть до 20 раз (против 5–6x у TurboQuant) с потерей точности менее одного процентного пункта. При этом KVTC тестировался на куда более широкой линейке моделей — от 1,5B до 70B. 

Явный минус подхода — необходимость однократной калибровки (примерно на 200K токенов). Для продакшен-сервисов с фиксированной моделью это не станет проблемой, однако для локального сценария «скачал GGUF и запустил свою модель» уже будет больно. Подробное описание метода доступно в статье, а в открытом доступе есть open-source реализация.

RotorQuant — community-проект, который решает конкретную проблему TurboQuant: умножение на полную d×d ортогональную матрицу — это 16 384 операций для d=128. RotorQuant заменяет ее на математическую хитрость, которая дает ~100 операций. 

В результате вращение выполняется в 10–31 раз быстрее, а сам алгоритм требует в 44 раза меньше параметров при сопоставимом качестве attention (косинусное сходство 0,990 против 0,991 у TurboQuant). Минус: проект пока проигрывает по качеству TurboQuant и находится на ранней стадии. Но идея красивая, и если авторы «дожмут» качество, проект может стать дефолтным выбором для мобильных и edge-сценариев. Исходный код проекта доступен на GitHub.

KIVI — проверенный бейзлайн (представленный на ICML 2024), который уже встроен в экосистему Hugging Face Transformers. Метод использует асимметричную 2-битную квантизацию (поканальную для ключей и потокеновую для значений). Такой подход сжимает KV-кэш в 16 раз, снижая пиковое потребление видеопамяти (peak memory) примерно в 2,6 раза. Для продакшена, где стабильность важнее максимального сжатия — вполне хороший вариант. Включить эту квантизацию в Transformers можно через cache_implementation="quantized" в методе generate().

Быстрая шпаргалка:

Метод

Сжатие

Калибровка

Модели 

Статус

TurboQuant

~5-6x

Нет

до 8B

15+ community-реализаций

KVTC (NVIDIA)

до 20x

Да (PCA)

1,5B–70B

OpenReview + open-source

RotorQuant

~5x

Нет

до 7B

Ранний community

KIVI

~16x (KV) / 2,6x peak mem

Нет

широко

В HuggingFace

Что работает прямо сейчас и как попробовать

Комьюнити уже создало более 15 реализаций — от простых Python-пакетов, устанавливаемых через pip install, до специализированных Metal-шейдеров.

Ниже внимательнее посмотрим на самые интересные и перспективные решения: одни из них уже готовы к использованию в продакшене, другие пока остаются полем для экспериментов.

llama.cpp

Если вы прогоняете модели локально через llama.cpp, это ваш основной вариант. TheTom/turboquant_plus (GitHub) — самый зрелый форк: есть поддержка Metal, CUDA, CPU, протестирован на моделях от 1,5B до 104B.

Собираем и запускаем:

git clone https://github.com/TheTom/turboquant\_plus.git
cd turboquant_plus
cmake -B build -DGGML_METAL=ON -DCMAKE_BUILD_TYPE=Release  # для Apple Silicon
# или -DGGML_CUDA=ON для NVIDIA
cmake --build build -j

# Симметричный turbo3 (3-bit K + 3-bit V), работает на большинстве моделей
./build/bin/llama-cli -m model.gguf \
  -ctk turbo3 -ctv turbo3 \
  -fa on -ngl 99 -c 32768

# Асимметричный — для моделей с Q4_K_M весами (Qwen2.5 и подобные)
./build/bin/llama-cli -m model.gguf \
  -ctk q8_0 -ctv turbo3 \
  -fa on -ngl 99 -c 32768

Доступные форматы KV-кэша:

  • turbo2 (2-bit) — сжатие в 6,4 раза, увеличение перплексии (PPL) на 6,5%. Подходит для экстремальной экономии памяти;

  • turbo3 (3-bit) — сжатие в 5 раз, рост PPL порядка 1%. Оптимальный выбор, с которого стоит начинать; 

  • turbo4 (4-bit) — сжатие в 3,8 раза. По точности практически неотличим от исходного формата FP16.

Бонусом идет Sparse V — это пропуск позиций с низкими attention-весами при декодинге. До +22,8% скорости декодирования на 32K контекста без потери качества.

На что стоит обратить внимание:

  • Симметричный turbo на Q4_K_M весах может выдать мусор. Это происходит, потому что квантизация весов уже снизила точность, и дополнительное сжатие KV-кэша на ключах добивает attention-маршрутизацию. Решение — использовать асимметричный режим, при котором ключи хранятся с более высокой точностью: -ctk q8_0 -ctv turbo3;

  • Модели с head_dim=64 могут падать: TurboQuant валидирован на head_dim ≥ 128;

  • Хорошая новость по масштабированию: большие модели переносят сжатие лучше, чем маленькие. 104B на turbo3 — всего +3,6% PPL, тогда как 70B — уже +11,4%.

Python + HuggingFace

back2matching/turboquant (GitHub, PyPI) — готовая интеграция для экосистемы Hugging Face Transformers. На сегодня это единственный пакет, который можно установить одной командой pip install и сразу получить сжатие KV-кэша ниже 8 бит (sub-8-bit).

pip install turboquant
from turboquant import TurboQuantMSE

# Квантизация любых векторов — KV-кэш, эмбеддинги
tq = TurboQuantMSE(dim=128, bits=4, device='cuda')

# Квантизация
indices, norms = tq.quantize(vectors)  # vectors: (N, 128)

# Деквантизация
vectors_hat = tq.dequantize(indices, norms)
Для интеграции с генерацией:
from turboquant import TurboQuantCache

cache = TurboQuantCache(
    key_bits=4,
    value_bits=2,
    protected_layers=[0, 1, -1, -2]  # первые/последние слои в FP16 - НУЖНО для лучшего качества
)
outputs = model(**inputs, past_key_values=cache, use_cache=True)

Обратите внимание на параметр protected_layers — это найденный комьюнити костыль. Первые и последние слои модели передают основной объем сигнала через остаточные связи (residual stream), поэтому их квантизацию лучше отключать.

Важное уточнение: в текущем виде пакет остается исследовательским инструментом. Он подходит для прототипирования и проверки гипотез, но для запуска в продакшене пока рановато.

vLLM

Поддержка TurboQuant уже замержена в основной репозиторий vLLM. Если собрать vLLM из ветки main, алгоритм заработает из коробки. Для тех, у кого vLLM уже развернут в продакшене, это самый простой и прямой путь внедрения. 

Достаточно одного флага:

# 3-bit с norm correction — рекомендуемый дефолт
vllm serve meta-llama/Llama-3.1-8B-Instruct \
  --kv-cache-dtype turboquant_3bit_nc

# Другие доступные пресеты:
# turboquant_4bit_nc  — 4-bit, самый безопасный по качеству
# turboquant_k8v4     — 8-bit ключи + 4-bit значения
# turboquant_k3v4_nc  — 3-bit ключи + 4-bit значения + norm correction

Под капотом реализован отдельный TurboQuantAttentionBackend.

Несколько цифр по емкости из бенчмарков PR с добавлением поддержки:

  • Qwen3.5-35B-A3B (гибридная MoE) — емкость KV-кэша выросла с 1,67M до 6,69M токенов, итого четырехкратный рост;

  • Gemma-3-27B (dense) — с 207K до 415K токенов, больше в два раза.

Важный урок из обсуждения в Pull Request, который стоит знать до того, как запускать в продакшн:

Дефолтный tq3 может убить reasoning. Проблема в том, что 2-bit значения оказываются слишком грубыми для задач на многошаговое рассуждение. 

Решение: используйте пресеты с коррекцией нормы (флаг _nc) либо асимметричный пресет k8v4 (8-битные ключи и 4-битные значения). Если ваша модель решает логические или вычислительные задачи, обязательно тестируйте ее на профильных бенчмарках, а не ограничивайтесь сравнением косинусного сходства. 

SGLang — еще в процессе

Поддержка метода находится в разработке (PR #21617 в состоянии Work In Progress / Draft). На данный момент уже реализованы базовая квантизация, Lloyd-Max кодбуки, выделение выбросов (outlier detection), Triton-ядра и интеграция с бэкендами FlashInfer и Triton. Все 42 юнит-теста проходят успешно, но до полноценного мержа в основную ветку ещё далеко. Отслеживать прогресс можно в Issue #21618.

Что выбрать — зависит от вашего сценария

Ваш сценарий

Инструмент

Как запустить

Локально на Mac (скорость)

turboquant_plus (Metal)

-ctk turbo3 -ctv turbo3 -fa on

Локально на NVIDIA

turboquant_plus (CUDA)

-ctk turbo3 -ctv turbo3 -ngl 99

Python + HuggingFace

pip install turboquant

TurboQuantCache(key_bits=4, value_bits=2)

Продакшн (vLLM)

vLLM из main

--kv-cache-dtype turboquant_3bit_nc

Общие рекомендации

Собрал несколько важных советов от комьюнити.

Ключи важнее значений. Ключам нужно больше бит. Оптимальный баланс по консенсусу: K=4-8bit, V=2-3bit.

Защищайте крайние слои. Первые два и последние два слоя трансформера лучше оставлять в формате FP16.

4-bit — безопасный дефолт. Если сомневаетесь, начинайте с 4-bit KV-кэша. При таком уровне сжатия сгенерированный текст при temperature=0 на большинстве моделей побитово совпадает с FP16. Формат 3-bit — отличный рабочий вариант для моделей от 8B параметров. Режим 2-bit стоит использовать только при критическом дефиците памяти и готовности к некоторой деградации качества. 

Грубая формула для планирования VRAM. Сочетание весов 4-bit (GPTQ/AWQ) и 3-bit TurboQuant KV-кэша позволяет разместить модель 70B с контекстом 500K+ токенов примерно в 34 ГБ видеопамяти. По сути, это позволяет уместить на 1–2 видеокартах то, что раньше требовало целого вычислительного кластера. 

Когда это нужно, а когда есть варианты лучше

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

Когда TurboQuant действительно нужен:

  • Длинный контекст от 32K+ токенов. На коротких контекстах (4K–8K) KV-кэш занимает мало места, и overhead квантизации перевешивает экономию. А вот на отрезках от 32K токенов кэш начинает доминировать в расходе VRAM, и именно здесь TurboQuant раскрывается в полной мере. 

  • RAG с большими документами. При загрузке в контекст всей кодовой базы или длинных PDF-файлов KV-кэш расходует видеопамять гораздо быстрее самих весов модели. 

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

  • Батчинг / высокий concurrency. Если вы обслуживаете много пользователей параллельно — KV-кэш каждого сидит в памяти;

  • Локальный инференс на ограниченном железе. На сетапах вроде Mac Mini с 24 ГБ объединенной памяти или RTX 4080 с 16 ГБ VRAM метод позволяет запустить модели и длинные контексты, которые раньше физически не помещались. 

Когда TurboQuant не поможет (или есть лучше):

  • Короткий контекст (< 8K токенов).

  • Модель не влезает по весам. TurboQuant сжимает KV-кэш, не веса.

  • MLA-архитектуры (DeepSeek V3, V4). Multi-head Latent Attention уже сжимает KV-кэш до латентных векторов архитектурно и убирает ~93% кэша. TurboQuant поверх MLA — это попытка сжать уже сжатое. Может дать что-то, но выигрыш будет минимальным по сравнению с обычными моделями.

  • Вам нужно максимальное сжатие и вы готовы к калибровке. KVTC от NVIDIA заявляет до 20x сжатия (против 5-6x у TurboQuant), но требует одноразовой PCA-калибровки. Если у вас фиксированная модель в продакшне и вы можете потратить время на калибровку, то KVTC может оказаться куда лучшим выбором.

  • Очень маленькие модели (< 1B). На 0.6B моделях качество деградирует заметно, модели не хватает избыточности, чтобы пережить сжатие. Начиная с 3B–4B все нормально, на 8B+ отлично.

Быстрый чеклист

Ответьте на три вопроса:

  1. Ваш контекст > 16K токенов? Если нет, то, скорее всего, не нужно.

  2. KV-кэш занимает > 30% вашего VRAM? Если нет, есть более полезные оптимизации.

  3. Модель ≥ 8B с head_dim ≥ 128? Если нет, результаты могут быть нестабильными.

Если три «да», ставьте turbo4, проверяйте качество на ваших примерах, и если все ок, то переключайтесь на turbo3 для большей экономии.

Вывод

Если коротко: TurboQuant — это рабочий практический инструмент для решения конкретной задачи: оптимизации KV-кэша при работе с длинным контекстом. Он работает без переобучения и калибровки модели, а его ограничения легко учитываются на практике. 

Если хочется погрузиться глубже — рекомендую посмотреть блог Google Research, и обязательно заглянуть в главный технический тред в llama.cpp — там сообщество в реальном времени разбирает все тонкости, с которыми можно столкнуться при реальном использовании. Для альтернативного взгляда стоит почитать про KVTC от NVIDIA: он предлагает иную философию и другие компромиссы, которые в некоторых сценариях могут оказаться предпочтительнее.

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

View the original on Хабр

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.