import React from 'react'; import Link from 'next/link'; import { GroupedSelectOption, SelectOption, JobConfig, ConfigDoc } from '@/types'; import { defaultSliderConfig } from './jobConfig'; import { defaultAudioSampleConfig, defaultSampleConfig, defaultIdeogramSamplesConfig, defaultYue2SampleConfig, defaultQwen25OmniSampleConfig, } from '@/helpers/defaultSamples'; type Control = 'depth' | 'line' | 'pose' | 'inpaint'; type DisableableSections = | 'model.quantize' | 'model.quantize_te' | 'train.timestep_type' | 'network.conv' | 'trigger_word' | 'train.diff_output_preservation' | 'train.blank_prompt_preservation' | 'train.unload_text_encoder' | 'slider'; type AdditionalSections = | 'datasets.control_path' | 'datasets.multi_control_paths' | 'datasets.do_i2v' | 'datasets.do_audio' | 'datasets.audio_normalize' | 'datasets.audio_preserve_pitch' | 'datasets.auto_frame_count' | 'sample.ctrl_img' | 'sample.multi_ctrl_imgs' | 'sample.duration' | 'train.audio_loss_multiplier' | 'datasets.num_frames' | 'model.multistage' | 'model.layer_offloading' | 'model.low_vram' | 'model.qie.match_target_res' | 'model.assistant_lora_path' | 'model.unconditional_lora_path' | 'model.model_kwargs.kv_cache' | 'model.model_kwargs.instruction' | 'ideogram_4_prompt'; type ModelGroup = 'image' | 'instruction' | 'video' | 'experimental' | 'audio' | 'llm'; export interface CustomModelSelectOption { label: string; options: SelectOption[]; getValue: (config: JobConfig) => string | undefined; onChange: (value: string, config: JobConfig, setJobConfig: (value: any, key: string) => void) => void; doc?: ConfigDoc; } export type SampleTag = { title: string; type: 'text' | 'multiline' | 'number'; full?: boolean; }; export interface SampleTags { [key: string]: SampleTag; } export type GenerateModality = 'image' | 'video' | 'audio'; // Per-arch overrides for the Generate page. Everything it needs is derived // from the training entry (name_or_path / quantize defaults, video/audio // group, ctrl_img section); set these only where the derivation is wrong. export interface GenerateOptions { modality?: GenerateModality; model?: { [key: string]: any }; // extra ModelConfig kwargs sample?: { [key: string]: any }; // GenerateImageConfig kwargs needsControlImage?: boolean; sizeLocked?: boolean; } export interface GenerateDefaults { arch: string; label: string; group: ModelGroup; modality: GenerateModality; model: { [key: string]: any }; sample: { [key: string]: any }; needsControlImage: boolean; sizeLocked: boolean; /** structured prompt fields (audio models): the prompt is their tagged form */ sampleTags?: SampleTags; } export interface ModelArch { name: string; label: string; /** label shown by the Generate page instead of `label` (training-specific * wording like "w/ Training Adapter" does not apply to inference) */ generateNameOverride?: string; group: ModelGroup; generate?: GenerateOptions; controls?: Control[]; isVideoModel?: boolean; hasMultiLinePrompts?: boolean; defaults?: { [key: string]: any }; disableSections?: DisableableSections[]; additionalSections?: AdditionalSections[]; accuracyRecoveryAdapters?: { [key: string]: string }; sampleTags?: SampleTags; gateUrl?: string; modelNotes?: React.ReactNode; customModelSelectOptions?: CustomModelSelectOption[]; } const defaultNameOrPath = ''; const defaultLinearRank = 32; export const modelArchs: ModelArch[] = [ { name: 'anima', label: 'Anima', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['circlestone-labs/Anima-Base-v1.0-Diffusers', defaultNameOrPath], 'config.process[0].model.quantize': [false, false], 'config.process[0].model.quantize_te': [false, false], 'config.process[0].model.qtype': ['', 'qfloat8'], 'config.process[0].model.qtype_te': ['', 'qfloat8'], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].sample.neg': [ 'worst quality, low quality, score_1, score_2, score_3, blurry, jpeg artifacts, sepia, signature, artist name', '', ], }, disableSections: ['network.conv'], additionalSections: ['model.low_vram', 'model.layer_offloading'], }, { name: 'flux', label: 'FLUX.1', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['black-forest-labs/FLUX.1-dev', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], }, disableSections: ['network.conv'], gateUrl: 'https://huggingface.co/black-forest-labs/FLUX.1-dev', }, { name: 'flux_kontext', label: 'FLUX.1-Kontext-dev', group: 'instruction', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['black-forest-labs/FLUX.1-Kontext-dev', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], }, disableSections: ['network.conv'], additionalSections: ['datasets.control_path', 'sample.ctrl_img'], gateUrl: 'https://huggingface.co/black-forest-labs/FLUX.1-Kontext-dev', }, { name: 'flex1', label: 'Flex.1', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['ostris/Flex.1-alpha', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].train.bypass_guidance_embedding': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], }, disableSections: ['network.conv'], }, { name: 'flex2', label: 'Flex.2', group: 'image', controls: ['depth', 'line', 'pose', 'inpaint'], defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['ostris/Flex.2-preview', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].model.model_kwargs': [ { invert_inpaint_mask_chance: 0.2, inpaint_dropout: 0.5, control_dropout: 0.5, inpaint_random_chance: 0.2, do_random_inpainting: true, random_blur_mask: true, random_dialate_mask: true, }, {}, ], 'config.process[0].train.bypass_guidance_embedding': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], }, disableSections: ['network.conv'], }, { name: 'chroma', label: 'Chroma', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['lodestones/Chroma1-Base', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], }, disableSections: ['network.conv'], }, { name: 'zeta_chroma', label: 'Zeta Chroma', group: 'experimental', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': [ 'lodestones/Zeta-Chroma/zeta-chroma-base-x0-pixel-dino-distance.safetensors', defaultNameOrPath, ], 'config.process[0].model.extras_name_or_path': ['Tongyi-MAI/Z-Image-Turbo', undefined], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], }, disableSections: ['network.conv'], }, { name: 'wan21:1b', label: 'Wan 2.1 (1.3B)', group: 'video', isVideoModel: true, defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Wan-AI/Wan2.1-T2V-1.3B-Diffusers', defaultNameOrPath], 'config.process[0].model.quantize': [false, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].sample.num_frames': [41, 1], 'config.process[0].sample.fps': [16, 1], 'config.process[0].datasets[x].fps': [16, undefined], }, disableSections: ['network.conv'], additionalSections: ['datasets.num_frames', 'model.low_vram', 'datasets.auto_frame_count'], }, { name: 'wan21_i2v:14b480p', label: 'Wan 2.1 I2V (14B-480P)', group: 'video', isVideoModel: true, defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Wan-AI/Wan2.1-I2V-14B-480P-Diffusers', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].sample.num_frames': [41, 1], 'config.process[0].sample.fps': [16, 1], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].datasets[x].fps': [16, undefined], }, disableSections: ['network.conv'], additionalSections: ['sample.ctrl_img', 'datasets.num_frames', 'model.low_vram', 'datasets.auto_frame_count'], }, { name: 'wan21_i2v:14b', label: 'Wan 2.1 I2V (14B-720P)', group: 'video', isVideoModel: true, defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Wan-AI/Wan2.1-I2V-14B-720P-Diffusers', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].sample.num_frames': [41, 1], 'config.process[0].sample.fps': [16, 1], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].datasets[x].fps': [16, undefined], }, disableSections: ['network.conv'], additionalSections: ['sample.ctrl_img', 'datasets.num_frames', 'model.low_vram', 'datasets.auto_frame_count'], }, { name: 'wan21:14b', label: 'Wan 2.1 (14B)', group: 'video', isVideoModel: true, defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Wan-AI/Wan2.1-T2V-14B-Diffusers', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].sample.num_frames': [41, 1], 'config.process[0].sample.fps': [16, 1], 'config.process[0].datasets[x].fps': [16, undefined], }, disableSections: ['network.conv'], additionalSections: ['datasets.num_frames', 'model.low_vram', 'datasets.auto_frame_count'], }, { name: 'wan22_14b:t2v', label: 'Wan 2.2 (14B)', group: 'video', isVideoModel: true, defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['ai-toolkit/Wan2.2-T2V-A14B-Diffusers-bf16', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].sample.num_frames': [41, 1], 'config.process[0].sample.fps': [16, 1], 'config.process[0].model.low_vram': [true, false], 'config.process[0].train.timestep_type': ['linear', 'sigmoid'], 'config.process[0].datasets[x].fps': [16, undefined], 'config.process[0].model.model_kwargs': [ { train_high_noise: true, train_low_noise: true, }, {}, ], }, disableSections: ['network.conv'], additionalSections: [ 'datasets.num_frames', 'model.low_vram', 'model.multistage', 'model.layer_offloading', 'datasets.auto_frame_count', ], accuracyRecoveryAdapters: { // '3 bit with ARA': 'uint3|ostris/accuracy_recovery_adapters/wan22_14b_t2i_torchao_uint3.safetensors', '4 bit with ARA': 'uint4|ostris/accuracy_recovery_adapters/wan22_14b_t2i_torchao_uint4.safetensors', }, }, { name: 'wan22_14b_i2v', label: 'Wan 2.2 I2V (14B)', group: 'video', isVideoModel: true, defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['ai-toolkit/Wan2.2-I2V-A14B-Diffusers-bf16', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].sample.num_frames': [41, 1], 'config.process[0].sample.fps': [16, 1], 'config.process[0].model.low_vram': [true, false], 'config.process[0].train.timestep_type': ['linear', 'sigmoid'], 'config.process[0].datasets[x].fps': [16, undefined], 'config.process[0].model.model_kwargs': [ { train_high_noise: true, train_low_noise: true, }, {}, ], }, disableSections: ['network.conv'], additionalSections: [ 'sample.ctrl_img', 'datasets.num_frames', 'model.low_vram', 'model.multistage', 'model.layer_offloading', 'datasets.auto_frame_count', ], accuracyRecoveryAdapters: { '4 bit with ARA': 'uint4|ostris/accuracy_recovery_adapters/wan22_14b_i2v_torchao_uint4.safetensors', }, }, { name: 'wan22_5b', label: 'Wan 2.2 TI2V (5B)', group: 'video', isVideoModel: true, defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Wan-AI/Wan2.2-TI2V-5B-Diffusers', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].model.low_vram': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].sample.num_frames': [121, 1], 'config.process[0].sample.fps': [24, 1], 'config.process[0].sample.width': [768, 1024], 'config.process[0].sample.height': [768, 1024], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].datasets[x].do_i2v': [true, undefined], 'config.process[0].datasets[x].fps': [24, undefined], }, disableSections: ['network.conv'], additionalSections: [ 'sample.ctrl_img', 'datasets.num_frames', 'model.low_vram', 'datasets.do_i2v', 'datasets.auto_frame_count', ], }, { name: 'lumina2', label: 'Lumina2', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Alpha-VLLM/Lumina-Image-2.0', defaultNameOrPath], 'config.process[0].model.quantize': [false, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], }, disableSections: ['network.conv'], }, { name: 'qwen_image', label: 'Qwen-Image', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Qwen/Qwen-Image', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].model.low_vram': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].model.qtype': ['qfloat8', 'qfloat8'], }, disableSections: ['network.conv'], additionalSections: ['model.low_vram', 'model.layer_offloading'], accuracyRecoveryAdapters: { '3 bit with ARA': 'uint3|ostris/accuracy_recovery_adapters/qwen_image_torchao_uint3.safetensors', }, }, { name: 'qwen_image:2512', label: 'Qwen-Image-2512', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Qwen/Qwen-Image-2512', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].model.low_vram': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].model.qtype': ['qfloat8', 'qfloat8'], }, disableSections: ['network.conv'], additionalSections: ['model.low_vram', 'model.layer_offloading'], // Training an ARA now, the other one will not work accuracyRecoveryAdapters: { '3 bit with ARA': 'uint3|ostris/accuracy_recovery_adapters/qwen_image_2512_torchao_uint3.safetensors', '4 bit with ARA': 'uint4|ostris/accuracy_recovery_adapters/qwen_image_2512_torchao_uint4.safetensors', }, }, { name: 'qwen_image_edit', label: 'Qwen-Image-Edit', group: 'instruction', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Qwen/Qwen-Image-Edit', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].model.low_vram': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].model.qtype': ['qfloat8', 'qfloat8'], }, disableSections: ['network.conv'], additionalSections: ['datasets.control_path', 'sample.ctrl_img', 'model.low_vram', 'model.layer_offloading'], accuracyRecoveryAdapters: { '3 bit with ARA': 'uint3|ostris/accuracy_recovery_adapters/qwen_image_edit_torchao_uint3.safetensors', }, }, { name: 'qwen_image_edit_plus', label: 'Qwen-Image-Edit-2509', group: 'instruction', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Qwen/Qwen-Image-Edit-2509', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].model.low_vram': [true, false], 'config.process[0].train.unload_text_encoder': [false, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].model.qtype': ['qfloat8', 'qfloat8'], 'config.process[0].model.model_kwargs': [ { match_target_res: false, }, {}, ], }, disableSections: ['network.conv', 'train.unload_text_encoder'], additionalSections: [ 'datasets.multi_control_paths', 'sample.multi_ctrl_imgs', 'model.low_vram', 'model.layer_offloading', 'model.qie.match_target_res', ], accuracyRecoveryAdapters: { '3 bit with ARA': 'uint3|ostris/accuracy_recovery_adapters/qwen_image_edit_2509_torchao_uint3.safetensors', }, }, { name: 'qwen_image_edit_plus:2511', label: 'Qwen-Image-Edit-2511', group: 'instruction', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Qwen/Qwen-Image-Edit-2511', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].model.low_vram': [true, false], 'config.process[0].train.unload_text_encoder': [false, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].model.qtype': ['qfloat8', 'qfloat8'], 'config.process[0].model.model_kwargs': [ { match_target_res: false, }, {}, ], }, disableSections: ['network.conv', 'train.unload_text_encoder'], additionalSections: [ 'datasets.multi_control_paths', 'sample.multi_ctrl_imgs', 'model.low_vram', 'model.layer_offloading', 'model.qie.match_target_res', ], accuracyRecoveryAdapters: { '3 bit with ARA': 'uint3|ostris/accuracy_recovery_adapters/qwen_image_edit_2511_torchao_uint3.safetensors', }, }, { name: 'hidream', label: 'HiDream', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['HiDream-ai/HiDream-I1-Full', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.lr': [0.0002, 0.0001], 'config.process[0].train.timestep_type': ['shift', 'sigmoid'], 'config.process[0].network.network_kwargs.ignore_if_contains': [['ff_i.experts', 'ff_i.gate'], []], }, disableSections: ['network.conv'], additionalSections: ['model.low_vram'], accuracyRecoveryAdapters: { '3 bit with ARA': 'uint3|ostris/accuracy_recovery_adapters/hidream_i1_full_torchao_uint3.safetensors', }, }, { name: 'hidream_e1', label: 'HiDream E1', group: 'instruction', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['HiDream-ai/HiDream-E1-1', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.lr': [0.0001, 0.0001], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].network.network_kwargs.ignore_if_contains': [['ff_i.experts', 'ff_i.gate'], []], }, disableSections: ['network.conv'], additionalSections: ['datasets.control_path', 'sample.ctrl_img', 'model.low_vram'], }, { name: 'sdxl', label: 'SDXL', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['stabilityai/stable-diffusion-xl-base-1.0', defaultNameOrPath], 'config.process[0].model.quantize': [false, false], 'config.process[0].model.quantize_te': [false, false], 'config.process[0].sample.sampler': ['ddpm', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['ddpm', 'flowmatch'], 'config.process[0].sample.guidance_scale': [6, 4], }, disableSections: ['model.quantize', 'train.timestep_type'], }, { name: 'sd15', label: 'SD 1.5', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['stable-diffusion-v1-5/stable-diffusion-v1-5', defaultNameOrPath], 'config.process[0].sample.sampler': ['ddpm', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['ddpm', 'flowmatch'], 'config.process[0].sample.width': [512, 1024], 'config.process[0].sample.height': [512, 1024], 'config.process[0].sample.guidance_scale': [6, 4], }, disableSections: ['model.quantize', 'train.timestep_type'], }, { name: 'omnigen2', label: 'OmniGen2', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['OmniGen2/OmniGen2', defaultNameOrPath], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].model.quantize': [false, false], 'config.process[0].model.quantize_te': [true, false], }, disableSections: ['network.conv'], additionalSections: ['datasets.control_path', 'sample.ctrl_img'], }, { name: 'flux2', label: 'FLUX.2', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['black-forest-labs/FLUX.2-dev', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].model.low_vram': [true, false], 'config.process[0].train.unload_text_encoder': [false, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].model.qtype': ['qfloat8', 'qfloat8'], 'config.process[0].model.model_kwargs': [ { match_target_res: false, }, {}, ], }, disableSections: ['network.conv'], additionalSections: [ 'datasets.multi_control_paths', 'sample.multi_ctrl_imgs', 'model.low_vram', 'model.layer_offloading', 'model.qie.match_target_res', ], gateUrl: 'https://huggingface.co/black-forest-labs/FLUX.2-dev', }, { name: 'zimage:turbo', label: 'Z-Image Turbo (w/ Training Adapter)', generateNameOverride: 'Z-Image Turbo', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Tongyi-MAI/Z-Image-Turbo', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].model.low_vram': [true, false], 'config.process[0].train.unload_text_encoder': [false, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].model.qtype': ['qfloat8', 'qfloat8'], 'config.process[0].model.assistant_lora_path': [ 'ostris/zimage_turbo_training_adapter/zimage_turbo_training_adapter_v2.safetensors', undefined, ], 'config.process[0].sample.guidance_scale': [1, 4], 'config.process[0].sample.sample_steps': [9, 25], }, disableSections: ['network.conv'], additionalSections: ['model.low_vram', 'model.layer_offloading', 'model.assistant_lora_path'], }, { name: 'zimage', label: 'Z-Image', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Tongyi-MAI/Z-Image', defaultNameOrPath], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].model.low_vram': [true, false], 'config.process[0].train.unload_text_encoder': [false, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].model.qtype': ['qfloat8', 'qfloat8'], 'config.process[0].sample.sample_steps': [30, 25], }, disableSections: ['network.conv'], additionalSections: ['model.low_vram', 'model.layer_offloading'], }, { name: 'zimage:deturbo', label: 'Z-Image De-Turbo (De-Distilled)', group: 'image', defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['ostris/Z-Image-De-Turbo', defaultNameOrPath], 'config.process[0].model.extras_name_or_path': ['Tongyi-MAI/Z-Image-Turbo', undefined], 'config.process[0].model.quantize': [true, false], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].model.low_vram': [true, false], 'config.process[0].train.unload_text_encoder': [false, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.timestep_type': ['weighted', 'sigmoid'], 'config.process[0].model.qtype': ['qfloat8', 'qfloat8'], 'config.process[0].sample.guidance_scale': [3, 4], 'config.process[0].sample.sample_steps': [25, 25], }, disableSections: ['network.conv'], additionalSections: ['model.low_vram', 'model.layer_offloading'], }, { name: 'minimax_h3', label: 'MiniMax-H3', group: 'video', isVideoModel: true, defaults: { // default updates when [selected, unselected] in the UI 'config.process[0].model.name_or_path': ['Comfy-Org/MiniMax-H3', defaultNameOrPath], // the Comfy-Org weights are pre-quantized (int8 convrot DiT, nvfp4 TE); these // qtypes match the checkpoints exactly, so the load is unchanged. Picking a // different qtype re-quantizes layer by layer into that format. 'config.process[0].model.quantize': [true, false], 'config.process[0].model.qtype': ['convrot8', 'qfloat8'], 'config.process[0].model.quantize_te': [true, false], 'config.process[0].model.qtype_te': ['nvfp4', 'qfloat8'], 'config.process[0].model.low_vram': [true, false], 'config.process[0].sample.sampler': ['flowmatch', 'flowmatch'], 'config.process[0].train.noise_scheduler': ['flowmatch', 'flowmatch'], 'config.process[0].train.cache_text_embeddings': [true, false], 'config.process[0].train.do_guidance_loss': [true, undefined], 'config.process[0].train.guidance_loss_target': [3.5, undefined], 'config.process[0].model.assistant_lora_path': [ 'ostris/minimax_h3_training_adapter/minimax_h3_training_adapter_v1.safetensors', undefined, ], 'config.process[0].network.linear': [16, defaultLinearRank], 'config.process[0].network.linear_alpha': [16, defaultLinearRank], 'config.process[0].network.network_kwargs.ignore_if_contains': [['adaln_proj'], []], 'config.process[0].sample.num_frames': [107, 1], 'config.process[0].sample.fps': [24, 1], 'config.process[0].sample.width': [768, 1024], 'config.process[0].sample.height': [768, 1024], 'config.process[0].sample.guidance_scale': [1, 4], 'config.process[0].sample.sample_steps': [28, 25], 'config.process[0].train.audio_loss_multiplier': [1.0, undefined], 'config.process[0].train.timestep_type': ['shift', 'sigmoid'], 'config.process[0].datasets[x].do_i2v': [false, undefined], 'config.process[0].datasets[x].do_audio': [true, undefined], 'config.process[0].datasets[x].cache_latents_to_disk': [true, false], 'config.process[0].datasets[x].fps': [24, undefined], 'config.process[0].datasets[x].num_frames': [39, undefined], 'config.process[0].datasets[x].auto_frame_count': [true, undefined], }, disableSections: ['network.conv'], additionalSections: [ 'sample.ctrl_img', 'datasets.num_frames', 'model.layer_offloading', 'model.low_vram', 'datasets.do_audio', 'datasets.audio_normalize', 'datasets.audio_preserve_pitch', 'datasets.do_i2v', 'train.audio_loss_multiplier', 'datasets.auto_frame_count', 'model.assistant_lora_path', ], customModelSelectOptions: [ { label: 'Distillation Handling Method', options: [ { value: 'cg', label: 'Contrastive Guidance' }, { value: 'ta', label: 'Training Adapter' }, { value: 'both', label: 'Contrastive Guidance + Training Adapter (default)' }, { value: 'none', label: 'None' }, ], getValue: (config: JobConfig) => { const assistantLoraPath = config?.config?.process?.[0]?.model?.assistant_lora_path; const hasAssistantLoraPath = assistantLoraPath && assistantLoraPath.trim() !== ''; const hasContrastiveGuidance = config?.config?.process?.[0]?.train?.do_guidance_loss; if (hasAssistantLoraPath && hasContrastiveGuidance) { return 'both'; } if (hasAssistantLoraPath) { return 'ta'; } if (hasContrastiveGuidance) { return 'cg'; } return 'none'; }, onChange: (value: string, config: JobConfig, setJobConfig: (value: any, key: string) => void) => { if (value === 'cg') { setJobConfig(true, 'config.process[0].train.do_guidance_loss'); setJobConfig(undefined, 'config.process[0].model.assistant_lora_path'); if (!config?.config?.process?.[0]?.train?.guidance_loss_target) { setJobConfig(3.5, 'config.process[0].train.guidance_loss_target'); } } else if (value === 'ta') { setJobConfig(undefined, 'config.process[0].train.do_guidance_loss'); setJobConfig(undefined, 'config.process[0].train.guidance_loss_target'); setJobConfig( 'ostris/minimax_h3_training_adapter/minimax_h3_training_adapter_v1.safetensors', 'config.process[0].model.assistant_lora_path', ); } else if (value === 'both') { setJobConfig(true, 'config.process[0].train.do_guidance_loss'); setJobConfig( 'ostris/minimax_h3_training_adapter/minimax_h3_training_adapter_v1.safetensors', 'config.process[0].model.assistant_lora_path', ); if (!config?.config?.process?.[0]?.train?.guidance_loss_target) { setJobConfig(3.5, 'config.process[0].train.guidance_loss_target'); } } else if (value === 'none') { setJobConfig(undefined, 'config.process[0].train.do_guidance_loss'); setJobConfig(undefined, 'config.process[0].train.guidance_loss_target'); setJobConfig(undefined, 'config.process[0].model.assistant_lora_path'); } }, doc: { title: 'MiniMax-H3 Distillation Handling', description: (
Weights load from the{' '}
Models Folder Path
{' '}
set in settings. Anything missing is downloaded there from Comfy-Org/MiniMax-H3 on first load
(~43GB total). Files used:
{`/
├── diffusion_models/
│ └── minimax_h3_fl2va_pruned_int8_convrot.safetensors
├── text_encoders/
│ └── qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors
└── vae/
├── minimax_h3_video_vae_fp16.safetensors
└── minimax_h3_audio_vae_fp32.safetensors`}
The checkpoints are pre-quantized and load directly: int8 ConvRot DiT (~21GB) and nvfp4 Qwen3-VL text encoder
(~16GB). The default qtypes (convrot8 / nvfp4) match the files exactly, so nothing
is re-quantized on load. Picking a different quantization re-quantizes the pre-quantized layers into that
format, one layer at a time.
Supports t2v and first-frame i2v (ctrl img / i2v datasets) with joint audio. The model is guidance-distilled — keep guidance scale at 1. Video is fixed 24 fps and frame counts snap down to the 17n+5 grid (5, 22, 39, 56, ..., 107, 124 ≈ 5s). Image datasets (num_frames 1) train as single frames, and a sample with num_frames 1 renders a single image.
How still-image references (dataset control images and sample ctrl images) are shown to the model. Video references always use the video path.
Picture: the native ref2va recipe — a single-frame reference block, shown to Qwen3-VL
as a <Picture i> block, scaled down only.
Static video clip: the image is held for 5 frames (2 latent frames) and routed through
the exact path a reference VIDEO takes — video sizing (matched to the target's pixel area), multi-frame
reference block, <Video k> timestamped presentation. Use this when training on image
references but sampling with video references, so the LoRA learns the pathway it will be used through.
Adds a handful of rows per reference. Frame count is adjustable with{' '}
model_kwargs.image_ref_video_frames (17n+5). Changing this re-caches text embeddings.
Reference-to-video: control images and videos condition the output as subject/style references (never as a
first frame). References keep their own aspect and are matched to the target's pixel area (images scale down
only, never up; a same-aspect video reference is exactly the target size). Each rides into the packed sequence
as a reference block, and is also shown to the Qwen3-VL conditioner as a <Picture i>{' '}
(image) or timestamped <Video k> (video) vision block. Training references come from the
dataset control path(s); sampling uses the sample ctrl images — always as references. The Image Reference
Presentation option can route still images through the video-reference path as short static clips.
Weights load like MiniMax-H3 (see that arch's notes) from the{' '}
Models Folder Path
, using diffusion_models/minimax_h3_ref2va_pruned_int8_convrot.safetensors — the ref2va partition
of the same release; text encoder and VAEs are shared with the fl2va arch. Everything else (pre-quantized
load, 24 fps, 17n+5 frame grid, guidance scale 1, single-image mode) matches MiniMax-H3.
Qwen2.5-Omni 7B thinker as a text-generating model: audio, image or video in, text out. Each dataset item is a media file (mp3, wav, flac, ogg, jpg, png, webp, mp4, ...) with a caption file next to it; the caption is the text the model learns to produce for that media. One dataset can mix all three kinds. Video files are used when Num Frames is above 1 and are seen as frames only (no audio track).
The instruction in model_kwargs.instruction is the user turn for every training item; use the
same wording when captioning with the trained LoRA. Samples take a media file per prompt and write the
generated text as a .txt file.
Media is encoded by the frozen audio and vision towers on the GPU each step, so Cache Latents to Disk can stay
off (the cache is about 54 MB per 300 seconds of audio). Batch size is 1. The LoRA trains the text stack only.
Watch loss/ce: next-token cross-entropy on the caption.
Experimental. The AR (composition) model memorizes quickly and does not work well on small datasets. A handful of songs is enough for it to learn the exact token sequence of each song; after that it stops generalizing and free-running samples drift away from the training material. Expect to need a large, varied dataset for the AR side to learn a style rather than the songs themselves.
YuE2 is two experts on one backbone. The AR expert reads the style line and lyrics and writes the song as a sequence of semantic codec tokens (25 per second). The NAR expert then renders those tokens into audio latents with flow matching. Training a LoRA here trains both: next-token loss on the AR over the whole song from its start, flow loss on the NAR over a random window.
The AR loss is the one to watch (loss/ar_ce). It starts near 5 and, on a small dataset, falls
toward 0 within a few hundred steps, which is memorization. ar_kl_weight in model kwargs anchors
the AR to the base model so it cannot collapse onto the training songs; ar_lr_multiplier and a
smaller AR rank slow it further. Style comes mostly from the NAR, lyric following from the AR. Do not use
caption dropout: a blank prompt breaks lyric following.
The official audio-to-token encoder is unreleased. Training uses the community tokenizer by Kytra ( @sin_ceriously ), a MERT-v2-FullSong head that maps real audio to YuE2 codec tokens:{' '} Mothersuperior/yue2-mothersuperior-realaudio-tokenizer-v4 . It is downloaded on first use. Its tokens are an approximation of the model's own, so rendered samples will not be bit-faithful to the training audio even when the AR replays a song exactly. Though it is extremely close.
ABC generation. Generation is two stages: the AR first writes a lead sheet of the whole song in ABC
notation (sections, chords, vocal and instrumental melody), then writes the codec tokens conditioned on that
sheet. It can also run without a sheet ("off" mode), which uses a different instruction line. Samples here do
the two stages with cot: full (chords) or cot: melody (melody only), or the single
stage with cot: off.
Training for both. Every song is transcribed to an ABC sheet with SheetSage2 and the AR is trained on
lyrics to sheet and sheet to tokens. abc_dropout (default 0.5) is the fraction of training items
fed without the sheet instead, as an off-mode prompt, so one LoRA works in both modes. Set it to 0 to train
the sheet path only, or 1 to train off mode only.
Caching is required. The sheet is produced at latent-cache time and stored with the latents and codec
tokens, so Cache Latents to Disk must stay on: without it, SheetSage2 (about 12 s per song), the MERT
tokenizer and the VAE would run again on every training step. The cache records which mode built it; changing{' '}
cot means deleting the dataset's _latent_cache folder so the sheets are rebuilt.
Audio has no resolution, so keep a single resolution bucket per dataset or every bucket duplicates the songs.
Prompt format: a style line, then [Lyrics], then the lyrics with bracketed section headers such
as [Verse 1] and [Chorus]. The Qwen3-Omni captioner has a YuE2 preset that writes
captions in this layout. Sample length is set by the Duration field in the sample section.