mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
feat: Add Custom location support for model conversion
This commit is contained in:
@@ -415,6 +415,8 @@
|
||||
"convertToDiffusersHelpText5": "Please make sure you have enough disk space. Models generally vary between 2GB-7GB in size.",
|
||||
"convertToDiffusersHelpText6": "Do you wish to convert this model?",
|
||||
"convertToDiffusersSaveLocation": "Save Location",
|
||||
"noCustomLocationProvided": "No Custom Location Provided",
|
||||
"convertingModelBegin": "Converting Model. Please wait.",
|
||||
"v1": "v1",
|
||||
"v2_base": "v2 (512px)",
|
||||
"v2_768": "v2 (768px)",
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
import { Flex, ListItem, Text, UnorderedList } from '@chakra-ui/react';
|
||||
// import { convertToDiffusers } from 'app/socketio/actions';
|
||||
import {
|
||||
Flex,
|
||||
ListItem,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
Text,
|
||||
Tooltip,
|
||||
UnorderedList,
|
||||
} from '@chakra-ui/react';
|
||||
import { makeToast } from 'app/components/Toaster';
|
||||
// import { convertToDiffusers } from 'app/socketio/actions';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import IAIAlertDialog from 'common/components/IAIAlertDialog';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAIInput from 'common/components/IAIInput';
|
||||
import { addToast } from 'features/system/store/systemSlice';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -15,6 +24,8 @@ interface ModelConvertProps {
|
||||
model: CheckpointModelConfig;
|
||||
}
|
||||
|
||||
type SaveLocation = 'InvokeAIRoot' | 'Custom';
|
||||
|
||||
export default function ModelConvert(props: ModelConvertProps) {
|
||||
const { model } = props;
|
||||
|
||||
@@ -23,22 +34,51 @@ export default function ModelConvert(props: ModelConvertProps) {
|
||||
|
||||
const [convertModel, { isLoading }] = useConvertMainModelsMutation();
|
||||
|
||||
const [saveLocation, setSaveLocation] = useState<string>('same');
|
||||
const [saveLocation, setSaveLocation] =
|
||||
useState<SaveLocation>('InvokeAIRoot');
|
||||
const [customSaveLocation, setCustomSaveLocation] = useState<string>('');
|
||||
|
||||
useEffect(() => {
|
||||
setSaveLocation('same');
|
||||
setSaveLocation('InvokeAIRoot');
|
||||
}, [model]);
|
||||
|
||||
const modelConvertCancelHandler = () => {
|
||||
setSaveLocation('same');
|
||||
setSaveLocation('InvokeAIRoot');
|
||||
};
|
||||
|
||||
const modelConvertHandler = () => {
|
||||
const responseBody = {
|
||||
base_model: model.base_model,
|
||||
model_name: model.model_name,
|
||||
body: {
|
||||
convert_dest_directory:
|
||||
saveLocation === 'Custom' ? customSaveLocation : undefined,
|
||||
},
|
||||
};
|
||||
|
||||
if (saveLocation === 'Custom' && customSaveLocation === '') {
|
||||
dispatch(
|
||||
addToast(
|
||||
makeToast({
|
||||
title: t('modelManager.noCustomLocationProvided'),
|
||||
status: 'error',
|
||||
})
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(
|
||||
addToast(
|
||||
makeToast({
|
||||
title: `${t('modelManager.convertingModelBegin')}: ${
|
||||
model.model_name
|
||||
}`,
|
||||
status: 'success',
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
convertModel(responseBody)
|
||||
.unwrap()
|
||||
.then((_) => {
|
||||
@@ -94,35 +134,30 @@ export default function ModelConvert(props: ModelConvertProps) {
|
||||
<Text>{t('modelManager.convertToDiffusersHelpText6')}</Text>
|
||||
</Flex>
|
||||
|
||||
{/* <Flex flexDir="column" gap={4}>
|
||||
<Flex flexDir="column" gap={2}>
|
||||
<Flex marginTop={4} flexDir="column" gap={2}>
|
||||
<Text fontWeight="600">
|
||||
{t('modelManager.convertToDiffusersSaveLocation')}
|
||||
</Text>
|
||||
<RadioGroup value={saveLocation} onChange={(v) => setSaveLocation(v)}>
|
||||
<RadioGroup
|
||||
value={saveLocation}
|
||||
onChange={(v) => setSaveLocation(v as SaveLocation)}
|
||||
>
|
||||
<Flex gap={4}>
|
||||
<Radio value="same">
|
||||
<Tooltip label="Save converted model in the same folder">
|
||||
{t('modelManager.sameFolder')}
|
||||
</Tooltip>
|
||||
</Radio>
|
||||
|
||||
<Radio value="root">
|
||||
<Radio value="InvokeAIRoot">
|
||||
<Tooltip label="Save converted model in the InvokeAI root folder">
|
||||
{t('modelManager.invokeRoot')}
|
||||
</Tooltip>
|
||||
</Radio>
|
||||
|
||||
<Radio value="custom">
|
||||
<Radio value="Custom">
|
||||
<Tooltip label="Save converted model in a custom folder">
|
||||
{t('modelManager.custom')}
|
||||
</Tooltip>
|
||||
</Radio>
|
||||
</Flex>
|
||||
</RadioGroup>
|
||||
</Flex> */}
|
||||
|
||||
{/* {saveLocation === 'custom' && (
|
||||
</Flex>
|
||||
{saveLocation === 'Custom' && (
|
||||
<Flex flexDirection="column" rowGap={2}>
|
||||
<Text fontWeight="500" fontSize="sm" variant="subtext">
|
||||
{t('modelManager.customSaveLocation')}
|
||||
@@ -130,13 +165,13 @@ export default function ModelConvert(props: ModelConvertProps) {
|
||||
<IAIInput
|
||||
value={customSaveLocation}
|
||||
onChange={(e) => {
|
||||
if (e.target.value !== '')
|
||||
setCustomSaveLocation(e.target.value);
|
||||
setCustomSaveLocation(e.target.value);
|
||||
}}
|
||||
width="full"
|
||||
/>
|
||||
</Flex>
|
||||
)} */}
|
||||
)}
|
||||
</Flex>
|
||||
</IAIAlertDialog>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
BaseModelType,
|
||||
CheckpointModelConfig,
|
||||
ControlNetModelConfig,
|
||||
ConvertModelConfig,
|
||||
DiffusersModelConfig,
|
||||
LoRAModelConfig,
|
||||
MainModelConfig,
|
||||
@@ -62,6 +63,7 @@ type DeleteMainModelResponse = void;
|
||||
type ConvertMainModelArg = {
|
||||
base_model: BaseModelType;
|
||||
model_name: string;
|
||||
body: ConvertModelConfig;
|
||||
};
|
||||
|
||||
type ConvertMainModelResponse =
|
||||
@@ -176,10 +178,11 @@ export const modelsApi = api.injectEndpoints({
|
||||
ConvertMainModelResponse,
|
||||
ConvertMainModelArg
|
||||
>({
|
||||
query: ({ base_model, model_name }) => {
|
||||
query: ({ base_model, model_name, body }) => {
|
||||
return {
|
||||
url: `models/convert/${base_model}/main/${model_name}`,
|
||||
method: 'PUT',
|
||||
body: body,
|
||||
};
|
||||
},
|
||||
invalidatesTags: [{ type: 'MainModel', id: LIST_TAG }],
|
||||
|
||||
@@ -378,6 +378,14 @@ export type components = {
|
||||
*/
|
||||
image_count: number;
|
||||
};
|
||||
/** Body_convert_model */
|
||||
Body_convert_model: {
|
||||
/**
|
||||
* Convert Dest Directory
|
||||
* @description Save the converted model to the designated directory
|
||||
*/
|
||||
convert_dest_directory?: string;
|
||||
};
|
||||
/** Body_create_board_image */
|
||||
Body_create_board_image: {
|
||||
/**
|
||||
@@ -5200,10 +5208,6 @@ export type operations = {
|
||||
*/
|
||||
convert_model: {
|
||||
parameters: {
|
||||
query?: {
|
||||
/** @description Save the converted model to the designated directory */
|
||||
convert_dest_directory?: string;
|
||||
};
|
||||
path: {
|
||||
/** @description Base model */
|
||||
base_model: components["schemas"]["BaseModelType"];
|
||||
@@ -5213,6 +5217,11 @@ export type operations = {
|
||||
model_name: string;
|
||||
};
|
||||
};
|
||||
requestBody?: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["Body_convert_model"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Model converted successfully */
|
||||
200: {
|
||||
|
||||
@@ -55,7 +55,9 @@ export type AnyModelConfig =
|
||||
| ControlNetModelConfig
|
||||
| TextualInversionModelConfig
|
||||
| MainModelConfig;
|
||||
|
||||
export type MergeModelConfig = components['schemas']['Body_merge_models'];
|
||||
export type ConvertModelConfig = components['schemas']['Body_convert_model'];
|
||||
|
||||
// Graphs
|
||||
export type Graph = components['schemas']['Graph'];
|
||||
|
||||
Reference in New Issue
Block a user