mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): update default settings for control adapters
- Split out main model defaults - Add controlnet/t2i defaults (which includes only the preprocessor)
This commit is contained in:
parent
1f69613f5d
commit
fd457955bc
@ -21,6 +21,7 @@ import { makeToast } from 'features/system/util/makeToast';
|
|||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { map } from 'lodash-es';
|
import { map } from 'lodash-es';
|
||||||
import { modelsApi } from 'services/api/endpoints/models';
|
import { modelsApi } from 'services/api/endpoints/models';
|
||||||
|
import { isNonRefinerMainModelConfig } from 'services/api/types';
|
||||||
|
|
||||||
export const addSetDefaultSettingsListener = (startAppListening: AppStartListening) => {
|
export const addSetDefaultSettingsListener = (startAppListening: AppStartListening) => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
@ -36,11 +37,13 @@ export const addSetDefaultSettingsListener = (startAppListening: AppStartListeni
|
|||||||
|
|
||||||
const modelConfig = await dispatch(modelsApi.endpoints.getModelConfig.initiate(currentModel.key)).unwrap();
|
const modelConfig = await dispatch(modelsApi.endpoints.getModelConfig.initiate(currentModel.key)).unwrap();
|
||||||
|
|
||||||
if (!modelConfig || !modelConfig.default_settings) {
|
if (!modelConfig) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { vae, vae_precision, cfg_scale, cfg_rescale_multiplier, steps, scheduler } = modelConfig.default_settings;
|
if (isNonRefinerMainModelConfig(modelConfig) && modelConfig.default_settings) {
|
||||||
|
const { vae, vae_precision, cfg_scale, cfg_rescale_multiplier, steps, scheduler } =
|
||||||
|
modelConfig.default_settings;
|
||||||
|
|
||||||
if (vae) {
|
if (vae) {
|
||||||
// we store this as "default" within default settings
|
// we store this as "default" within default settings
|
||||||
@ -91,6 +94,7 @@ export const addSetDefaultSettingsListener = (startAppListening: AppStartListeni
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch(addToast(makeToast({ title: t('toast.parameterSet', { parameter: 'Default settings' }) })));
|
dispatch(addToast(makeToast({ title: t('toast.parameterSet', { parameter: 'Default settings' }) })));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -253,23 +253,3 @@ export const CONTROLNET_PROCESSORS: ControlNetProcessorsDict = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CONTROLNET_MODEL_DEFAULT_PROCESSORS: {
|
|
||||||
[key: string]: ControlAdapterProcessorType;
|
|
||||||
} = {
|
|
||||||
canny: 'canny_image_processor',
|
|
||||||
mlsd: 'mlsd_image_processor',
|
|
||||||
depth: 'depth_anything_image_processor',
|
|
||||||
bae: 'normalbae_image_processor',
|
|
||||||
sketch: 'pidi_image_processor',
|
|
||||||
scribble: 'lineart_image_processor',
|
|
||||||
lineart: 'lineart_image_processor',
|
|
||||||
lineart_anime: 'lineart_anime_image_processor',
|
|
||||||
softedge: 'hed_image_processor',
|
|
||||||
shuffle: 'content_shuffle_image_processor',
|
|
||||||
openpose: 'dw_openpose_image_processor',
|
|
||||||
mediapipe: 'mediapipe_face_processor',
|
|
||||||
pidi: 'pidi_image_processor',
|
|
||||||
zoe: 'zoe_depth_image_processor',
|
|
||||||
color: 'color_map_image_processor',
|
|
||||||
};
|
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
import type {
|
import type { ControlAdapterProcessorType, zControlAdapterProcessorType } from 'features/controlAdapters/store/types';
|
||||||
ControlAdapterProcessorType,
|
|
||||||
zControlAdapterProcessorType,
|
|
||||||
} from 'features/controlAdapters/store/types';
|
|
||||||
import type { Equals } from 'tsafe';
|
import type { Equals } from 'tsafe';
|
||||||
import { assert } from 'tsafe';
|
import { assert } from 'tsafe';
|
||||||
import { describe, test } from 'vitest';
|
import { describe, test } from 'vitest';
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
import { skipToken } from '@reduxjs/toolkit/query';
|
||||||
|
import { isNil } from 'lodash-es';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useGetModelConfigWithTypeGuard } from 'services/api/hooks/useGetModelConfigWithTypeGuard';
|
||||||
|
import { isControlNetOrT2IAdapterModelConfig } from 'services/api/types';
|
||||||
|
|
||||||
|
export const useControlNetOrT2IAdapterDefaultSettings = (modelKey?: string | null) => {
|
||||||
|
const { modelConfig, isLoading } = useGetModelConfigWithTypeGuard(
|
||||||
|
modelKey ?? skipToken,
|
||||||
|
isControlNetOrT2IAdapterModelConfig
|
||||||
|
);
|
||||||
|
|
||||||
|
const defaultSettingsDefaults = useMemo(() => {
|
||||||
|
return {
|
||||||
|
preprocessor: {
|
||||||
|
isEnabled: !isNil(modelConfig?.default_settings?.preprocessor),
|
||||||
|
value: modelConfig?.default_settings?.preprocessor || 'none',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}, [modelConfig?.default_settings]);
|
||||||
|
|
||||||
|
return { defaultSettingsDefaults, isLoading };
|
||||||
|
};
|
@ -0,0 +1,105 @@
|
|||||||
|
import { Button, Flex, Heading, Text } from '@invoke-ai/ui-library';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { useControlNetOrT2IAdapterDefaultSettings } from 'features/modelManagerV2/hooks/useControlNetOrT2IAdapterDefaultSettings';
|
||||||
|
import { DefaultPreprocessor } from 'features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/DefaultPreprocessor';
|
||||||
|
import type { FormField } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/MainModelDefaultSettings';
|
||||||
|
import { addToast } from 'features/system/store/systemSlice';
|
||||||
|
import { makeToast } from 'features/system/util/makeToast';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import type { SubmitHandler } from 'react-hook-form';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { PiCheckBold } from 'react-icons/pi';
|
||||||
|
import { useUpdateModelMutation } from 'services/api/endpoints/models';
|
||||||
|
|
||||||
|
export type ControlNetOrT2IAdapterDefaultSettingsFormData = {
|
||||||
|
preprocessor: FormField<string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ControlNetOrT2IAdapterDefaultSettings = () => {
|
||||||
|
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const { defaultSettingsDefaults, isLoading: isLoadingDefaultSettings } =
|
||||||
|
useControlNetOrT2IAdapterDefaultSettings(selectedModelKey);
|
||||||
|
|
||||||
|
const [updateModel, { isLoading: isLoadingUpdateModel }] = useUpdateModelMutation();
|
||||||
|
|
||||||
|
const { handleSubmit, control, formState, reset } = useForm<ControlNetOrT2IAdapterDefaultSettingsFormData>({
|
||||||
|
defaultValues: defaultSettingsDefaults,
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = useCallback<SubmitHandler<ControlNetOrT2IAdapterDefaultSettingsFormData>>(
|
||||||
|
(data) => {
|
||||||
|
if (!selectedModelKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = {
|
||||||
|
preprocessor: data.preprocessor.isEnabled ? data.preprocessor.value : null,
|
||||||
|
};
|
||||||
|
|
||||||
|
updateModel({
|
||||||
|
key: selectedModelKey,
|
||||||
|
body: { default_settings: body },
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.then((_) => {
|
||||||
|
dispatch(
|
||||||
|
addToast(
|
||||||
|
makeToast({
|
||||||
|
title: t('modelManager.defaultSettingsSaved'),
|
||||||
|
status: 'success',
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
reset(data);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
if (error) {
|
||||||
|
dispatch(
|
||||||
|
addToast(
|
||||||
|
makeToast({
|
||||||
|
title: `${error.data.detail} `,
|
||||||
|
status: 'error',
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[selectedModelKey, dispatch, reset, updateModel, t]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isLoadingDefaultSettings) {
|
||||||
|
return <Text>{t('common.loading')}</Text>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Flex gap="4" justifyContent="space-between" w="full" pb={4}>
|
||||||
|
<Heading fontSize="md">{t('modelManager.defaultSettings')}</Heading>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
leftIcon={<PiCheckBold />}
|
||||||
|
colorScheme="invokeYellow"
|
||||||
|
isDisabled={!formState.isDirty}
|
||||||
|
onClick={handleSubmit(onSubmit)}
|
||||||
|
type="submit"
|
||||||
|
isLoading={isLoadingUpdateModel}
|
||||||
|
>
|
||||||
|
{t('common.save')}
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex flexDir="column" gap={8}>
|
||||||
|
<Flex gap={8}>
|
||||||
|
<Flex gap={4} w="full">
|
||||||
|
<DefaultPreprocessor control={control} name="preprocessor" />
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,66 @@
|
|||||||
|
import type { ComboboxOnChange } from '@invoke-ai/ui-library';
|
||||||
|
import { Combobox, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
|
import type { ControlNetOrT2IAdapterDefaultSettingsFormData } from 'features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/ControlNetOrT2IAdapterDefaultSettings';
|
||||||
|
import type { FormField } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/MainModelDefaultSettings';
|
||||||
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
|
import { useCallback, useMemo } from 'react';
|
||||||
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
|
import { useController } from 'react-hook-form';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const OPTIONS = [
|
||||||
|
{ label: 'Canny', value: 'canny_image_processor' },
|
||||||
|
{ label: 'MLSD', value: 'mlsd_image_processor' },
|
||||||
|
{ label: 'Depth Anything', value: 'depth_anything_image_processor' },
|
||||||
|
{ label: 'Normal BAE', value: 'normalbae_image_processor' },
|
||||||
|
{ label: 'Pidi', value: 'pidi_image_processor' },
|
||||||
|
{ label: 'Lineart', value: 'lineart_image_processor' },
|
||||||
|
{ label: 'Lineart Anime', value: 'lineart_anime_image_processor' },
|
||||||
|
{ label: 'HED', value: 'hed_image_processor' },
|
||||||
|
{ label: 'Content Shuffle', value: 'content_shuffle_image_processor' },
|
||||||
|
{ label: 'DW OpenPose', value: 'dw_openpose_image_processor' },
|
||||||
|
{ label: 'MediaPipe Face', value: 'mediapipe_face_processor' },
|
||||||
|
{ label: 'ZoeDepth', value: 'zoe_depth_image_processor' },
|
||||||
|
{ label: 'Color Map', value: 'color_map_image_processor' },
|
||||||
|
{ label: 'None', value: 'none' },
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
type DefaultSchedulerType = ControlNetOrT2IAdapterDefaultSettingsFormData['preprocessor'];
|
||||||
|
|
||||||
|
export function DefaultPreprocessor(props: UseControllerProps<ControlNetOrT2IAdapterDefaultSettingsFormData>) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { field } = useController(props);
|
||||||
|
|
||||||
|
const onChange = useCallback<ComboboxOnChange>(
|
||||||
|
(v) => {
|
||||||
|
if (!v) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const updatedValue = {
|
||||||
|
...(field.value as FormField<string>),
|
||||||
|
value: v.value,
|
||||||
|
};
|
||||||
|
field.onChange(updatedValue);
|
||||||
|
},
|
||||||
|
[field]
|
||||||
|
);
|
||||||
|
|
||||||
|
const value = useMemo(() => OPTIONS.find((o) => o.value === (field.value as FormField<string>).value), [field]);
|
||||||
|
|
||||||
|
const isDisabled = useMemo(() => {
|
||||||
|
return !(field.value as DefaultSchedulerType).isEnabled;
|
||||||
|
}, [field.value]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl flexDir="column" gap={2} alignItems="flex-start">
|
||||||
|
<Flex justifyContent="space-between" w="full">
|
||||||
|
<InformationalPopover feature="controlNetProcessor">
|
||||||
|
<FormLabel>{t('controlnet.processor')}</FormLabel>
|
||||||
|
</InformationalPopover>
|
||||||
|
<SettingToggle control={props.control} name="preprocessor" />
|
||||||
|
</Flex>
|
||||||
|
<Combobox isDisabled={isDisabled} value={value} options={OPTIONS} onChange={onChange} />
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
}
|
@ -1,17 +1,17 @@
|
|||||||
import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { DefaultSettingsFormData } from './DefaultSettingsForm';
|
import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings';
|
||||||
|
|
||||||
type DefaultCfgRescaleMultiplierType = DefaultSettingsFormData['cfgRescaleMultiplier'];
|
type DefaultCfgRescaleMultiplierType = MainModelDefaultSettingsFormData['cfgRescaleMultiplier'];
|
||||||
|
|
||||||
export function DefaultCfgRescaleMultiplier(props: UseControllerProps<DefaultSettingsFormData>) {
|
export function DefaultCfgRescaleMultiplier(props: UseControllerProps<MainModelDefaultSettingsFormData>) {
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
|
||||||
const sliderMin = useAppSelector((s) => s.config.sd.cfgRescaleMultiplier.sliderMin);
|
const sliderMin = useAppSelector((s) => s.config.sd.cfgRescaleMultiplier.sliderMin);
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { DefaultSettingsFormData } from './DefaultSettingsForm';
|
import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings';
|
||||||
|
|
||||||
type DefaultCfgType = DefaultSettingsFormData['cfgScale'];
|
type DefaultCfgType = MainModelDefaultSettingsFormData['cfgScale'];
|
||||||
|
|
||||||
export function DefaultCfgScale(props: UseControllerProps<DefaultSettingsFormData>) {
|
export function DefaultCfgScale(props: UseControllerProps<MainModelDefaultSettingsFormData>) {
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
|
||||||
const sliderMin = useAppSelector((s) => s.config.sd.guidance.sliderMin);
|
const sliderMin = useAppSelector((s) => s.config.sd.guidance.sliderMin);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { ComboboxOnChange } from '@invoke-ai/ui-library';
|
import type { ComboboxOnChange } from '@invoke-ai/ui-library';
|
||||||
import { Combobox, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
import { Combobox, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { SCHEDULER_OPTIONS } from 'features/parameters/types/constants';
|
import { SCHEDULER_OPTIONS } from 'features/parameters/types/constants';
|
||||||
import { isParameterScheduler } from 'features/parameters/types/parameterSchemas';
|
import { isParameterScheduler } from 'features/parameters/types/parameterSchemas';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
@ -9,11 +9,11 @@ import type { UseControllerProps } from 'react-hook-form';
|
|||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { DefaultSettingsFormData } from './DefaultSettingsForm';
|
import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings';
|
||||||
|
|
||||||
type DefaultSchedulerType = DefaultSettingsFormData['scheduler'];
|
type DefaultSchedulerType = MainModelDefaultSettingsFormData['scheduler'];
|
||||||
|
|
||||||
export function DefaultScheduler(props: UseControllerProps<DefaultSettingsFormData>) {
|
export function DefaultScheduler(props: UseControllerProps<MainModelDefaultSettingsFormData>) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
|
||||||
|
@ -1,141 +0,0 @@
|
|||||||
import { Button, Flex, Heading } from '@invoke-ai/ui-library';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import type { ParameterScheduler } from 'features/parameters/types/parameterSchemas';
|
|
||||||
import { addToast } from 'features/system/store/systemSlice';
|
|
||||||
import { makeToast } from 'features/system/util/makeToast';
|
|
||||||
import { useCallback } from 'react';
|
|
||||||
import type { SubmitHandler } from 'react-hook-form';
|
|
||||||
import { useForm } from 'react-hook-form';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { PiCheckBold } from 'react-icons/pi';
|
|
||||||
import { useUpdateModelMutation } from 'services/api/endpoints/models';
|
|
||||||
|
|
||||||
import { DefaultCfgRescaleMultiplier } from './DefaultCfgRescaleMultiplier';
|
|
||||||
import { DefaultCfgScale } from './DefaultCfgScale';
|
|
||||||
import { DefaultScheduler } from './DefaultScheduler';
|
|
||||||
import { DefaultSteps } from './DefaultSteps';
|
|
||||||
import { DefaultVae } from './DefaultVae';
|
|
||||||
import { DefaultVaePrecision } from './DefaultVaePrecision';
|
|
||||||
|
|
||||||
export interface FormField<T> {
|
|
||||||
value: T;
|
|
||||||
isEnabled: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type DefaultSettingsFormData = {
|
|
||||||
vae: FormField<string>;
|
|
||||||
vaePrecision: FormField<string>;
|
|
||||||
scheduler: FormField<ParameterScheduler>;
|
|
||||||
steps: FormField<number>;
|
|
||||||
cfgScale: FormField<number>;
|
|
||||||
cfgRescaleMultiplier: FormField<number>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const DefaultSettingsForm = ({
|
|
||||||
defaultSettingsDefaults,
|
|
||||||
}: {
|
|
||||||
defaultSettingsDefaults: DefaultSettingsFormData;
|
|
||||||
}) => {
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
|
||||||
|
|
||||||
const [updateModel, { isLoading }] = useUpdateModelMutation();
|
|
||||||
|
|
||||||
const { handleSubmit, control, formState, reset } = useForm<DefaultSettingsFormData>({
|
|
||||||
defaultValues: defaultSettingsDefaults,
|
|
||||||
});
|
|
||||||
|
|
||||||
const onSubmit = useCallback<SubmitHandler<DefaultSettingsFormData>>(
|
|
||||||
(data) => {
|
|
||||||
if (!selectedModelKey) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = {
|
|
||||||
vae: data.vae.isEnabled ? data.vae.value : null,
|
|
||||||
vae_precision: data.vaePrecision.isEnabled ? data.vaePrecision.value : null,
|
|
||||||
cfg_scale: data.cfgScale.isEnabled ? data.cfgScale.value : null,
|
|
||||||
cfg_rescale_multiplier: data.cfgRescaleMultiplier.isEnabled ? data.cfgRescaleMultiplier.value : null,
|
|
||||||
steps: data.steps.isEnabled ? data.steps.value : null,
|
|
||||||
scheduler: data.scheduler.isEnabled ? data.scheduler.value : null,
|
|
||||||
};
|
|
||||||
|
|
||||||
updateModel({
|
|
||||||
key: selectedModelKey,
|
|
||||||
body: { default_settings: body },
|
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
.then((_) => {
|
|
||||||
dispatch(
|
|
||||||
addToast(
|
|
||||||
makeToast({
|
|
||||||
title: t('modelManager.defaultSettingsSaved'),
|
|
||||||
status: 'success',
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
reset(data);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
if (error) {
|
|
||||||
dispatch(
|
|
||||||
addToast(
|
|
||||||
makeToast({
|
|
||||||
title: `${error.data.detail} `,
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[selectedModelKey, dispatch, reset, updateModel, t]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Flex gap="4" justifyContent="space-between" w="full" pb={4}>
|
|
||||||
<Heading fontSize="md">{t('modelManager.defaultSettings')}</Heading>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
leftIcon={<PiCheckBold />}
|
|
||||||
colorScheme="invokeYellow"
|
|
||||||
isDisabled={!formState.isDirty}
|
|
||||||
onClick={handleSubmit(onSubmit)}
|
|
||||||
type="submit"
|
|
||||||
isLoading={isLoading}
|
|
||||||
>
|
|
||||||
{t('common.save')}
|
|
||||||
</Button>
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
<Flex flexDir="column" gap={8}>
|
|
||||||
<Flex gap={8}>
|
|
||||||
<Flex gap={4} w="full">
|
|
||||||
<DefaultVae control={control} name="vae" />
|
|
||||||
</Flex>
|
|
||||||
<Flex gap={4} w="full">
|
|
||||||
<DefaultVaePrecision control={control} name="vaePrecision" />
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<Flex gap={8}>
|
|
||||||
<Flex gap={4} w="full">
|
|
||||||
<DefaultScheduler control={control} name="scheduler" />
|
|
||||||
</Flex>
|
|
||||||
<Flex gap={4} w="full">
|
|
||||||
<DefaultSteps control={control} name="steps" />
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<Flex gap={8}>
|
|
||||||
<Flex gap={4} w="full">
|
|
||||||
<DefaultCfgScale control={control} name="cfgScale" />
|
|
||||||
</Flex>
|
|
||||||
<Flex gap={4} w="full">
|
|
||||||
<DefaultCfgRescaleMultiplier control={control} name="cfgRescaleMultiplier" />
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,17 +1,17 @@
|
|||||||
import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { DefaultSettingsFormData } from './DefaultSettingsForm';
|
import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings';
|
||||||
|
|
||||||
type DefaultSteps = DefaultSettingsFormData['steps'];
|
type DefaultSteps = MainModelDefaultSettingsFormData['steps'];
|
||||||
|
|
||||||
export function DefaultSteps(props: UseControllerProps<DefaultSettingsFormData>) {
|
export function DefaultSteps(props: UseControllerProps<MainModelDefaultSettingsFormData>) {
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
|
||||||
const sliderMin = useAppSelector((s) => s.config.sd.steps.sliderMin);
|
const sliderMin = useAppSelector((s) => s.config.sd.steps.sliderMin);
|
||||||
|
@ -3,7 +3,7 @@ import { Combobox, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
|||||||
import { skipToken } from '@reduxjs/toolkit/query';
|
import { skipToken } from '@reduxjs/toolkit/query';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { map } from 'lodash-es';
|
import { map } from 'lodash-es';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
@ -11,11 +11,11 @@ import { useController } from 'react-hook-form';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useGetModelConfigQuery, useGetVaeModelsQuery } from 'services/api/endpoints/models';
|
import { useGetModelConfigQuery, useGetVaeModelsQuery } from 'services/api/endpoints/models';
|
||||||
|
|
||||||
import type { DefaultSettingsFormData } from './DefaultSettingsForm';
|
import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings';
|
||||||
|
|
||||||
type DefaultVaeType = DefaultSettingsFormData['vae'];
|
type DefaultVaeType = MainModelDefaultSettingsFormData['vae'];
|
||||||
|
|
||||||
export function DefaultVae(props: UseControllerProps<DefaultSettingsFormData>) {
|
export function DefaultVae(props: UseControllerProps<MainModelDefaultSettingsFormData>) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
import type { ComboboxOnChange } from '@invoke-ai/ui-library';
|
import type { ComboboxOnChange } from '@invoke-ai/ui-library';
|
||||||
import { Combobox, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
import { Combobox, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { isParameterPrecision } from 'features/parameters/types/parameterSchemas';
|
import { isParameterPrecision } from 'features/parameters/types/parameterSchemas';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { DefaultSettingsFormData } from './DefaultSettingsForm';
|
import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings';
|
||||||
|
|
||||||
const options = [
|
const options = [
|
||||||
{ label: 'FP16', value: 'fp16' },
|
{ label: 'FP16', value: 'fp16' },
|
||||||
{ label: 'FP32', value: 'fp32' },
|
{ label: 'FP32', value: 'fp32' },
|
||||||
];
|
];
|
||||||
|
|
||||||
type DefaultVaePrecisionType = DefaultSettingsFormData['vaePrecision'];
|
type DefaultVaePrecisionType = MainModelDefaultSettingsFormData['vaePrecision'];
|
||||||
|
|
||||||
export function DefaultVaePrecision(props: UseControllerProps<DefaultSettingsFormData>) {
|
export function DefaultVaePrecision(props: UseControllerProps<MainModelDefaultSettingsFormData>) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
|
||||||
|
@ -17,12 +17,13 @@ import { DefaultScheduler } from './DefaultScheduler';
|
|||||||
import { DefaultSteps } from './DefaultSteps';
|
import { DefaultSteps } from './DefaultSteps';
|
||||||
import { DefaultVae } from './DefaultVae';
|
import { DefaultVae } from './DefaultVae';
|
||||||
import { DefaultVaePrecision } from './DefaultVaePrecision';
|
import { DefaultVaePrecision } from './DefaultVaePrecision';
|
||||||
interface FormField<T> {
|
|
||||||
|
export interface FormField<T> {
|
||||||
value: T;
|
value: T;
|
||||||
isEnabled: boolean;
|
isEnabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultSettingsFormData = {
|
export type MainModelDefaultSettingsFormData = {
|
||||||
vae: FormField<string>;
|
vae: FormField<string>;
|
||||||
vaePrecision: FormField<string>;
|
vaePrecision: FormField<string>;
|
||||||
scheduler: FormField<ParameterScheduler>;
|
scheduler: FormField<ParameterScheduler>;
|
||||||
@ -41,11 +42,11 @@ export const MainModelDefaultSettings = () => {
|
|||||||
|
|
||||||
const [updateModel, { isLoading: isLoadingUpdateModel }] = useUpdateModelMutation();
|
const [updateModel, { isLoading: isLoadingUpdateModel }] = useUpdateModelMutation();
|
||||||
|
|
||||||
const { handleSubmit, control, formState, reset } = useForm<DefaultSettingsFormData>({
|
const { handleSubmit, control, formState, reset } = useForm<MainModelDefaultSettingsFormData>({
|
||||||
defaultValues: defaultSettingsDefaults,
|
defaultValues: defaultSettingsDefaults,
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = useCallback<SubmitHandler<DefaultSettingsFormData>>(
|
const onSubmit = useCallback<SubmitHandler<MainModelDefaultSettingsFormData>>(
|
||||||
(data) => {
|
(data) => {
|
||||||
if (!selectedModelKey) {
|
if (!selectedModelKey) {
|
||||||
return;
|
return;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Box, Flex, Text } from '@invoke-ai/ui-library';
|
import { Box, Flex, Text } from '@invoke-ai/ui-library';
|
||||||
import { skipToken } from '@reduxjs/toolkit/query';
|
import { skipToken } from '@reduxjs/toolkit/query';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { ControlNetOrT2IAdapterDefaultSettings } from 'features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/ControlNetOrT2IAdapterDefaultSettings';
|
||||||
import { TriggerPhrases } from 'features/modelManagerV2/subpanels/ModelPanel/TriggerPhrases';
|
import { TriggerPhrases } from 'features/modelManagerV2/subpanels/ModelPanel/TriggerPhrases';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useGetModelConfigQuery } from 'services/api/endpoints/models';
|
import { useGetModelConfigQuery } from 'services/api/endpoints/models';
|
||||||
@ -64,6 +65,11 @@ export const ModelView = () => {
|
|||||||
<MainModelDefaultSettings />
|
<MainModelDefaultSettings />
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
{(data.type === 'controlnet' || data.type === 't2i_adapter') && (
|
||||||
|
<Box layerStyle="second" borderRadius="base" p={4}>
|
||||||
|
<ControlNetOrT2IAdapterDefaultSettings />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
{(data.type === 'main' || data.type === 'lora') && (
|
{(data.type === 'main' || data.type === 'lora') && (
|
||||||
<Box layerStyle="second" borderRadius="base" p={4}>
|
<Box layerStyle="second" borderRadius="base" p={4}>
|
||||||
<TriggerPhrases />
|
<TriggerPhrases />
|
||||||
|
@ -4,9 +4,9 @@ import { useCallback, useMemo } from 'react';
|
|||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
|
|
||||||
import type { DefaultSettingsFormData, FormField } from './DefaultSettingsForm';
|
import type { FormField } from './MainModelDefaultSettings/MainModelDefaultSettings';
|
||||||
|
|
||||||
export function SettingToggle<T>(props: UseControllerProps<DefaultSettingsFormData>) {
|
export function SettingToggle<T, F extends Record<string, FormField<T>>>(props: UseControllerProps<F>) {
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
|
||||||
const value = useMemo(() => {
|
const value = useMemo(() => {
|
Loading…
x
Reference in New Issue
Block a user