mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
single model view
This commit is contained in:
parent
87ce74e05d
commit
c46eb72d45
@ -3,10 +3,12 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
ConfirmationAlertDialog,
|
ConfirmationAlertDialog,
|
||||||
Flex,
|
Flex,
|
||||||
|
Icon,
|
||||||
IconButton,
|
IconButton,
|
||||||
Text,
|
Text,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
|
Box,
|
||||||
} from '@invoke-ai/ui-library';
|
} from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { setSelectedModelKey } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
import { setSelectedModelKey } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
||||||
@ -15,6 +17,7 @@ import { addToast } from 'features/system/store/systemSlice';
|
|||||||
import { makeToast } from 'features/system/util/makeToast';
|
import { makeToast } from 'features/system/util/makeToast';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { IoWarning } from 'react-icons/io5';
|
||||||
import { PiTrashSimpleBold } from 'react-icons/pi';
|
import { PiTrashSimpleBold } from 'react-icons/pi';
|
||||||
import { useDeleteModelsMutation } from 'services/api/endpoints/models';
|
import { useDeleteModelsMutation } from 'services/api/endpoints/models';
|
||||||
import type { AnyModelConfig } from 'services/api/types';
|
import type { AnyModelConfig } from 'services/api/types';
|
||||||
@ -88,8 +91,16 @@ const ModelListItem = (props: ModelListItemProps) => {
|
|||||||
<Tooltip label={model.description} placement="bottom">
|
<Tooltip label={model.description} placement="bottom">
|
||||||
<Text>{model.name}</Text>
|
<Text>{model.name}</Text>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
{model.format === 'checkpoint' && (
|
||||||
|
<Tooltip label="Checkpoint">
|
||||||
|
<Box>
|
||||||
|
<Icon as={IoWarning} />
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={onOpen}
|
onClick={onOpen}
|
||||||
icon={<PiTrashSimpleBold />}
|
icon={<PiTrashSimpleBold />}
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
import { Box } from '@invoke-ai/ui-library';
|
||||||
|
import { useAppSelector } from '../../../app/store/storeHooks';
|
||||||
|
import { ImportModels } from './ImportModels';
|
||||||
|
import { ModelView } from './ModelPanel/ModelView';
|
||||||
|
|
||||||
|
export const ModelPane = () => {
|
||||||
|
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
||||||
|
return (
|
||||||
|
<Box layerStyle="first" p={2} borderRadius="base" w="full" h="full">
|
||||||
|
{selectedModelKey ? <ModelView /> : <ImportModels />}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,15 @@
|
|||||||
|
import { FormControl, FormLabel, Text } from '@invoke-ai/ui-library';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
label: string;
|
||||||
|
value: string | null | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ModelAttrView = ({ label, value }: Props) => {
|
||||||
|
return (
|
||||||
|
<FormControl flexDir="column" alignItems="flex-start" gap={0}>
|
||||||
|
<FormLabel>{label}</FormLabel>
|
||||||
|
<Text fontSize="md">{value || '-'}</Text>
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,116 @@
|
|||||||
|
import { skipToken } from '@reduxjs/toolkit/query';
|
||||||
|
import { useAppSelector } from '../../../../app/store/storeHooks';
|
||||||
|
import { useGetModelQuery } from '../../../../services/api/endpoints/models';
|
||||||
|
import { Flex, Text, Heading } from '@invoke-ai/ui-library';
|
||||||
|
import DataViewer from '../../../gallery/components/ImageMetadataViewer/DataViewer';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import {
|
||||||
|
CheckpointModelConfig,
|
||||||
|
ControlNetConfig,
|
||||||
|
DiffusersModelConfig,
|
||||||
|
IPAdapterConfig,
|
||||||
|
LoRAConfig,
|
||||||
|
T2IAdapterConfig,
|
||||||
|
TextualInversionConfig,
|
||||||
|
VAEConfig,
|
||||||
|
} from '../../../../services/api/types';
|
||||||
|
import { ModelAttrView } from './ModelAttrView';
|
||||||
|
|
||||||
|
export const ModelView = () => {
|
||||||
|
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
||||||
|
const { data, isLoading } = useGetModelQuery(selectedModelKey ?? skipToken);
|
||||||
|
|
||||||
|
const modelConfigData = useMemo(() => {
|
||||||
|
if (!data) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const modelFormat = data.config.format;
|
||||||
|
const modelType = data.config.type;
|
||||||
|
|
||||||
|
if (modelType === 'main') {
|
||||||
|
if (modelFormat === 'diffusers') {
|
||||||
|
return data.config as DiffusersModelConfig;
|
||||||
|
} else if (modelFormat === 'checkpoint') {
|
||||||
|
return data.config as CheckpointModelConfig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (modelType) {
|
||||||
|
case 'lora':
|
||||||
|
return data.config as LoRAConfig;
|
||||||
|
case 'embedding':
|
||||||
|
return data.config as TextualInversionConfig;
|
||||||
|
case 't2i_adapter':
|
||||||
|
return data.config as T2IAdapterConfig;
|
||||||
|
case 'ip_adapter':
|
||||||
|
return data.config as IPAdapterConfig;
|
||||||
|
case 'controlnet':
|
||||||
|
return data.config as ControlNetConfig;
|
||||||
|
case 'vae':
|
||||||
|
return data.config as VAEConfig;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return <Text>Loading</Text>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!modelConfigData) {
|
||||||
|
return <Text>Something went wrong</Text>;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Flex flexDir="column" h="full">
|
||||||
|
<Flex flexDir="column" gap={1} p={2}>
|
||||||
|
<Heading as="h2" fontSize="lg">
|
||||||
|
{modelConfigData.name}
|
||||||
|
</Heading>
|
||||||
|
{modelConfigData.source && <Text variant="subtext">Source: {modelConfigData.source}</Text>}
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex flexDir="column" p={2} gap={3}>
|
||||||
|
<Flex>
|
||||||
|
<ModelAttrView label="Description" value={modelConfigData.description} />
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={2}>
|
||||||
|
<ModelAttrView label="Base Model" value={modelConfigData.base} />
|
||||||
|
<ModelAttrView label="Model Type" value={modelConfigData.type} />
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={2}>
|
||||||
|
<ModelAttrView label="Format" value={modelConfigData.format} />
|
||||||
|
<ModelAttrView label="Path" value={modelConfigData.path} />
|
||||||
|
</Flex>
|
||||||
|
{modelConfigData.type === 'main' && (
|
||||||
|
<>
|
||||||
|
<Flex gap={2}>
|
||||||
|
{modelConfigData.format === 'diffusers' && (
|
||||||
|
<ModelAttrView label="Repo Variant" value={modelConfigData.repo_variant} />
|
||||||
|
)}
|
||||||
|
{modelConfigData.format === 'checkpoint' && (
|
||||||
|
<ModelAttrView label="Config Path" value={modelConfigData.config} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
<ModelAttrView label="Variant" value={modelConfigData.variant} />
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={2}>
|
||||||
|
<ModelAttrView label="Prediction Type" value={modelConfigData.prediction_type} />
|
||||||
|
<ModelAttrView label="Upcast Attention" value={`${modelConfigData.upcast_attention}`} />
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={2}>
|
||||||
|
<ModelAttrView label="ZTSNR Training" value={`${modelConfigData.ztsnr_training}`} />
|
||||||
|
<ModelAttrView label="VAE" value={modelConfigData.vae} />
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{modelConfigData.type === 'ip_adapter' && (
|
||||||
|
<Flex gap={2}>
|
||||||
|
<ModelAttrView label="Image Encoder Model ID" value={modelConfigData.image_encoder_model_id} />
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex h="full">{!!data?.metadata && <DataViewer label="metadata" data={data.metadata} />}</Flex>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
};
|
@ -1,14 +0,0 @@
|
|||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
export const zBaseModel = z.enum(['any', 'sd-1', 'sd-2', 'sdxl', 'sdxl-refiner']);
|
|
||||||
export const zModelType = z.enum([
|
|
||||||
'main',
|
|
||||||
'vae',
|
|
||||||
'lora',
|
|
||||||
'controlnet',
|
|
||||||
'embedding',
|
|
||||||
'ip_adapter',
|
|
||||||
'clip_vision',
|
|
||||||
't2i_adapter',
|
|
||||||
'onnx', // TODO(psyche): Remove this when removed from backend
|
|
||||||
]);
|
|
@ -1,16 +1,25 @@
|
|||||||
import { Box,Flex } from '@invoke-ai/ui-library';
|
import { Flex, Heading, Tab, TabList, TabPanel, TabPanels, Tabs, Box, Button } from '@invoke-ai/ui-library';
|
||||||
import { ImportModels } from 'features/modelManagerV2/subpanels/ImportModels';
|
import ImportModelsPanel from 'features/modelManager/subpanels/ImportModelsPanel';
|
||||||
import { ModelManager } from 'features/modelManagerV2/subpanels/ModelManager';
|
import MergeModelsPanel from 'features/modelManager/subpanels/MergeModelsPanel';
|
||||||
import { memo } from 'react';
|
import ModelManagerPanel from 'features/modelManager/subpanels/ModelManagerPanel';
|
||||||
|
import ModelManagerSettingsPanel from 'features/modelManager/subpanels/ModelManagerSettingsPanel';
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
|
import { memo, useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { SyncModelsIconButton } from '../../../modelManager/components/SyncModels/SyncModelsIconButton';
|
||||||
|
import { ModelManager } from '../../../modelManagerV2/subpanels/ModelManager';
|
||||||
|
import { ModelPane } from '../../../modelManagerV2/subpanels/ModelPane';
|
||||||
|
|
||||||
|
type ModelManagerTabName = 'modelManager' | 'importModels' | 'mergeModels' | 'settings';
|
||||||
|
|
||||||
const ModelManagerTab = () => {
|
const ModelManagerTab = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box w="full" h="full">
|
<Flex w="full" h="full" gap="2">
|
||||||
<Flex w="full" h="full" gap={4}>
|
|
||||||
<ModelManager />
|
<ModelManager />
|
||||||
<ImportModels />
|
<ModelPane />
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,6 +26,10 @@ type UpdateModelArg = {
|
|||||||
|
|
||||||
type UpdateModelResponse = paths['/api/v2/models/i/{key}']['patch']['responses']['200']['content']['application/json'];
|
type UpdateModelResponse = paths['/api/v2/models/i/{key}']['patch']['responses']['200']['content']['application/json'];
|
||||||
|
|
||||||
|
|
||||||
|
type GetModelResponse =
|
||||||
|
paths['/api/v2/models/i/{key}']['get']['responses']['200']['content']['application/json'];
|
||||||
|
|
||||||
type ListModelsArg = NonNullable<paths['/api/v2/models/']['get']['parameters']['query']>;
|
type ListModelsArg = NonNullable<paths['/api/v2/models/']['get']['parameters']['query']>;
|
||||||
|
|
||||||
type DeleteMainModelArg = {
|
type DeleteMainModelArg = {
|
||||||
@ -165,6 +169,12 @@ export const modelsApi = api.injectEndpoints({
|
|||||||
providesTags: buildProvidesTags<MainModelConfig>('MainModel'),
|
providesTags: buildProvidesTags<MainModelConfig>('MainModel'),
|
||||||
transformResponse: buildTransformResponse<MainModelConfig>(mainModelsAdapter),
|
transformResponse: buildTransformResponse<MainModelConfig>(mainModelsAdapter),
|
||||||
}),
|
}),
|
||||||
|
getModel: build.query<GetModelResponse, string>({
|
||||||
|
query: (key) => {
|
||||||
|
return buildModelsUrl(`i/${key}`);
|
||||||
|
},
|
||||||
|
providesTags: ['Model'],
|
||||||
|
}),
|
||||||
updateModels: build.mutation<UpdateModelResponse, UpdateModelArg>({
|
updateModels: build.mutation<UpdateModelResponse, UpdateModelArg>({
|
||||||
query: ({ key, body }) => {
|
query: ({ key, body }) => {
|
||||||
return {
|
return {
|
||||||
@ -320,4 +330,5 @@ export const {
|
|||||||
useGetModelsInFolderQuery,
|
useGetModelsInFolderQuery,
|
||||||
useGetCheckpointConfigsQuery,
|
useGetCheckpointConfigsQuery,
|
||||||
useGetModelImportsQuery,
|
useGetModelImportsQuery,
|
||||||
|
useGetModelQuery
|
||||||
} = modelsApi;
|
} = modelsApi;
|
||||||
|
@ -22,7 +22,7 @@ export type paths = {
|
|||||||
"/api/v2/models/i/{key}": {
|
"/api/v2/models/i/{key}": {
|
||||||
/**
|
/**
|
||||||
* Get Model Record
|
* Get Model Record
|
||||||
* @description Get a model record
|
* @description Get a model record and metadata
|
||||||
*/
|
*/
|
||||||
get: operations["get_model_record"];
|
get: operations["get_model_record"];
|
||||||
/**
|
/**
|
||||||
@ -4202,6 +4202,13 @@ export type components = {
|
|||||||
*/
|
*/
|
||||||
type: "freeu";
|
type: "freeu";
|
||||||
};
|
};
|
||||||
|
/** GetModelResponse */
|
||||||
|
GetModelResponse: {
|
||||||
|
/** Config */
|
||||||
|
config: (components["schemas"]["MainDiffusersConfig"] | components["schemas"]["MainCheckpointConfig"]) | (components["schemas"]["ONNXSD1Config"] | components["schemas"]["ONNXSD2Config"] | components["schemas"]["ONNXSDXLConfig"]) | (components["schemas"]["VaeDiffusersConfig"] | components["schemas"]["VaeCheckpointConfig"]) | (components["schemas"]["ControlNetDiffusersConfig"] | components["schemas"]["ControlNetCheckpointConfig"]) | components["schemas"]["LoRAConfig"] | components["schemas"]["TextualInversionConfig"] | components["schemas"]["IPAdapterConfig"] | components["schemas"]["CLIPVisionDiffusersConfig"] | components["schemas"]["T2IConfig"];
|
||||||
|
/** Metadata */
|
||||||
|
metadata: (components["schemas"]["BaseMetadata"] | components["schemas"]["HuggingFaceMetadata"] | components["schemas"]["CivitaiMetadata"]) | null;
|
||||||
|
};
|
||||||
/** Graph */
|
/** Graph */
|
||||||
Graph: {
|
Graph: {
|
||||||
/**
|
/**
|
||||||
@ -11169,7 +11176,7 @@ export type operations = {
|
|||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Get Model Record
|
* Get Model Record
|
||||||
* @description Get a model record
|
* @description Get a model record and metadata
|
||||||
*/
|
*/
|
||||||
get_model_record: {
|
get_model_record: {
|
||||||
parameters: {
|
parameters: {
|
||||||
@ -11182,7 +11189,7 @@ export type operations = {
|
|||||||
/** @description The model configuration was retrieved successfully */
|
/** @description The model configuration was retrieved successfully */
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": (components["schemas"]["MainDiffusersConfig"] | components["schemas"]["MainCheckpointConfig"]) | (components["schemas"]["ONNXSD1Config"] | components["schemas"]["ONNXSD2Config"] | components["schemas"]["ONNXSDXLConfig"]) | (components["schemas"]["VaeDiffusersConfig"] | components["schemas"]["VaeCheckpointConfig"]) | (components["schemas"]["ControlNetDiffusersConfig"] | components["schemas"]["ControlNetCheckpointConfig"]) | components["schemas"]["LoRAConfig"] | components["schemas"]["TextualInversionConfig"] | components["schemas"]["IPAdapterConfig"] | components["schemas"]["CLIPVisionDiffusersConfig"] | components["schemas"]["T2IConfig"];
|
"application/json": components["schemas"]["GetModelResponse"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
/** @description Bad request */
|
/** @description Bad request */
|
||||||
|
Loading…
Reference in New Issue
Block a user