вспомнить тот факт, что никакие ЯМ не могут правильно складывать и умножать любые наперед заданные числа без использования сторонних средств Т.е. ЯМ не могут на любой выборке из сети обучиться и выработать универсальную процедуру сложения и умножения чисел на конечном числе примеров, которые в них имеются. То чему могут обучиться среднестатистические школяры уже в начальных классах. Когда-то и такие числа могут быть востребованы, и что это будет за ИИ, который не может правильно обучиться достаточно простой для человеческого интеллекта задаче обобщения?
По вашему утверждению выходит, что школяр способен умножить 15580146 на 550624703 без калькулятора и не ошибиться ни в одной из цифр.
Многие ошибочно считают, что модель это большая коробка, где внутри она думает, размышляет как лучше ответить и на выходе просто выдает слова. Модель называется моделью не просто так, это не база данных, не коробка с мозгом, это моделирование какого-то процесса.
Люди собирали статистику, им больше доверия. Если проверять, то корректно.
Проверять корректно это не сказать "умножь 2 гигантских числа и выдай ответ".
Недавнее золото на олимпиаде от LLM показало, что модель способна делать куда более сложные вычисления, без сторонних средств, нужно "всего-лишь" 10 страниц детальных инструкций в системный промпт. Сам промпт уже выкладывали.
Для корректной проверки утверждения "ЯМ не могут на любой выборке из сети обучиться и выработать универсальную процедуру сложения и умножения чисел на конечном числе примеров" пойти хотя бы похожим путём:
### Выведи правило умножения чисел по шагам.
### Выведи правило складывая чисел по шагам.
### Умножай числа по всем шагам правила умножения.
### Cкладывай числа по всем шагам правила сложения.
### Если число большое, делай разбивку на большее количество шагов.
Умножь 15580146 и 550624703. Финальный ответ напиши в \boxed{}
Модель приступает к умножению
Модель приступает к сложению
8578776499523438 - ответ модели 8578813263946638 - правильный ответ
Ответ не правильный, хотя в общих чертах выглядит похоже, ошибка в нескольких разрядах. Тут нет проблемы с тем, что модель не может вывести универсальную процедуру, процедура выведена верно, следование процедуре тоже верное. Проверим вручную, где возникла ошибка.
Промежуточный результат умножения. С учётом сдвига, все числа правильные:
Внимательно приглядевшись, видно, что проблема тут начинается на 3 разряде. Вместо двух 0, добавлен 1 ноль. Если вручную сложить все числа с правильным добавлением 0 разрядов, то ответ будет правильный.
И это проблема не модели, а проблема токенизатора.
Даже если у LLM будут рекурсивные вычисления внутри, ещё до вывода наружу, это не поможет умножать столь гигантские числа без ошибок в паре цифр просто по статистике, потому что остается фактор температуры и токенизатора - внешние для модели факторы. Это как оценивать возможности модели по тому, может ли она подсчитать количество r в strawberry, игнорируя фактор токенизатора.
Снизим температуру до 0 и попробуем рассказать модели, что у неё есть проблема токенизатора. Во всех случаях запуск локально на модели Qwen3-Coder-480B-A35B-Instruct-UD-Q2_K_XL, каждый раз новый чистый чат, чтобы не было фактора кэширования или ещё чего-то.
Изменим промпт так:
### Выведи правило умножения чисел по шагам.
### Выведи правило складывая чисел по шагам.
### Умножай числа по всем шагам правила умножения.
### Cкладывай числа по всем шагам правила сложения.
### Если число большое, делай разбивку на большее количество шагов.
Учти, что у тебя проблема с токенизатором, когда ты добавляешь разрядные 0, может быть ошибка с их количеством. Тебе нужно придумать другой способ сложения после умножения.
Умножь 15580146 и 550624703. Финальный ответ напиши в \boxed{}
Модель считает с учётом проблемы токенизатора
8578813263946638 - ответ модели 8578813263946638 - правильный ответ
Это помогло избавиться от двух внешних факторов и теперь результат правильный.
Это не означает, что модель всегда будет считать правильно даже так, это чтобы показать, что "если проверять, то корректно", то внешние от модели факторы играют большую роль.
Чтобы это понять не нужно даже проводить специальных исследований, а вспомнить тот факт, что никакие ЯМ не могут правильно складывать и умножать любые наперед заданные числа без использования сторонних средств, см. 1, 2 с примерами. Т.е. ЯМ не могут на любой выборке из сети обучиться и выработать универсальную процедуру сложения и умножения чисел на конечном числе примеров, которые в них имеются. То чему могут обучиться среднестатистические школяры уже в начальных классах.
По 1 ссылке как раз противоположное говорится, что модели могут это сделать. По 2 ссылке не корректный эксперимент, поэтому там даже 5-значные числа не складывались, промпт автора требовал в ответ только число.
Более правильный промп был бы такой, который при этом легко парсить:
Ты получаешь на вход арифметическое выражение.
Проведи все необходимые вычисления и в конце напиши ответ в блоке \boxes{}.
Само выражение:
5234535646 * 654 + 5243564363456456
Ответ 5246987749768940 правильный
Конечно LLM это не калькулятор, на больших числах точность не будет 100% в любом случае, но вывести какие-то правила и следовать им они могут, могут "прикинуть" ответ, если числа большие, чтобы потом сделать более точные вычисления:
Пример деления больших чисел
62 правильный ответ
И так как модель это не калькулятор, она может складывать и гигантские BigInt числа, которые не укладываются в стандартный диапазон js чисел или калькулятора. Модель будет долго высчитывать это по шагам по правилам сложения и в итоге выдаст правильный ответ:
Для запуска нормальной модели нужна видео карточка за 1500$ и памятью на 32гига. Нормальные модели начинаются от 30B.
Для запуска 30B из статьи нужно всего 2 гб VRAM и будет работать на скорости 10+ t/s.
В статье Qwen3-Coder-30B, но полное название модели Qwen3-Coder-30B-A3B. A3B - означает, что это MoE модель, где на каждый токен активных параметров всего 3B.
В llama.cpp есть оптимизация для работы с MoE моделями через --override-tensor exps=CPU или просто --cpu-moe. Этот параметр отправляет MoE-веса на CPU, а тензоры внимания и общие ffn тензоры всех слоев на GPU. Это работает так, что даже настоящую большую DeepSeek R1 671B можно запустить на игровом ПК и особо не заскучать дожидаясь ответов.
Несколько дней назад в LM Studio 0.3.23 добавили возможность активировать этот параметр. Во время загрузки модели нужно включить "Force MoE expert weights onto CPU" и выставить полную выгрузку всех слоёв несмотря на предупреждение о том, что памяти не хватит. Flash Attention тоже стоит включить, это сэкономит много памяти контекста.
LM Studio 0.3.23
Нужно всего 2 Гб VRAM + контекст. Например, на 32к контекста потребуется +2 Гб. Скорость работы на 4060ti + i7-14700 получилась 14 t/s.
LM Studio Qwen3-Coder-30B-A3B-Instruct-Q4_K_M.gguf
Скорость можно повысить, если воспользоваться параметром --n-cpu-moe и заполнить VRAM до отказу, сколько есть. Этого параметра пока нет в LM Studio, поэтому нужно запускать llama.cpp напрямую. llama-server создает и веб-клиент и openai completions api, как и LM Studio Local Server, поэтому для работы с Continue ничего не изменится.
И на таких маленьких моделях лучше брать квант побольше, не тот, что в LM Studio предлагается по умолчанию. По умолчанию там Q4_K_M, лучше взять Q5_K_M или сразу Q6_K. Ещё лучше обратить внимание на имя авторов квантов и поискать среди них Unsloth, у них выбрать кванты с припиской XL, это динамическое квантование UD, при том же размере дает выше качество.
Сейчас много разных MoE-моделей. Можно запустить и openai_gpt-oss-120b, там тоже всего 5.1B активных параметров, для запуска нужно 4гб VRAM и 62гб RAM. Скорость просядет, так как объем модели куда выше, и уже много тензоров считается на CPU, но всё еще приемлемая.
Но llama.cpp не умеет делать веб поиск, зачем же тогда там зпускать эту модель? Или есть уже коммит в этом проекте для поддержки режима веб поиска?
llama.cpp запускает openai compatiable api сервер, который можно запускать даже без встроенного веб-клиента. Поиск сейчас делают через вызов внешних инструментов по протоколу MCP.
Если запускать llama.cpp напрямую, то подключить можно любой клиент, в котором есть поддержка и MCP, и возможность подключаться к произвольному openai api серверу, например, Open WebUI или Cherry Studio, и даже сам Jan умеет подключаться к созданному серверу.
Напрямую запускать llama.cpp имеет смысл, например, можно указывать произвольный путь к модели, но чаще потому, что клиенты не поддерживают все параметры запуска, например --cpu-moe, через который на 1 gpu можно запускать тяжелые модели с ускорением в 2 раза. Или если нет возможности указать флаг --no-context-shift, например, в LM Studio нет такой возможности, то она зациклится в бесконечном поиске, каждый раз срезая начало, чтобы этого избежать нужно сильно увеличить размер контекста.
Модель Jan-v1 обучена вызывать инструменты под названием web_search и visit_tool, чтобы эти инструменты появились, нужен MCP сервер serper. В Jan нужно включить "экспериментальные функции", появится дополнительный пункт MCP Servers, и там будет serper. Включив его и введя бесплатный ключ с сайта serper появятся 2 инструмента.
В других клиентах тоже можно добавить, распространенный способ подключения MCP через json формат. Например, в LM Studio нажав Install -> Edit mcp.json:
После установки инструмент появится в списке. Это работает не только с моделью Jan-V1, по сути это работает с любой моделью, которая уже знает про MCP, только качество не обязательно будет на уровне.
И через эти инструменты можно не только гуглить, можно, например, кидать сразу ссылку и просить сделать пересказ:
Пользователи Firefox на Reddit предположили, что проблема кроется в использовании формата Open Neural Network Exchange (ONNX) от Microsoft вместо более эффективного GGUF.
Вообще, у Firefox локально работает переводчик с английского на русский, весит мало, 30мб, работает быстро, качество сойдет - тоже использует onnx. В целом onnx хорошо заточен на работу на CPU-only.
Так как для группировки вкладок это локальная модель тоже, то это либо создание первичной семантической базы, после чего жор процессора спадет, либо баг. По крайней мере пишут, что нужное для исправления есть: https://bugzilla.mozilla.org/show_bug.cgi?id=1982278
В v8 есть 3 уровня запуска кода: как есть, первый быстрый оптимизатор, второй тяжелый jit-оптимизатор. В общем "прогрев" кода.
Время затраченное на работу оптимизатора просто суммируется к времени работы 1 цикла, если блоки кода поменять местами, картина изменится на противоположную (только надо учесть, что в одном случае есть Math.random, а во втором нет).
Вообще, из-за этих оптимизаторов и сборки мусора, делать эти микробенчмарки очень тяжело, выше комментатор правильно написал про тонкости.
На хабре есть статья про мономорфизм и полиморфизм прям от одного из разработчиков V8, там всё это куда более детально рассказано: https://habr.com/ru/articles/303542/
Минимально нужно хотя бы делать 3 холостых прогона, делать паузу на сколько-то секунд, сделать ещё прогон, снова пауза, и только после этого можно делать финальный прогон, где цифры уже будут ближе к реальности. Если выполнить такой ритуал, дать всем оптимизаторам время на выполнение, то разница будет ожидаемо никакой:
const delay = ms => new Promise(d => setTimeout(d, ms))
function getA(obj) { return obj.a }
function run1() { let arr1 = [] console.time("ordered"); for (let i = 0; i < 1e7; i++) { const o = makeObjOrdered(); arr1.push(o) } console.timeEnd("ordered"); console.log(arr1.slice(0,10)) }
function run2() { let arr2 = [] console.time("random"); for (let i = 0; i < 1e7; i++) { const o = makeObjRandom(); arr2.push(o) } console.timeEnd("random"); console.log(arr2.slice(0,10)) }
Однако именно эта 15% просадка — это и есть цена за разные Hidden Classes и полиморфный IC, которая становится заметна при большом количестве вызовов
10 миллионов вызовов, куда уж больше. И в реальном проекте не будет даже 15% разницы, как только пройдет jit-оптимизатор, разница будет смазана до нескольких процентов, которые будут не важны, так как основным тормозом будет i/o, который съест все эти микрооптимизации. Эти микрооптимизации работают только в таких бенчмарках с гигантскими циклами.
В 2016 это может и было актуально, когда вышла статья Убийцы оптимизации, на данный момент все эти деоптимизации уже не актуальны, а сами разработчики V8 говорят, что пишите как вам удобно.
В моём примере была гораздо сильнее — из-за мега-морфного кеша и деоптимизаций.
В вашем случае разница потому, что в 1 случае оптимизатор просто выкинул цикл вообще, поэтому и получилось 5 ms.
Не проблема создать пример, когда ordered будет куда медленнее, чем random:
Код 1
function makeObjOrdered() {
return { a: 1, b: 2, c: 3 };
}
function makeObjRandom() {
return Math.random() > 0.5 ? { a: 1, b: 2, c: 3 } : {o: 3, a: 1, b: 2}
}
let arr1 = []
console.time("ordered");
for (let i = 0; i < 1e7; i++) {
const o = makeObjOrdered();
arr1.push(o)
}
console.timeEnd("ordered");
console.log(arr1.slice(0,10))
let arr2 = []
console.time("random");
for (let i = 0; i < 1e7; i++) {
const o = makeObjRandom();
arr2.push(o)
}
console.timeEnd("random");
console.log(arr2.slice(0,10))
ordered: 411.947ms random: 251.125ms
И в вашем примере нет ни мега-морфизма, ни даже полиморфизма, так как вы не сделали функцию, которая работает с объектом, и на вход функция как раз должна получать объекты с разным порядком свойств, вы же просто создаете объект и ни как его не используете.
Чтобы увидеть работу более тяжелого jit-оптимизатора, который подключается после прогона функции несколько раз, прогоните 3-4 цикла, и у вас уже не будет никакой разницы в итоге, кроме погрешности:
Код 2
function makeObjOrdered() {
return (Math.random() > 0.5) ? {a: 1, b: 2, c: 3} : {a: 1, b: 2, c: 3}
}
function makeObjRandom() {
return (Math.random() > 0.5) ? {a: 1, b: 2, c: 3} : {o: 3, a: 1, b: 2}
}
function getA(obj) {
return obj.a
}
for(let i = 0; i < 3; i+=1) {
const arr1 = []
console.time("ordered")
for (let i = 0; i < 1e7; i++) {
const o = makeObjOrdered()
arr1.push(getA(o))
}
console.timeEnd("ordered")
console.log(arr1)
const arr2 = []
console.time("random")
for (let i = 0; i < 1e7; i++) {
const o = makeObjRandom()
arr2.push(getA(o))
}
console.timeEnd("random")
console.log(arr2)
}
Мы видим, что функция с разным порядком свойств (и разными Map) работает значительно медленнее, а не с небольшой разницей в пару пунктов. Это говорит о том, что разница связана именно с перестройкой скрытых классов и ухудшением IC, а не с накладными расходами
Если в равные условия поставить и не давать оптимизатору пропустить цикл, то:
function makeObjOrdered() {
return (Math.random() > 0.5) ? {a: 1, b: 2, c: 3} : {a: 1, b: 2, c: 3}
}
function makeObjRandom() {
return (Math.random() > 0.5) ? {a: 1, b: 2, c: 3} : {o: 3, a: 1, b: 2}
}
const arr1 = []
console.time("ordered")
for (let i = 0; i < 1e7; i++) {
const o = makeObjOrdered()
arr1.push(o.a)
}
console.timeEnd("ordered")
console.log(arr1)
const arr2 = []
console.time("random")
for (let i = 0; i < 1e7; i++) {
const o = makeObjRandom()
arr2.push(o.a)
}
console.timeEnd("random")
console.log(arr2)
Старшая 120b MXFP4 запускается на 5060ti16+64Гб ОЗУ 10т/с с 8 слоями в видеопамяти.
gpt-oss-120b это MoE модель размером 120B, но для каждого нового токена используется только 5.1B активных параметров, которые постоянно меняются. Выгружая 8 слоев из 37 в видеопамять, это 14гб VRAM, то не все активные параметры попадают в эту VRAM, то есть VRAM не используется на каждом шагу, лишь эти 8 слоев которые выборочно могут попасть, а могут не попасть в список активных параметров. Это главное отличие от Dense-моделей, где каждый слой участвует в вычислениях на каждом шагу.
Для MoE сейчас используют более эффективный способ заполнить эти 14гб, куда сильнее ускоряя работу модели. Нужно выгрузить тензоры внимания со всех слоев в VRAM, а MoE тензоры оставляете на CPU, тензоры внимания каждого слоя нужны во время каждого шага, поэтому вы используете VRAM для каждого токена, за счет этого получается ускорение.
GPU 4060ti 16gb, то есть слабее чем 5060ti, также 8 слоев в видеопамяти, используется 14гб: .\llama-server.exe -m "openai_gpt-oss-120b-MXFP4.gguf" -fa -ngl 8
7.6 t/s
Используем новый подход, добавляем параметр --cpu-moe и выгружаем все 37 слоев (для удобства указано 99): .\llama-server.exe -m "openai_gpt-oss-120b-MXFP4.gguf" -fa --cpu-moe -ngl 99
13.7 t/s
Модель работает почти в 2 раза быстрее, при этом использует всего 3гб VRAM, вместо 14гб.
Можно засунуть целые слои, чтобы заполнить те же 14гб. Для этого есть новый параметр --n-cpu-moe X, количество moe-слоев которые будут выгружена на CPU, остальное останется на GPU. Начиная от полного числа слоев, 37 в данном случае, число надо уменьшать вниз, пока хватает памяти, для 14гб это будет 28 слоев: .\llama-server.exe -m "openai_gpt-oss-120b-MXFP4.gguf" -fa --n-cpu-moe 28 -ngl 99
16 t/s
Было 7.6 t/s, стало 16 t/s, скорость в 2.1 раза выше, чем была при том же расходе VRAM.
--cpu-moe и-cmoe это синонимы для -ot exps=CPU или --override-tensor=CPU, поэтому можно встретить и такие параметры. Сейчас это не применить в LM Studio, они используют движок llama.cpp, но не добавили возможно указать эти параметры, поэтому запуск llama-server из состава llama.cpp.
Вот именно тот факт что при плохой draft модели получается фигня и показывает что результат ухудшается но в самом сложном для отлова варианте. Драфт модель может предложить токен, близкий по вероятности к верному, но не лучший.
Это на столько редкие и не критичные события, что их в 99% случаях даже нет смысла учитывать. Если она сгенерирует не правильный вариант - это тоже самое, что оригинал сгенерировал выше не правильный вариант.
То, что выбор черновой модели важная часть, это да. Для той же 235B лучше взять 4B вместо 0.6B, скорость и процент принятия будет куда лучше.
Модели в целом не идеальны, особенно квантованные, они на пустом месте могут выдать рандомный ответ, и небольшие редкие искажения черновика не сильно повлияют на итоговый результат. Ускорение оправдано, 4 t/s или 7 t/s это ощутимая разница.
Тот сценарий я создал зная слабость модели, это просто, чтобы показать, что спекулятивное декодирование не 1 в 1 работает, и это можно учитывать, например, выбирая черновую модель получше, но критичного тут ничего нет. Достаточно вернуть температуру на 0.6, и даже с 16 токенами на черновой 0.6B модель генерирует правильный ответ 4 из 6 раз. Ускорение тоже продолжает работать.
Полагаю speculative decoding начинает плохо работать с большими значениями температуры.
Температура не играет роли. Первичная идея спекулятивного декодирования это завершать очевидные варианты, а не подменить собой основную модель.
Есть такая последовательность "И вот таким образом сп", черновая модель предложить ['сп', 'ек', 'у', 'ля', 'тив', 'ное', ' дек', 'од', 'ирование', ' это', ' большое', ' я', 'бл', 'око'], основная модель примет только 9 токенов, остальные отбросит, а что-то вроде <meta name="viewport" content="width=device-width, initial-scale=1.0"/> вообще сразу принимается целиком.
Тут нет сценария, что основная модель только проверяет, потому что основная модель отвергает почти 50% токенов, и оставляет только очевидные продолжения, это не влияет на её глубину понимания вопроса.
чисто поразмышлять, если основная модель только как проверочная, значит варианты генерации, основанные на более глубоком понимании задачи тупо ей будут не доступны, либо вероятность такого ответа значительно понизится
Не, никаких отличий от использования просто основной модели и модели с черновиком в плане глубокого понимания или вероятностей нет. Основная просто отвергнет все токены и сгенерирует ответ сама.
Просто задача с эмодзи сложная, и если основная модель плавает в решение, то черновая может повести её по пути, где решение не рабочее, но просто потому, что такая ветка могла бы возникнуть и при генерации основной моделью самой по себе.
Вот тот же запрос прям у оригинальной Qwen3-235B-A22B-2507 на их сайте. С первой же попытки модель не справилась:
То, что задача не простая, вот, например, что сгенерировал Gemini 2.5 Pro, эмодзи пропали, потому что вместо массива, он сделал строку и не правильно её нарезал:
но речь же не идет об одном токене, а сразу о нескольких, и их количество наверное фиксированное
Если речь про черновую последовательность, то её размер не фиксированный, есть максимальное и минимальное значение (от 0 до 16 по-умолчанию), генерация черновика прерывается как только токены перестают попадать в greedy семплинг значения --draft-p-min, по умолчанию 0.8.
Большая модель могла бы легко генерировать и 2, и 3, и 4 токена за раз, но чтобы сгенерировать токен в позиции n+1, нужно знать токен в позиции n, а у нас доступен только токен в позиции n-1. Поэтому модель вынуждена генерировать всё последовательно, шаг за шагом, хотя может параллельно высчитать сразу несколько токенов за тоже время.
Как-то делал демонстрацию на тему, что в llama.cpp есть параметр --parallel N, и можно почти без потерь, если хватает вычислительных ресурсов, генерировать даже 8 параллельных запросов:
Черновая модель на основе текущей последовательности генерирует продолжение, допустим последовательность из 8 новых токенов.
Большая модель получает эти 8 токенов и создает 8 гипотетических последовательностей, каждая на 1 токен больше. "Стартовая + n", "Стартовая + n + n+1" и т.д.
Большая модель запускает параллельные вычисления для этих 8 вариантов будущего, она параллельно высчитывает 8 новых токенов и если они совпадут с черновой, то те будут приняты.
Получаем 8 вариантов logits и начиная с 1 токена сравниваем вероятности большой модели и черновика, первое не соответствие и остальные отбрасываются, а начальные принимаются.
Так за счет параллельных вычислений мы получили больше новых токенов за плюс-минус время вычисления 1 токена и накладных расходов. Так что снижение --draft (синоним -draft-max) до 4 - это не только повышает шанс принятия нового токена, но и снижает количество параллельных вычислений, что на больших MoE-моделях, которые вычисляются на CPU, где ядер мало, дает дополнительный смысл.
На сколько может расходиться качество результата с использованием Speculative decoding?
Допустим, стартовая последовательность: Кот Черновая предлагает: любит есть колбасу и спать Для большой модели создается 5 последовательностей, которые считаются одновременно:
За 1 шаг готовы все 5 вариантов, но если большая считает, что "кот любит есть рыбу", то вместо +5 принятых черновых будет +2 и +1 токен от большой модели, итого +3 токена вместо +1.
P("любит" | "Кот") - это вычисление вероятности, то есть это не 1 в 1 совпадение токена черновой и большой, а вероятность с которой большая модель согласна с тем, что тут может быть такой токен. Поэтому, черновая модель может увести большую не туда, то есть её качество тоже играет роль, но на сколько расходится качество - нет точного ответа.
(по гуглил вроде пишут не падает).
Есть шанс заруинить. Допустим взяли черновую очень маленькую 0.6B, поэтому она качественно не очень хороша для большой модели, но в среднем работает. И тут может быть такая ситуация:
Модель: Qwen3-235B-A22B-Instruct-2507-UD-Q4_K_XL + Qwen3-0.6B-Q8_0 Температура: 0.01, top_k: 20, top_p: 0.95, min_p: 0.05 Запрос: Напиши эффект матрицы из эмодзи в одном index.html Выставил температуру минимально, результаты должны быть максимально близки.
Без черновика: 6 прогонов, каждый раз результат правильный. --draft 4: 6 прогонов, результат правильный. --draft 10: 6 прогонов, результат правильный 50 на 50. --draft 16: 10 прогонов, каждый раз результат не корректный.
Поэтому предсказывать значение по умолчанию в 16 токенов качественно не выгодно.
Модуль спекулятивного декодирования MTP, который из DeepSeek, а теперь ещё и из GLM 4.5, обучается вместе с основной моделью, поэтому такой вариант должен работать лучше, но поддержки MTP в llama.cpp пока нет. В отчете про DeepSeek (раздел 5.4.3. Multi-Token Prediction Evaluation) описывают, что в MTP предсказывают только 2 следующих токена, видимо как раз из-за лучшего качества результата.
Я не знаю на сколько из далека вам нужна теория, поэтому с самого начала, если что просто переходите на следующий пункт.
Про квантизацию
Веса модели это массив млрд цифр типа float. Стандартный размер float это 32-бита на вес, то есть это числа такого вида: 0.340282347234423412354675889478
Эти числа образуют собой матрицы чисел, матрицы (тензоры) перемножаются друг на друга и модель выдает результат. Фактически в модели нет ничего кроме этих чисел, там нет скрытых слоев знаний или слоев данных, просто так удачно сложились значения этих весов, что на выходе выходит что-то осмысленное плюс различные эмерджентные свойства. Подбор этих весов это и есть обучение модели.
Количество цифр после запятой велико, чем дальше они от начала, тем меньший вклад вносят в итоговый результат умножения, поэтому можно просто сократить их в 2 раза и перейти на float16. Это имеет почти нулевое влияние на качество, но увеличивает скорость инференса и скорость обучения в 2 раза. float16 уже выглядит так: 0.1245236426236046
16 бит на вес - цифр после запятой всё ещё достаточно, можно сократить их ещё в 2 раза и получить fp8, в fp8 как раз обучена DeepSeek, но обычно другие модели обучают до сих пор в f16.
Есть ещё всякие детали, вроде распределения мантисы и экспоненты, и то, что сейчас используют более точный bfloat16, вместо обычного float16, есть fp4 в nvidia 5000 серии и т.д. Чтобы квантование в fp4 или fp8 хорошо работало, устройство должно поддерживать операции с этим типом чисел, иначе нужны преобразования весов на лету до поддерживаемых типов.
Квантование в gguf работает не просто сокращением чисел после запятой, там в основном используются целочисленные типы int, а перегнать число с плавающей запятой в int - это само по себе снижение точности, в gguf же ещё происходит и объединение весов в суперблоки, из-за чего срезаются выбросы, если в суперблок попали веса не похожие на общие в среднем веса суперблока. В среднем если точности хватает, это не так важно, но чем агрессивнее квантование, тем больше будет потерь.
Ну это упрощенно, gguf позволяет сохранять веса и без квантования и квантовать любым другим способом, не только через суперблоки. Например, в ik_llama недавно добавили Trellis quants IQx_KT, работающие аналогично как в exl3, и они в целом дают лучшее качество при меньшем весе и большую скорость, но хорошо работают только на GPU, на CPU происходит просадка скорости.
Цифра рядом с Q - это то количество бит, которое будет затрачено на основные веса модели, а буквы XL, L, M, S - это на сколько выше будут квантованы важные тензоры, например, внимания, которые сильнее влияют на качество, чем основное тело модели. L - Large на 2-3 уровня выше, M - Medium на 1-2 уровня выше, S - Small на 0-1 уровня выше. Ну и XL - eXtra Lagre, там динамичное число и могут быть на много уровней выше.
Например, вначале в gguf было квантование прямо в лоб, был тип Q4_0 - это просто урезание весов до int4, или 4 bpw (bite per weight), или чуть позже Q4_1, оно чуть получше, но эти типы работали плохо и качество сильно падало.
Сам алгоритм квантования был изменен, качество стало выше, размер меньше. Эти кванты до сих пор везде используются как база, те самые популярные Q4_K_M или IQ4_XS. Q4 - это 4 бита на основные веса K - это скорее всего Kawrakow, просто отделяет Q4_0, Q5_0 кванты от Q4_K, Q5_K и т.д. M - Medium, значит важные веса на 2 уровня выше и квантуются как Q6_K. Супер важные тензоры остаются в fp32 или f16 (f16 - это общее название для bf16 и fp16).
В таких квантах тензоры квантованы не равномерно и суммарный BPW для Q4_K_M будет 4.82 BPW, при этом размере чуть больше чем у Q4_0, по качеству это выходит почти как 5 бит на вес, соответственно и качество ощутимо лучше.
IQ4_XS или IQ2_XSS - это уже более продвинутый тип квантования через матрицу важности imatrix, сами XS и XSS это уже именно алгоритмы квантования тензоров, количество S передает смысл сохраняемой точности, чем их больше, тем ниже точность.
В форке ik_llama есть новые кванты IQ2_KS и KSS, в данном случае K просто показывает, что это другой квант, у них точность выше чем у XS и XSS, а размер тот же.
В общем чем ниже число, тем ниже бит на вес, тем хуже качество модели. 8 бит на вес работает почти без потерь, квантование Q6_K - очень близко к без потерь, Q5_K_M процентов на 2-3% хуже, Q4_K_M процентов на 5% и т.д. IQ кванты лучше чем статичные K кванты, поэтому IQ4_XS весит меньше, но работает на уровне Q4_K_M. Кванты из ik_llama ещё лучше, поэтому могут весить ещё меньше при том же качестве.
В общем это примерное описание, не нужно воспринимать эту информация как истину, этого достаточно, чтобы примерно понимать что к чему, но везде могут быть исключения и прочие тонкости.
Между ними разница на треть по размеру дискового пространства, но и алгоритмы сильно разные. Качество тоже разнится?
Качество отличается, квантование это способ снизить размер за счет снижения качества. Весь смысл в том, сколько качества нужно потратить на каждый шаг снижения веса. Один из способов померить разницу - это замерить PPL или KLD, их описание есть в статье. Чем эти значения ниже, тем меньше отклонений от оригинальной модели.
DeepSeek R1 0528 ppl
Кроме общего представления, можно заметить, что новые кванты из ik_llama весят меньше, а PPL такой же как у более крупных квантов, квантованных старыми способами.
Например, новый квант IQ2_KS весит 196гб и имеет PPL 3.6378, а квант UD-Q2_K_XL весит 234гб и PPL 3.6062. Разницы почти нет, при этом размер на 38гб меньше. Новый квант IQ2_K_R4 имеет размер 220гб и PPL 3.5069, что ощутимо ниже чем у UD-Q2_K_XL, а вес меньше на 14гб.
Но разницы почти нет это довольно условное представление. Разницы почти нет на тексте wiki.test.raw, это узкий диапазон текстов на английском из википедии, а для другого языка или для вашего редкого сценария разница может быть куда более ощутимой.
Или "экономия диска" (и более быстрая загрузка?), а потребление VRAM одинаковое в итоге? Или действительно IQ2_M так хорош, что при экономии всего (и диска, и VRAM) даст сравнимое качество с Q3_K_L?
Потребление VRAM будет разное, чем сильнее квантование, тем меньше, по сути столько, сколько весит модель физически + размер контекста, столько и нужно VRAM или RAM. Веса распаковываются на лету, поэтому скорость работы разных квантов будет разной, так как везде разные алгоритмы, и поэтому эту скорость можно ускорить на той же пропускной способности памяти. По крайней мере для скоростей PP это заметная разница.
i-кванты обычно тяжелее по вычислительным ресурсам, чем статичные K-кванты. Я как-то давно делал простое сравнение, хотя размер по весу у моделей примерно одинаковый, но скорости отличаются. Новые IQK кванты легче старых i-квантов (в сравнении их нет):
Или вот IQ1M и IQ2_XXS - по размеру на диске разница не принципиальная. В 8GB VRAM ни одна не влезел, а в 12 любая (наверное). При этом IQ2, наверное, сильно лучше IQ1?
Про сильно лучше - это сомнительно, что сильно, но лучше это да, обычно чем больше цифра и какие бы ни были символы, тем лучше. И там разница почти 1гб, это можно дополнительно ~16к контекста вместить, это не так уж и мало, иногда как раз 0.5гб и не хватает и взять их не откуда.
Опять же, исключением для цифры может быть у разного типа квантования, например, старые из llama.cpp и новые из ik_llama.cpp. На графике выше видно, что новый IQ3_K_R4 на том же уровне как старый IQ4_XS, при этом новый весит на 33гб меньше, но это скорее исключение.
Speculative decoding (в RooCode для LM Studio есть такая галочка - хоть это и не в рамках подхода из данного поста)
В статье есть немного про спекулятивное декодирование, в DeepSeek оно называется MTP. Смысл в том, что нужна очень маленькая модель для черновиков, на которую не жалко потратить немного ресурсов, и они должны быть из одного семейства, иначе не заработает.
Сначала маленькая предлагает последовательность токенов, например 16 новых токенов, большая модель внедряет эти токены в свою последовательность и производит расчет, если вероятности совпадают, то большая принимает эти токены. Ускорение происходит за счет того, что большая модель не тратит время на генерацию шаг за шагом, а проверяет вероятности сразу для всех токенов параллельно. Сам алгоритм не так важен, главное, что за счет kv-кэша проверить токены быстрее, чем высчитать их с нуля.
Маленькая модель - это 0.6B, 1B или 1.5B, размеры 3B или 4B уже слишком большие, но и они могут быть полезны в редких ситуациях.
Ну и получается, что помимо большой модели (которую хочется максимальную по локальным ресурсам запустить) надо еще и мелкую стартовать? (в таком не вижу большого смысла, лоакльные ресурсы и так ограничены).
Берем gemma-3-27b UD-Q5_K_XL, она занимает 21гб. Берем gemma-3-1b Q4_K_M, она занимает 800мб. Черновой модели тоже нужен контекст, где-то суммарно будет 1.5гб VRAM, две модели влезают в 24гб + 22к контекста.
Qwen3-235B-A22B-2507-UD-Q4_K_XL, было 4.8 t/s, стало 7.1 t/s
Процент принятия 56%, было 4.8 t/s, стало 7.1 t/s, ускорение в 1.5 раза, вполне нормально, можно попробовать подобрать другую модель для черновика или квант этой модели. Но черновая модель не всегда помогает, может сделать и хуже.
По умолчанию черновик генерирует последовательность в 16 токенов, шанс что будет принята такая длинная последовательность не велика, а времени тратится и на проверку и на генерацию. Если модели очень сильно отличаются, то тут может помочь снизить длину последовательности. Параметром --draft-max 4 или --draft-max 8 можно сократить последовательность до 4/8 токенов.
Тут тот случай, когда для большой Qwen3-235B-A22B-2507 в качестве черновика лучше подойдет Qwen3-4B, урезав последовательность до 4 можно получить скорость 7.5 t/s, но правда это всего на 0.2 t/s больше, чем Qwen3-1.7B, с которой 7.3 t/s.
Возьмем огромную модель Qwen3-Coder 480B-A35B, черновая Qwen3-1.7B. Модели уже совсем разные по качеству ответов. Черновая модель с базовыми настройками делает хуже, уменьшение длины последовательности помогает и увеличивает процент принятия до 73%, хотя дает прирост скорости всего 5%, с 5.9 до 6.3 t/s.
Qwen3-Coder-480B-A35B-UD-Q2_K_XL
И ещё один вариант, когда модель не влезает в RAM и считывается с nvme. Снова огромная Qwen3-Coder 480B-A35B, в кванте UD-Q3_K_XL.
Qwen3-Coder-480B-A35B-UD-Q3_K_XL
Тут уже черновая модель помогает намного лучше, было 2.3 t/s, стало 4.2 t/s, с натяжкой можно пользоваться.
Тут тоже информация не на 100% верная, нужно перепроверять и тестировать.
Или они независимы и можно draft запустить через API где-то за копейки (модель легкая и супербыстрая), а финал локально доделать (не слишком долго, ибо только верификация)?
Задержки будут большими, да и нет такого функционала.
Можно использовать 2 GPU. Основную модель запустить на основной GPU, а черновую на второй карте. Не знаю, можно ли так сделать в LM Studio, в llama-server это делается командой: .\llama-server -m "gemma-3-27b-it-UD-Q5_K_XL.gguf" -ts 24,0 -ngl 99 -fa -md "gemma-3-1b-it-Q4_K_M.gguf" -ngld 99 -devd cuda1
Через -ts 24,0 запрещаем использовать вторую GPU для основной модели, через -devd cuda1 направляем draft модель на устройство cuda1. -ngl 99 выгрузить все слои основной модели, -ngld 99 выгрузить все слои черновой модели.
Вторая карта медленная 4060, поэтому ускорение слабое, но всё равно есть:
Модель large работает на мобильной 3070 8gb терпимо. Транскрибация правда довольно медленная получается, примерно 1 к 1 по времени. Т.е. час видео
Попробуйте whisper.cpp, должно быть быстрее на 3070. Модели в формате ggml (по сути тоже самое, что gguf) лежат тут: https://huggingface.co/ggerganov/whisper.cpp. У whisper ещё вышла модель whisper-large-v3-turbo, она быстрее и легче чем просто large-v3.
На 4060ti часовая лекция разбирается: – за 7 минут на large-v3 неквантованная, 4гб vram – за 5.1 минуты на large-v3 в кванте q5_0, 2.5гб vram – за 2.3 минуты на large-v3-turbo в кванте q8_0, 1.6гб vram.
4060ti, Andrei1980/whisper-large-rus-ggml неквантованная large v3, транскрипция часовой лекции за 7 минут
Qwen устроил неделю релизов. Суммарно они представили по хронологии:
Qwen3-235B-A22B-2507
Qwen3-235B-A22B-Thinking-2507
Qwen3-Qwen3-Coder-480B-A35B
Qwen Wan2.2 размером 5B и 14B (генерация видео из текста или из картинки)
Qwen3-30B-A3B-Instruct-2507
Qwen3-30B-A3B-Thinking-2507
Qwen3-Coder-30B-A3B-Instruct
Маленький Qwen3-Coder-30B-A3B они назвали Qwen3-Coder-Flash, для своего размера он показывает не плохие результаты.
Серия маленьких 30B-A3B моделей интересна не только тем, что их можно запустить даже на CPU с нормальной скоростью, так как активных параметров всего 3B, но и тем, что увеличили нативный контекст до 256к. Большая Qwen3-235B-A22B-Thinking-2507 сделала лучший пересказ книги, книга занимала 215к токенов и влезала целиком в 256к, теперь интересно на сколько хорош контекст у очень легковесной Qwen3-30B-A3B-Thinking-2507. Модель маленькая, и можно её сравнить с Gemma3 27B у которого 128к.
Результат Gemma3 уже есть в статье, он выдумывает и ошибается даже на 32к контексте. Поэтому тот же вопрос, что и для Gemma3 27B.
В какой момент была включена Roll Over Beethoven? Что произошло дальше?
Qwen3-30B-A3B-Thinking-2507-IQ4_K.gguf, ответ правильный
Сам ответ правильный, это при том, что в контекст загружена вся книга целиком, а не как в случае Gemma только 32к контекста, но последний момент с уходом в Лабиринт Смерти - технически правильно, но тут как будто бы это не к месту упомянуто, так как перед походом было много других событий.
Можно попробовать дать куда более сложное задание, пройти по всей книге и обобщить факты из разных эпизодов, из начала, середины и конца книги. Это частая проблема для многих моделей на SWA, так как скользящее окно контекста обычно всего 4к.
Ответь на 3 вопроса по книге:
Какие по ходу книги были ники у гг
Кто такая Вика, почему их две
Сколько раз гг встречался с Маньяком, а сколько раз с Человеком без Лица
Не забыл упомянуть про личность номер 7
Про игру отражений правильное замечание
Qwen3-30B-A3B-Thinking-2507-IQ4_K.gguf
Для такой маленькой модели ответы вполне хороши. Ошибка и путаница про встречи с Маньяком, часть правильно, часть спутана, части не хватает, но это как раз и есть самая сложная часть собрать по книге все встречи. После провала Gemma3 27B и Llama4 Scout 109B-A17B, казалось что маленькие модели не способы переваривать огромный контекст, но у Qwen3 30B-A3B на первый взгляд получилось куда лучше.
В предыдущем комментарии я слегка ошибся, для вмещения 256к контекста нужно не 8гб, а 23гб. Скорости на скриншотах низкие, так как почти всю память отдал под контекст, используя -ot exps=CPU даже тут, если контекст уменьшить, то скорости будут ожидаемо большими. Появились сборки бинарников ik_llama под Windows, бенчмарк скорости на них: https://github.com/Thireus/ik_llama.cpp
По вашему утверждению выходит, что школяр способен умножить 15580146 на 550624703 без калькулятора и не ошибиться ни в одной из цифр.
Многие ошибочно считают, что модель это большая коробка, где внутри она думает, размышляет как лучше ответить и на выходе просто выдает слова. Модель называется моделью не просто так, это не база данных, не коробка с мозгом, это моделирование какого-то процесса.
Проверять корректно это не сказать "умножь 2 гигантских числа и выдай ответ".
Недавнее золото на олимпиаде от LLM показало, что модель способна делать куда более сложные вычисления, без сторонних средств, нужно "всего-лишь" 10 страниц детальных инструкций в системный промпт. Сам промпт уже выкладывали.
Для корректной проверки утверждения "ЯМ не могут на любой выборке из сети обучиться и выработать универсальную процедуру сложения и умножения чисел на конечном числе примеров" пойти хотя бы похожим путём:
Модель приступает к умножению
Модель приступает к сложению
8578776499523438 - ответ модели
8578813263946638 - правильный ответ
Ответ не правильный, хотя в общих чертах выглядит похоже, ошибка в нескольких разрядах. Тут нет проблемы с тем, что модель не может вывести универсальную процедуру, процедура выведена верно, следование процедуре тоже верное. Проверим вручную, где возникла ошибка.
Промежуточный результат умножения. С учётом сдвига, все числа правильные:
Значит ошибка должна быть на этапе сложения. Посмотрим, что выдала модель:
Внимательно приглядевшись, видно, что проблема тут начинается на 3 разряде. Вместо двух 0, добавлен 1 ноль. Если вручную сложить все числа с правильным добавлением 0 разрядов, то ответ будет правильный.
И это проблема не модели, а проблема токенизатора.
Даже если у LLM будут рекурсивные вычисления внутри, ещё до вывода наружу, это не поможет умножать столь гигантские числа без ошибок в паре цифр просто по статистике, потому что остается фактор температуры и токенизатора - внешние для модели факторы. Это как оценивать возможности модели по тому, может ли она подсчитать количество r в strawberry, игнорируя фактор токенизатора.
Снизим температуру до 0 и попробуем рассказать модели, что у неё есть проблема токенизатора. Во всех случаях запуск локально на модели Qwen3-Coder-480B-A35B-Instruct-UD-Q2_K_XL, каждый раз новый чистый чат, чтобы не было фактора кэширования или ещё чего-то.
Изменим промпт так:
Модель считает с учётом проблемы токенизатора
8578813263946638 - ответ модели
8578813263946638 - правильный ответ
Это помогло избавиться от двух внешних факторов и теперь результат правильный.
Это не означает, что модель всегда будет считать правильно даже так, это чтобы показать, что "если проверять, то корректно", то внешние от модели факторы играют большую роль.
По 1 ссылке как раз противоположное говорится, что модели могут это сделать.
По 2 ссылке не корректный эксперимент, поэтому там даже 5-значные числа не складывались, промпт автора требовал в ответ только число.
Более правильный промп был бы такой, который при этом легко парсить:
Конечно LLM это не калькулятор, на больших числах точность не будет 100% в любом случае, но вывести какие-то правила и следовать им они могут, могут "прикинуть" ответ, если числа большие, чтобы потом сделать более точные вычисления:
Пример деления больших чисел
И так как модель это не калькулятор, она может складывать и гигантские BigInt числа, которые не укладываются в стандартный диапазон js чисел или калькулятора. Модель будет долго высчитывать это по шагам по правилам сложения и в итоге выдаст правильный ответ:
Ответ от LLM и результат в js совпадают
del
Для запуска 30B из статьи нужно всего 2 гб VRAM и будет работать на скорости 10+ t/s.
В статье Qwen3-Coder-30B, но полное название модели Qwen3-Coder-30B-A3B. A3B - означает, что это MoE модель, где на каждый токен активных параметров всего 3B.
В llama.cpp есть оптимизация для работы с MoE моделями через
--override-tensor exps=CPU
или просто--cpu-moe
. Этот параметр отправляет MoE-веса на CPU, а тензоры внимания и общие ffn тензоры всех слоев на GPU. Это работает так, что даже настоящую большую DeepSeek R1 671B можно запустить на игровом ПК и особо не заскучать дожидаясь ответов.Несколько дней назад в LM Studio 0.3.23 добавили возможность активировать этот параметр. Во время загрузки модели нужно включить "Force MoE expert weights onto CPU" и выставить полную выгрузку всех слоёв несмотря на предупреждение о том, что памяти не хватит. Flash Attention тоже стоит включить, это сэкономит много памяти контекста.
Нужно всего 2 Гб VRAM + контекст. Например, на 32к контекста потребуется +2 Гб. Скорость работы на 4060ti + i7-14700 получилась 14 t/s.
Скорость можно повысить, если воспользоваться параметром
--n-cpu-moe
и заполнить VRAM до отказу, сколько есть. Этого параметра пока нет в LM Studio, поэтому нужно запускать llama.cpp напрямую. llama-server создает и веб-клиент и openai completions api, как и LM Studio Local Server, поэтому для работы с Continue ничего не изменится..\llama-server.exe -m "D:\models\lmstudio-community\Qwen3-Coder-30B-A3B-Instruct-GGUF\Qwen3-Coder-30B-A3B-Instruct-Q4_K_M.gguf" --n-cpu-moe 16 -ngl 99 -fa -c 32768
Загружено 15гб VRAM, скорость выросла до 38 t/s.
И на таких маленьких моделях лучше брать квант побольше, не тот, что в LM Studio предлагается по умолчанию. По умолчанию там Q4_K_M, лучше взять Q5_K_M или сразу Q6_K. Ещё лучше обратить внимание на имя авторов квантов и поискать среди них Unsloth, у них выбрать кванты с припиской XL, это динамическое квантование UD, при том же размере дает выше качество.
Сейчас много разных MoE-моделей. Можно запустить и openai_gpt-oss-120b, там тоже всего 5.1B активных параметров, для запуска нужно 4гб VRAM и 62гб RAM. Скорость просядет, так как объем модели куда выше, и уже много тензоров считается на CPU, но всё еще приемлемая.
Для Jan-V1 нужно включить не browsermcp, а serper, получив бесплатный ключ.
llama.cpp запускает openai compatiable api сервер, который можно запускать даже без встроенного веб-клиента. Поиск сейчас делают через вызов внешних инструментов по протоколу MCP.
Если запускать llama.cpp напрямую, то подключить можно любой клиент, в котором есть поддержка и MCP, и возможность подключаться к произвольному openai api серверу, например, Open WebUI или Cherry Studio, и даже сам Jan умеет подключаться к созданному серверу.
Напрямую запускать llama.cpp имеет смысл, например, можно указывать произвольный путь к модели, но чаще потому, что клиенты не поддерживают все параметры запуска, например
--cpu-moe
, через который на 1 gpu можно запускать тяжелые модели с ускорением в 2 раза.Или если нет возможности указать флаг
--no-context-shift
, например, в LM Studio нет такой возможности, то она зациклится в бесконечном поиске, каждый раз срезая начало, чтобы этого избежать нужно сильно увеличить размер контекста.Модель Jan-v1 обучена вызывать инструменты под названием web_search и visit_tool, чтобы эти инструменты появились, нужен MCP сервер serper. В Jan нужно включить "экспериментальные функции", появится дополнительный пункт MCP Servers, и там будет serper. Включив его и введя бесплатный ключ с сайта serper появятся 2 инструмента.
В других клиентах тоже можно добавить, распространенный способ подключения MCP через json формат. Например, в LM Studio нажав Install -> Edit mcp.json:
После установки инструмент появится в списке. Это работает не только с моделью Jan-V1, по сути это работает с любой моделью, которая уже знает про MCP, только качество не обязательно будет на уровне.
И через эти инструменты можно не только гуглить, можно, например, кидать сразу ссылку и просить сделать пересказ:
Вообще, у Firefox локально работает переводчик с английского на русский, весит мало, 30мб, работает быстро, качество сойдет - тоже использует onnx. В целом onnx хорошо заточен на работу на CPU-only.
Так как для группировки вкладок это локальная модель тоже, то это либо создание первичной семантической базы, после чего жор процессора спадет, либо баг. По крайней мере пишут, что нужное для исправления есть: https://bugzilla.mozilla.org/show_bug.cgi?id=1982278
В v8 есть 3 уровня запуска кода: как есть, первый быстрый оптимизатор, второй тяжелый jit-оптимизатор. В общем "прогрев" кода.
Время затраченное на работу оптимизатора просто суммируется к времени работы 1 цикла, если блоки кода поменять местами, картина изменится на противоположную (только надо учесть, что в одном случае есть Math.random, а во втором нет).
Вообще, из-за этих оптимизаторов и сборки мусора, делать эти микробенчмарки очень тяжело, выше комментатор правильно написал про тонкости.
На хабре есть статья про мономорфизм и полиморфизм прям от одного из разработчиков V8, там всё это куда более детально рассказано: https://habr.com/ru/articles/303542/
Минимально нужно хотя бы делать 3 холостых прогона, делать паузу на сколько-то секунд, сделать ещё прогон, снова пауза, и только после этого можно делать финальный прогон, где цифры уже будут ближе к реальности.
Если выполнить такой ритуал, дать всем оптимизаторам время на выполнение, то разница будет ожидаемо никакой:
Код 3
function makeObjOrdered() {
return (Math.random() > 0.5) ? {a: 1, b: 2, c: 3} : {a: 1, b: 2, c: 3}
}
function makeObjRandom() {
return (Math.random() > 0.5) ? {a: 1, b: 2, c: 3} : {o: 3, a: 1, b: 2}
}
const delay = ms => new Promise(d => setTimeout(d, ms))
function getA(obj) {
return obj.a
}
function run1() {
let arr1 = []
console.time("ordered");
for (let i = 0; i < 1e7; i++) {
const o = makeObjOrdered();
arr1.push(o)
}
console.timeEnd("ordered");
console.log(arr1.slice(0,10))
}
function run2() {
let arr2 = []
console.time("random");
for (let i = 0; i < 1e7; i++) {
const o = makeObjRandom();
arr2.push(o)
}
console.timeEnd("random");
console.log(arr2.slice(0,10))
}
for(let i = 0; i < 4; i+=1) {
run1()
run2()
}
await delay(10000)
run1()
run2()
await delay(10000)
run1()
run2()
ordered: 332.928ms
random: 331.127ms
10 миллионов вызовов, куда уж больше. И в реальном проекте не будет даже 15% разницы, как только пройдет jit-оптимизатор, разница будет смазана до нескольких процентов, которые будут не важны, так как основным тормозом будет i/o, который съест все эти микрооптимизации. Эти микрооптимизации работают только в таких бенчмарках с гигантскими циклами.
В 2016 это может и было актуально, когда вышла статья Убийцы оптимизации, на данный момент все эти деоптимизации уже не актуальны, а сами разработчики V8 говорят, что пишите как вам удобно.
В вашем случае разница потому, что в 1 случае оптимизатор просто выкинул цикл вообще, поэтому и получилось 5 ms.
Не проблема создать пример, когда ordered будет куда медленнее, чем random:
Код 1
ordered: 411.947ms
random: 251.125ms
И в вашем примере нет ни мега-морфизма, ни даже полиморфизма, так как вы не сделали функцию, которая работает с объектом, и на вход функция как раз должна получать объекты с разным порядком свойств, вы же просто создаете объект и ни как его не используете.
Чтобы увидеть работу более тяжелого jit-оптимизатора, который подключается после прогона функции несколько раз, прогоните 3-4 цикла, и у вас уже не будет никакой разницы в итоге, кроме погрешности:
Код 2
ordered: 230.519ms
random: 236.495ms
Если в равные условия поставить и не давать оптимизатору пропустить цикл, то:
gpt-oss-120b это MoE модель размером 120B, но для каждого нового токена используется только 5.1B активных параметров, которые постоянно меняются. Выгружая 8 слоев из 37 в видеопамять, это 14гб VRAM, то не все активные параметры попадают в эту VRAM, то есть VRAM не используется на каждом шагу, лишь эти 8 слоев которые выборочно могут попасть, а могут не попасть в список активных параметров. Это главное отличие от Dense-моделей, где каждый слой участвует в вычислениях на каждом шагу.
Для MoE сейчас используют более эффективный способ заполнить эти 14гб, куда сильнее ускоряя работу модели. Нужно выгрузить тензоры внимания со всех слоев в VRAM, а MoE тензоры оставляете на CPU, тензоры внимания каждого слоя нужны во время каждого шага, поэтому вы используете VRAM для каждого токена, за счет этого получается ускорение.
Подробнее про это есть вот тут: Запускаем настоящую DeepSeek R1 671B на игровом ПК и смотрим вменяемая ли она на огромном контексте (160к)
GPU 4060ti 16gb, то есть слабее чем 5060ti, также 8 слоев в видеопамяти, используется 14гб:
.\llama-server.exe -m "openai_gpt-oss-120b-MXFP4.gguf" -fa -ngl 8
Используем новый подход, добавляем параметр
--cpu-moe
и выгружаем все 37 слоев (для удобства указано 99):.\llama-server.exe -m "openai_gpt-oss-120b-MXFP4.gguf" -fa --cpu-moe -ngl 99
Модель работает почти в 2 раза быстрее, при этом использует всего 3гб VRAM, вместо 14гб.
Можно засунуть целые слои, чтобы заполнить те же 14гб. Для этого есть новый параметр
--n-cpu-moe X
, количество moe-слоев которые будут выгружена на CPU, остальное останется на GPU. Начиная от полного числа слоев, 37 в данном случае, число надо уменьшать вниз, пока хватает памяти, для 14гб это будет 28 слоев:.\llama-server.exe -m "openai_gpt-oss-120b-MXFP4.gguf" -fa --n-cpu-moe 28 -ngl 99
Было 7.6 t/s, стало 16 t/s, скорость в 2.1 раза выше, чем была при том же расходе VRAM.
--cpu-moe
и-cmoe
это синонимы для-ot exps=CPU
или--override-tensor=CPU
, поэтому можно встретить и такие параметры. Сейчас это не применить в LM Studio, они используют движок llama.cpp, но не добавили возможно указать эти параметры, поэтому запуск llama-server из состава llama.cpp.Это на столько редкие и не критичные события, что их в 99% случаях даже нет смысла учитывать. Если она сгенерирует не правильный вариант - это тоже самое, что оригинал сгенерировал выше не правильный вариант.
То, что выбор черновой модели важная часть, это да. Для той же 235B лучше взять 4B вместо 0.6B, скорость и процент принятия будет куда лучше.
Модели в целом не идеальны, особенно квантованные, они на пустом месте могут выдать рандомный ответ, и небольшие редкие искажения черновика не сильно повлияют на итоговый результат. Ускорение оправдано, 4 t/s или 7 t/s это ощутимая разница.
Тот сценарий я создал зная слабость модели, это просто, чтобы показать, что спекулятивное декодирование не 1 в 1 работает, и это можно учитывать, например, выбирая черновую модель получше, но критичного тут ничего нет.
Достаточно вернуть температуру на 0.6, и даже с 16 токенами на черновой 0.6B модель генерирует правильный ответ 4 из 6 раз. Ускорение тоже продолжает работать.
Температура не играет роли. Первичная идея спекулятивного декодирования это завершать очевидные варианты, а не подменить собой основную модель.
Есть такая последовательность "И вот таким образом сп", черновая модель предложить ['сп', 'ек', 'у', 'ля', 'тив', 'ное', ' дек', 'од', 'ирование', ' это', ' большое', ' я', 'бл', 'око'], основная модель примет только 9 токенов, остальные отбросит, а что-то вроде
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
вообще сразу принимается целиком.Тут нет сценария, что основная модель только проверяет, потому что основная модель отвергает почти 50% токенов, и оставляет только очевидные продолжения, это не влияет на её глубину понимания вопроса.
Не, никаких отличий от использования просто основной модели и модели с черновиком в плане глубокого понимания или вероятностей нет. Основная просто отвергнет все токены и сгенерирует ответ сама.
Просто задача с эмодзи сложная, и если основная модель плавает в решение, то черновая может повести её по пути, где решение не рабочее, но просто потому, что такая ветка могла бы возникнуть и при генерации основной моделью самой по себе.
Вот тот же запрос прям у оригинальной Qwen3-235B-A22B-2507 на их сайте. С первой же попытки модель не справилась:
То, что задача не простая, вот, например, что сгенерировал Gemini 2.5 Pro, эмодзи пропали, потому что вместо массива, он сделал строку и не правильно её нарезал:
Если речь про черновую последовательность, то её размер не фиксированный, есть максимальное и минимальное значение (от 0 до 16 по-умолчанию), генерация черновика прерывается как только токены перестают попадать в greedy семплинг значения
--draft-p-min
, по умолчанию 0.8.Большая модель могла бы легко генерировать и 2, и 3, и 4 токена за раз, но чтобы сгенерировать токен в позиции n+1, нужно знать токен в позиции n, а у нас доступен только токен в позиции n-1. Поэтому модель вынуждена генерировать всё последовательно, шаг за шагом, хотя может параллельно высчитать сразу несколько токенов за тоже время.
Как-то делал демонстрацию на тему, что в llama.cpp есть параметр
--parallel N
, и можно почти без потерь, если хватает вычислительных ресурсов, генерировать даже 8 параллельных запросов:Спекулятивное декодирование работает так:
Черновая модель на основе текущей последовательности генерирует продолжение, допустим последовательность из 8 новых токенов.
Большая модель получает эти 8 токенов и создает 8 гипотетических последовательностей, каждая на 1 токен больше. "Стартовая + n", "Стартовая + n + n+1" и т.д.
Большая модель запускает параллельные вычисления для этих 8 вариантов будущего, она параллельно высчитывает 8 новых токенов и если они совпадут с черновой, то те будут приняты.
Получаем 8 вариантов logits и начиная с 1 токена сравниваем вероятности большой модели и черновика, первое не соответствие и остальные отбрасываются, а начальные принимаются.
Так за счет параллельных вычислений мы получили больше новых токенов за плюс-минус время вычисления 1 токена и накладных расходов. Так что снижение
--draft
(синоним-draft-max
) до 4 - это не только повышает шанс принятия нового токена, но и снижает количество параллельных вычислений, что на больших MoE-моделях, которые вычисляются на CPU, где ядер мало, дает дополнительный смысл.Если нужны детали, можно почитать их тут: https://arxiv.org/abs/2302.01318
Допустим, стартовая последовательность: Кот
Черновая предлагает: любит есть колбасу и спать
Для большой модели создается 5 последовательностей, которые считаются одновременно:
За 1 шаг готовы все 5 вариантов, но если большая считает, что "кот любит есть рыбу", то вместо +5 принятых черновых будет +2 и +1 токен от большой модели, итого +3 токена вместо +1.
P("любит" | "Кот") - это вычисление вероятности, то есть это не 1 в 1 совпадение токена черновой и большой, а вероятность с которой большая модель согласна с тем, что тут может быть такой токен.
Поэтому, черновая модель может увести большую не туда, то есть её качество тоже играет роль, но на сколько расходится качество - нет точного ответа.
Есть шанс заруинить. Допустим взяли черновую очень маленькую 0.6B, поэтому она качественно не очень хороша для большой модели, но в среднем работает. И тут может быть такая ситуация:
Модель: Qwen3-235B-A22B-Instruct-2507-UD-Q4_K_XL + Qwen3-0.6B-Q8_0
Температура: 0.01, top_k: 20, top_p: 0.95, min_p: 0.05
Запрос:
Напиши эффект матрицы из эмодзи в одном index.html
Выставил температуру минимально, результаты должны быть максимально близки.
Без черновика: 6 прогонов, каждый раз результат правильный.
--draft 4
: 6 прогонов, результат правильный.--draft 10
: 6 прогонов, результат правильный 50 на 50.--draft 16
: 10 прогонов, каждый раз результат не корректный.Поэтому предсказывать значение по умолчанию в 16 токенов качественно не выгодно.
Модуль спекулятивного декодирования MTP, который из DeepSeek, а теперь ещё и из GLM 4.5, обучается вместе с основной моделью, поэтому такой вариант должен работать лучше, но поддержки MTP в llama.cpp пока нет. В отчете про DeepSeek (раздел 5.4.3. Multi-Token Prediction Evaluation) описывают, что в MTP предсказывают только 2 следующих токена, видимо как раз из-за лучшего качества результата.
Как лучше всего не знаю, попробуйте Jan или сразу llama.cpp.
Я не знаю на сколько из далека вам нужна теория, поэтому с самого начала, если что просто переходите на следующий пункт.
Про квантизацию
Веса модели это массив млрд цифр типа float. Стандартный размер float это 32-бита на вес, то есть это числа такого вида:
0.340282347234423412354675889478
Эти числа образуют собой матрицы чисел, матрицы (тензоры) перемножаются друг на друга и модель выдает результат. Фактически в модели нет ничего кроме этих чисел, там нет скрытых слоев знаний или слоев данных, просто так удачно сложились значения этих весов, что на выходе выходит что-то осмысленное плюс различные эмерджентные свойства. Подбор этих весов это и есть обучение модели.
Количество цифр после запятой велико, чем дальше они от начала, тем меньший вклад вносят в итоговый результат умножения, поэтому можно просто сократить их в 2 раза и перейти на float16. Это имеет почти нулевое влияние на качество, но увеличивает скорость инференса и скорость обучения в 2 раза. float16 уже выглядит так:
0.1245236426236046
16 бит на вес - цифр после запятой всё ещё достаточно, можно сократить их ещё в 2 раза и получить fp8, в fp8 как раз обучена DeepSeek, но обычно другие модели обучают до сих пор в f16.
Есть ещё всякие детали, вроде распределения мантисы и экспоненты, и то, что сейчас используют более точный bfloat16, вместо обычного float16, есть fp4 в nvidia 5000 серии и т.д. Чтобы квантование в fp4 или fp8 хорошо работало, устройство должно поддерживать операции с этим типом чисел, иначе нужны преобразования весов на лету до поддерживаемых типов.
Квантование в gguf работает не просто сокращением чисел после запятой, там в основном используются целочисленные типы int, а перегнать число с плавающей запятой в int - это само по себе снижение точности, в gguf же ещё происходит и объединение весов в суперблоки, из-за чего срезаются выбросы, если в суперблок попали веса не похожие на общие в среднем веса суперблока. В среднем если точности хватает, это не так важно, но чем агрессивнее квантование, тем больше будет потерь.
Ну это упрощенно, gguf позволяет сохранять веса и без квантования и квантовать любым другим способом, не только через суперблоки. Например, в ik_llama недавно добавили Trellis quants IQx_KT, работающие аналогично как в exl3, и они в целом дают лучшее качество при меньшем весе и большую скорость, но хорошо работают только на GPU, на CPU происходит просадка скорости.
Цифра рядом с Q - это то количество бит, которое будет затрачено на основные веса модели, а буквы XL, L, M, S - это на сколько выше будут квантованы важные тензоры, например, внимания, которые сильнее влияют на качество, чем основное тело модели.
L - Large на 2-3 уровня выше, M - Medium на 1-2 уровня выше, S - Small на 0-1 уровня выше. Ну и XL - eXtra Lagre, там динамичное число и могут быть на много уровней выше.
Например, вначале в gguf было квантование прямо в лоб, был тип Q4_0 - это просто урезание весов до int4, или 4 bpw (bite per weight), или чуть позже Q4_1, оно чуть получше, но эти типы работали плохо и качество сильно падало.
Потом пришел Kawrakow (тот самый создатель форка ik_llama) и сделал нормальные кванты. Его выступление об истории квантова можно посмотреть тут: https://fosdem.org/2025/schedule/event/fosdem-2025-5991-history-and-advances-of-quantization-in-llama-cpp/
Сам алгоритм квантования был изменен, качество стало выше, размер меньше. Эти кванты до сих пор везде используются как база, те самые популярные Q4_K_M или IQ4_XS.
Q4 - это 4 бита на основные веса
K - это скорее всего Kawrakow, просто отделяет Q4_0, Q5_0 кванты от Q4_K, Q5_K и т.д.
M - Medium, значит важные веса на 2 уровня выше и квантуются как Q6_K.
Супер важные тензоры остаются в fp32 или f16 (f16 - это общее название для bf16 и fp16).
В таких квантах тензоры квантованы не равномерно и суммарный BPW для Q4_K_M будет 4.82 BPW, при этом размере чуть больше чем у Q4_0, по качеству это выходит почти как 5 бит на вес, соответственно и качество ощутимо лучше.
IQ4_XS или IQ2_XSS - это уже более продвинутый тип квантования через матрицу важности imatrix, сами XS и XSS это уже именно алгоритмы квантования тензоров, количество S передает смысл сохраняемой точности, чем их больше, тем ниже точность.
В форке ik_llama есть новые кванты IQ2_KS и KSS, в данном случае K просто показывает, что это другой квант, у них точность выше чем у XS и XSS, а размер тот же.
В общем чем ниже число, тем ниже бит на вес, тем хуже качество модели. 8 бит на вес работает почти без потерь, квантование Q6_K - очень близко к без потерь, Q5_K_M процентов на 2-3% хуже, Q4_K_M процентов на 5% и т.д.
IQ кванты лучше чем статичные K кванты, поэтому IQ4_XS весит меньше, но работает на уровне Q4_K_M. Кванты из ik_llama ещё лучше, поэтому могут весить ещё меньше при том же качестве.
В общем это примерное описание, не нужно воспринимать эту информация как истину, этого достаточно, чтобы примерно понимать что к чему, но везде могут быть исключения и прочие тонкости.
Качество отличается, квантование это способ снизить размер за счет снижения качества. Весь смысл в том, сколько качества нужно потратить на каждый шаг снижения веса. Один из способов померить разницу - это замерить PPL или KLD, их описание есть в статье. Чем эти значения ниже, тем меньше отклонений от оригинальной модели.
Кроме общего представления, можно заметить, что новые кванты из ik_llama весят меньше, а PPL такой же как у более крупных квантов, квантованных старыми способами.
Например, новый квант IQ2_KS весит 196гб и имеет PPL 3.6378, а квант UD-Q2_K_XL весит 234гб и PPL 3.6062. Разницы почти нет, при этом размер на 38гб меньше. Новый квант IQ2_K_R4 имеет размер 220гб и PPL 3.5069, что ощутимо ниже чем у UD-Q2_K_XL, а вес меньше на 14гб.
Но разницы почти нет это довольно условное представление. Разницы почти нет на тексте wiki.test.raw, это узкий диапазон текстов на английском из википедии, а для другого языка или для вашего редкого сценария разница может быть куда более ощутимой.
Потребление VRAM будет разное, чем сильнее квантование, тем меньше, по сути столько, сколько весит модель физически + размер контекста, столько и нужно VRAM или RAM.
Веса распаковываются на лету, поэтому скорость работы разных квантов будет разной, так как везде разные алгоритмы, и поэтому эту скорость можно ускорить на той же пропускной способности памяти. По крайней мере для скоростей PP это заметная разница.
i-кванты обычно тяжелее по вычислительным ресурсам, чем статичные K-кванты. Я как-то давно делал простое сравнение, хотя размер по весу у моделей примерно одинаковый, но скорости отличаются. Новые IQK кванты легче старых i-квантов (в сравнении их нет):
Про сильно лучше - это сомнительно, что сильно, но лучше это да, обычно чем больше цифра и какие бы ни были символы, тем лучше.
И там разница почти 1гб, это можно дополнительно ~16к контекста вместить, это не так уж и мало, иногда как раз 0.5гб и не хватает и взять их не откуда.
Опять же, исключением для цифры может быть у разного типа квантования, например, старые из llama.cpp и новые из ik_llama.cpp. На графике выше видно, что новый IQ3_K_R4 на том же уровне как старый IQ4_XS, при этом новый весит на 33гб меньше, но это скорее исключение.
В статье есть немного про спекулятивное декодирование, в DeepSeek оно называется MTP.
Смысл в том, что нужна очень маленькая модель для черновиков, на которую не жалко потратить немного ресурсов, и они должны быть из одного семейства, иначе не заработает.
Сначала маленькая предлагает последовательность токенов, например 16 новых токенов, большая модель внедряет эти токены в свою последовательность и производит расчет, если вероятности совпадают, то большая принимает эти токены. Ускорение происходит за счет того, что большая модель не тратит время на генерацию шаг за шагом, а проверяет вероятности сразу для всех токенов параллельно. Сам алгоритм не так важен, главное, что за счет kv-кэша проверить токены быстрее, чем высчитать их с нуля.
Маленькая модель - это 0.6B, 1B или 1.5B, размеры 3B или 4B уже слишком большие, но и они могут быть полезны в редких ситуациях.
Берем gemma-3-27b UD-Q5_K_XL, она занимает 21гб. Берем gemma-3-1b Q4_K_M, она занимает 800мб. Черновой модели тоже нужен контекст, где-то суммарно будет 1.5гб VRAM, две модели влезают в 24гб + 22к контекста.
Ускорение в 1.5 раза, и никаким другим способом не получить такое ускорение столь малыми усилиями.
Если взять большую MoE Qwen3-235B-A22B, в качестве черновика маленькую dense Qwen3.
Вместо
-ot exps=CPU
теперь писать просто--cpu-moe
.Qwen3-235B-A22B-2507-UD-Q4_K_XL + Qwen3-4B-UD-Q5_K_XL:
.\llama-server -m "Qwen3-235B-A22B-Instruct-2507-UD-Q4_K_XL-00001-of-00003.gguf" -ts 24,0 -ngl 99 --cpu-moe -fa -t -1 -md "Qwen3-1.7B-UD-Q4_K_XL.gguf" -ngld 99 --no-warmup
Процент принятия 56%, было 4.8 t/s, стало 7.1 t/s, ускорение в 1.5 раза, вполне нормально, можно попробовать подобрать другую модель для черновика или квант этой модели. Но черновая модель не всегда помогает, может сделать и хуже.
По умолчанию черновик генерирует последовательность в 16 токенов, шанс что будет принята такая длинная последовательность не велика, а времени тратится и на проверку и на генерацию.
Если модели очень сильно отличаются, то тут может помочь снизить длину последовательности.
Параметром
--draft-max 4
или--draft-max 8
можно сократить последовательность до 4/8 токенов.Тут тот случай, когда для большой Qwen3-235B-A22B-2507 в качестве черновика лучше подойдет Qwen3-4B, урезав последовательность до 4 можно получить скорость 7.5 t/s, но правда это всего на 0.2 t/s больше, чем Qwen3-1.7B, с которой 7.3 t/s.
Возьмем огромную модель Qwen3-Coder 480B-A35B, черновая Qwen3-1.7B. Модели уже совсем разные по качеству ответов. Черновая модель с базовыми настройками делает хуже, уменьшение длины последовательности помогает и увеличивает процент принятия до 73%, хотя дает прирост скорости всего 5%, с 5.9 до 6.3 t/s.
И ещё один вариант, когда модель не влезает в RAM и считывается с nvme. Снова огромная Qwen3-Coder 480B-A35B, в кванте UD-Q3_K_XL.
Тут уже черновая модель помогает намного лучше, было 2.3 t/s, стало 4.2 t/s, с натяжкой можно пользоваться.
Тут тоже информация не на 100% верная, нужно перепроверять и тестировать.
Задержки будут большими, да и нет такого функционала.
Можно использовать 2 GPU. Основную модель запустить на основной GPU, а черновую на второй карте. Не знаю, можно ли так сделать в LM Studio, в llama-server это делается командой:
.\llama-server -m "gemma-3-27b-it-UD-Q5_K_XL.gguf" -ts 24,0 -ngl 99 -fa -md "gemma-3-1b-it-Q4_K_M.gguf" -ngld 99 -devd cuda1
Через
-ts 24,0
запрещаем использовать вторую GPU для основной модели, через-devd cuda1
направляем draft модель на устройство cuda1.-ngl 99
выгрузить все слои основной модели,-ngld 99
выгрузить все слои черновой модели.Вторая карта медленная 4060, поэтому ускорение слабое, но всё равно есть:
Попробуйте whisper.cpp, должно быть быстрее на 3070. Модели в формате ggml (по сути тоже самое, что gguf) лежат тут: https://huggingface.co/ggerganov/whisper.cpp. У whisper ещё вышла модель whisper-large-v3-turbo, она быстрее и легче чем просто large-v3.
На 4060ti часовая лекция разбирается:
– за 7 минут на large-v3 неквантованная, 4гб vram
– за 5.1 минуты на large-v3 в кванте q5_0, 2.5гб vram
– за 2.3 минуты на large-v3-turbo в кванте q8_0, 1.6гб vram.
Есть файнтюны для русского языка, но тоже не идеальные:
– для large-v3: Andrei1980/whisper-large-rus-ggml (обучена лучше)
– для large-v3-turbo: dvislobokov/whisper-large-v3-turbo-russian (обучена хуже, путает слова)
Для английского есть модели получше чем whisper, рейтинг тут: https://huggingface.co/spaces/hf-audio/open_asr_leaderboard
Для русского ещё есть модели: vosk, GigaAM и T-one.
Qwen устроил неделю релизов. Суммарно они представили по хронологии:
Qwen3-235B-A22B-2507
Qwen3-235B-A22B-Thinking-2507
Qwen3-Qwen3-Coder-480B-A35B
Qwen Wan2.2 размером 5B и 14B (генерация видео из текста или из картинки)
Qwen3-30B-A3B-Instruct-2507
Qwen3-30B-A3B-Thinking-2507
Qwen3-Coder-30B-A3B-Instruct
Маленький Qwen3-Coder-30B-A3B они назвали Qwen3-Coder-Flash, для своего размера он показывает не плохие результаты.
Серия маленьких 30B-A3B моделей интересна не только тем, что их можно запустить даже на CPU с нормальной скоростью, так как активных параметров всего 3B, но и тем, что увеличили нативный контекст до 256к.
Большая Qwen3-235B-A22B-Thinking-2507 сделала лучший пересказ книги, книга занимала 215к токенов и влезала целиком в 256к, теперь интересно на сколько хорош контекст у очень легковесной Qwen3-30B-A3B-Thinking-2507. Модель маленькая, и можно её сравнить с Gemma3 27B у которого 128к.
Результат Gemma3 уже есть в статье, он выдумывает и ошибается даже на 32к контексте. Поэтому тот же вопрос, что и для Gemma3 27B.
Сам ответ правильный, это при том, что в контекст загружена вся книга целиком, а не как в случае Gemma только 32к контекста, но последний момент с уходом в Лабиринт Смерти - технически правильно, но тут как будто бы это не к месту упомянуто, так как перед походом было много других событий.
Можно попробовать дать куда более сложное задание, пройти по всей книге и обобщить факты из разных эпизодов, из начала, середины и конца книги. Это частая проблема для многих моделей на SWA, так как скользящее окно контекста обычно всего 4к.
Для такой маленькой модели ответы вполне хороши. Ошибка и путаница про встречи с Маньяком, часть правильно, часть спутана, части не хватает, но это как раз и есть самая сложная часть собрать по книге все встречи.
После провала Gemma3 27B и Llama4 Scout 109B-A17B, казалось что маленькие модели не способы переваривать огромный контекст, но у Qwen3 30B-A3B на первый взгляд получилось куда лучше.
В предыдущем комментарии я слегка ошибся, для вмещения 256к контекста нужно не 8гб, а 23гб. Скорости на скриншотах низкие, так как почти всю память отдал под контекст, используя -ot exps=CPU даже тут, если контекст уменьшить, то скорости будут ожидаемо большими. Появились сборки бинарников ik_llama под Windows, бенчмарк скорости на них: https://github.com/Thireus/ik_llama.cpp
Разгрузка на одну GPU через
-ngl 99 -ot exps=CPU -fa
Подробнее как это работает:
Запускаем настоящую DeepSeek R1 671B на игровом ПК и смотрим вменяемая ли она на огромном контексте (160к)
Квант IQ4_K: 7гб VRAM + контекст + 134гб RAM.
Квант UD-Q2_K_XL: 5гб VRAM + контекст + 82гб RAM.
8к контекста требуют 0.7гб VRAM, 256к контекста требуют 25гб. Контекст работает через SWA, включается автоматически при использовании
-fa
.Скорости выше уже были:
Сейчас вышли ещё 2 большие модели:
Qwen3-235B-A22B-Thinking-2507 на данный момент с лучшим удержанием контекста среди локальных моделей
Qwen3-Coder-480B-A35B, которую всё еще можно запустить локально
И скоро должна выйти маленькая Qwen3-30B-A3B-Instruct-2507.
Вышла от Qwen модель для видео Wan 2.2 5B и 14B, требует от 8гб VRAM, для 14B gguf уже есть.
Только что вышли GLM-4.5-355B-A32B и GLM-4.5-Air-106B-A12B от Zhipu AI:
Автор пишет, что это закрытый бенчмарк, только несколько примеров показывает. В целом можно понять, что из себя этот бенчмарк представляет:
https://www.reddit.com/r/LocalLLaMA/comments/1jbgezr/comment/mhu4nxo/?context=3