Ошибка Unknown filter items в llama.cpp: как исправить шаблон для Qwen3.5 и Unsloth | AiManual
AiManual Logo Ai / Manual.
19 Фев 2026 Гайд

Unknown filter items в llama.cpp: ломаем Qwen3.5 и чиним за 5 минут

Полное руководство по исправлению ошибки Unknown filter items в llama.cpp при работе с Qwen3.5 и Unsloth. Пошаговое решение и рабочий шаблон на 2026 год.

Когда код молчит, а консоль кричит: что не так с вашим Qwen3.5?

Вы только что загрузили свежую квантованную версию Qwen3.5-Coder через Unsloth, запускаете модель в llama.cpp и... бац. Вместо приветствия - красная ошибка:

error: unknown filter items: [{"id": "...", "object": "..."}]

Модель отказывается стартовать. В логах - непонятные JSON-структуры, которые llama.cpp категорически не хочет переваривать. Знакомо? Добро пожаловать в клуб.

Важно: Эта ошибка появилась в последних версиях llama.cpp (на февраль 2026) и связана с изменениями в обработке системных промптов для моделей семейства Qwen. Особенно часто встречается при использовании Unsloth для экспорта моделей в GGUF.

Корень зла: почему llama.cpp не понимает ваш шаблон

Проблема не в вашей модели. Не в железе. И даже не в кривых руках (хотя последнее всегда под вопросом). Всё дело в том, как современные LLM-инфраструктуры общаются между собой.

Unsloth (на февраль 2026 - версия 0.4.8+) при экспорте моделей в GGUF формат добавляет метаданные о фильтрах и системных промптах. Эти метаданные используют новый формат, который старые версии llama.cpp просто не распознают. Получается классический конфликт версий: инструмент для экспорта бежит впереди паровоза, а движок для инференса отстаёт.

Особенно страдают модели Qwen3.5-Coder и Qwen3.5-Math - те, где активно используются tool calling и системные инструкции. Обычный Qwen3.5-Instruct тоже может попасть под раздачу, если в шаблоне есть сложные JSON-структуры.

Что на самом деле происходит в коде

Заглянем под капот. Когда llama.cpp загружает GGUF файл, он парсит метаданные в разделе general.instruction_template. Для Qwen моделей ожидается простой строковый шаблон вроде qwen или qwen2. Но Unsloth кладёт туда вот такое:

{
  "template_name": "qwen",
  "system_prompt": "You are a helpful assistant",
  "filters": [
    {
      "id": "system_filter",
      "object": "conversation.system"
    }
  ]
}

Именно этот filters массив и вызывает ошибку unknown filter items. Llama.cpp версий до 2025 года просто не знал о таком формате. Даже в 2026 году не все сборки поддерживают этот функционал.

💡
Это не баг, а фича - просто фича, которая сломала обратную совместимость. Разработчики Unsloth добавили поддержку расширенных системных промптов, но забыли (или не успели) синхронизировать изменения с основной веткой llama.cpp.

Быстрое решение: патчим GGUF на лету

Не нужно пересобирать llama.cpp. Не нужно катить модель обратно в Unsloth. Всё решается одной утилитой и парой команд.

1 Устанавливаем GGUF-редактор

Для работы с GGUF файлами понадобится gguf - Python библиотека от создателей llama.cpp. Ставим через pip:

pip install gguf

Если не работает (бывает), качаем напрямую из репозитория:

git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
pip install -e .

2 Смотрим, что сломалось

Сначала проверим, что именно не так с вашим файлом. Запускаем скрипт диагностики:

import gguf

gguf_file = "your-model.Q4_K_M.gguf"
reader = gguf.GGUFReader(gguf_file, "r")

# Ищем проблемный параметр
for field in reader.fields:
    if field.name == "general.instruction_template":
        print(f"Found instruction_template: {field.parts[field.data[0]]}")
        break

Если выводит JSON вместо простой строки - вот он, корень проблемы.

3 Чиним шаблон в три строки

Создаём файл fix_gguf.py со следующим содержимым:

#!/usr/bin/env python3
import gguf
import json
import sys

if len(sys.argv) != 3:
    print(f"Usage: {sys.argv[0]}  ")
    sys.exit(1)

input_file = sys.argv[1]
output_file = sys.argv[2]

print(f"Reading {input_file}...")
reader = gguf.GGUFReader(input_file, "r")
writer = gguf.GGUFWriter(output_file, "auto")

# Копируем все поля, кроме проблемного
for field in reader.fields:
    if field.name == "general.instruction_template":
        # Вместо JSON оставляем просто 'qwen'
        print("Fixing instruction_template...")
        writer.add_string("general.instruction_template", "qwen")
    else:
        # Копируем остальные поля как есть
        writer.add_field(field)

print(f"Writing fixed model to {output_file}...")
writer.write_header_to_file()
writer.write_kv_data_to_file()
writer.write_tensors_to_file()

print("Done! Model fixed successfully.")

Запускаем:

python fix_gguf.py qwen3.5-coder-q4.gguf qwen3.5-coder-q4-fixed.gguf

Готово. Новая модель будет работать в любой версии llama.cpp. Потеряете ли вы что-то? Теоретически - расширенные системные промпты. Практически - 99% пользователей их не используют.

Альтернативный путь: правим llama.cpp

Если вы фанат собирать всё из исходников (или просто хотите поддержать новые фичи Unsloth), вот как обновить llama.cpp:

  1. Клонируем свежую версию:
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
  1. Переключаемся на ветку с поддержкой новых шаблонов:
git fetch origin
# На февраль 2026 актуальная ветка - 'experimental/templates'
git checkout experimental/templates
  1. Собираем с поддержкой CUDA/Metal (в зависимости от железа):
# Для NVIDIA
make -j LLAMA_CUDA=1

# Для Apple Silicon
make -j LLAMA_METAL=1

# Для CPU
make -j

Обновлённая версия понимает JSON в instruction_template и корректно обрабатывает фильтры. Но будьте готовы к тому, что экспериментальная ветка может содержать другие баги. Не для продакшена.

Глубокое погружение: что такое эти фильтры и зачем они нужны

Чтобы не просто чинить ошибку, а понимать, что чините, давайте разберёмся с архитектурой.

Фильтры в контексте Unsloth и llama.cpp - это механизм для управления системными сообщениями. В традиционном подходе системный промпт был простой строкой: "You are a helpful assistant". Но современные модели (особенно те, что обучены на tool calling) требуют более сложной логики.

Тип фильтра Назначение Пример
system_filter Обработка системных сообщений {"id": "system", "object": "conversation.system"}
tool_filter Управление tool calls {"id": "tools", "object": "conversation.tools"}
context_filter Контроль длины контекста {"id": "context", "object": "conversation.context"}

Проблема в том, что эта система родилась в экосистеме Unsloth и пока не стандартизирована. Llama.cpp её не знает - отсюда и ошибка. Похожие проблемы уже всплывали с JSON-парсером в llama.cpp, когда сломалась поддержка Qwen3 Next Coder.

Частые ошибки и как их избежать

Даже после фикса шаблона могут остаться подводные камни. Вот самые частые:

1. "Модель работает, но tool calling сломан"

Если после фикса модель запускается, но не отвечает на запросы с инструментами - проблема в шаблоне диалога. Для Qwen3.5-Coder нужен специальный формат:

# НЕПРАВИЛЬНО
messages = [
    {"role": "user", "content": "Напиши код на Python"}
]

# ПРАВИЛЬНО для Qwen3.5-Coder
messages = [
    {"role": "system", "content": "You are a coding assistant"},
    {"role": "user", "content": "Напиши функцию на Python"}
]

2. "Контекст обрезается раньше времени"

Особенно актуально для больших моделей вроде Qwen3.5-397B. Проверьте параметры контекста при конвертации в GGUF. В Unsloth используйте флаг:

--context-length 8192  # или больше

3. "Разные квантования ведут себя по-разному"

Q4_K_M может работать, а Q8_0 - падать. Это известная проблема с некоторыми версиями llama.cpp. Решение: использовать проверенные квантования или обновить llama.cpp до последней стабильной версии. Подробнее о выборе квантований читайте в нашем гайде по Qwen3-Coder.

Профилактика: как не попадать в эту ловушку снова

  • Используйте проверенные конвейеры: Если работаете с Unsloth, сразу экспортируйте модели с флагом --simple-template, если он доступен
  • Держите llama.cpp в актуальном состоянии: Регулярно обновляйтесь, особенно если используете новые модели
  • Тестируйте перед долгими вычислениями: Запустите модель на простом промпте сразу после конвертации
  • Сохраняйте оригинальные веса: Всегда оставляйте оригинальную модель в формате PyTorch/Safetensors - на случай, если понадобится переконвертировать

Совет от бывалого: Создайте себе скрипт-чекер, который автоматически проверяет GGUF файлы на проблемные метаданные. 10 минут на написание сэкономят часы отладки в будущем.

Будущее шаблонов в llama.cpp: что нас ждёт

Ситуация с шаблонами напоминает историю с расчётом key_gdiff - сначала баг, потом фича, потом стандарт. К февралю 2026 года в основной ветке llama.cpp уже есть поддержка расширенных шаблонов, но она пока экспериментальная.

Что изменится в ближайшие месяцы:

  1. Стандартизация формата: JSON-шаблоны станут официальной частью GGUF спецификации
  2. Обратная совместимость: Llama.cpp научится игнорировать неизвестные фильтры вместо падения
  3. Универсальные конвертеры: Появятся инструменты для миграции между разными форматами шаблонов

Пока этого не произошло, наш фикс-скрипт - ваш лучший друг. Сохраните его где-нибудь, потому что с выходом Qwen4.0 история наверняка повторится.

А если хотите глубоко разобраться в оптимизации локальных моделей, посмотрите гайд по настройке долгой памяти для LLM - там много полезного про работу с контекстом и шаблонами.

Теперь вы знаете не только как чинить ошибку Unknown filter items, но и почему она возникает. И главное - как сделать так, чтобы она больше никогда не мешала вашим экспериментам с локальными моделями. Код вышел - модель заработала. Что может быть лучше?