feat(ui): allow changing model format in MM

This commit is contained in:
psychedelicious
2025-09-18 19:08:18 +10:00
parent 57787e3dcf
commit 82409d1ecd
5 changed files with 58 additions and 1 deletions

View File

@@ -942,6 +942,7 @@
"modelConverted": "Model Converted",
"modelDeleted": "Model Deleted",
"modelDeleteFailed": "Failed to delete model",
"modelFormat": "Model Format",
"modelImageDeleted": "Model Image Deleted",
"modelImageDeleteFailed": "Model Image Delete Failed",
"modelImageUpdated": "Model Image Updated",

View File

@@ -1,4 +1,4 @@
import type { BaseModelType, ModelType, ModelVariantType } from 'features/nodes/types/common';
import type { BaseModelType, ModelFormat, ModelType, ModelVariantType } from 'features/nodes/types/common';
import type { AnyModelConfig } from 'services/api/types';
import {
isCLIPEmbedModelConfig,
@@ -225,6 +225,24 @@ export const MODEL_VARIANT_TO_LONG_NAME: Record<ModelVariantType, string> = {
depth: 'Depth',
};
export const MODEL_FORMAT_TO_LONG_NAME: Record<ModelFormat, string> = {
omi: 'OMI',
diffusers: 'Diffusers',
checkpoint: 'Checkpoint',
lycoris: 'LyCORIS',
onnx: 'ONNX',
olive: 'Olive',
embedding_file: 'Embedding (file)',
embedding_folder: 'Embedding (folder)',
invokeai: 'InvokeAI',
t5_encoder: 'T5 Encoder',
bnb_quantized_int8b: 'BNB Quantized (int8b)',
bnb_quantized_nf4b: 'BNB Quantized (nf4b)',
gguf_quantized: 'GGUF Quantized',
api: 'API',
unknown: 'Unknown',
};
/**
* List of base models that make API requests
*/

View File

@@ -0,0 +1,32 @@
import type { ComboboxOnChange, ComboboxOption } from '@invoke-ai/ui-library';
import { Combobox } from '@invoke-ai/ui-library';
import { typedMemo } from 'common/util/typedMemo';
import { MODEL_FORMAT_TO_LONG_NAME } from 'features/modelManagerV2/models';
import { useCallback, useMemo } from 'react';
import type { Control } from 'react-hook-form';
import { useController } from 'react-hook-form';
import type { UpdateModelArg } from 'services/api/endpoints/models';
import { objectEntries } from 'tsafe';
const options: ComboboxOption[] = objectEntries(MODEL_FORMAT_TO_LONG_NAME).map(([value, label]) => ({
label,
value,
}));
type Props = {
control: Control<UpdateModelArg['body']>;
};
const ModelFormatSelect = ({ control }: Props) => {
const { field } = useController({ control, name: 'format' });
const value = useMemo(() => options.find((o) => o.value === field.value), [field.value]);
const onChange = useCallback<ComboboxOnChange>(
(v) => {
field.onChange(v?.value);
},
[field]
);
return <Combobox value={value} options={options} onChange={onChange} />;
};
export default typedMemo(ModelFormatSelect);

View File

@@ -22,6 +22,7 @@ import { type UpdateModelArg, useUpdateModelMutation } from 'services/api/endpoi
import type { AnyModelConfig } from 'services/api/types';
import BaseModelSelect from './Fields/BaseModelSelect';
import ModelFormatSelect from './Fields/ModelFormatSelect';
import ModelTypeSelect from './Fields/ModelTypeSelect';
import ModelVariantSelect from './Fields/ModelVariantSelect';
import PredictionTypeSelect from './Fields/PredictionTypeSelect';
@@ -132,6 +133,10 @@ export const ModelEdit = memo(({ modelConfig }: Props) => {
<FormLabel>{t('modelManager.modelType')}</FormLabel>
<ModelTypeSelect control={form.control} />
</FormControl>
<FormControl flexDir="column" alignItems="flex-start" gap={1}>
<FormLabel>{t('modelManager.modelFormat')}</FormLabel>
<ModelFormatSelect control={form.control} />
</FormControl>
{modelConfig.type !== 'clip_vision' && (
<FormControl flexDir="column" alignItems="flex-start" gap={1}>
<FormLabel>{t('modelManager.baseModel')}</FormLabel>

View File

@@ -167,6 +167,7 @@ export const zModelFormat = z.enum([
'api',
'unknown',
]);
export type ModelFormat = z.infer<typeof zModelFormat>;
export const zModelIdentifierField = z.object({
key: z.string().min(1),