mirror of
https://github.com/ostris/ai-toolkit.git
synced 2026-04-30 11:11:37 +00:00
Fixed some bugs with ui and lock job name to prevent issues with continuing training.
This commit is contained in:
@@ -28,6 +28,7 @@ export default function TrainingForm() {
|
|||||||
const { datasets, status: datasetFetchStatus } = useDatasetList();
|
const { datasets, status: datasetFetchStatus } = useDatasetList();
|
||||||
const [datasetOptions, setDatasetOptions] = useState<{ value: string; label: string }[]>([]);
|
const [datasetOptions, setDatasetOptions] = useState<{ value: string; label: string }[]>([]);
|
||||||
|
|
||||||
|
|
||||||
const [jobConfig, setJobConfig] = useNestedState<JobConfig>(objectCopy(defaultJobConfig));
|
const [jobConfig, setJobConfig] = useNestedState<JobConfig>(objectCopy(defaultJobConfig));
|
||||||
const [status, setStatus] = useState<'idle' | 'saving' | 'success' | 'error'>('idle');
|
const [status, setStatus] = useState<'idle' | 'saving' | 'success' | 'error'>('idle');
|
||||||
|
|
||||||
@@ -54,6 +55,7 @@ export default function TrainingForm() {
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
setGpuIDs(data.gpu_ids);
|
setGpuIDs(data.gpu_ids);
|
||||||
setJobConfig(JSON.parse(data.job_config));
|
setJobConfig(JSON.parse(data.job_config));
|
||||||
|
// setJobConfig(data.name, 'config.name');
|
||||||
})
|
})
|
||||||
.catch(error => console.error('Error fetching training:', error));
|
.catch(error => console.error('Error fetching training:', error));
|
||||||
}
|
}
|
||||||
@@ -111,6 +113,8 @@ export default function TrainingForm() {
|
|||||||
saveJob();
|
saveJob();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log('jobConfig.config.process[0].network.linear', jobConfig?.config?.process[0].network?.linear);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TopBar>
|
<TopBar>
|
||||||
@@ -142,6 +146,7 @@ export default function TrainingForm() {
|
|||||||
value={jobConfig.config.name}
|
value={jobConfig.config.name}
|
||||||
onChange={value => setJobConfig(value, 'config.name')}
|
onChange={value => setJobConfig(value, 'config.name')}
|
||||||
placeholder="Enter training name"
|
placeholder="Enter training name"
|
||||||
|
disabled={runId !== null}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
@@ -199,17 +204,18 @@ export default function TrainingForm() {
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Card>
|
</Card>
|
||||||
{jobConfig.config.process[0].network?.linear && (
|
{jobConfig.config.process[0].network?.type && (
|
||||||
<Card title="LoRA Configuration">
|
<Card title="LoRA Configuration">
|
||||||
<NumberInput
|
<NumberInput
|
||||||
label="Linear Rank"
|
label="Linear Rank"
|
||||||
value={jobConfig.config.process[0].network.linear}
|
value={jobConfig.config.process[0].network.linear}
|
||||||
onChange={value => {
|
onChange={value => {
|
||||||
|
console.log('onChange', value);
|
||||||
setJobConfig(value, 'config.process[0].network.linear');
|
setJobConfig(value, 'config.process[0].network.linear');
|
||||||
setJobConfig(value, 'config.process[0].network.linear_alpha');
|
setJobConfig(value, 'config.process[0].network.linear_alpha');
|
||||||
}}
|
}}
|
||||||
placeholder="eg. 16"
|
placeholder="eg. 16"
|
||||||
min={1}
|
min={0}
|
||||||
max={1024}
|
max={1024}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -16,20 +16,25 @@ export interface TextInputProps extends InputProps {
|
|||||||
value: string;
|
value: string;
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
type?: 'text' | 'password';
|
type?: 'text' | 'password';
|
||||||
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TextInput = (props: TextInputProps) => {
|
export const TextInput = (props: TextInputProps) => {
|
||||||
const { label, value, onChange, placeholder, required } = props;
|
const { label, value, onChange, placeholder, required, disabled } = props;
|
||||||
return (
|
return (
|
||||||
<div className={classNames(props.className)}>
|
<div className={classNames(props.className)}>
|
||||||
{label && <label className={labelClasses}>{label}</label>}
|
{label && <label className={labelClasses}>{label}</label>}
|
||||||
<input
|
<input
|
||||||
type={props.type || 'text'}
|
type={props.type || 'text'}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={e => onChange(e.target.value)}
|
onChange={e => {
|
||||||
className={inputClasses}
|
if (disabled) return;
|
||||||
|
onChange(e.target.value);
|
||||||
|
}}
|
||||||
|
className={`${inputClasses} ${disabled && 'opacity-30 cursor-not-allowed'}`}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
required={required}
|
required={required}
|
||||||
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -50,10 +55,10 @@ export const NumberInput = (props: NumberInputProps) => {
|
|||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(e) => {
|
onChange={e => {
|
||||||
// Use parseFloat instead of Number to properly handle decimal values
|
// Use parseFloat instead of Number to properly handle decimal values
|
||||||
const rawValue = e.target.value;
|
const rawValue = e.target.value;
|
||||||
|
|
||||||
// Special handling for empty or partial inputs
|
// Special handling for empty or partial inputs
|
||||||
if (rawValue === '' || rawValue === '-' || rawValue === '.') {
|
if (rawValue === '' || rawValue === '-' || rawValue === '.') {
|
||||||
// For empty or partial inputs (like just a minus sign or decimal point),
|
// For empty or partial inputs (like just a minus sign or decimal point),
|
||||||
@@ -62,18 +67,18 @@ export const NumberInput = (props: NumberInputProps) => {
|
|||||||
onChange(0);
|
onChange(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let value = parseFloat(rawValue);
|
let value = Number(rawValue);
|
||||||
|
|
||||||
// Handle NaN cases
|
// Handle NaN cases
|
||||||
if (isNaN(value)) {
|
if (isNaN(value)) {
|
||||||
value = 0;
|
value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply min/max constraints only for valid numbers
|
// Apply min/max constraints only for valid numbers
|
||||||
if (min !== undefined && value < min) value = min;
|
if (min !== undefined && value < min) value = min;
|
||||||
if (max !== undefined && value > max) value = max;
|
if (max !== undefined && value > max) value = max;
|
||||||
|
|
||||||
onChange(value);
|
onChange(value);
|
||||||
}}
|
}}
|
||||||
className={inputClasses}
|
className={inputClasses}
|
||||||
|
|||||||
@@ -77,6 +77,10 @@ export function useNestedState<T>(initialState: T): [T, (value: any, path?: stri
|
|||||||
const [state, setState] = React.useState<T>(initialState);
|
const [state, setState] = React.useState<T>(initialState);
|
||||||
|
|
||||||
const setValue = React.useCallback((value: any, path?: string) => {
|
const setValue = React.useCallback((value: any, path?: string) => {
|
||||||
|
if (path === undefined) {
|
||||||
|
setState(value);
|
||||||
|
return
|
||||||
|
}
|
||||||
setState(prevState => setNestedValue(prevState, value, path));
|
setState(prevState => setNestedValue(prevState, value, path));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user