'use client'; import { useMemo } from 'react'; import { modelArchs, ModelArch } from './options'; import { defaultDatasetConfig } from './jobConfig'; import { JobConfig } from '@/types'; import { objectCopy } from '@/utils/basic'; import { TextInput, SelectInput, Checkbox, FormGroup, NumberInput } from '@/components/formInputs'; import Card from '@/components/Card'; import { X } from 'lucide-react'; type Props = { jobConfig: JobConfig; setJobConfig: (value: any, key: string) => void; status: 'idle' | 'saving' | 'success' | 'error'; handleSubmit: (event: React.FormEvent) => void; runId: string | null; gpuIDs: string | null; setGpuIDs: (value: string | null) => void; gpuList: any; datasetOptions: any; }; const isDev = process.env.NODE_ENV === 'development'; export default function SimpleJob({ jobConfig, setJobConfig, handleSubmit, status, runId, gpuIDs, setGpuIDs, gpuList, datasetOptions, }: Props) { const modelArch = useMemo(() => { return modelArchs.find(a => a.name === jobConfig.config.process[0].model.arch) as ModelArch; }, [jobConfig.config.process[0].model.arch]); const isVideoModel = !!modelArch?.isVideoModel; return ( <>
setJobConfig(value, 'config.name')} placeholder="Enter training name" disabled={runId !== null} required /> setGpuIDs(value)} options={gpuList.map((gpu: any) => ({ value: `${gpu.index}`, label: `GPU #${gpu.index}` }))} /> { if (value?.trim() === '') { value = null; } setJobConfig(value, 'config.process[0].trigger_word'); }} placeholder="" required /> {/* Model Configuration Section */} { const currentArch = modelArchs.find(a => a.name === jobConfig.config.process[0].model.arch); if (!currentArch || currentArch.name === value) { return; } // revert defaults from previous model for (const key in currentArch.defaults) { setJobConfig(currentArch.defaults[key][1], key); } // update the defaults when a model is selected const newArch = modelArchs.find(model => model.name === value); if (newArch?.defaults) { for (const key in newArch.defaults) { setJobConfig(newArch.defaults[key][0], key); } } // set new model setJobConfig(value, 'config.process[0].model.arch'); // update controls for datasets const controls = newArch?.controls ?? []; const datasets = jobConfig.config.process[0].datasets.map(dataset => { const newDataset = objectCopy(dataset); newDataset.controls = controls; return newDataset; } ); setJobConfig(datasets, 'config.process[0].datasets'); }} options={ modelArchs .map(model => { return { value: model.name, label: model.label, }; }) .filter(x => x) as { value: string; label: string }[] } /> { if (value?.trim() === '') { value = null; } setJobConfig(value, 'config.process[0].model.name_or_path'); }} placeholder="" required />
setJobConfig(value, 'config.process[0].model.quantize')} /> setJobConfig(value, 'config.process[0].model.quantize_te')} />
setJobConfig(value, 'config.process[0].network.type')} options={[ { value: 'lora', label: 'LoRA' }, { value: 'lokr', label: 'LoKr' }, ]} /> {jobConfig.config.process[0].network?.type == 'lokr' && ( setJobConfig(parseInt(value), 'config.process[0].network.lokr_factor')} options={[ { value: '-1', label: 'Auto' }, { value: '4', label: '4' }, { value: '8', label: '8' }, { value: '16', label: '16' }, { value: '32', label: '32' }, ]} /> )} {jobConfig.config.process[0].network?.type == 'lora' && ( { console.log('onChange', value); setJobConfig(value, 'config.process[0].network.linear'); setJobConfig(value, 'config.process[0].network.linear_alpha'); }} placeholder="eg. 16" min={0} max={1024} required /> )} setJobConfig(value, 'config.process[0].save.dtype')} options={[ { value: 'bf16', label: 'BF16' }, { value: 'fp16', label: 'FP16' }, { value: 'fp32', label: 'FP32' }, ]} /> setJobConfig(value, 'config.process[0].save.save_every')} placeholder="eg. 250" min={1} required /> setJobConfig(value, 'config.process[0].save.max_step_saves_to_keep')} placeholder="eg. 4" min={1} required />
setJobConfig(value, 'config.process[0].train.batch_size')} placeholder="eg. 4" min={1} required /> setJobConfig(value, 'config.process[0].train.gradient_accumulation')} placeholder="eg. 1" min={1} required /> setJobConfig(value, 'config.process[0].train.steps')} placeholder="eg. 2000" min={1} required />
setJobConfig(value, 'config.process[0].train.optimizer')} options={[ { value: 'adamw8bit', label: 'AdamW8Bit' }, { value: 'adafactor', label: 'Adafactor' }, ]} /> setJobConfig(value, 'config.process[0].train.lr')} placeholder="eg. 0.0001" min={0} required /> setJobConfig(value, 'config.process[0].train.optimizer_params.weight_decay')} placeholder="eg. 0.0001" min={0} required />
setJobConfig(value, 'config.process[0].train.timestep_type')} options={[ { value: 'sigmoid', label: 'Sigmoid' }, { value: 'linear', label: 'Linear' }, { value: 'shift', label: 'Shift' }, ]} /> setJobConfig(value, 'config.process[0].train.content_or_style')} options={[ { value: 'balanced', label: 'Balanced' }, { value: 'content', label: 'High Noise' }, { value: 'style', label: 'Low Noise' }, ]} /> setJobConfig(value, 'config.process[0].train.noise_scheduler')} options={[ { value: 'flowmatch', label: 'FlowMatch' }, { value: 'ddpm', label: 'DDPM' }, ]} />
setJobConfig(value, 'config.process[0].train.ema_config.use_ema')} /> setJobConfig(value, 'config.process[0].train.ema_config?.ema_decay')} placeholder="eg. 0.99" min={0} />
setJobConfig(value, 'config.process[0].train.unload_text_encoder')} />
setJobConfig(value, 'config.process[0].train.diff_output_preservation')} /> setJobConfig(value, 'config.process[0].train.diff_output_preservation_multiplier')} placeholder="eg. 1.0" min={0} /> setJobConfig(value, 'config.process[0].train.diff_output_preservation_class')} placeholder="eg. woman" />
<> {jobConfig.config.process[0].datasets.map((dataset, i) => (

Dataset {i + 1}

setJobConfig(value, `config.process[0].datasets[${i}].folder_path`)} options={datasetOptions} /> setJobConfig(value, `config.process[0].datasets[${i}].network_weight`)} placeholder="eg. 1.0" />
setJobConfig(value, `config.process[0].datasets[${i}].default_caption`)} placeholder="eg. A photo of a cat" /> setJobConfig(value, `config.process[0].datasets[${i}].caption_dropout_rate`)} placeholder="eg. 0.05" min={0} required />
setJobConfig(value, `config.process[0].datasets[${i}].cache_latents_to_disk`) } /> setJobConfig(value, `config.process[0].datasets[${i}].is_reg`)} />
{[ [256, 512, 768], [1024, 1280, 1536], ].map(resGroup => (
{resGroup.map(res => ( { const resolutions = dataset.resolution.includes(res) ? dataset.resolution.filter(r => r !== res) : [...dataset.resolution, res]; setJobConfig(resolutions, `config.process[0].datasets[${i}].resolution`); }} /> ))}
))}
))}
setJobConfig(value, 'config.process[0].sample.sample_every')} placeholder="eg. 250" min={1} required /> setJobConfig(value, 'config.process[0].sample.sampler')} options={[ { value: 'flowmatch', label: 'FlowMatch' }, { value: 'ddpm', label: 'DDPM' }, ]} />
setJobConfig(value, 'config.process[0].sample.guidance_scale')} placeholder="eg. 1.0" min={0} required /> setJobConfig(value, 'config.process[0].sample.sample_steps')} placeholder="eg. 1" className="pt-2" min={1} required />
setJobConfig(value, 'config.process[0].sample.width')} placeholder="eg. 1024" min={0} required /> setJobConfig(value, 'config.process[0].sample.height')} placeholder="eg. 1024" className="pt-2" min={0} required />
setJobConfig(value, 'config.process[0].sample.seed')} placeholder="eg. 0" min={0} required /> setJobConfig(value, 'config.process[0].sample.walk_seed')} />
{isVideoModel && (
setJobConfig(value, 'config.process[0].sample.num_frames')} placeholder="eg. 0" min={0} required /> setJobConfig(value, 'config.process[0].sample.fps')} placeholder="eg. 0" min={0} required />
)}
{jobConfig.config.process[0].sample.prompts.map((prompt, i) => (
setJobConfig(value, `config.process[0].sample.prompts[${i}]`)} placeholder="Enter prompt" required />
))}
{status === 'success' &&

Training saved successfully!

} {status === 'error' &&

Error saving training. Please try again.

}
); }