Железо
UGREEN DXP4800 Pro — обычный четырёхдисковый NAS. Внутри Intel Core i3-1315U: 2 производительных и 4 энергоэффективных ядра, 8 потоков. Памяти 32 ГБ DDR5, видеокарты нет — только встроенная графика Intel (Xe, 64 исполнительных блока), которая берёт память из тех же 32 ГБ. NPU нет.
Пока шли тесты, NAS продолжал работать NAS'ом: Home Assistant и остальные домашние сервисы крутились как обычно. Так что цифры — это то, что получится в жизни, а не на стерильном стенде.
Правила
- Каждый движок — в своём Docker-контейнере с лимитом 20 ГБ памяти, строго по одному. После прогона контейнер удаляется.
- Всё на отдельном SSD: модели, датасеты, результаты. Системный диск NAS и фотоархив не трогали.
- Повторяемость:
temperature 0, фиксированный seed, медианы вместо средних. Все сырые ответы моделей сохранены, отчёты генерируются скриптами из них. - Кто что делал. Тесты, скрипты и отчёты делал Claude — ИИ-агент, который работал с NAS по ssh. Владелец NAS решал, что и зачем тестировать, и слушал синтез речи вслепую.
Чем гоняли
| Движок | Для чего | Где |
|---|---|---|
| llama.cpp (Vulkan) | LLM, VLM, OCR-модели, эмбеддинги, Qwen3-ASR | iGPU |
| OpenVINO Model Server | whisper | iGPU / CPU |
| Immich ML (OpenVINO / CPU) | поиск по фото, лица, OCR | iGPU / CPU |
| whisper.cpp | whisper для сравнения | iGPU / CPU |
| onnx-asr | Parakeet, Canary, Vosk | CPU |
| audio.cpp | Qwen3-TTS, CosyVoice3, OmniVoice, Supertonic | iGPU / CPU |
| PyTorch / piper-tts | Silero, Piper, Borealis | CPU |
| stable-diffusion.cpp | генерация картинок | iGPU (Vulkan, SYCL) |
Как оценивали качество
- Публичные датасеты с эталонными ответами: FLEURS (речь), Crossmodal-3600 (фото с подписями на 36 языках), CVQA, MMStar, ChartQA (вопросы по картинкам), Belebele, Global-MMLU, MGSM (понимание, знания, арифметика), MIRACL и XQuAD (поиск и ответы), JSONSchemaBench.
- Синтетика с заранее известным ответом. Документы, счета и квитанции ЖКХ, голосовые команды для Home Assistant, фото вывесок, 195 фраз-ловушек для синтеза речи. Мы сами их сгенерировали, поэтому правильный ответ известен до последней буквы.
- Круговые проверки. Синтезированную речь распознаём лучшим STT и сравниваем с исходным текстом.
- Живая оценка там, где автоматика слепа. Ударения и интонацию слушал человек, вслепую. Описания фото по пятибалльной шкале оценивал Claude, сверяясь с самими фото.
Про маленькие выборки
Во многих тестах 40–200 вопросов. Разница в 2–5 пунктов между соседними моделями — часто просто шум. На страницах мы стараемся это проговаривать и не делать выводов из мелких различий.
Грабли
Всё, на что мы наступили. Если будешь поднимать такое у себя, проверь этот список заранее.
llama.cpp на встроенной графике Intel
--cache-ram 0— обязательно. Без него каждый запрос с новым промптом получает +10 секунд непонятной задержки.- Gemma 4: только с
--swa-fullиcache_prompt: falseв каждом запросе, иначе мусор в ответах или зависание видеокарты. - Модели с динамическим разрешением картинок (Qwen3-VL, Qwen3.5):
--image-max-tokens 1024. Без этого фото с телефона превращается в 8 тысяч токенов и минуты ожидания. - dots.ocr:
--no-mmproj-offload, иначе на Vulkan пишет «tasktasktask…». PaddleOCR-VL требует свой--chat-template-file.
Модели со зрением
- Лимит
--image-max-tokensломает Gemma 4 и Qwen3.6 — вместо него фото лучше заранее уменьшить до ~1024 px. - Визуальный энкодер Qwen3.6 и Gemma 4 26B на Vulkan сбоит («the CLIP graph uses unsupported operators by the backend»): через несколько запросов модель залипает на одном ответе. Лечится
--no-mmproj-offload— энкодер на CPU, ~50 с на фото. - Gemma 4 26B с картинками — ровно 12K контекста: на 8K мусор, на 16K не хватает 20 ГБ.
Генерация картинок (stable-diffusion.cpp)
- На Vulkan FLUX.2/FLUX.3 Klein и Z-Image рисуют чистый шум — ломается диффузионная модель. Работает SYCL (образ
master-sycl). sd-serverна SYCL зависает на второй картинке — запускайsd-cliна каждую картинку (минута на старт).- На 768 px SYCL без
--vae-tilingдекодирует только полосу посередине кадра. - Пока идёт генерация, другим моделям на iGPU места нет — иначе «failed during weight preparation».
Очереди на NAS
- У каждого шага цепочки —
timeout, а маркеры конца проверяй строкой целиком (grep -qx):grep -q FINAL_DONEоднажды «нашёл»VLM_FINAL_DONE, и две тяжёлые задачи запустились одновременно.
JSON и вызов инструментов
- В JSON Schema для llama.cpp пиши
[0-9], а не\d:\dграмматика молча пропускает и ничего не проверяет. - Задавай
maxLengthу строк, иначе модель может уйти в бесконечную строку под грамматикой. - gpt-oss и LFM2.5 не принимают грамматику
root ::= [ABCD]— сервер отвечает ошибкой 500. - Vistral-24B вообще не вызывает инструменты, отвечает текстом.
Речь
- OVMS whisper живёт на
/v3/audio/transcriptions, а не на/v1. - Qwen3-ASR через llama-server возвращает текст с префиксом
language Russian<asr_text>, его надо срезать. - Parakeet на коротких кусках после VAD иногда переходит на украинский. Задать язык нельзя.
- Silero без нормализации текста выбрасывает цифры и латиницу. Supertonic падает на «₽».
- Whisper всегда кодирует 30 секунд аудио, поэтому короткая команда стоит столько же, сколько длинная фраза.
Immich
- Модель поиска по умолчанию не понимает русский. Меняй до первой индексации.
- ESLAV OCR (единственный, кто читает кириллицу) в v3.3.3 не запускается на OpenVINO, только на CPU.
Сухие отчёты
Подробные отчёты каждой фазы — со всеми таблицами, методикой и ограничениями:
- 🔍 Фаза 1 · Immich — Поиск по фото
- 🎙️ Фаза 2 · STT — Распознавание речи
- 🗣️ Фаза 3 · TTS — Синтез речи
- 🏠 Фаза 4 · STT → LLM → TTS — Голосовой ассистент
- 💬 Фаза 5 · LLM — Языковые модели
- 📄 Фаза 6 · OCR — Документы и OCR
- 👁️ Фаза 7 · VLM — Вопросы по фото
- 📚 Фаза 8 · RAG — Поиск по документам (RAG)
- 🎨 Фаза 9 · генерация — Картинки по описанию