Головна / Статті / KV-кеш простими словами: чому довгий контекст — це рахунок за пам’ять, а не розум

KV-кеш простими словами: чому довгий контекст — це рахунок за пам’ять, а не розум

Зрозуміле пояснення KV-кешу: що він зберігає, як порахувати його розмір, чому довгий контекст з’їдає пам’ять і чотири способи зменшити витрати на локальних моделях.

1921 слів

Коли рахуєш пам’ять для локальних моделей, постійно натрапляєш на термін «KV-кеш». Порахувати його легко, а пояснити напрочуд важко. Цей текст — чиста теорія, без вибору заліза й без форматів файлів. Дочитавши, ви розумітимете, що лежить у кеші, чому модель без нього не може працювати і чому більше вікно контексту — це насправді запит пам’яті, а не інтелекту.

Навіщо потрібен кеш

Мовна модель пише по одному токену за раз і, щоб обрати наступний, озирається на всі попередні. Цей погляд назад називається увагою (attention), і це дорогий крок.

Тепер уявіть, що кешу немає зовсім. Щоб видати токен 5, модель обробляє токени з 1 по 4. Для токена 6 — з 1 по 5. Для токена 7 — з 1 по 6. Та сама робота повторюється над тими самими токенами, і втрати ростуть із кожним новим словом.

Кеш перетворює повторну роботу на збережену. Модель і далі звертає увагу на кожен попередній токен, але не перераховує їх щоразу. Внесок кожного токена обчислюється один раз, зберігається й перевикористовується до кінця розмови. На кожен токен зберігаються дві речі — звідси й назва.

Запити, ключі та значення

Токен починається як список чисел, що називається ембедінгом, — можна вважати, що це зміст токена, записаний у вигляді координат. Модель множить цей ембедінг на три окремі навчені матриці. Їх зафіксовано під час навчання, і потім вони не змінюються. Кожна перетворює той самий вхід на свій вектор.

Три матриці входять у ваги моделі й однакові для всіх токенів. Відрізняється лише вхідний ембедінг, тому три вихідні вектори в кожного токена свої.

Уявіть бібліотеку. На корінці кожної книжки є ярлик, а всередині — текст. Ярлик на корінці грає роль ключа, текст — роль значення, а питання, з яким приходить відвідувач, — роль запиту. Ніхто не читає полицю цілком. Відвідувачі пробігають очима корінці, обирають доречні ярлики й відкривають лише ці книжки. Увага робить те саме з однією поправкою: вона відкриває всі книжки, а потім змішує їхній вміст, надаючи більшої ваги тим, чиї ярлики краще пасують до питання.

Ключі потрібні для зіставлення, значення — для змісту. Цей поділ пояснює, чому зберігати треба і те, і те. Одне вирішує, наскільки важливий минулий токен, а інше повідомляє, що в ньому сказано.

Що викидається, а що лишається

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

Із ключами та значеннями інша історія. До ключа й значення токена 5 модель звертатиметься, коли писатиме токен 6, токен 600 і токен 60 000. І вони ніколи не змінюються, адже ніщо з того, що відбувається потім, не змінює того, що запропонував токен 5. Порахувати один раз і зберігати завжди — саме правильний компроміс.

Чому кеш так розростається

Повернімося до бібліотеки. Кожен токен, що надходить, заповнює дві картки — ярлик і картку зі змістом — і підшиває їх до картотеки. Поки розмова відкрита, нічого не видаляється. Дві обставини роблять цю картотеку більшою, ніж здається.

По-перше, у моделях багато шарів, і кожен шар має власну бібліотеку. Вісімдесят шарів — вісімдесят будівель, і в кожній на кожен токен підшивається пара карток. По-друге, кожен шар ділить роботу між кількома читачами, яких називають головами (heads), і кожен читач заводить свою пару, тож кількість множиться ще раз.

На цій моделі один токен розмови коштує 320 КіБ. Тисяча токенів — 320 МіБ. Кеш крихітний у розрахунку на токен і величезний у розрахунку на розмову.

Усе це однією формулою

Усе сказане стискається в один рядок, і кожен член можна прочитати в config.json моделі:

cache bytes = 2  ×  layers  ×  tokens  ×  kv_heads  ×  head_dim  ×  bytes_each
              │        │          │           │            │            │
              │        │          │           │            │            └ 2 at FP16, 1 at 8-bit
              │        │          │           │            └ numbers per head
              │        │          │           └ how many key/value sets per layer
              │        │          └ your context length
              │        └ every layer keeps its own
              └ one key and one value

Обирати ви можете лише один член. Шари, голови й розмірності задано під час навчання. Байти на значення випливають із точності кешу. Токени — це довжина контексту, і це та ручка, яку ви контролюєте.

Оскільки токени стоять у звичайному множенні, ріст лінійний і безжальний: подвойте контекст — і кеш подвоїться. Знижок за довгі розмови не буває.

Порівняймо дві реальні моделі

На реальних цифрах це стає менш абстрактним:

  • Qwen3.6-27B тримає зростаючий кеш лише в 16 зі своїх 64 шарів, по 4 набори ключів і значень у кожному. Вартість: 64 МіБ на кожну 1000 токенів.
  • Llama-3.1-70B тримає його в усіх 80 шарах, по 8 наборів ключів і значень у кожному. Вартість: 320 МіБ на кожну 1000 токенів.

Це вп’ятеро дорожче в розрахунку на токен, і пояснюється це архітектурою, а не розміром. Кількість параметрів моделі нічого не скаже про рахунок за її кеш.

Іще одна тонкість: у Llama-3.1-70B 64 читачі, а наборів карток зберігається лише 8. Ця невідповідність навмисна. Групи по вісім читачів ділять один набір замість того, щоб кожен збирав власну копію. Техніка називається grouped-query attention (увага з групуванням запитів), і її використовує майже кожна сучасна модель. Це ніби шістдесят чотири людини купували кожен свою газету, а натомість офісом ходять вісім примірників. Читають і далі всі, але рахунок із газетного кіоску зменшується вісімкратно.

Економія вісімкратна за невеликої втрати якості. Без неї довгий контекст на моделі 70B потребував би більше пам’яті, ніж має будь-яка окрема машина.

Переводимо токени в сторінки

Кількість токенів важко уявити, тож ось ті самі вікна у звичних одиницях читання, з розрахунку приблизно три чверті слова на токен:

8K tokens  ≈   6,000 words  ≈   25 pages   a long report
32K tokens  ≈  25,000 words  ≈  100 pages   a short book
128K tokens  ≈  98,000 words  ≈  390 pages   a full novel
256K tokens  ≈ 197,000 words  ≈  790 pages   two novels

Запитуючи вікно на 128K, ви просите модель тримати в голові роман і не відпускати його. Перенесімо це на реальне залізо: Llama-3.1-70B із 8-бітними вагами на машині, де доступно близько 114 ГіБ.

context      weights      cache      total      left over
   8K        65.2 GiB     2.5 GiB    67.7 GiB    46.0 GiB
  32K        65.2 GiB    10.0 GiB    75.2 GiB    38.5 GiB
 128K        65.2 GiB    40.0 GiB   105.2 GiB     8.5 GiB

На 25 сторінках кеш майже непомітний. На довжині роману він виростає до 40 ГіБ. Для порівняння: уся Qwen3.6-27B з усіма вагами займає 25 ГіБ, тож один чат завдовжки з роман на моделі 70B потребує більше пам’яті, ніж добрій моделі 27B потрібно загалом.

Ваги не змінилися. Змінилося лише те, скільки розмови модель попросили пам’ятати.

Довге вікно контексту — це не налаштування. Це постійний резерв пам’яті, який оплачується наново за кожну відкриту розмову.

Цю частину часто пропускають. Ваги схожі на товарний запас крамниці: закуплені один раз, і всі покупці дивляться те саме. Кеш схожий на примірочну. Кожному покупцеві потрібна своя, і вона зайнята, поки він не піде. Двом читачам, кожен із яких читає свій роман, потрібні два кеші по 40 ГіБ. Ось чому модель, якій просторо на особистій машині, починає задихатися, коли нею одночасно користуються кілька людей.

Чотири способи зменшити рахунок

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

  1. Обмежте контекст під завдання. Це найдешевше рішення. Звичайний чат використовує кілька тисяч токенів, а 32K покриває більшість завдань із програмування. Запитуючи максимальне вікно для кожного завдання, ви щоразу платите максимальну ціну.
  2. Квантизуйте кеш, але обережно. Зберігання кожного числа у 8 бітах замість 16 зменшує його вдвічі. Заковика в тому, що ключі й значення переносять це неоднаково. Опубліковані вимірювання показують, що 8-бітні ключі зберігають близько 98% збігу з прогоном у повній точності, а 4-бітні падають приблизно до 12%. Значення витримують грубіше поводження, тож спершу стискайте значення, а ключі тримайте у 8 бітах або точніше.
  3. Обирайте архітектури, розраховані на це. Grouped-query attention зараз усюди, а гібридні архітектури йдуть далі: більшість шарів отримує невелике зведення фіксованого розміру замість зростаючого стосу карток. Так модель може заявляти 256K і все одно вміщатися.
  4. Перегляньте ваги. Зниження точності ваг звільняє пам’ять для кешу. У рядку для 128K вище 4-бітні ваги перетворюють 8,5 ГіБ вільного місця на 37,8 ГіБ.

Вибір моделі з урахуванням кешу

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

Той самий бюджет на кеш дає вшістнадцятеро більше контексту в найкращої з них. Кількість параметрів, якщо порівнювати її так, як зазвичай порівнюють, майже не відрізняється, а вартість кешу різниться в 16 разів.

Qwen3.6-35B-A3B тут — добра модель на щодень. За 20 МіБ на 1000 токенів контекст майже безплатний, і навіть повному вікну на 256K потрібно лише 5 ГіБ кешу. Економити контекст більше не доводиться, а саме заради цього й варто мати потужну машину. Коли короткому завданню потрібно більше глибини міркувань, наступний крок — щільна 27B, утричі дорожча на токен, що все одно небагато.

Llama-3.1-70B важче виправдати на довгому контексті на машині зі 114 ГіБ. Модель не слабша. На 128K вона займає 105 ГіБ, а на 256K хоче 145 ГіБ, яких просто немає. Щоб утримати її кеш у розумних 20 ГіБ, контекст доведеться обмежити приблизно 66K. Якщо модель усе одно змушує економити контекст, пам’ять краще витратити на ту, що не змушує.

Звідси корисна звичка: дивіться вартість кешу на 1000 токенів раніше, ніж кількість параметрів. Параметри кажуть, скільки коштує завантажити модель. Цифра кешу каже, скільки коштує нею користуватися. Це відповіді на різні питання, а назва моделі рекламує лише одне з них.

Якщо коротко

KV-кеш — це запис уже наявної розмови, що робиться один раз на токен, щоб моделі ніколи не доводилося його перераховувати. Для кожного токена, у кожному шарі й для кожного набору ключів і значень він зберігає ключ, який вирішує, наскільки важливий цей токен, і значення, яке фіксує, що токен привносить.

Це ще й єдина частина рахунку за пам’ять, що росте під час роботи моделі. Ваги коштують фіксовану суму під час завантаження, а кеш — поточна витрата, яка росте разом із кількістю токенів і відкритих розмов.

Наступного разу, задаючи довжину контексту, думайте про неї в гігабайтах, а не в токенах. У розглянутих тут моделях вікно на 128K обходиться від 8 до 40 ГіБ залежно від вибору, тож вирішувати варто свідомо.