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,
|
||||
ConfirmationAlertDialog,
|
||||
Flex,
|
||||
Icon,
|
||||
IconButton,
|
||||
Text,
|
||||
Tooltip,
|
||||
useDisclosure,
|
||||
Box,
|
||||
} from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
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 { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IoWarning } from 'react-icons/io5';
|
||||
import { PiTrashSimpleBold } from 'react-icons/pi';
|
||||
import { useDeleteModelsMutation } from 'services/api/endpoints/models';
|
||||
import type { AnyModelConfig } from 'services/api/types';
|
||||
@ -88,8 +91,16 @@ const ModelListItem = (props: ModelListItemProps) => {
|
||||
<Tooltip label={model.description} placement="bottom">
|
||||
<Text>{model.name}</Text>
|
||||
</Tooltip>
|
||||
{model.format === 'checkpoint' && (
|
||||
<Tooltip label="Checkpoint">
|
||||
<Box>
|
||||
<Icon as={IoWarning} />
|
||||
</Box>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
<IconButton
|
||||
onClick={onOpen}
|
||||
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 { ImportModels } from 'features/modelManagerV2/subpanels/ImportModels';
|
||||
import { ModelManager } from 'features/modelManagerV2/subpanels/ModelManager';
|
||||
import { memo } from 'react';
|
||||
import { Flex, Heading, Tab, TabList, TabPanel, TabPanels, Tabs, Box, Button } from '@invoke-ai/ui-library';
|
||||
import ImportModelsPanel from 'features/modelManager/subpanels/ImportModelsPanel';
|
||||
import MergeModelsPanel from 'features/modelManager/subpanels/MergeModelsPanel';
|
||||
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 { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Box w="full" h="full">
|
||||
<Flex w="full" h="full" gap={4}>
|
||||
<ModelManager />
|
||||
<ImportModels />
|
||||
</Flex>
|
||||
</Box>
|
||||
<Flex w="full" h="full" gap="2">
|
||||
<ModelManager />
|
||||
<ModelPane />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -26,6 +26,10 @@ type UpdateModelArg = {
|
||||
|
||||
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 DeleteMainModelArg = {
|
||||
@ -165,6 +169,12 @@ export const modelsApi = api.injectEndpoints({
|
||||
providesTags: buildProvidesTags<MainModelConfig>('MainModel'),
|
||||
transformResponse: buildTransformResponse<MainModelConfig>(mainModelsAdapter),
|
||||
}),
|
||||
getModel: build.query<GetModelResponse, string>({
|
||||
query: (key) => {
|
||||
return buildModelsUrl(`i/${key}`);
|
||||
},
|
||||
providesTags: ['Model'],
|
||||
}),
|
||||
updateModels: build.mutation<UpdateModelResponse, UpdateModelArg>({
|
||||
query: ({ key, body }) => {
|
||||
return {
|
||||
@ -320,4 +330,5 @@ export const {
|
||||
useGetModelsInFolderQuery,
|
||||
useGetCheckpointConfigsQuery,
|
||||
useGetModelImportsQuery,
|
||||
useGetModelQuery
|
||||
} = modelsApi;
|
||||
|
@ -22,7 +22,7 @@ export type paths = {
|
||||
"/api/v2/models/i/{key}": {
|
||||
/**
|
||||
* Get Model Record
|
||||
* @description Get a model record
|
||||
* @description Get a model record and metadata
|
||||
*/
|
||||
get: operations["get_model_record"];
|
||||
/**
|
||||
@ -4202,6 +4202,13 @@ export type components = {
|
||||
*/
|
||||
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: {
|
||||
/**
|
||||
@ -11169,7 +11176,7 @@ export type operations = {
|
||||
};
|
||||
/**
|
||||
* Get Model Record
|
||||
* @description Get a model record
|
||||
* @description Get a model record and metadata
|
||||
*/
|
||||
get_model_record: {
|
||||
parameters: {
|
||||
@ -11182,7 +11189,7 @@ export type operations = {
|
||||
/** @description The model configuration was retrieved successfully */
|
||||
200: {
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user