Как написать урок

Урок это список шагов, и каждый описан как то, что должно быть на холсте после него. Приложение читает холст, чтобы понять, где человек, поэтому урок не хранит своего состояния: удалите ноду, и урок вернётся к её шагу. Как уроки выглядят для человека: Как устроены уроки. Эта страница о встроенном уроке в коде; человек делает свой урок в приложении, и такой урок переносится файлом урока: Формат файла урока.

Где что лежит

ЧтоГде
Шагиsrc/shared/lessons/lessons.ts (и src/shared/lessons/sets/ для групп уроков, например семейств моделей для картинок или видео).
Текстыsrc/shared/lessons/texts.en.ts, texts.ru.ts (и sets/*.texts.*.ts), под теми же id урока и шага.
Почему это значениеsrc/shared/lessons/reasons.en.ts, reasons.ru.ts: по одному предложению на правило.
Какой файлsrc/shared/lessons/files.ts (виды файлов моделей, FILES), fileTables.ts (таблицы поздних наборов и пары одного семейства).
Правила, которые соблюдает каждый урокsrc/shared/lessons/schema.ts (lessonProblems).
Проверка холстаsrc/shared/lessons/engine.ts, fit.ts (есть ли в этом ComfyUI то, что нужно уроку), flow.ts.
Файлы уроковsrc/shared/lessons/share/ (format.ts читает и проверяет файл, mine.ts «Мои уроки», authoring.ts редактор, tryLesson.ts проба с пустого холста).
Панельsrc/renderer/components/lessons/LessonPanel.tsx, MyLessons.tsx, LessonEditor.tsx.
Страница викиdocs/wiki/lessons/<Name>.md и .ru.md с комментарием <!-- lesson: <id> -->.

Шаг

{ id: 'model', roles: [node('checkpoint', 'CheckpointLoaderSimple')], fields: [field('checkpoint', 'ckpt_name', chosen)] }
  • read: true: шаг, который только объясняет; человек читает его и идёт дальше. Знание кладите сюда, а шаги с действием держите короткими. Шаг для чтения ничего не просит; шаг, который ничего не просит, должен быть шагом для чтения.
  • roles: ноды, которые должны быть на холсте, у каждой имя роли и классы, которые подходят.
  • links: link(from, output, to, input, via?); via перечисляет ноды, которые могут стоять посередине (загрузчик LoRA).
  • fields: field(role, name, test). Проверки (FieldTest в src/shared/lessons/engine.ts): chosen, equals, between (с prefer, значение, которое ставит «Сделать за меня»; frames для 4n + 1 у Wan), text (наименьшая длина и настоящие слова, метки, которые он должен содержать, латиница, без «без шляпы»), weighted (вес в промпте в диапазоне), file (файл модели нужного вида), sameFamily (LoRA или ControlNet семейства чекпойнта), size и aspect (размер, на котором учили модель), less, same и differs (по сравнению с другим полем) и has-trigger (слова-триггеры выбранной LoRA).
  • why: id предложения в reasons.*.ts. «Осталось сделать» показывает его, когда значение неверное, чтобы человек понял, зачем шагу это значение, а не только что оно неверно.

Пишите собственные имена классов и портов ComfyUI. Урок, чьих классов или входов нет в ComfyUI человека, пишет «Этот урок пока не подходит к вашему ComfyUI» и называет причины, а не даёт неверных указаний.

Какой файл модели

Шаг, который спрашивал только «выбрано ли что-нибудь», засчитывал первый файл списка, каким бы он ни был. Поэтому поле, куда выбирают файл модели, называет нужный вид:

  • FILES в files.ts: вид с семействами, к которым файл может (или не может) относиться, метками, которые его имя должно содержать (high, i2v, umt5) и не должно, папкой внутри models и примером имени. Файл судят по семейству из его метаданных, иначе по имени; файл, о семействе которого ничего не известно, проверяют только по меткам.
  • Набор может дать свои виды таблицей слов (FileRow: has, any, not): VIDEO_FILE_KINDS в sets/video.ts и SET_FILE_KINDS в fileTables.ts. withFileTable ставит каждую строку в её урок.
  • FAMILY_PAIRS в fileTables.ts держит LoRA или ControlNet в семействе чекпойнта, с которым они работают; withFamilyPairs ставит правило на место.
  • О неверном файле говорится словами человека: у каждого вида есть предложение lessons.fileKind.<вид> в каталоге.

Тексты

Для каждого урока: title, result (одна строка: что получится у человека) и для каждого id шага короткий title и body (небольшой markdown: абзацы, список, code). Пишите {role}, чтобы назвать ноду урока: приложение подставит имя ноды так, как его показывает библиотека этого ComfyUI. Простые слова, сначала действие, меню называется так, как его называет меню. Слово из словаря подчёркивается точками там, где встречается впервые, поэтому объяснять его на месте не нужно.

Порядок

  • LESSONS это порядок, в котором человек их встречает, по группам (LESSON_PATH).
  • LESSON_AFTER говорит, на графе какого урока стоит урок (показывается в списке, но не навязывается).
  • Уроки для взрослых (ADULT_LESSONS) закрыты переключателем «Настройки ▸ Приватность ▸ Содержимое для взрослых (18+)» и видны одной закрытой строкой.

Тесты

  • tests/unit/lessonSchema.test.ts прогоняет lessonProblems по каждому уроку: id, шаги, роли до использования, предложение для каждого why, виды файлов, которые знает приложение.
  • tests/unit/lessons.test.ts и lessons.<набор>.test.ts проходят каждый урок с пустого холста до конца, делая то, что он говорит, проверяют, что каждый объясняющий шаг показан один раз и что место в уроке читается по графу (удалённая нода возвращает назад).
  • tests/unit/lessonFit.test.ts проверяет, когда урок подходит к ComfyUI, а когда нет; lessonImageFiles.test.ts и lessonModel.test.ts проверяют виды файлов.
  • tests/unit/lessonFiles.*.test.ts читают, проверяют, хранят, экспортируют и импортируют файлы уроков.
  • tests/unit/wiki.test.ts проверяет, что у каждого id урока есть страница вики с пометкой <!-- lesson: <id> --> на обоих языках.
  • tests/e2e/lessons.test.ts проходит урок в окне.

См. также

Страница перенесена из wiki репозитория приложения (docs/wiki/dev/Writing-A-Lesson.ru.md, ревизия b8e3f71). То же руководство встроено в приложение: «Справка ▸ Руководство».

Чтобы обновить её, выполните npm run import, а затем npm run build в папке сайта.