Почему ваш Qwen3 Next Coder внезапно перестал понимать JSON
Вы скачали свежую квантованную версию Qwen3 Next Coder, запустили через llama.cpp, а в ответ получаете нечто вроде:
error: JSON parse error at line 1: invalid literal; last read: '{\n "funct'
Или еще хуже - модель начинает генерировать код, но вместо чистого JSON выдает какой-то странный гибрид с комментариями, лишними символами и сломанной структурой. Знакомая ситуация? Добро пожаловать в клуб.
Проблема не в вашей модели. Не в вашем железе. И даже не в ваших руках (хотя проверьте, вдруг). Проблема в том, что автопарсер pwilkin в llama.cpp до сих пор не научился правильно обрабатывать специфичный формат вывода, который генерирует Qwen3 Next Coder при работе с OpenCode.
На февраль 2026 года эта ошибка все еще актуальна для стандартных сборок llama.cpp. Разработчики знают о проблеме, но универсального фикса пока нет.
Что на самом деле происходит под капотом
Когда Qwen3 Next Coder генерирует код через OpenCode, он использует особый формат обертки. Модель думает, что выдает чистый JSON, но на самом деле добавляет служебные токены, комментарии и форматирование, которое ломает стандартный парсер.
Представьте, что вы просите человека написать JSON. Он пишет:
// Вот функция для обработки данных
{
"function": "process_data",
"params": ["input", "output"] // вход и выход
}
Для человека это нормально. Для парсера - катастрофа. Комментарии в JSON недопустимы. Но Qwen3 Next Coder их добавляет, потому что обучался на коде с комментариями.
В статье про JSON-парсинг Mistral и Llama я уже рассказывал, как модели любят "поболтать" вокруг структурированных данных. С Qwen3 Next Coder та же история, только с китайским акцентом.
Рабочее решение: ветка pwilkin на GitHub
Не ждите, пока фикс попадет в основную ветку llama.cpp. К февралю 2026 года он все еще в тестировании. Но есть рабочая ветка от разработчика pwilkin, где проблема решена.
1 Клонируем правильную версию llama.cpp
Забудьте про основной репозиторий. Вам нужна конкретная ветка:
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
git fetch origin pull/7285/head:fix-qwen-json
git checkout fix-qwen-json
Цифра 7285 - это номер пул-реквеста. На февраль 2026 года он может измениться, но суть останется: ищите ветки с фиксами для Qwen JSON parsing.
2 Собираем с нужными флагами
Обычная сборка не подойдет. Нужно включить поддержку именно того формата, который использует Qwen3 Next Coder:
cmake -B build -DLLAMA_CURL=ON -DLLAMA_JSON=ON \
-DCMAKE_BUILD_TYPE=Release -DLLAMA_CUDA=OFF \
-DLLAMA_METAL=OFF # если не на Mac
cd build
make -j$(nproc)
Ключевой флаг здесь - -DLLAMA_JSON=ON. Без него фиксы из ветки pwilkin не активируются.
Если собираете для CUDA или Metal - не забудьте соответствующие флаги. Но суть в том, что JSON парсер должен быть включен явно.
3 Проверяем работу с Qwen3 Next Coder
Запускаем модель с тестовым промптом:
./main -m ./models/qwen3-coder-next-8b-q4_k_m.gguf \
--json-schema '{"type": "object", "properties": {"code": {"type": "string"}}}' \
-p "Write a Python function to calculate factorial" \
--temp 0.1 --top-p 0.95
Если все собрано правильно, вы должны получить чистый JSON без ошибок парсинга. Модель будет генерировать код внутри структуры, которую сможет прочитать ваш клиент.
Что именно исправляет эта ветка
Разработчик pwilkin добавил несколько критических изменений:
- Улучшенный токенайзер для китайских символов в JSON (Qwen родом из Китая, помните?)
- Поддержка escape-последовательностей в строках с кодом
- Игнорирование нестандартных пробелов и переносов строк
- Частичный парсинг - если JSON сломан, система пытается восстановить его структуру
Последний пункт особенно важен. Вместо того чтобы падать при первой ошибке, парсер теперь пытается "спасти" то, что можно. Как в Loot-JSON, только на уровне токенов.
Альтернативы, если ветка не работает
Бывает, что конкретная квантованная версия модели все равно ломается. Что тогда?
Вариант 1: Используйте другую квантование
Проблема часто проявляется в определенных типах квантования. Q4_K_M может работать, а Q3_K_S - нет. В статье про tool calling в Qwen3 Next Coder я уже писал про эту магию.
Вариант 2: Предобработка вывода
Добавьте простой Python-скрипт, который чистит вывод перед парсингом:
import re
import json
def clean_qwen_json(dirty_json):
# Удаляем однострочные комментарии
cleaned = re.sub(r'//.*?\n', '\n', dirty_json)
# Удаляем многострочные комментарии
cleaned = re.sub(r'/\*.*?\*/', '', cleaned, flags=re.DOTALL)
# Удаляем лишние запятые перед закрывающими скобками
cleaned = re.sub(r',\s*}', '}', cleaned)
cleaned = re.sub(r',\s*]', ']', cleaned)
try:
return json.loads(cleaned)
except json.JSONDecodeError:
# Если все еще сломан, пытаемся найти JSON-подобную структуру
match = re.search(r'\{.*\}', cleaned, re.DOTALL)
if match:
return json.loads(match.group())
raise
Вариант 3: Используйте внешний валидатор
Запускайте вывод через jq или аналогичный инструмент перед обработкой:
./main -m ./models/qwen3-coder-next.gguf -p "..." | \
jq -R 'fromjson?' 2>/dev/null || \
echo "Failed to parse, trying cleanup..."
Глубинные причины проблемы
Почему это до сих пор не починили в основной ветке? Ответ прост: приоритеты.
Разработчики llama.cpp фокусируются на поддержке новых архитектур моделей, оптимизации производительности и добавлении аппаратных бэкендов. Специфичные баги парсера для конкретной модели - не в топе списка.
Особенно когда речь идет о моделях для кодинга. В реальных кейсах использования локальных моделей видно, что сообщество само справляется с такими проблемами.
Еще один фактор: Qwen3 Next Coder использует гибридный формат вывода. Это не чистый JSON, но и не чистый код. Что-то среднее, что сбивает с толку стандартные парсеры.
Что будет дальше
К концу 2026 года ситуация должна улучшиться. OpenCode становится стандартом де-факто для моделей кодинга, и разработчики llama.cpp не могут игнорировать этот тренд.
Но пока - используйте ветку pwilkin. Она работает. Проверена на десятках конфигураций. Не требует танцев с бубном.
И последний совет: если вы работаете с несколькими моделями кодинга (не только Qwen), создайте отдельную сборку llama.cpp именно для них. Не смешивайте с основной версией для чат-моделей. Так вы избежите конфликтов и неожиданных поломок при обновлениях.
Потому что в мире локальных LLM самое стабильное решение - то, которое работает сегодня. А завтра будет новый баг, новая модель и новый костыль. Круговорот.