Интересное что-то
553 subscribers
2.79K photos
253 videos
140 files
4.59K links
Материалы и мысли, понадерганные отовсюду
Блог: https://t.iss.one/asisakov_channel
Чат: https://t.iss.one/youknowds_chat
Download Telegram
PEP-814: frozendict

В Python 3.15 появится полноценный иммутабельный словарь.

PEP: https://peps.python.org/pep-0814
Обсуждение: https://discuss.python.org/t/pep-814-add-frozendict-built-in-type/104854
Оригинальный PR: https://github.com/python/cpython/pull/144757
Исходники (да, они с dict лежат в одном файле на 8к строк)

Зачем?

Главный вопрос: зачем питону вдруг через 35 лет понадобился иммутабельный словарь? Мотивации в ПЕПе явно не очень хватает. Но я докину:
1. frozendict можно будет шарить между разными интерпретаторами без какого-либо оверхеда
2. С иммутабельными объектами куда проще работать в режиме Free-Threading
3. Многие другие новые идеи вроде Виртуальных Потоков тоже хотели бы иметь аналог иммутабельного словаря

Ну а types.MappingProxyType(mapping) был только surface-immutable. Все равно можно было поменять оригинальный объект mapping.

И вот у нас появилась точная копия обычного dict, только иммутабельная:

Примеры

frozendict является collections.abc.Mapping и таким же Generic с двумя параметрами:


>>> frozendict.__mro__
(<class 'frozendict'>, <class 'object'>)

>>> obj = frozendict({'a': 1})

>>> frozendict[str, int]
frozendict[str, int]


Но не умеет ничего из collections.abc.MutableMapping:


>>> obj['a'] = 2
TypeError: 'frozendict' object does not support item assignment

>>> obj.update
AttributeError: 'frozendict' object has no attribute 'update'


Зато умеет в hash, если все ключи и значения умеют в hash:


>>> hash(obj)
6343282633043897990

>>> hash(frozendict({1: []}))
TypeError: unhashable type: 'list'


Как его менять? А вот так, создавая новые:


>>> obj = frozendict({'a': 1})
>>> id(obj)
4352339472

>>> obj |= {'b': 2} # <- тут мы создали новый frozendict
>>> obj
frozendict({'a': 1, 'b': 2})
>>> id(obj)
4352341680


Детали реализации

Чтобы вы понимали, насколько они похожи: frozendict просто переиспользует clinic макросы dict для определения своих методов (=использует те же методы):


static PyMethodDef frozendict_methods[] = {
DICT___CONTAINS___METHODDEF
{"__getitem__", dict_subscript, METH_O | METH_COEXIST, getitem__doc__},
DICT___SIZEOF___METHODDEF
DICT_GET_METHODDEF
DICT_KEYS_METHODDEF
DICT_ITEMS_METHODDEF
DICT_VALUES_METHODDEF
DICT_FROMKEYS_METHODDEF
DICT_COPY_METHODDEF
DICT___REVERSED___METHODDEF
{"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
{NULL, NULL} /* sentinel */
};


Интересно, как работает hash: он полностью дублирует алгоритм хеша из frozenset.

В C-API тоже добавили функций для работы с новым словарем: PyFrozenDict_New, PyAnyDict_Check проверяет на dict, frozendict или их подтипы.

А еще половина stdlib поменяет константы с dict на frozendict.

Отличный ПЕП, простая реализация, крутая фича. Питон победа!

Обсуждение: как вы относитесь к иммутабельности в питоне и вообще?

| Поддержать | YouTube | GitHub | Чат |
Привет, товарищи-статистики!

Интересный вопрос по базе: почему при средних объемах выборки мы используем t-распределение, если средние уже вроде бы распределены нормально?

Действительно, при некотором объеме выборки (условно 30-50 измерений) у нас соблюдается не только нормальность средних, но и выборочная дисперсия начинает вести себя предсказуемо (моделируется через Хи-квадрат, одно не 1-в-1 с ним совпадает!). Это обеспечивает в принципе t-распределение для большинства случайный величин, то есть что-то универсальное.

Но многих в контексте "среднего объема" выборок ставит в тупик наблюдение о выборочных средних согласно нормальном распределении, значит и перевод в z-score должно давать z-нормальное, однако применение критерия без знания дисперсии генеральной дает именно t-распределение. Почему?

Действительно, наблюдаешь нормальность средних, применяешь z-score = z-нормальное. Но это если есть знания отклонения средних, что на практике невозможно, увы. Однако мы можем использовать оценку отклонения средних, стандартную ошибку: именно это и лежит в критерии в знаменателе.

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

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

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

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

В этом смысле t-распределение хорошо абсорбирует шум от выборочной дисперсии небольших выборок, оно естественным образом дает нам необходимый запас осторожности (консерватизма), пока выборка мала. При n -> бесконечность, выборочная дисперсия будет приближаться к истинной, то есть практически не колебаться, а значит от выборки к выборке мы будем делить по сути на саму дисперсию, что и хочет от нас как раз z-критерий, поэтому t станет z! - то, с чего начинался пост.

Можно сказать пафоснее: t статистика это есть нормированная z статистика и при стремлении n в бесконечность у нас нормировка, - отношение дисперсии истинной на дисперсию оцененную, - превращается в 1. Такие дела)

P.S. Что такое средняя выборка вопрос риторический и зависит от природы данных, готовых ответов у меня тут для вас нет: собирайте данные вашего домена, исследуйте.
Привет, товарищи-статистики! С праздником, днём Красной Армии, днём образования первой регулярной и массовой армии в мире, которая отстаивала интересы трудящихся.

Раз сегодня праздник, то и пост будет несложный, чтоб не прерывал отдых

Когда на курсе я с ребятами дохожу до p-value, мы рассматриваем распределение p-value при верности H0. Оно, распределение, равномерное, и частенько возникает вопрос: но почему оно равномерное? Ведь чаще же значения статистики будут у центра в рамках z-распределения, то есть как будто должно быть больше p-value's около 1 (с перекосом в пользу единицы).

А давайте посмотрим, почему равномерное.
Forwarded from AI и грабли
Кодинг-агент в телефоне (ч.1)

Частый вопрос в ИИ чатиках – как работать с ИИ агентом с телефона. Единственный стабильно рабочий совет, который я видел – ставить Claude Code на VPS и подключаться через termius.

Ниже инструкция:

1️⃣ Покупаем VPS. Топ: Hetzner, DigitalOcean. Дешман: RackNerd. В РФ – хз, посоветуйте в комментах

2️⃣ Настраиваем его с sudo доступом без пароля – чтобы агент мог делать все. VPS – по сути сэндбокс

Если вы не опытный пользователь linux, то просто открываем Claude Code локально и вставляем этот промпт для базовой настройки:

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

Требования:

Базовая настройка:

- Новый пользователь agent с sudo без пароля, чтобы агент мог сам запускать sudo-команды без интерактивного режима
- Доступ по ssh-ключу к новому пользователю agent (заранее сгенерируй ssh-ключи локально)
- Доступ к root-пользователю должен быть закрыт. Доступ по паролю – тоже
- Файерволл и fail2ban

Дополнительные настройки:

- Адекватная настройка bash history
- Swap 2GB
- Caddy
- uv для python и bun для javascript – через install.sh скрипты (найди в интернете)
- Docker + Compose v2 (добавить agent в группу docker)

ВАЖНО:

- Во время работы ты не должен получать доступ к секретам (пароль VPS, приватный ssh ключ, etc)
- Если что-то требует ввода секретных данных, то проси меня делать вручную
- В остальных случаях старайся использовать non-interactive режим, чтобы я участвовал в процессе минимально
- Задавай уточняющие вопросы, если есть что-то, что не прописано явно


3️⃣ Скачиваем и подключаем Termius на телефон

Тут все просто – добавляем ip, пароль оставляем пустым, на плашку AI Agent можно забить. Единственная сложность – нужно сразу создать ssh ключи и прокинуть публичный на VPS

Credentials → SSH.id, Key, Certificate, FIDO2 → Generate key → ✔️

Почему-то скопировать публичный ключ прям отсюда нельзя. Поэтому сохраняем настройки, возвращаемся в главное меню Vault → Keychain → ED25519-00 → 📤 → Copy Public Key

Дальше с десктопа:
ssh agent "printf '%s\n' 'ВСТАВЛЯЕМ СЮДА КЛЮЧ' >> ~/.ssh/authorized_keys"


Возвращаемся в Vault → Hosts, тапаем на созданный сервер, оказываемся в командной строке, вуаля

Осталось установить Claude Code:

curl -fsSL https://claude.ai/install.sh | bash


Дальше пишем claude и получаем красоту на скрине выше.

Из комментов (спасибо @nobilix):

1) без tmux никуда - соединение рвется, а с tmux - просто супер
2) в Termius важно включить галочку "Use Mosh" - будет моментальный отклик на нажатие клавиш
3) в Termius есть встроенный SFTP - оч удобно по файлам бегать и читать (использует тот же конфиг)
4) сменить дефолтный порт с 22 на другой (безопасность)
5) можно настроить пуш уведомления через хуки CC


Вот, теперь можно не вылезать из CC даже в туалете

@ai_grably
Forwarded from AI и грабли
Кодинг-агент в телефоне (ч.2)

В прошлом посте расписал дефолтный подход с termius. Но консольный UX на тачскрине – достаточно сомнительный. Так что у меня давно чесались руки затестить еще одну идею, которую еще нигде не видел. И вот вчера руки наконец дошли

В чем идея:

1. Есть очень хороший кодинговый агент OpenCode. Пожалуй, ближайший к CC по плотности фич, а по качеству реализации, пожалуй, даже лучше

2. В отличие от остальных агентов, он написан в классическом клиент-серверном подходе – отдельно бэк, отдельно фронт

3. И у него есть два фронта – уже привычный нам консольный текстовый UI и веб версия

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

Дальше – пошаговый гайд + подводные камни:

1️⃣ Берем инструкцию из предыдущего поста и настраиваем себе VPS с нуля – у агента будет полный доступ к нему

2️⃣ Ставим opencode. В любом агенте на локальном устройстве пишем:

Настрой мне opencode web на удаленной машине (подключаться через ssh agent):
1. Изучи документацию opencode
2. Установи opencode
3. Настрой caddy (с моим доменом или просто http – обсуди со мной оба варианта)
4. Настрой запуск в бэкграунде (tmux, docker, pm2, systemd – помоги мне выбрать)
5. Создай папку ~/projects

- Сначала вместе сформулируем план, а после моего аппрува пойдешь выполнять (или говорить мне, что выполнить, если нужен интерактивный ввод).
- Выполняй команды гранулярно (двигаемся step-by-step)
- Обязательно настрой доступ к OpenCode по паролю
- Не читай и не запрашивай пароли – они не должны оказаться у тебя в контексте


Опционально: просим настроить в caddy Oauth через GitHub вместо багованного Basic Auth опенкода

3️⃣ Подключаем подписку

Недавно OpenAI сделали нативную интеграцию с OpenCode и обычная ChatGPT подписка за 20$ дает жирные лимиты на топовую gpt-5.2

1. Открываем только что задеплоенный opencode
2. Пишем /model в чате
3. В открывшемся окне – Connect Provider справа вверху
4. Переходим по ссылке в лк OpenAI и даем доступ

❗️Тут проблема – флоу OpenAI редиректит на https://localhost:1455, OpenCode ждет ответ не локально, а на VPS

Решение: перед попыткой входом временно пробрасываем порты в отдельном терминале
ssh -L 1455:localhost:1455 agent -N


4️⃣ Создаем WebApp на смартфоне

Открываем адрес нашего OpenCode в Safary → ··· меню → share → добавить на домашний экран (скрины в комментах)

Кстати, так же можно создать WebApp и на десктопе, чтобы это было как отдельное приложение, а не одна из сотен вкладок в браузере (скрин в комментах)

———

Готово, у вас есть агент с полноценным UI, который доступен с любого устройства и поддерживает почти все современные фичи – CLAUDE.md/AGENT.md, MCP, LSP, skills, subagents

Бонус: теперь вы знаете как поднять такое для нетехнических сотрудников.

Ваш, @ai_grably
Forwarded from AI и грабли
Протухание контента

Только собрался писать пост о том, как я его учил свою подругу маркетолога использовать OpenCode, который пару дней назад появился в форме десктопного аппа с нормальным UI,

Как сегодня выходит десктопный UI для кодекс 🤯

———

Скачать OpenCode (Mac, Windows, Linux)
Скачать Codex (Mac-only)

Обзор по фичам на картинке ниже (разбор только по десктопным фичам):

ваш, @ai_grably
Transformers v5

Пост (от декабря): https://huggingface.co/blog/transformers-v5
Полный список изменений: https://github.com/huggingface/transformers/releases/tag/v5.0.0

- Теперь токенизаторы используют только tokenizers, что раньше было fast. Более подробно можно прочитать в их блоге https://huggingface.co/blog/tokenizers
- Теперь dtype будет auto по дефолту (раньше было fp32)
- Убрали load_in_8bit и теперь надо передавать конфиг напрямую
- Много аргументов в трейнере поменяли. Например,report_to теперь по дефолту none
- Также сделали методы для получения отдельных модальностей у модели для SentenceTransformers, так что ждем когда появится новая версия
😥Грёбаная неопределенность только успевают нарастать в этом мире. Ровно как и грёбаная энтропия и грёбаные цены на золото/ жизнь/ бензычъ.

Принимать взвешенные решения в таких условиях - аццкий ад.

Но! На то есть - серебрянная пуля/ синяя таблетка/ узбагоин (выбери нужное).
Это - фильтр, через который можно просеивать собственные решения. Фильтр, основанный на твоих личных жизненных принципах.

Миллиардер Рэй Дэлио описал свои принципы и подходы в книге "Принципы". По ссылке получасовой ютуб-саммари этой книги.

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

Кто хочет поразгонять - ловите промпт:


Промпт для разбора жизненных принципов

## Роль

Ты — коуч, который мыслит как Рэй Далио, автор книги "Принципы". Твоя задача — помочь человеку нащупать и сформулировать его личные жизненные принципы через рефлексию и честный разбор паттернов поведения.

## Методология

### Фаза 1: Сбор фактуры

Начни с открытого вопроса:
> "Расскажи о себе: что тебе нравится делать, что не нравится, как ты работаешь, отдыхаешь, общаешься. Не структурируй — просто говори, что приходит в голову."

Слушай и отмечай:
- Повторяющиеся паттерны
- Противоречия (говорит одно, делает другое)
- Эмоциональные маркеры (где энергия, где угасание)
- Что человек называет сам, но не осознаёт как паттерн

Задавай уточняющие вопросы, но не уводи в сторону.

### Фаза 2: Исследование боли

Далио говорит: "Боль + Рефлексия = Прогресс"

Найди точки, где человек:
- Сдавался раньше времени
- Терял энергию
- Конфликтовал с другими или собой
- Чувствовал себя не на своём месте

Ключевой вопрос: "Что ты чувствовал в этот момент? Это была злость, стыд, обида или что-то другое?"

Эмоция — ключ к пониманию реального принципа, который управляет поведением.

### Фаза 3: Поиск структуры

Ищи ответы на:
- Топливо: что даёт энергию?
- Кайф: от какой деятельности получает удовольствие?
- Боль: что истощает, бесит, демотивирует?
- Компенсаторы: что/кто помогает закрывать слабые стороны?

### Фаза 4: Формулировка принципов

Принцип должен быть:
- Конкретным (не "быть лучше", а "работать в партнёрстве с комплементом")
- Проверяемым (можно понять, следуешь ему или нет)
- Основанным на реальном опыте, а не на "как надо"

Группируй принципы:
- Про работу / продуктивность
- Про отношения / общение
- Про себя / ограничения
- Про рост / зону развития

### Фаза 5: Тест на практике

Возьми текущую ситуацию выбора и прогони через принципы:
> "У тебя есть X, Y, Z. Давай проверим каждый вариант через твои принципы."

Создай простую таблицу: принцип vs вариант.

### Фаза 6: Поиск механизмов

Принципы без механизмов — просто слова. Спроси:
> "Как ты будешь себя возвращать к этому принципу, когда захочется его нарушить?"

Варианты механизмов:
- Внешний партнёр / accountability
- Правила-триггеры ("если X, то Y")
- Ограничения ("новое можно только после Z")

## Правила ведения диалога

1. Не давай советов раньше времени — сначала собери фактуру
2. Возвращай к сути — если человек уходит в сторону, мягко верни
3. Называй паттерны — человек часто не видит, что повторяется
4. Используй его слова — когда он сам что-то точно сформулировал, зафиксируй
5. Один вопрос за раз — не перегружай
6. Проверяй резонанс — "Это отзывается? Что хочешь поправить?"

## Ключевые вопросы

- "Что ты чувствуешь в момент, когда сдаёшься?"
- "Где в жизни ты продолжал что-то делать долго без быстрого результата?"
- "Опиши идеальную роль — что делаешь, с кем, как часто контакт с людьми?"
- "Если бы мог оставить только одно направление — какое?"
- "Это осознанная стратегия или способ не выбирать?"

## Финал

Когда принципы собраны, резюмируй:
- Список принципов (компактно)
- Главное противоречие / зона роста
- Один практический шаг на ближайшую неделю


Не забудьте Рэю отсыпать огоньков! Ласковое слово даже миллиардеру приятно❤️
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Душный NLP
🎄 Лучшие статьи 2025 года — выбор инженеров Яндекса

Miss me? Как и обещали, возвращаемся не с обзором, а с «кое-чем ещё», но не менее полезным. Мы попросили инженеров Яндекса, чьи разборы вы можете почитать в канале, поделиться (уже) прошлогодними статьями, которые им запомнились больше всего.

ToolOrchestra: Elevating Intelligence via Efficient Model and Tool Orchestration

Статья о маленькой модели (Qwen3-8B-Based), которая, по сути, выполняет функцию планера и роутера во вспомогательные инструменты (глобальный/локальный поиск), специализированные модели (вроде Qwen3-Coder) и модели общего назначения (GPT-5) для решения задач. Кроме того, модель обучена учитывать преференции пользователя по использованию тулов и размену качества на скорость и цену. С помощью обучения на несложной синтетике у авторов получается модель, которая даёт высокий скор на HLE, FRAMES, tau2-bench и при этом оказывается более cost-effective.

Stabilizing Reinforcement Learning with LLMs: Formulation and Practices

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

Artificial Hivemind: The Open-Ended Homogeneity of Language Models (and Beyond)

Исследователи из разных университетов изучили ответы моделей на запросы, допускающие ответ в свободной форме (вроде «в чём смысл жизни?» или «сочини стихотворение о времени»). Обнаружили, что ответы одной и той же модели, и совершенно разных, по форме и содержанию очень похожи. Известные техники повышения разнообразия — регулировка температуры или Min-p Sampling — не сильно помогают. Например, большинство моделей стали сравнивать время с рекой.

Вероятно, эффект обусловлен тем, что модели обучаются на похожих данных, собранных из интернета, или даже на синтетике, сгенерированной другими моделями. Кроме того, выяснили, что предпочтения LLM-as-a-Judge плохо коррелируют с оценками людей, особенно на примерах, где предпочтения асессоров расходятся.

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

DAPO: An Open-Source LLM Reinforcement Learning System at Scale

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

Любопытными статьями поделились Владимир Платонов, Алексей Зотов, Денис Кузнеделев и Артём Харинаев

Душный NLP
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Душный NLP
Ускорение E2E-инференса через оптимизацию KV-кэша. Часть I

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

Её можно разделить на pre-train и post-train. Первые требуют изменений до обучения модели: это архитектурные решения вроде GQA/MQA/MLA, смешивание глобального и локального атеншена, а также другие модификации, которые обычно стоят дорого из-за переобучения.

Post-train-методы можно применять к уже готовой модели: это различные sparse-стратегии, pruning, удаление повторов токенов и другие техники, которые уменьшают объём KV или сокращают число обращений к нему во время инференса.

KV-бюджеты удобно делить на dense и sparse, отдельно для prefill и отдельно для decode. В варианте dense prefill + dense decode (обычный KV-кэш) каждый новый Q взаимодействует со всеми K и V до него: ко всем токенам промпта и всем ранее сгенерированным токенам. Тогда KV-бюджет равен сумме длины промпта и длины генерации.

Если сделать sparse только на prefill, а decode оставить плотным, то Q перестаёт смотреть на весь промпт, но общий выигрыш заметен в основном в сценариях «длинный промпт — короткий ответ». Если же оставить dense prefill и сделать sparse decode, это часто релевантно reasoning/CoT-сценариям. Sparse и на prefill, и на decode даёт максимальную экономию бюджета, но обычно сильнее всего ухудшает качество.

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

Один из сильных post-train-методов оптимизации KV-кэша — ShadowKV, который позволяет получать минимальные просадки на бенчмарках без дообучения и увеличивает throughput до трёх раз. О нём мы подробно поговорим в следующей части.

Разбор подготовил Владислав Кругликов

Душный NLP
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Душный NLP
Ускорение E2E-инференса через оптимизацию KV-кэша. Часть II

В первой части разбора мы говорили о методах оптимизации KV-кэша в принципе. А сегодня речь пойдёт об одном конкретном подходе — ShadowKV.

В его основе наблюдение, что post-RoPE key cache обладает attention locality — соседние токены часто имеют высокую cosine similarity, и только небольшая часть токенов выбивается из этого паттерна. Поэтому их режут на чанки по 8 токенов и строят landmarks — репрезентативные средние ключи для чанка. Это значительно ускоряет этап выбора ключей на шаге декодирования, а также улучшает доступ к памяти и позволяет лучше насыщать шину.

Ключевой момент в том, что лучше всего сжимается именно pre-RoPE K: он хорошо раскладывается в низкий ранг с минимальной ошибкой, заметно лучше, чем V. Поэтому ShadowKV делает так: pre-RoPE K сжимается через SVD, а V не сжимается, а уезжает в CPU (RAM), чтобы экономить GPU память и bandwidth.

При этом небольшое число токенов, которые плохо объясняются landmark’ами, выделяются как outliers (выбросы) и сохраняются полнорангово. В статье отмечают, что значимая доля outliers — это sink tokens. Достаточно порядка 0,049% бюджета на выбросы, чтобы попасть в точку diminishing returns: это минимальное количество outliers, которое почти полностью закрывает деградацию качества, а дальнейшее увеличение бюджета даёт лишь пренебрежимо малый дополнительный вклад.

На этапе prefill пайплайн строится так: параллельно с основным префиллом быстро вычисляются landmarks и outliers, и это вычисление перекрывается с отгрузкой V на CPU. В результате дополнительные шаги минимально увеличивают critical path, потому что большая часть работы делается в overlap-режиме.

Q на decode скорится не по всем токенам, а по landmarks каждого чанка. Затем выбираются лучшие чанки, и уже все токены из выбранных чанков отправляются в kernel attention. Для этого K восстанавливаются обратно из low-rank пространства, а соответствующие V подгружаются из CPU.

Дополнительно используется оптимизация в духе branch prediction или speculative-подходов. Между двумя соседними шагами декодирования выбранный набор токенов обычно меняется незначительно, потому что запросы на соседних шагах похожи. Поэтому можно кэшировать уже подгруженные токены для каждого слоя и на следующем шаге считать разность множеств, догружая только те токены, которых ещё нет в рабочем наборе. Эта оптимизация lossless относительно ShadowKV, потому что сохраняется инвариант: на каждом шаге в аттеншн всё равно попадает актуальный набор токенов — просто часть из них переиспользуется без повторной загрузки.

На бенчмарках деградация остаётся минимальной при бюджете около 1,56% от полного объёма KV. При этом в практических сценариях ShadowKV обеспечивает заметный прирост скорости и позволяет поддерживать существенно больший размер батча — за счёт снижения нагрузки на VRAM и уменьшения стоимости аттеншн на длинных контекстах.

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

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

Разбор подготовил Владислав Кругликов

Душный NLP
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM