← Все статьи

Fine-tuning Qwen 3 0.6B: с 10% до 92% точности классификации вопросов

Эксперимент с домашним чат-ботом: как дообучить крошечную локальную LLM через Unsloth и двухбуквенные коды категорий вместо имён меток.

Содержание

Коротко

Автор строит домашний чат-бот с RAG по бытовым вопросам — от бассейна до записи к врачу. Перед векторным поиском вопрос прогоняется через классификатор на Qwen 3 0.6B (600M параметров). Промпт без дообучения дал ~10% точности; после дообучения через Unsloth и смены формата ответа на двухбуквенные коды — ~92%.

Что произошло

Идея простая: индекс в векторной базе размечен метаданными (категории вроде pool, hvac, cooking). Запрос «Когда меняли насос в бассейне?» сначала должен попасть в категорию pool, и только потом искать среди релевантных записей — так сужается пространство поиска и растёт качество RAG.

Для ответов на общие вопросы автор использует Qwen 3 4B, а для классификации — сверхлёгкую Qwen 3 0.6B локально через Ollama. Гипотеза: хватит ли 600M параметров, если показать модели ~850 размеченных пар «вопрос → категория» и прогнать QLoRA в Unsloth.

Базовая линия — только промпт с жёстким списком из 19 категорий и требованием вернуть ровно одно имя. На батарее из 131 интеграционного теста правильных ответов было 13 (~10%). Типичные сбои: модель злоупотребляет широкими метками вроде electric, выдумывает категории (apartments) или возвращает фрагменты вместо полного имени.

Первое дообучение подняло точность до ~79%, но оставались обрезанные ответы (ac вместо hvac) и путаница между семантически близкими темами (вода: pool, water heater, fountain). Второй эксперимент — вместо имён категорий модель учат выдавать фиксированные двухбуквенные коды (KK = hvac, OO = pool и т.д.) без пересекающегося смысла в тексте ответа. Точность выросла до ~92% (120 из 131). Оставшиеся 11 ошибок в основном «водные» категории: water heaterpool, guttersmosquito.

Почему это важно

Классификация перед RAG — дешёвый способ улучшить полноту поиска без раздувания эмбеддинг-индекса. Маленькая модель на CPU/GPU потребляет меньше, чем гонять каждый запрос через 4B+, и её можно переобучать на новых категориях дома или офиса.

Статья наглядно показывает, что формат выхода важнее «ещё одного абзаца в промпте»: короткие непересекающиеся коды стабилизируют генерацию у крошечных LLM лучше, чем свободный текст с 19 длинными метками. Это переносимо на маршрутизацию запросов, первичную сортировку обращений в поддержке, фильтрацию логов — везде, где нужен дешёвый предварительный классификатор.

Автор также отмечает цикл обратной связи: пользовательские исправления можно добавлять в датасет для следующего цикла дообучения, не переписывая весь пайплайн.

На практике

  1. Зафиксируйте базовую линию — прогоните «сырую» модель на отложенном тесте до любого дообучения; без цифр не видно, помогло ли дообучение.
  2. Датасет — ~850 примеров с разбиением 70/15/15 (обучение/валидация/тест); следите за балансом редких категорий.
  3. Unsloth + QLoRA — стартовые гиперпараметры из документации часто достаточны; важнее качество разметки, чем тонкая настройка на первом проходе.
  4. Формат ответа — попробуйте неизменяемые коды фиксированной длины вместо имён классов, если модель «обрезает» или путает похожие слова.
  5. Постобработка — маппинг код → категория на стороне приложения; при необходимости нормализуйте синонимы (achvac).
  6. Альтернатива — автор добавил отдельную статью с логистической регрессией на эмбеддингах; для некоторых задач классический ML проще, чем LLM-классификатор.
Этап Точность (131 тест)
Промпт без дообучения ~10%
Fine-tuning, имена категорий ~79%
Fine-tuning, двухбуквенные коды ~92%

Итог

Домашний эксперимент — хороший кейс «маленькая LLM как узкий инструмент»: не заменяет большую модель для ответов, но надёжно режет поток запросов по метаданным. Если строите локальный RAG, имеет смысл заложить отдельный лёгкий классификатор и экспериментировать с форматом меток до раздувания промпта.