Prefill и decode, узкие места
Почему первый токен ответа появляется с паузой, а остальные «печатаются» с постоянной скоростью, и как по пропускной способности памяти предсказать токены в секунду любой модели на любом железе.
Зачем это нужно
Заголовок раздела «Зачем это нужно»Отправьте модели длинный документ с просьбой пересказать. Сначала ничего не происходит: секунда, две. Потом текст начинает «печататься» с ровной скоростью, слово за словом. В уроке 8.1.1 вы увидите и вторую странность: провайдеры берут за токены ответа в несколько раз больше, чем за токены вопроса, хотя вопрос обычно длиннее.
Обе странности объясняет одно: инференсинференс, вывод моделиEN inferenceСм. «reasoning»: в китайском одно и то же слово. LLM состоит из двух фаз с совершенно разной физикой. Первая упирается в скорость вычислений, вторая — в скорость памяти. Поймёте это — и сможете без замеров, с карандашом в руках сказать:
- сколько токенов в секунду выдаст Qwen3-8B на вашей видеокарте, а сколько — на ноутбуке без неё;
- почему 4-битное квантование (урок 7.2.1) ускоряет генерацию в 3–4 раза;
- почему сервер, обслуживающий сотню пользователей сразу, выдаёт в десятки раз больше токенов, чем для одного, на том же железе (следующий урок);
- почему DeepSeek ради уменьшения KV-кэшаKV-кэшEN KV cache придумала MLA, а prefill и decode держит на разных машинах.
Две фазы генерации
Заголовок раздела «Две фазы генерации»Вспомните авторегрессионную генерацию и KV-кэш из урока 4.6.4: модель выдаёт по одному токену, а ключи и значения прошлых токенов хранит, чтобы не пересчитывать.
Фаза 1 — prefillprefill (предзаполнение)EN prefillПервая фаза генерации: весь промпт проходит через модель одним параллельным проходом, заполняется KV-кэш и получается первый токен. Упирается в вычисления.. Весь промпт из токенов проходит через модель одним проходом. Все позиций считаются параллельно: каждый слой умножает матрицу активаций на матрицу весов. По пути ключи и значения всех токенов записываются в KV-кэш, а из логитов последней позиции сэмплируется первый токен ответа.
Фаза 2 — decodeдекодирование (фаза decode)EN decode phaseВторая фаза: один токен за один проход модели. На каждый токен заново читаются все (активные) веса и KV-кэш, поэтому фаза упирается в пропускную способность памяти.. Дальше модель работает в цикле: подаёт на вход один новый токен,
читает KV-кэш, выдаёт следующий токен, дописывает его ключ и значение в кэш. И так до токена конца или до max_tokens.
Каждый шаг — полный проход через все слои ради одного токена.
flowchart LR
P["Промпт: T токенов"] --> PF["Prefill<br/>один проход по всем T<br/>(матрица × матрица)"]
PF --> KV[("KV-кэш")]
PF --> T1["Токен 1"]
T1 --> D["Шаг decode<br/>1 токен за проход<br/>(вектор × матрица)"]
KV <--> D
D --> TN["Токен 2, 3, …"]
TN -->|"ещё не конец"| D| Prefill | Decode | |
|---|---|---|
| Токенов за проход | весь промпт ( = сотни–тысячи) | 1 на каждую последовательность |
| Главная операция | умножение матрицы на матрицу (GEMM, General Matrix Multiply) | умножение вектора на матрицу (GEMV, General Matrix–Vector) |
| Что ограничивает | вычисления (FLOP/с) | пропускная способность памяти (байт/с) |
| Какую метрику задаёт | время до первого токена | скорость «печати» |
| Сколько раз выполняется | один раз на запрос | столько раз, сколько токенов в ответе |
Пример. Модель на 8 млрд параметров на RTX 4090, промпт 2000 токенов, ответ 500 токенов. Prefill займёт около 0.4 с, а decode — около 10 с (при реальных ~50 токенах/с). Промпт вчетверо длиннее ответа, но ответ занимает в 25 раз больше времени. Откуда эти числа — дальше.
Сколько стоит один токен: FLOPs и байты
Заголовок раздела «Сколько стоит один токен: FLOPs и байты»Чтобы понять, во что упирается каждая фаза, посчитаем две вещи: сколько операций нужно на токен и сколько байт придётся прочитать из памяти.
Операции. Каждый вес модели участвует в обработке токена ровно один раз: одно умножение и одно сложение. Поэтому прямой проход стоит около FLOPsFLOPs, число операций с плавающей точкойEN floating-point operations (FLOPs)Не путайте FLOPs (сколько операций нужно сделать) и FLOP/s, FLOPS (сколько операций железо делает в секунду). на токен, где — число параметров. Это та же двойка, что в формуле из урока 5.1.1: 2 на прямой проход и 4 на обратный. Для Llama 3 8B это GFLOP на каждый токен (приставка «гига» — миллиард, ).
К этому добавляется внимание к контексту: на позиции каждый слой считает скалярных произведений с ключами и взвешенную сумму значений — около FLOPs ( — число слоёв, — размер модели). Откуда четвёрка: скалярное произведение векторов длины — это умножений и сложений, FLOPs; таких произведений , итого . Взвешенная сумма векторов длины — ещё . Вместе на слой. У Llama 3 8B (, ) на позиции 8192 это GFLOP — заметно, но меньше .
Байты. Чтобы обработать токен, нужно прочитать из видеопамяти все веса (в BF16 — по 2 байта на параметр, у Llama 3 8B это 16 ГБ) и весь KV-кэш контекста (128 КиБ на токен у Llama 3 8B, см. урок 5.2.1).
А теперь главное. При prefill веса читаются один раз на весь промпт: прочитали матрицу слоя — и сразу умножили её на все токенов. При decode веса читаются один раз на один токен. Работа на каждый прочитанный байт различается в раз.
Арифметическая интенсивность и roofline
Заголовок раздела «Арифметическая интенсивность и roofline»У любого вычислителя два предела:
- пиковая производительность — сколько операций в секунду он может сделать (FLOP/с);
- пропускная способность памятипропускная способность памятиEN memory bandwidthСколько байт в секунду память отдаёт вычислителю. RTX 4080 — около 717 ГБ/с, H100 — 3.35 ТБ/с, двухканальная DDR5 — около 90 ГБ/с. Главное число для скорости decode. — сколько байт в секунду память успевает подвезти.
Операция, которой нужно операций и байт, займёт не меньше секунд: нельзя посчитать быстрее пика и нельзя получить данные быстрее, чем их отдаёт память. Отношение
называется арифметической интенсивностьюарифметическая интенсивностьEN arithmetic intensityСколько операций приходится на один прочитанный из памяти байт (FLOP/байт). Decode с батчем 1 в BF16 — около 1, prefill на 1000 токенов — около 1000.. Сравним её с отношением — точкой перегиба (ridge point). Если , операция ограничено памятьюограничено памятью (memory-bound)EN memory-boundОперация, которая дольше ждёт данные из памяти, чем считает. Ускоряется, если читать меньше байт (квантование, GQA, MLA) или делать больше работы на каждый прочитанный байт (батчинг).: вычислитель простаивает в ожидании данных. Если — ограничено вычислениямиограничено вычислениями (compute-bound)EN compute-boundОперация, в которой вычислитель загружен полностью, а память успевает подвозить данные. Ускоряется только более быстрым железом или меньшим числом операций.: память успевает, вычислитель загружен.
Это и есть модель rooflineмодель roofline («крыша»)EN roofline modelДостижимая производительность = min(пик FLOP/с, интенсивность × пропускная способность памяти). Точка перегиба (ridge point) = пик / пропускная способность; у H100 около 295 FLOP/байт.: достижимая производительность равна . График похож на крышу — наклонный скат (упор в память), затем ровный конёк (упор в вычисления). Для обучения вы уже применяли её в уроке 5.7.1; здесь — для инференса.
xychart-beta title "Roofline: достижимые TFLOPS в зависимости от интенсивности" x-axis "FLOP на байт" ["1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024"] y-axis "TFLOPS (BF16)" 0 --> 1000 line [3.4, 6.7, 13.4, 26.8, 53.6, 107.2, 214.4, 428.8, 857.6, 989, 989] line [0.7, 1.4, 2.9, 5.7, 11.5, 22.9, 45.9, 91.8, 97.5, 97.5, 97.5]
Характеристики популярных устройств (плотные BF16-операции тензорных ядер, без «маркетинговой» разреженности):
| Устройство | Память, ГБ/с | BF16, TFLOPS | Точка перегиба, FLOP/байт |
|---|---|---|---|
| RTX 4080 | 717 | 97.5 | 136 |
| RTX 4090 | 1008 | 165 | 164 |
| A100 80GB | 2039 | 312 | 153 |
| H100 SXM | 3350 | 989 | 295 |
| ПК, DDR5 в 2 канала | ~90 | — | — |
| EPYC, DDR4-3200 в 8 каналов | ~205 | — | — |
| EPYC 9004, DDR5-4800 в 12 каналов | ~460 | — | — |
Нижние три строки — не видеокарты, а обычная оперативная память: домашний ПК с двумя «каналами» памяти и серверные процессоры AMD EPYC, у которых каналов 8–12 (каждый канал — отдельная «дорога» к памяти, их пропускные способности складываются). Вычислительную мощность процессоров мы не указываем: для decode важна именно память. H100 SXM — серверная версия карты H100 для специальных плат.
Теперь посчитаем интенсивность фаз (веса в BF16, 2 байта на параметр):
Decode с одним пользователем делает 1 операцию на байт при точке перегиба 136–295: тензорные ядра больше 99% времени ждут память. Prefill промпта из 1000 токенов делает 1000 операций на байт — выше точки перегиба любого GPU из таблицы, то есть упирается в вычисления. А вот короткий промпт из 100 токенов на H100 (точка перегиба 295) ещё memory-bound: граница между фазами проходит не по названию, а по интенсивности.
Сколько токенов в секунду ждать
Заголовок раздела «Сколько токенов в секунду ждать»Раз decode упирается в память, его скорость при батче 1 оценивается одной формулой:
Пример. Qwen3-8B (8.2 млрд параметров) в BF16 весит 16.4 ГБ. На RTX 4080 с 717 ГБ/с выйдет не больше токенов/с. В 4-битном формате Q4_K_M (формат программы llama.cpp, разберём его в уроке 7.2.1; ≈4.9 бита на вес, файл около 5 ГБ) — токена/с. Вот почему квантование ускоряет генерацию: байт меньше — шаг короче.
Потолок скорости decode при батче 1 (токенов/с, только веса, без KV-кэша):
| Модель | Размер весов | DDR5, 2 канала | EPYC, 8 каналов | RTX 4080 | RTX 4090 | H100 |
|---|---|---|---|---|---|---|
| Qwen3-8B, BF16 | 16.4 ГБ | 5 | 12 | 44 | 61 | 204 |
| Qwen3-8B, Q4_K_M | 5.0 ГБ | 18 | 41 | 143 | 201 | 667 |
| Qwen3-32B, Q4_K_M | 20.1 ГБ | 4 | 10 | 36 | 50 | 167 |
| Llama 3 70B, 4.5 бита | 39.7 ГБ | 2 | 5 | 18 | 25 | 84 |
| Qwen3-30B-A3B, Q4_K_M | 2.0 ГБ активных | 44 | 101 | 355 | 499 | 1657 |
Реальные программы достигают 50–85% этого потолка: часть времени уходит на запуск ядер, синхронизацию и чтение
KV-кэша. Но порядок величин формула даёт верно, и это лучший способ заранее понять, «потянет» ли железо модель.
Как перейти от неё к числу карт под целый сервис (нагрузка, KV-кэш, батч, запас) — в «оценках на салфетке» урока
11.2.1; собрать такой калькулятор
можно в домашней работе s11-hw04-capacity.
MoE читает только активных экспертов. Последняя строка таблицы — модель смесь экспертовсмесь экспертов (MoE)EN mixture of experts (MoE) на 30.5 млрд параметров, из которых на токен работают 3.3 млрд (активные параметрыактивные параметрыEN activated (active) parametersСколько параметров MoE-модели реально участвует в обработке одного токена. «A22B» в названии Qwen3-235B-A22B — 22 млрд активных из 235 млрд.). Памяти ей нужно как 30B-модели, а при батче 1 читается и считается только 3.3B — скорость как у 3B-модели. Поэтому MoE так хороши для локального запуска, если хватает памяти. DeepSeek-V3 устроена так же: 671 млрд параметров, 37 млрд активных (урок 5.3.1).
Длинный контекст замедляет decode. На каждом шаге читается ещё и KV-кэш всего контекста. У Llama 3 8B на 32 тысячах токенов это 4.3 ГБ сверху к 16 ГБ весов — генерация медленнее примерно на 20%. При 128 тысячах кэш весит уже столько же, сколько модель, и скорость падает вдвое. Поэтому GQA, MLA и FP8-кэш не только экономят память, но и ускоряют генерацию.
Почему батчинг ускоряет
Заголовок раздела «Почему батчинг ускоряет»Пусть на сервере не один пользователь, а . На каждом шаге decode модель делает по одному токену для каждой последовательности: умножает не вектор, а матрицу на те же веса. Веса читаются один раз и служат всем. Операций в раз больше, а байт весов — столько же:
где — байт на параметр. Пока ниже точки перегиба, шаг длится почти столько же, сколько при , а токенов выходит в раз больше. Если бы на каждом шаге читались только веса, батч из 64 пользователей дал бы почти бесплатное 64-кратное ускорение.
Но есть подвох: KV-кэш батчинг не делит. У каждой последовательности свой контекст и свой кэш, и его надо прочитать целиком. Посчитаем по roofline для Llama 3 8B в BF16 на H100, контекст 2048 токенов у каждой последовательности (0.27 ГБ кэша на последовательность). Каждая строка считается так: байты шага = веса + × кэш одной последовательности; длительность шага = байты / 3350 ГБ/с; токенов/с = / шаг. Например, при : с, то есть 9.9 мс, и токенов/с.
| Батч | Шаг, мс | Всего токенов/с | На одного пользователя | Память: веса + кэш |
|---|---|---|---|---|
| 1 | 4.9 | 205 | 205 | 16.3 ГБ |
| 8 | 5.4 | 1 472 | 184 | 18.2 ГБ |
| 32 | 7.4 | 4 349 | 136 | 24.6 ГБ |
| 64 | 9.9 | 6 450 | 101 | 33.2 ГБ |
| 128 | 15.1 | 8 505 | 66 | 50.4 ГБ |
| 256 | 25.3 | 10 116 | 40 | 84.8 ГБ — не влезает в 80 ГБ |
Три вывода:
- Суммарная скорость (throughputthroughput (суммарная скорость сервиса)EN throughputСколько токенов в секунду сервер выдаёт всем пользователям вместе. Батчинг повышает throughput ценой роста TPOT у каждого пользователя.) выросла в 50 раз, а скорость для каждого пользователя упала всего в 5 раз. Именно так облачные провайдеры делают токены дешёвыми.
- Даже при батче 256 шаг упирается в память, а не в вычисления: растёт чтение KV-кэша. Для одних только весов переход в compute-bound случился бы при (точка перегиба H100), но кэш его отодвигает.
- Батч ограничен объёмом памяти: при 256 пользователях кэш уже не помещается. Сократили кэш вдвое (FP8, GQA, MLA) — примерно вдвое больше пользователей на одной карте и заметно дешевле токен. Это экономика, на которой DeepSeek начала ценовую войну 2024 года (Китайская линза).
Сколько памяти уходит на KV-кэш
Заголовок раздела «Сколько памяти уходит на KV-кэш»Батч ограничен не только вычислениями, но и памятью: у каждого запроса свой KV-кэш, и он растёт с длиной контекста. Выберите в калькуляторе модель, поставьте длину контекста 32 768 и батч 16 и сравните результат с памятью вашей карты (32 ГБ). Потом переключите точность на FP8 и посмотрите, сколько запросов теперь помещается. Именно поэтому серверы вроде vLLM управляют KV-кэшем как памятью операционной системы (урок 7.1.2).
Метрики: TTFT, TPOT, throughput
Заголовок раздела «Метрики: TTFT, TPOT, throughput»Скорость инференса нельзя описать одним числом. Различают три:
- время до первого токенавремя до первого токена (TTFT)EN time to first token (TTFT)Сколько пользователь ждёт первое слово ответа: очередь + prefill всего промпта. Растёт с длиной промпта. — время до первого токена: ожидание в очереди плюс prefill. Растёт с длиной промпта. Именно его вы ощущаете как «модель задумалась».
- время на выходной токенвремя на выходной токен (TPOT)EN time per output token (TPOT)Средняя пауза между токенами ответа после первого — длительность шага decode. 1 / TPOT — скорость «печати» для одного пользователя. — средний интервал между следующими токенами, то есть длительность шага decode. Скорость «печати» для одного пользователя — .
- throughput — сколько токенов в секунду сервер выдаёт всем пользователям вместе.
Полное время ответа из токенов:
Вернёмся к примеру из начала: 8B-модель на RTX 4090, промпт 2000 токенов. Prefill — около FLOPs. При 165 TFLOPS и загрузке около 50% выходит с. TPOT — около 20 мс (50 токенов/с). Ответ из 500 токенов придёт за с.
Метрики тянут в разные стороны. Больше батч — выше throughput, но выше и TPOT у каждого. Длинный prefill чужого запроса задерживает шаги decode всех остальных. Сервисы задают целевые уровни (SLO), например «TTFT меньше 2 с, TPOT меньше 50 мс», и ищут максимальный throughput, при котором эти уровни соблюдаются. Как именно — в следующем уроке, а нагрузочный тест собственного LLM-сервиса против SLO — в уроке 8.4.3.
Практика
Заголовок раздела «Практика»Задание в браузере: калькулятор скорости генерации
Заголовок раздела «Задание в браузере: калькулятор скорости генерации»Соберите калькулятор, который по паспортным данным GPU и модели предсказывает размер весов и кэша, точку перегиба, скорость decode при разном батче, время prefill и максимальный батч. Потом проверьте им таблицы этого урока.
# Калькулятор скорости генерации — оценка «на салфетке» по roofline-модели.
# Единицы: память — в ГБ (1 ГБ = 1e9 байт), пропускная способность — в ГБ/с,
# пиковая производительность — в TFLOPS (1e12 операций в секунду), параметры — в миллиардах.
GPUS = {
# имя: (пропускная способность памяти, ГБ/с; плотные BF16 TFLOPS тензорных ядер)
"RTX 4080": (716.8, 97.5),
"RTX 4090": (1008, 165.2),
"A100 80GB": (2039, 312),
"H100 SXM": (3350, 989),
}
def weights_gb(params_b, bits):
"""Сколько ГБ занимают веса модели.
params_b — число параметров в миллиардах, bits — бит на параметр (16 для BF16, 4 для INT4).
weights_gb(8, 16) == 16.0; weights_gb(70, 4) == 35.0
"""
# TODO: ваш код
...
def kv_cache_gb(layers, kv_heads, head_dim, context, batch=1, bytes_per_value=2):
"""Размер KV-кэша в ГБ: 2 (K и V) · слои · KV-головы · размер головы · длина · батч · байт на число.
Llama 3 8B (32 слоя, 8 KV-голов, голова 128) на 8192 токенах в BF16 — около 1.074 ГБ.
"""
# TODO: ваш код
...
def ridge_point(bandwidth_gbs, peak_tflops):
"""«Точка перегиба» roofline: сколько FLOP на байт нужно, чтобы упереться в вычисления.
ridge = пиковые FLOP/с / байт/с. Для H100 SXM: 989e12 / 3350e9 ≈ 295.2 FLOP/байт.
"""
# TODO: ваш код
...
def decode_throughput(params_b, bits, bandwidth_gbs, peak_tflops, batch=1, kv_gb_per_seq=0.0):
"""Скорость шага декодирования для батча из batch последовательностей.
За один шаг каждая из batch последовательностей получает один новый токен. Для этого нужно:
* прочитать из памяти все веса один раз (их делят все последовательности батча)
и KV-кэш каждой последовательности: байты = веса + batch · kv_gb_per_seq;
* выполнить 2 · N · batch операций (N — число параметров).
Время шага = max(время чтения памяти, время вычислений) — roofline.
Для MoE передавайте в params_b число АКТИВНЫХ параметров.
Возвращает кортеж (токенов/с суммарно, токенов/с на одну последовательность).
"""
# TODO: ваш код
...
def prefill_seconds(params_b, prompt_tokens, peak_tflops, mfu=0.5):
"""Время prefill: 2 · N · T операций при доле mfu от пиковой производительности.
prefill_seconds(8, 4000, 989, 0.5) ≈ 0.129 с
"""
# TODO: ваш код
...
def max_batch(memory_gb, params_b, bits, kv_gb_per_seq):
"""Сколько последовательностей поместится в память одновременно (целое число).
Сначала в память кладём веса, всё остальное отдаём под KV-кэш.
Если веса не помещаются — 0.
"""
# TODO: ваш код
...
# Проверьте себя кнопкой «Запустить»:
print(weights_gb(8.03, 16), kv_cache_gb(32, 8, 128, 8192))
print(ridge_point(*GPUS["H100 SXM"]))
print(decode_throughput(8.03, 16, *GPUS["RTX 4090"]))
print(prefill_seconds(8, 4000, 989), max_batch(80, 8.03, 16, 0.268))
Локально: почувствуйте memory-bound своими руками
Заголовок раздела «Локально: почувствуйте memory-bound своими руками»Возьмём один «слой» — матрицу — и будем умножать на неё батчи разного размера. При батче 1 это ровно шаг decode: прочитать все веса ради одного вектора. Код работает на CPU (нужен только PyTorch):
# Почему батчинг ускоряет: один и тот же «слой» 8192×8192 на батчах разного размера (CPU)import time
import torch
torch.manual_seed(0)d = 8192W = torch.randn(d, d) # 8192² чисел × 4 байта = 268 МБ — больше кэша любого процессораprint(f"Веса слоя: {W.numel() * 4 / 1e6:.0f} МБ, потоков: {torch.get_num_threads()}")
def bench(B, repeats=5): x = torch.randn(B, d) x @ W.T # прогрев t0 = time.perf_counter() for _ in range(repeats): x @ W.T return (time.perf_counter() - t0) / repeats
print(" батч время, мс токенов/с ГФЛОП/с ГБ/с (веса)")for B in [1, 4, 16, 64, 256]: t = bench(B) flops = 2 * B * d * d # умножение + сложение на каждый вес и каждый токен print(f"{B:5d} {t * 1e3:9.2f} {B / t:9.0f} {flops / t / 1e9:7.1f} {W.numel() * 4 / t / 1e9:6.1f}")Пример вывода на слабой облачной машине с 4 потоками (у вас числа будут больше, но картина та же):
Веса слоя: 268 МБ, потоков: 4 батч время, мс токенов/с ГФЛОП/с ГБ/с (веса) 1 44.76 22 3.0 6.0 4 60.69 66 8.8 4.4 16 96.00 167 22.4 2.8 64 152.93 418 56.2 1.8 256 381.70 671 90.0 0.7Как читать: при переходе от батча 1 к батчу 4 время выросло лишь в 1.4 раза, а «токенов» стало вчетверо больше. До батча 64 время растёт намного медленнее батча — это зона memory-bound. От 64 к 256 время выросло уже в 2.5 раза при вчетверо большем батче: вычислитель начинает загружаться, и «бесплатный» батч заканчивается. Столбец «ГБ/с» при батче 1 — это реальная пропускная способность памяти вашей машины на такой операции. Сравните её с паспортной.
Проверь себя
Заголовок раздела «Проверь себя»- Генерация состоит из двух фаз. Prefill обрабатывает промпт одним проходом и упирается в вычисления; decode выдаёт по токену за проход и упирается в пропускную способность памяти.
- Арифметическая интенсивность (FLOP на байт) против точки перегиба железа (у H100 ≈ 295) показывает, что ограничивает операцию. Decode с батчем 1 — около 1 FLOP/байт.
- Потолок скорости decode: токенов/с ≈ пропускная способность / байт за токен. Квантование, MoE, GQA и MLA уменьшают байты и потому ускоряют генерацию.
- Батчинг делит чтение весов между пользователями и умножает throughput, но KV-кэш у каждого свой — он ограничивает и скорость, и число пользователей на GPU.
- Метрики: TTFT (очередь + prefill), TPOT (шаг decode) и throughput. Сервер ищет баланс между ними.
Так об этом спрашивают на собеседовании: «Почему decode упирается в память? Сколько токенов в секунду даст Qwen3-8B на одной RTX 4080?» — разбор с батчами и KV-кэшем в задаче 2 урока 11.3.3.
Дальше: как vLLM и SGLang выжимают максимум из этой физики — непрерывный батчинг, страничный KV-кэш, префикс-кэш, спекулятивное декодирование и раздельные prefill и decode у Kimi и DeepSeek.