Пару недель назад я рассказывал здесь, как три ночи чинил рендер, который не был сломан. С тех пор в главном ничего не изменилось: я по-прежнему энтузиаст, а не разработчик; код печатает машина, а что и зачем печатать, решаю я. Правда, машин в этот раз было две: код писала Claude Opus 4.8 в режиме ultracode с рассуждением, выкрученным на максимум (xhigh), а вторая — Fable 5 — атаковала приложение. О нём ближе к концу. Изменилось всё остальное. Typhoonminigen — бесплатное open-source (MIT) нативное macOS-приложение для локальной генерации FLUX.2 Klein на Apple Silicon, без Python, без ComfyUI, без облака — доросло до версии 2.0: 57 новых функций, 150+ исправлений. Про них и статья. Но начать придётся не с функций, а с признания: самый живучий баг приложения сидел не в коде. Он сидел во мне.

Тултип, в который я поверил сам
В 1.0 генерация шла ровно за четыре шага. Не «по умолчанию четыре» — жёстко четыре. Klein — дистиллированная модель, обученная выдавать картинку за 4 шага, так написано в её описании. Я прочитал, поверил и захардкодил четвёрку. Мало того — собственными руками написал тултип: «steps are fixed».
Построил клетку. Повесил табличку. И выложил на GitHub версию 1.0.
А потом я увидел (точнее, запустил аналитику и исследования): сам движок, на котором у меня всё и держится, спокойно гоняет Klein на 10, 20 и даже 50 шагах. Как так? Открыл исходники движка: он принимает любое число шагов. Вообще любое. Никто, кроме меня, ничего не фиксировал. Я твёрдо верил, что максимум — только 4 шага!
В 2.0 на месте таблички — настоящий слайдер от 1 до 50. Сразу скажу знающим: чудес нет, дистилляция никуда не делась, четыре шага остаются сладкой точкой. Но на сложных сценах 10–20 шагов реально дожимают детали — руки, мелкую фактуру, дальние планы. Слайдер до 50 — не обещание, а свобода проверить самому.

В первой статье мораль была «битое и сломанное — разные вещи». Здесь она рифмуется: ограниченное и ограниченное мной — тоже разные вещи. Ограничение было самовнушением. Верой в собственную табличку.
Со свободой разобрались. Теперь — функция, которую я считаю самой крутой во всей версии. Писать про неё придётся аккуратно.
Фото, которое слушается слов
Кидаю в приложение своё фото. Пишу обычным русским языком: «убери со стола лишнее, добавь вечерний свет из окна». Жму Generate — и получаю новую версию сцены: моё фото узнаваемо, просьба выполнена. Референсов теперь до четырёх (было три): можно смешать свою фотографию, стиль и пару объектов.
А теперь — что происходит под капотом на самом деле, иначе вы мне сами в комментариях объясните. Это НЕ инпейнт. Маски нет, пиксели точечно никто не правит. Модель пересоздаёт всю сцену заново, опираясь на фото как на референс. Фон может «пересняться», мелочи — уплыть. Я бы назвал это не «фотошоп словами», а пересъёмка сцены по описанию.
У такой природы есть честный плюс: раз сцена рождается целиком, свет, тени и перспектива в результате согласованы между собой — не получаешь типичного коллажного эффекта, когда объект будто приклеен и живёт с чужими тенями. Для вариаций на тему своего фото, концептов, смены антуража — отлично. «Убрать прыщик, не тронув остальное» — не сюда: за точечной правкой идите в редакторы с масками, тут их нет.

LoRA: лимит, который я тоже выдумал
Второй раз на те же грабли — только теперь я хотя бы узнал их в лицо. В 1.0 можно было подключить максимум два LoRA-адаптера. Почему два? Потому что я перестраховался. Движок просто складывает дельты весов — ему всё равно, сколько их.
В 2.0 адаптеров сколько угодно, у каждого своя сила. Появился свип: одна кнопка — и приложение рендерит шесть картинок одного промпта и сида на силах от 0.6 до 1.1, вместо того чтобы крутить ползунок руками шесть раз, как делал я. Силу можно запечь в копию адаптера, несколько адаптеров — слить в один файл. У адаптеров появились карточки с описанием и происхождением, в промпте работает плейсхолдер [trigger], а импорт идёт прямо по ссылке Hugging Face — с проверкой совместимости ДО скачивания, а не после того, как гигабайты уже слиты.

Чужие адаптеры — хорошо. Но раз лимитов больше нет, логичный следующий шаг — учить свои.
Приложение, которое говорит «нет»
Обучение LoRA прямо в приложении — самая большая новая система. Родилась она из самой громкой аварии.
Первый запуск обучения 9B заморозил мой Mac намертво. 32 ГБ памяти, своп раздулся, диск кончился, курсор умер. Холодный старт кнопкой — тот самый жест, который надеешься никогда не делать на Маке.
Из этой заморозки выросла функция: приложение теперь считает заранее. Прошу обучить 9B на 32 гигабайтах — оно отказывается: 9B нужно 48+ ГБ, вот кнопка 4B. Сначала обидно. Потом понимаешь: приложение, которое умеет говорить «нет», — это фича. 4B на 32 ГБ обучается спокойно. Оттуда же, из заморозки, — живая телеметрия CPU/GPU/RAM/MLX/диска и красный чип в статус-баре, который загорается ДО того, как своп и диск заморозят Mac, а не после.

Само обучение устроено так: мастерская, 10–50 своих фото, локальная vision-модель сама пишет подписи, подписи правятся пачкой через найти/заменить. Дальше — живая кривая loss, чекпоинты, пауза и стоп, очередь тренировок одна за другой: ночной конвейер.
И моя любимая деталь — матрица сравнения чекпоинтов. Валидационные промпты по столбцам, чекпоинты по строкам, а сверху пришпилена строка «без LoRA вообще». Если твой чекпоинт выглядит как она — LoRA ничему не научилась, и никакие «да вроде похоже» не спасут. Строка сверху ловит тебя на вранье самому себе. Лучший чекпоинт публикуется в библиотеку одним нажатием, а если недожал — обучение продлевается на +250/+500/+1000 шагов.
Вкладка Models: скучная часть, которой я горжусь
Всему этому хозяйству нужны веса — и раньше моделей было, по сути, две. Теперь — целая вкладка: Klein 4B и 9B, у каждого варианты квантования на выбор (4B — Low/Medium/Better/Best, 9B — Standard/Best), отдельные текст-энкодеры Qwen3 в 8-bit и 4-bit, базовые недистиллированные веса для обучения, общий VAE, vision-модель в 4-bit/8-bit.

Про эти Low/Medium/Better/Best стоит сказать отдельно, потому что в 1.0 такого выбора не было вообще: каждая модель качалась в одном-единственном виде — как я решил, так все и жили. Знакомый почерк, да? Теперь качество — ручка под твой Mac: пресет выбирает квантование, то есть точность весов. Best — полный bf16, максимум детали и максимум памяти; Low — восьмибитный трансформер, легче и быстрее. Это не фильтр «получше/похуже», а честный обмен: резкость против гигабайтов и секунд. И деталь, которой я горжусь отдельно: на 9B приложение прямо предупреждает, когда две ступени дадут одинаковую картинку — обе работают на одном bf16-трансформере и различаются только текст-энкодером, так что с обоими энкодерами на диске Standard и Best отрендерят одно и то же. Приложение, которое отговаривает тебя качать лишние гигабайты, — тоже фича.

А вот скучная часть, которой я горжусь: большие файлы качаются в шесть параллельных потоков и переживают отмену, выход и краш — каждый кусок продолжается со своего байта. Есть очередь загрузок, и вкладка не блокируется, пока что-то качается. Кто хоть раз терял 20 гигабайт на 97% — поймёт.


Один ИИ подставил другого
В приложении живёт локальный помощник — ничего не уходит с Mac. Describe описывает загруженное фото в готовый промпт. Ask отвечает на вопросы о твоём рендере: «читается ли текст?», «что не так со светом?». Compare оценивает, насколько рендер попал в референс, — по сцене и стилю, от 0 до 10.
А улучшайзер промпта стал прозрачным: переписанный им промпт сохраняется и виден в галерее — что модель видела на самом деле. Прозрачность окупилась быстро. На одном рендере вылезла кривая надпись «LIGTHOFE». Я её не просил. Открываю сохранённый промпт — улучшайзер сам дописал «с элегантной надписью». Один ИИ подставил другого, а сдал обоих лог. Без сохранённого промпта я бы опять три ночи искал несуществующий баг рендера.


Можно спросить и на русском языке.

Картинка смертна, рецепт — нет
Теперь можно собрать десятки разных задач и нажать Run all. На бегущей задаче — живой «шаг X из N» и оценка времени; любую можно поднять в топ, продублировать — с тем же сидом, со случайными или с последовательными, — запустить батчем. Рендеры, поставленные во время тренировки LoRA, не падают: молча ждут и стартуют сами, когда тренер освободит GPU.
Галерея научилась искать по промпту, имени LoRA и точному сиду, фильтровать по модели, адаптеру и качеству, помечать варианты одного промпта как «итерация N/M» и апскейлить пачками ×2/×4 через ту же очередь. У каждой картинки записаны скорость в секундах на шаг и пиковая память. А рецепт зашит прямо в PNG: перетащи картинку обратно в приложение — и все настройки восстановятся, даже если из галереи ты её давно удалил.

247 обложек, отрендеренных вручную
Библиотека готовых сцен выросла со ~100 до 247 карточек в 19 студиях. У каждой карточки превью — не стоковая картинка, а реальный рендер именно этого рецепта, с закреплёнными настройками вплоть до сида: тап → Generate → воспроизводишь обложку пиксель в пиксель.
Все 247 превью я отрендерил сам, за несколько вечеров. Это была самая нудная и самая честная работа над версией: если рецепт не выдаёт свою обложку — он не попадает в библиотеку.
Библиотека теперь редактируемая: любые карточки и разделы можно скрыть (и вернуть кнопкой Restore all), можно создавать свои карточки и свои разделы. А кнопка Save as card прямо из формы Generate забирает промпт, чипы, настройки, сид и текущий рендер как обложку — удачный эксперимент превращается в карточку одним нажатием.

Перед релизом я приказал ИИ Fable 5 атаковать
Vibe-coding принято ругать: накодил ИИ — жди дыр. Спорить не буду. Вместо этого расскажу, как доводился релиз.
Перед выпуском я приказал другой новой модели Claude — Fable 5 — не «проверить», а атаковать приложение: девять агентов параллельно, установка «найди, где ломается, не хвали». Код писала одна модель, ломала другая.

За два захода — около ста реальных находок. Например: тренировка, запущенная между задачами очереди, молча сжигала остаток очереди; служебный запрос загрузчика утаскивал токен авторизации на чужой хост; при зеркальной аугментации датасета файлы a_flip.jpg и a.png давали один файл подписей и тихо затирали друг друга.
Потом свежие агенты атаковали сами исправления — и нашли в фиксах ещё 12 багов. Итого около 150 правок за две ночи. Что чинить, а что отбраковать — решал я. Печатал не я, но за качество отвечаю я.

Что честно НЕ умеет
Традиция первой статьи: список того, чего нет. Инпейнта и масок нет. ControlNet нет. Негативных промптов нет. Видео нет. Консистентность персонажа между генерациями не гарантирована. Длинный читаемый текст в кадре — по-прежнему слабое место (см. дело LIGTHOFE).
Для новичков есть тур на первом запуске, вкладка Help про каждую кнопку и окно What’s New после обновления — дальше разберётесь без меня.

Требования: Apple Silicon (M1 и новее), macOS 14+. 16 ГБ хватает для Klein 4B, 32 ГБ — для 9B и для обучения 4B. Klein 4B под Apache 2.0 качается без аккаунта; 9B — non-commercial, нужен бесплатный токен Hugging Face. Приложение бесплатное, open source под MIT, без аккаунтов, промпты можно писать по-русски.
2.0 в цифрах
Напоследок — статистика, я сам её люблю.
- Между релизами прошло 19 дней.
- Кода на Swift стало вдвое больше: было ~11,7 тысячи строк, стало ~25,4 тысячи; файлов — было 54, стало 74.
- Новых функций — 57, исправлений — больше 150.
- Готовых сцен — 247 в 19 студиях, и у всех 247 обложки отрендерены вручную.
- Скачиваемых компонентов моделей во вкладке Models — 14.
- Атака перед релизом: 9 агентов, около 100 находок, и ещё 12 багов — в самих исправлениях.


Клетки и таблички
Ещё несколько недель назад я воевал с полосами на картинках и считал, что четыре шага — закон природы. Сегодня приложение учит LoRA по ночам, отказывается от задач, которые не влезут в память, и хранит рецепт каждой картинки в ней самой. Из этого я вынес одно: если точно знаешь, чего хочешь, — сделать это теперь можно и без профильного образования. Клетки по дороге в основном свои собственные. И таблички на них — тоже.
Исходники — на GitHub
Попробуйте на своём Mac: комфортно — от 16 ГБ, но Klein 4B заводится даже на 8, пусть и со скрипом. А если что-то пойдёт не так или чего-то не хватит — напишите, мне правда интересно.
