Квантование ломает вызов инструментов не так, как показывает BFCL: проверил на MCP-серверах

от автора

Есть простая практическая задача, из-за которой я вообще все это затеял. Вы берете маленькую модель, квантуете ее, чтобы она влезла в ноутбучную видеокарту, и хотите заранее понимать, насколько просядет ее способность вызывать инструменты. Обычно для этого смотрят на BFCL или ToolACE: там все измерено, есть таблицы, есть готовые цифры деградации по уровням квантования. И кажется логичным, что этими цифрами можно пользоваться.

Оказалось, что нельзя. Точнее, можно, но результат будет вводить в заблуждение вместо того, чтобы помогать. Я собрал бенчмарк QuantMCP, который берет те же самые модели и те же уровни квантования, но направляет их на схемы инструментов серверов Model Context Protocol вместо курируемых схем бенчмарка. И корреляция между тем, как модель деградирует на BFCL, и тем, как та же модель деградирует на MCP-схемах, получилась равна минус 0.755 (ранговая корреляция Спирмена по 8 парам «модель × квант», три семейства моделей).

Минус. То есть рейтинг «какой квант сильнее всего вредит этой модели», снятый на BFCL, на схемах не просто теряет предсказательную силу, он систематически указывает в противоположную сторону. И что мне кажется самым важным: когда я добавил третье семейство моделей и данных стало больше, корреляция не поползла к нулю, как бывает, когда изначальный сигнал был шумом. Она стала еще более отрицательной. На двух семействах было минус 0.551 по шести парам, добавление Qwen3-1.7B сдвинуло ее до минус 0.755 по восьми.

Диаграмма рассеяния Cross-Benchmark Consistency: дельта деградации на BFCL против дельты на MCP-схемах, ρ = -0.755

Диаграмма рассеяния Cross-Benchmark Consistency: дельта деградации на BFCL против дельты на MCP-схемах, ρ = -0.755

Вкладка Cross-Benchmark (CBC) лидерборда. Точки не лежат вдоль диагонали, а расходятся по разным квадрантам — это и есть отрицательная корреляция в виде картинки.

Это прямое продолжение прошлой статьи про соседний проект QuantCall. Там я на курируемых схемах BFCL намерил, что квантование ломает Llama-3.2-1B на каждом уровне, включая самый щадящий Q8_0, а оба Qwen3, и меньшая на 0.6B, и большая на 1.7B, держатся ровно. Вывод оттуда был такой: деградацию от квантования предсказывает семейство модели, а не ее размер. И заканчивал я ту статью открытым вопросом. Схемы BFCL аккуратные и короткие, их специально причесывали под бенчмарк, а что будет, если направить те же модели и те же кванты на схемы настоящих серверов, которых никто не приглаживал. Цифра минус 0.755 выше и есть ответ, и он оказался не таким, как я ждал.

Зачем это вообще нужно, если есть MCP-Bench и подобные

Тут напрашивается возражение: ну разумеется, другой бенчмарк дает другие числа, что здесь нового. Но интересен не сам факт расхождения, а его величина и знак. За последний год появилось несколько серьезных проектов, которые гоняют модели против живых MCP-серверов: MCP-Bench с 28 серверами и 250 инструментами, MCP-Universe с 231 задачей по шести доменам, MCP-Atlas с тысячей задач, написанных вручную экспертами. Все они отвечают на вопрос «насколько модель вообще умеет пользоваться инструментами», и почти всегда речь идет о больших, топовых моделях.

Мой вопрос другой, и я не нашел, чтобы его кто-то закрывал напрямую. Меня интересует не абсолютная способность модели, а именно кривая деградации от квантования, потому что это ровно то, что определяет, влезет ли модель на мое железо и можно ли ей после этого доверять вызов инструментов. И проверять это надо на настоящих, неизмененных схемах MCP, потому что синтетика тут не годится: как выяснилось дальше, именно форма схемы и вскрывает поведение, которого на курируемых сигнатурах просто не видно. При этом весь бенчмарк работает полностью офлайн: серверы поднимаются в песочнице на детерминированных фикстурах, никаких обращений к живым API, никаких платных запросов, и все воспроизводится на одной RTX 3050 с 4 гигабайтами видеопамяти.

Три способа сломаться, которых BFCL не показывает

Именно сырой вывод модели убедил меня, что отрицательная корреляция это не артефакт бенчмарка, а реальное поведение. Я не поверил числам сразу, а сел и прочитал, что модель на самом деле выдает на каждой задаче. И увидел три отдельных, стабильно воспроизводящихся сценария поломки, которым в результатах BFCL для тех же моделей нет аналога.

Первый и самый показательный: Llama-3.2-1B на fp16 и Q8_0 вместо вызова инструмента возвращает обратно его же схему. Не сломанный вызов, а именно определение JSON Schema самого инструмента, аккуратно завернутое в оболочку tool-call, но без единого заполненного значения аргумента.

{"type": "function", "function": {"name": "read_graph", "parameters": {"$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": {}}}}

Самое любопытное, что происходит дальше по уровням квантования. На Q5_K_M и Q4_K_M та же модель частично переключается на более плоскую форму, где значения аргументов уже подставлены, и парсер такую форму принимает как вызов. То есть квантование не ухудшило модель равномерно, а поменяло, какой именно сломанный формат она выдает по умолчанию, и случайно более пригодный для разбора формат оказался на более низкой точности. Правда, там же вылезает вторая проблема: модель начинает галлюцинировать названия инструментов, зовет read_file и rename_file, которых в настоящем @modelcontextprotocol/server-filesystem не существует (реальные имена это read_text_file и move_file). На более простых и коротких сигнатурах BFCL режим «эхо схемы», судя по всему, не запускается вообще; он проявляется только тогда, когда у схемы аргументов есть структура, которую можно отразить.

Вывод Llama-3.2-1B на fp16: модель возвращает JSON Schema инструмента read_graph вместо вызова с аргументами

Вывод Llama-3.2-1B на fp16: модель возвращает JSON Schema инструмента read_graph вместо вызова с аргументами

Тот самый прогон: инструкция про граф знаний, и вместо вызова — echo его же схемы.

Второй сценарий вскрыл самописный sqlite-сервер, и он совсем про другое. На вопрос «какие таблицы есть в этой базе», который решается вызовом list_tables вообще без аргументов, Qwen3-0.6B на fp16 не полезла в инструмент, а прямо ответила выдуманной, но правдоподобно звучащей схемой: таблицы users, orders, products. Ни одной из них в реальной фикстуре нет, там employees и inventory. На вопросы вроде «какая зарплата у Carla Diaz» или «сколько на складе виджетов», где достаточно одного read_query, та же модель иногда отвечала, что не может ответить без дополнительной информации. И вот здесь становится видно, зачем я развел две метрики: SVR-MCP (вызов валиден по схеме) и TSR (результат действительно правильный). Когда модель все-таки вызывает write_query с синтаксически корректным SQL, этот SQL порой ссылается на таблицу salaries или колонку employee_id, которых в схеме просто нет. Вызов при этом формально валиден, потому что аргумент это строка, а вот выполнение дает неверный результат, и метрики честно расходятся.

Третий сценарий это тот же режим «эхо схемы», но сконцентрированный на аргументах-массивах объектов. В тире memory (граф знаний) инструменты принимают что-то вроде entities: [{name, entityType, observations: [...]}, ...], то есть вложенные структуры, а не плоские строки. Llama-3.2-1B держится ровно на 0.200 SVR-MCP на всех проверенных квантах, это самый низкий и самый плоский результат среди всех тиров, и сырой вывод подтверждает, что поломка та же, что и на файловой системе, просто на вложенных аргументах она срабатывает заметно стабильнее.

История с индексом сложности схем: это был баг

Еще в начале я завел метрику под названием Schema Complexity Index (SCI): для каждого инструмента считаю z-нормализованную глубину вложенности, число свойств, наличие union-типов и длину описания. Гипотеза (я называю ее H2) простая: более сложные схемы должны деградировать при квантовании сильнее. Первый прогон по четырем тирам показал ровно обратное. Самый простой по схемам тир, sqlite, дал самый большой разброс деградации, а тир memory, который я в своей же спецификации отметил как «самый вложенный и union-тяжелый», по SCI оказался вторым с конца по сложности.

Результат выглядел неправильно, и он таким и был. Мои функции подсчета глубины и числа свойств рекурсивно заходили внутрь вложенных объектов, но не заходили внутрь items у массива. Из-за этого аргумент «массив объектов» получал ровно ту же оценку сложности, что и одна плоская строка. Я починил рекурсию, и SCI тира memory сдвинулся с минус 0.359 (второй самый низкий из четырех) до плюс 0.194 (второй самый высокий), то есть на 0.55 стандартного отклонения, и это самый большой сдвиг среди всех тиров.

Таблица Schema Complexity Index по тирам: memory теперь +0.1942, второй по сложности из четырех, и результат per-tool регрессии n=38

Таблица Schema Complexity Index по тирам: memory теперь +0.1942, второй по сложности из четырех, и результат per-tool регрессии n=38

Вкладка Schema Complexity после фикса. Memory встал туда, где ему и место — рядом со сложными filesystem и git, а не рядом с sqlite.

Но фикс бага не закрыл вопрос H2, и я не считаю это провалом. Так и должно быть, когда переходишь от статистики без мощности к нормальной. У исходного теста было ровно четыре точки, по одной на тир, и это никогда бы не дало осмысленной корреляции, независимо от бага. Я перестроил тест так, чтобы считать точку не на тир, а на каждый инструмент: беру SCI конкретного из 38 живых инструментов и сопоставляю с его собственной дельтой деградации. Получилось n = 38, наклон регрессии плюс 0.045 при 95-процентном бутстреп-интервале от минус 0.064 до плюс 0.170. Наклон положительный, то есть в ту сторону, которую и предсказывает H2, в отличие от результата на уровне тиров, но интервал спокойно накрывает ноль. Это нормальный, содержательный нулевой результат: не «слишком мало точек, чтобы что-то сказать», как было честно раньше, а «нормально посчитанный тест эффекта не находит, и вот вам доверительный интервал в подтверждение».

Где я сам себе не до конца верю

Далее представлен список ограничений, которые есть в данной работе.

Восемь пар «модель × квант» для самой корреляции CBC это очень мало для строгого p-value на Спирмене. Знак устойчив во всех прогонах (три отдельные оценки на двух семействах прыгали от минус 0.824 до минус 0.265, прежде чем осесть около минус 0.551, а с третьим семейством дали минус 0.755), но к точной величине надо относиться как к нестабильной, доверять стоит именно знаку.

Три семейства моделей: Qwen3-0.6B, Qwen3-1.7B, Llama-3.2-1B. С Qwen3-1.7B был отдельный сюжет: ее веса в fp16 не влезают в 4 гигабайта при пригодной длине контекста. Ровно с этим же ограничением на том же классе железа столкнулся и соседний проект. Поэтому для этого семейства прогнаны только Q8_0, Q5_K_M и Q4_K_M, а базовой линией вместо fp16 служит Q8_0.

Четыре типа серверов: filesystem, git, sqlite и memory, всего 39 инструментов. Для трех из четырех это референсные реализации, а для sqlite пришлось написать свою обертку, повторяющую историческую поверхность инструментов, потому что официальный референсный сервер сейчас не поддерживается апстримом.

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

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

Таблица лидерборда QuantMCP со всеми прогонами, отсортированная по SVR-MCP

Таблица лидерборда QuantMCP со всеми прогонами, отсортированная по SVR-MCP

Полная таблица, которую можно отфильтровать по тиру и уровню квантования прямо в браузере.

Куда смотреть

Весь код и полное описание методики, откуда взято каждое число в этом посте, лежат в репозитории: github.com/Happynood/quant-mcp-bench. Там же в README есть ссылки на все остальное: набор для оценки с фикстурами задач и замороженными схемами инструментов (quantmcp-suite), сырые результаты вместе с данными по CBC и SCI-регрессии (quantmcp-results) и лидерборд в виде Gradio Space (quantmcp-leaderboard). Если хочется контекста, откуда все это выросло, рядом лежит проект-сосед quant-toolcall-bench: тот самый бенчмарк квантования на BFCL, с которым здесь все и сравнивается.

ссылка на оригинал статьи https://habr.com/ru/articles/1057150/