Qwen3-0.6B RU Struct v2 (GGUF, Q4_K_M)
Дообученный под извлечение структурированного резюме из русской переписки. Модель не сочиняет текст, а заполняет фиксированную JSON-схему; красивый ответ строит детерминированный рендерер в приложении. Подход и обоснование — ADR-0019 в репозитории проекта.
Часть диплома «кроссплатформенный мессенджер с E2EE и on-device AI»: модель работает локально на устройстве, данные переписки не покидают телефон.
Схема вывода
{"topic": "str", "when": "str|null", "place": "str|null",
"people": ["str"], "actions": [{"who": "str", "what": "str"}],
"mood": "+|0|-", "open": "str|null"}
Пустые поля — null, пустые списки — []. Поля не должны выдумываться:
если в переписке нет факта — null, а не правдоподобное значение.
Формат запроса
Qwen3 — reasoning-модель: в системный промпт добавляется /no_think,
иначе ответ уходит в reasoning_content и content приходит пустым.
Схема на русском, ответ — строго JSON-объект.
Качество
Оценка на внутреннем наборе (406 входов: 400 синтетических от генератора
переписок + 6 написанных вручную). Метрики считаются одним кодом
(tools/ram-bench/structured.py), поля сверяются с разметкой входа, а не с
ответом модели.
| Набор | valid | поля | грундинг | воздержание |
|---|---|---|---|---|
| Синтетика (400) | 0.746 (с GBNF 1.000) | 1.000 | 1.000 | 1.000 |
| Ручные (6) | — | 6/6 | 6/6 | 1/1 |
Грундинг — доля значений, дословно присутствующих во входе (защита от выдумывания). Воздержание — доля пустых переписок, на которых модель честно вернула «нет фактов».
На устройстве (realme RMX5377, Q4_K_M, llama-cli, 60 входов):
без GBNF valid 0.900; с GBNF valid 1.000, поля 0.994, грундинг 1.000.
Использование
llama-cli -m qwen3-struct-v2-Q4_K_M.gguf \
--temp 0 -no-cnv \
-p '<system>/no_think</system>\n<user>Инструкция…\n\nАня: привет</user>'
В приложении грамматика не передаётся: llama_cpp_dart 0.9.0-dev.12 в
_prefill кормит GBNF токенами промпта и падает на его тексте. Валидность
держится обучением, а не декодером.
Артефакты в репозитории
| Файл | Назначение |
|---|---|
qwen3-struct-v2-Q4_K_M.gguf | для приложения (397 МБ) |
adapter/ | LoRA-адаптер — воспроизводимость дообучения (40 МБ) |
merged/ | merged bf16 в формате HF transformers (1.2 ГБ) |
SHA-256 GGUF: f0f3d707d1f28ebabd92c38a00d1321298d42e7e39e45d0f443612b283ce1b90
(приложение проверяет его при докачке — FR-32).
Обучение
- База:
Qwen/Qwen3-0.6B(Apache-2.0) - LoRA, затем merge и конвертация в GGUF, квант Q4_K_M (397 МБ)
- Данные: 14 826 примеров (8 944 структурированных + replay), из них синтетика от генератора переписок и дистилляция с более крупной модели
- Датасет v5_v2: утечка между train и eval — 0
Ограничения
- Домен — бытовая русская переписка; на других темах качество не измерялось.
- Синтетика даёт 100% полей, ручные входы — хуже: метрика на генераторе не заменяет проверку на живых примерах (см. ADR-0019 и отчёт #193).
- Воздержание обучено, но на нестандартных входах возможны правдоподобные выдумки — приложение показывает поля пользователю, а не действует по ним.
- GBNF в приложении отключён (баг биндинга), поэтому валидность 0.900, а не 1.000; JSON-парсер терпимый и уводит в fallback на сырой текст.
Происхождение
Дообучение и оценка — в рамках дипломного проекта. Артефакты и скрипты:
tools/train/ и tools/ram-bench/ в репозитории проекта.