mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Merge branch 'release/invokeai-3-0-alpha' of https://github.com/invoke-ai/InvokeAI into release/invokeai-3-0-alpha
This commit is contained in:
commit
f32a2f135c
@ -92,6 +92,7 @@ class CompelInvocation(BaseInvocation):
|
||||
|
||||
with ModelPatcher.apply_lora_text_encoder(text_encoder_info.context.model, _lora_loader()),\
|
||||
ModelPatcher.apply_ti(tokenizer_info.context.model, text_encoder_info.context.model, ti_list) as (tokenizer, ti_manager),\
|
||||
ModelPatcher.apply_clip_skip(text_encoder_info.context.model, self.clip.skipped_layers),\
|
||||
text_encoder_info as text_encoder:
|
||||
|
||||
compel = Compel(
|
||||
@ -131,6 +132,24 @@ class CompelInvocation(BaseInvocation):
|
||||
),
|
||||
)
|
||||
|
||||
class ClipSkipInvocationOutput(BaseInvocationOutput):
|
||||
"""Clip skip node output"""
|
||||
type: Literal["clip_skip_output"] = "clip_skip_output"
|
||||
clip: ClipField = Field(None, description="Clip with skipped layers")
|
||||
|
||||
class ClipSkipInvocation(BaseInvocation):
|
||||
"""Skip layers in clip text_encoder model."""
|
||||
type: Literal["clip_skip"] = "clip_skip"
|
||||
|
||||
clip: ClipField = Field(None, description="Clip to use")
|
||||
skipped_layers: int = Field(0, description="Number of layers to skip in text_encoder")
|
||||
|
||||
def invoke(self, context: InvocationContext) -> ClipSkipInvocationOutput:
|
||||
self.clip.skipped_layers += self.skipped_layers
|
||||
return ClipSkipInvocationOutput(
|
||||
clip=self.clip,
|
||||
)
|
||||
|
||||
|
||||
def get_max_token_count(
|
||||
tokenizer, prompt: Union[FlattenedPrompt, Blend, Conjunction],
|
||||
|
@ -30,6 +30,7 @@ class UNetField(BaseModel):
|
||||
class ClipField(BaseModel):
|
||||
tokenizer: ModelInfo = Field(description="Info to load tokenizer submodel")
|
||||
text_encoder: ModelInfo = Field(description="Info to load text_encoder submodel")
|
||||
skipped_layers: int = Field(description="Number of skipped layers in text_encoder")
|
||||
loras: List[LoraInfo] = Field(description="Loras to apply on model loading")
|
||||
|
||||
|
||||
@ -154,6 +155,7 @@ class MainModelLoaderInvocation(BaseInvocation):
|
||||
submodel=SubModelType.TextEncoder,
|
||||
),
|
||||
loras=[],
|
||||
skipped_layers=0,
|
||||
),
|
||||
vae=VaeField(
|
||||
vae=ModelInfo(
|
||||
|
@ -615,6 +615,24 @@ class ModelPatcher:
|
||||
text_encoder.resize_token_embeddings(init_tokens_count)
|
||||
|
||||
|
||||
@classmethod
|
||||
@contextmanager
|
||||
def apply_clip_skip(
|
||||
cls,
|
||||
text_encoder: CLIPTextModel,
|
||||
clip_skip: int,
|
||||
):
|
||||
skipped_layers = []
|
||||
try:
|
||||
for i in range(clip_skip):
|
||||
skipped_layers.append(text_encoder.text_model.encoder.layers.pop(-1))
|
||||
|
||||
yield
|
||||
|
||||
finally:
|
||||
while len(skipped_layers) > 0:
|
||||
text_encoder.text_model.encoder.layers.append(skipped_layers.pop())
|
||||
|
||||
class TextualInversionModel:
|
||||
name: str
|
||||
embedding: torch.Tensor # [n, 768]|[n, 1280]
|
||||
|
@ -23,7 +23,7 @@
|
||||
"dev": "concurrently \"vite dev\" \"yarn run theme:watch\"",
|
||||
"dev:host": "concurrently \"vite dev --host\" \"yarn run theme:watch\"",
|
||||
"build": "yarn run lint && vite build",
|
||||
"typegen": "npx openapi-typescript http://localhost:9090/openapi.json --output src/services/api/schema.d.ts -t",
|
||||
"typegen": "npx ts-node scripts/typegen.ts",
|
||||
"preview": "vite preview",
|
||||
"lint:madge": "madge --circular src/main.tsx",
|
||||
"lint:eslint": "eslint --max-warnings=0 .",
|
||||
@ -83,7 +83,7 @@
|
||||
"konva": "^9.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"nanostores": "^0.9.2",
|
||||
"openapi-fetch": "0.4.0",
|
||||
"openapi-fetch": "^0.6.1",
|
||||
"overlayscrollbars": "^2.2.0",
|
||||
"overlayscrollbars-react": "^0.5.0",
|
||||
"patch-package": "^7.0.0",
|
||||
|
@ -1,55 +0,0 @@
|
||||
diff --git a/node_modules/openapi-fetch/dist/index.js b/node_modules/openapi-fetch/dist/index.js
|
||||
index cd4528a..8976b51 100644
|
||||
--- a/node_modules/openapi-fetch/dist/index.js
|
||||
+++ b/node_modules/openapi-fetch/dist/index.js
|
||||
@@ -1,5 +1,5 @@
|
||||
// settings & const
|
||||
-const DEFAULT_HEADERS = {
|
||||
+const CONTENT_TYPE_APPLICATION_JSON = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
const TRAILING_SLASH_RE = /\/*$/;
|
||||
@@ -29,18 +29,29 @@ export function createFinalURL(url, options) {
|
||||
}
|
||||
return finalURL;
|
||||
}
|
||||
+function stringifyBody(body) {
|
||||
+ if (body instanceof ArrayBuffer || body instanceof File || body instanceof DataView || body instanceof Blob || ArrayBuffer.isView(body) || body instanceof URLSearchParams || body instanceof FormData) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (typeof body === "string") {
|
||||
+ return body;
|
||||
+ }
|
||||
+
|
||||
+ return JSON.stringify(body);
|
||||
+ }
|
||||
+
|
||||
export default function createClient(clientOptions = {}) {
|
||||
const { fetch = globalThis.fetch, ...options } = clientOptions;
|
||||
- const defaultHeaders = new Headers({
|
||||
- ...DEFAULT_HEADERS,
|
||||
- ...(options.headers ?? {}),
|
||||
- });
|
||||
+ const defaultHeaders = new Headers(options.headers ?? {});
|
||||
async function coreFetch(url, fetchOptions) {
|
||||
const { headers, body: requestBody, params = {}, parseAs = "json", querySerializer = defaultSerializer, ...init } = fetchOptions || {};
|
||||
// URL
|
||||
const finalURL = createFinalURL(url, { baseUrl: options.baseUrl, params, querySerializer });
|
||||
+ // Stringify body if needed
|
||||
+ const stringifiedBody = stringifyBody(requestBody);
|
||||
// headers
|
||||
- const baseHeaders = new Headers(defaultHeaders); // clone defaults (don’t overwrite!)
|
||||
+ const baseHeaders = new Headers(stringifiedBody ? { ...CONTENT_TYPE_APPLICATION_JSON, ...defaultHeaders } : defaultHeaders); // clone defaults (don’t overwrite!)
|
||||
const headerOverrides = new Headers(headers);
|
||||
for (const [k, v] of headerOverrides.entries()) {
|
||||
if (v === undefined || v === null)
|
||||
@@ -54,7 +65,7 @@ export default function createClient(clientOptions = {}) {
|
||||
...options,
|
||||
...init,
|
||||
headers: baseHeaders,
|
||||
- body: typeof requestBody === "string" ? requestBody : JSON.stringify(requestBody),
|
||||
+ body: stringifiedBody ?? requestBody,
|
||||
});
|
||||
// handle empty content
|
||||
// note: we return `{}` because we want user truthy checks for `.data` or `.error` to succeed
|
@ -527,7 +527,8 @@
|
||||
"showOptionsPanel": "Show Options Panel",
|
||||
"hidePreview": "Hide Preview",
|
||||
"showPreview": "Show Preview",
|
||||
"controlNetControlMode": "Control Mode"
|
||||
"controlNetControlMode": "Control Mode",
|
||||
"clipSkip": "Clip Skip"
|
||||
},
|
||||
"settings": {
|
||||
"models": "Models",
|
||||
@ -551,7 +552,8 @@
|
||||
"generation": "Generation",
|
||||
"ui": "User Interface",
|
||||
"favoriteSchedulers": "Favorite Schedulers",
|
||||
"favoriteSchedulersPlaceholder": "No schedulers favorited"
|
||||
"favoriteSchedulersPlaceholder": "No schedulers favorited",
|
||||
"showAdvancedOptions": "Show Advanced Options"
|
||||
},
|
||||
"toast": {
|
||||
"serverError": "Server Error",
|
||||
|
3
invokeai/frontend/web/scripts/package.json
Normal file
3
invokeai/frontend/web/scripts/package.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
23
invokeai/frontend/web/scripts/typegen.ts
Normal file
23
invokeai/frontend/web/scripts/typegen.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import fs from 'node:fs';
|
||||
import openapiTS from 'openapi-typescript';
|
||||
|
||||
const OPENAPI_URL = 'http://localhost:9090/openapi.json';
|
||||
const OUTPUT_FILE = 'src/services/api/schema.d.ts';
|
||||
|
||||
async function main() {
|
||||
process.stdout.write(
|
||||
`Generating types "${OPENAPI_URL}" --> "${OUTPUT_FILE}"...`
|
||||
);
|
||||
const types = await openapiTS(OPENAPI_URL, {
|
||||
exportType: true,
|
||||
transform: (schemaObject, metadata) => {
|
||||
if ('format' in schemaObject && schemaObject.format === 'binary') {
|
||||
return schemaObject.nullable ? 'Blob | null' : 'Blob';
|
||||
}
|
||||
},
|
||||
});
|
||||
fs.writeFileSync(OUTPUT_FILE, types);
|
||||
process.stdout.write(` OK!\r\n`);
|
||||
}
|
||||
|
||||
main();
|
@ -86,6 +86,7 @@ import { addRequestedBoardImageDeletionListener } from './listeners/boardImagesD
|
||||
import { addSelectionAddedToBatchListener } from './listeners/selectionAddedToBatch';
|
||||
import { addImageDroppedListener } from './listeners/imageDropped';
|
||||
import { addImageToDeleteSelectedListener } from './listeners/imageToDeleteSelected';
|
||||
import { addModelSelectedListener } from './listeners/modelSelected';
|
||||
|
||||
export const listenerMiddleware = createListenerMiddleware();
|
||||
|
||||
@ -220,3 +221,6 @@ addSelectionAddedToBatchListener();
|
||||
|
||||
// DND
|
||||
addImageDroppedListener();
|
||||
|
||||
// Models
|
||||
addModelSelectedListener();
|
||||
|
@ -0,0 +1,42 @@
|
||||
import { makeToast } from 'app/components/Toaster';
|
||||
import { modelSelected } from 'features/parameters/store/actions';
|
||||
import {
|
||||
modelChanged,
|
||||
vaeSelected,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { zMainModel } from 'features/parameters/store/parameterZodSchemas';
|
||||
import { addToast } from 'features/system/store/systemSlice';
|
||||
import { startAppListening } from '..';
|
||||
import { lorasCleared } from '../../../../../features/lora/store/loraSlice';
|
||||
|
||||
export const addModelSelectedListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: modelSelected,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
const state = getState();
|
||||
const [base_model, type, name] = action.payload.split('/');
|
||||
|
||||
if (state.generation.model?.base_model !== base_model) {
|
||||
dispatch(
|
||||
addToast(
|
||||
makeToast({
|
||||
title: 'Base model changed, clearing submodels',
|
||||
status: 'warning',
|
||||
})
|
||||
)
|
||||
);
|
||||
dispatch(vaeSelected(null));
|
||||
dispatch(lorasCleared());
|
||||
// TODO: controlnet cleared
|
||||
}
|
||||
|
||||
const newModel = zMainModel.parse({
|
||||
id: action.payload,
|
||||
base_model,
|
||||
name,
|
||||
});
|
||||
|
||||
dispatch(modelChanged(newModel));
|
||||
},
|
||||
});
|
||||
};
|
@ -93,7 +93,8 @@ export type AppFeature =
|
||||
| 'discordLink'
|
||||
| 'bugLink'
|
||||
| 'localization'
|
||||
| 'consoleLogging';
|
||||
| 'consoleLogging'
|
||||
| 'dynamicPrompting';
|
||||
|
||||
/**
|
||||
* A disable-able Stable Diffusion feature
|
||||
@ -104,7 +105,10 @@ export type SDFeature =
|
||||
| 'variation'
|
||||
| 'symmetry'
|
||||
| 'seamless'
|
||||
| 'hires';
|
||||
| 'hires'
|
||||
| 'lora'
|
||||
| 'embedding'
|
||||
| 'vae';
|
||||
|
||||
/**
|
||||
* Configuration options for the InvokeAI UI.
|
||||
|
@ -32,7 +32,7 @@ const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => {
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
return (
|
||||
<Tooltip label={tooltip} placement="top" hasArrow>
|
||||
<Tooltip label={tooltip} placement="top" hasArrow isOpen={true}>
|
||||
<MultiSelect
|
||||
ref={inputRef}
|
||||
searchable={searchable}
|
||||
@ -66,6 +66,7 @@ const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => {
|
||||
'&[data-disabled]': {
|
||||
backgroundColor: mode(base300, base700)(colorMode),
|
||||
color: mode(base600, base400)(colorMode),
|
||||
cursor: 'not-allowed',
|
||||
},
|
||||
},
|
||||
value: {
|
||||
@ -108,6 +109,10 @@ const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => {
|
||||
color: mode('white', base50)(colorMode),
|
||||
},
|
||||
},
|
||||
'&[data-disabled]': {
|
||||
color: mode(base500, base600)(colorMode),
|
||||
cursor: 'not-allowed',
|
||||
},
|
||||
},
|
||||
rightSection: {
|
||||
width: 24,
|
||||
|
@ -67,6 +67,7 @@ const IAIMantineSelect = (props: IAISelectProps) => {
|
||||
'&[data-disabled]': {
|
||||
backgroundColor: mode(base300, base700)(colorMode),
|
||||
color: mode(base600, base400)(colorMode),
|
||||
cursor: 'not-allowed',
|
||||
},
|
||||
},
|
||||
value: {
|
||||
@ -109,6 +110,10 @@ const IAIMantineSelect = (props: IAISelectProps) => {
|
||||
color: mode('white', base50)(colorMode),
|
||||
},
|
||||
},
|
||||
'&[data-disabled]': {
|
||||
color: mode(base500, base600)(colorMode),
|
||||
cursor: 'not-allowed',
|
||||
},
|
||||
},
|
||||
rightSection: {
|
||||
width: 32,
|
||||
|
@ -0,0 +1,31 @@
|
||||
import { Box, Tooltip } from '@chakra-ui/react';
|
||||
import { Text } from '@mantine/core';
|
||||
import { forwardRef, memo } from 'react';
|
||||
|
||||
interface ItemProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||
label: string;
|
||||
description?: string;
|
||||
tooltip?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const IAIMantineSelectItemWithTooltip = forwardRef<HTMLDivElement, ItemProps>(
|
||||
({ label, tooltip, description, disabled, ...others }: ItemProps, ref) => (
|
||||
<Tooltip label={tooltip} placement="top" hasArrow>
|
||||
<Box ref={ref} {...others}>
|
||||
<Box>
|
||||
<Text>{label}</Text>
|
||||
{description && (
|
||||
<Text size="xs" color="base.600">
|
||||
{description}
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
)
|
||||
);
|
||||
|
||||
IAIMantineSelectItemWithTooltip.displayName = 'IAIMantineSelectItemWithTooltip';
|
||||
|
||||
export default memo(IAIMantineSelectItemWithTooltip);
|
@ -26,7 +26,7 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import { clamp } from 'lodash-es';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { roundDownToMultiple } from 'common/util/roundDownToMultiple';
|
||||
import {
|
||||
FocusEvent,
|
||||
memo,
|
||||
@ -36,9 +36,9 @@ import {
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { BiReset } from 'react-icons/bi';
|
||||
import IAIIconButton, { IAIIconButtonProps } from './IAIIconButton';
|
||||
import { roundDownToMultiple } from 'common/util/roundDownToMultiple';
|
||||
|
||||
const SLIDER_MARK_STYLES: ChakraProps['sx'] = {
|
||||
mt: 1.5,
|
||||
|
@ -7,6 +7,7 @@ import IAICollapse from 'common/components/IAICollapse';
|
||||
import ParamDynamicPromptsCombinatorial from './ParamDynamicPromptsCombinatorial';
|
||||
import ParamDynamicPromptsToggle from './ParamDynamicPromptsEnabled';
|
||||
import ParamDynamicPromptsMaxPrompts from './ParamDynamicPromptsMaxPrompts';
|
||||
import { useFeatureStatus } from '../../system/hooks/useFeatureStatus';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
@ -21,6 +22,13 @@ const selector = createSelector(
|
||||
const ParamDynamicPromptsCollapse = () => {
|
||||
const { activeLabel } = useAppSelector(selector);
|
||||
|
||||
const isDynamicPromptingEnabled =
|
||||
useFeatureStatus('dynamicPrompting').isFeatureEnabled;
|
||||
|
||||
if (!isDynamicPromptingEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<IAICollapse label="Dynamic Prompts" activeLabel={activeLabel}>
|
||||
<Flex sx={{ gap: 2, flexDir: 'column' }}>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { memo } from 'react';
|
||||
import { BiCode } from 'react-icons/bi';
|
||||
import { FaCode } from 'react-icons/fa';
|
||||
|
||||
type Props = {
|
||||
onClick: () => void;
|
||||
@ -13,15 +13,24 @@ const AddEmbeddingButton = (props: Props) => {
|
||||
size="sm"
|
||||
aria-label="Add Embedding"
|
||||
tooltip="Add Embedding"
|
||||
icon={<BiCode />}
|
||||
icon={<FaCode />}
|
||||
sx={{
|
||||
p: 2,
|
||||
color: 'base.700',
|
||||
color: 'base.500',
|
||||
_hover: {
|
||||
color: 'base.550',
|
||||
color: 'base.600',
|
||||
},
|
||||
_active: {
|
||||
color: 'base.700',
|
||||
},
|
||||
_dark: {
|
||||
color: 'base.500',
|
||||
_hover: {
|
||||
color: 'base.400',
|
||||
},
|
||||
_active: {
|
||||
color: 'base.300',
|
||||
},
|
||||
},
|
||||
}}
|
||||
variant="link"
|
||||
|
@ -6,24 +6,17 @@ import {
|
||||
PopoverTrigger,
|
||||
Text,
|
||||
} from '@chakra-ui/react';
|
||||
import { SelectItem } from '@mantine/core';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIMantineMultiSelect from 'common/components/IAIMantineMultiSelect';
|
||||
import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
|
||||
import { MODEL_TYPE_MAP } from 'features/system/components/ModelSelect';
|
||||
import { forEach } from 'lodash-es';
|
||||
import {
|
||||
PropsWithChildren,
|
||||
forwardRef,
|
||||
useCallback,
|
||||
useMemo,
|
||||
useRef,
|
||||
} from 'react';
|
||||
import { PropsWithChildren, useCallback, useMemo, useRef } from 'react';
|
||||
import { useGetTextualInversionModelsQuery } from 'services/api/endpoints/models';
|
||||
import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants';
|
||||
|
||||
type EmbeddingSelectItem = {
|
||||
label: string;
|
||||
value: string;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
type Props = PropsWithChildren & {
|
||||
onSelect: (v: string) => void;
|
||||
isOpen: boolean;
|
||||
@ -35,25 +28,37 @@ const ParamEmbeddingPopover = (props: Props) => {
|
||||
const { data: embeddingQueryData } = useGetTextualInversionModelsQuery();
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const currentMainModel = useAppSelector(
|
||||
(state: RootState) => state.generation.model
|
||||
);
|
||||
|
||||
const data = useMemo(() => {
|
||||
if (!embeddingQueryData) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const data: EmbeddingSelectItem[] = [];
|
||||
const data: SelectItem[] = [];
|
||||
|
||||
forEach(embeddingQueryData.entities, (embedding, _) => {
|
||||
if (!embedding) return;
|
||||
if (!embedding) {
|
||||
return;
|
||||
}
|
||||
|
||||
const disabled = currentMainModel?.base_model !== embedding.base_model;
|
||||
|
||||
data.push({
|
||||
value: embedding.name,
|
||||
label: embedding.name,
|
||||
description: embedding.description,
|
||||
group: MODEL_TYPE_MAP[embedding.base_model],
|
||||
disabled,
|
||||
tooltip: disabled
|
||||
? `Incompatible base model: ${embedding.base_model}`
|
||||
: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
return data;
|
||||
}, [embeddingQueryData]);
|
||||
return data.sort((a, b) => (a.disabled && !b.disabled ? 1 : -1));
|
||||
}, [embeddingQueryData, currentMainModel?.base_model]);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(v: string[]) => {
|
||||
@ -108,10 +113,12 @@ const ParamEmbeddingPopover = (props: Props) => {
|
||||
data={data}
|
||||
maxDropdownHeight={400}
|
||||
nothingFound="No Matching Embeddings"
|
||||
itemComponent={SelectItem}
|
||||
itemComponent={IAIMantineSelectItemWithTooltip}
|
||||
disabled={data.length === 0}
|
||||
filter={(value, selected, item: EmbeddingSelectItem) =>
|
||||
item.label.toLowerCase().includes(value.toLowerCase().trim()) ||
|
||||
filter={(value, selected, item: SelectItem) =>
|
||||
item.label
|
||||
?.toLowerCase()
|
||||
.includes(value.toLowerCase().trim()) ||
|
||||
item.value.toLowerCase().includes(value.toLowerCase().trim())
|
||||
}
|
||||
onChange={handleChange}
|
||||
@ -124,28 +131,3 @@ const ParamEmbeddingPopover = (props: Props) => {
|
||||
};
|
||||
|
||||
export default ParamEmbeddingPopover;
|
||||
|
||||
interface ItemProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||
value: string;
|
||||
label: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
const SelectItem = forwardRef<HTMLDivElement, ItemProps>(
|
||||
({ label, description, ...others }: ItemProps, ref) => {
|
||||
return (
|
||||
<div ref={ref} {...others}>
|
||||
<div>
|
||||
<Text>{label}</Text>
|
||||
{description && (
|
||||
<Text size="xs" color="base.600">
|
||||
{description}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
SelectItem.displayName = 'SelectItem';
|
||||
|
@ -8,6 +8,7 @@ import { size } from 'lodash-es';
|
||||
import { memo } from 'react';
|
||||
import ParamLoraList from './ParamLoraList';
|
||||
import ParamLoraSelect from './ParamLoraSelect';
|
||||
import { useFeatureStatus } from '../../system/hooks/useFeatureStatus';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
@ -23,6 +24,12 @@ const selector = createSelector(
|
||||
const ParamLoraCollapse = () => {
|
||||
const { activeLabel } = useAppSelector(selector);
|
||||
|
||||
const isLoraEnabled = useFeatureStatus('lora').isFeatureEnabled;
|
||||
|
||||
if (!isLoraEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<IAICollapse label={'LoRA'} activeLabel={activeLabel}>
|
||||
<Flex sx={{ flexDir: 'column', gap: 2 }}>
|
||||
|
@ -1,19 +1,16 @@
|
||||
import { Flex, Text } from '@chakra-ui/react';
|
||||
import { SelectItem } from '@mantine/core';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { RootState, stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIMantineMultiSelect from 'common/components/IAIMantineMultiSelect';
|
||||
import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
|
||||
import { loraAdded } from 'features/lora/store/loraSlice';
|
||||
import { MODEL_TYPE_MAP } from 'features/system/components/ModelSelect';
|
||||
import { forEach } from 'lodash-es';
|
||||
import { forwardRef, useCallback, useMemo } from 'react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useGetLoRAModelsQuery } from 'services/api/endpoints/models';
|
||||
import { loraAdded } from '../store/loraSlice';
|
||||
|
||||
type LoraSelectItem = {
|
||||
label: string;
|
||||
value: string;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
@ -28,27 +25,37 @@ const ParamLoraSelect = () => {
|
||||
const { loras } = useAppSelector(selector);
|
||||
const { data: lorasQueryData } = useGetLoRAModelsQuery();
|
||||
|
||||
const currentMainModel = useAppSelector(
|
||||
(state: RootState) => state.generation.model
|
||||
);
|
||||
|
||||
const data = useMemo(() => {
|
||||
if (!lorasQueryData) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const data: LoraSelectItem[] = [];
|
||||
const data: SelectItem[] = [];
|
||||
|
||||
forEach(lorasQueryData.entities, (lora, id) => {
|
||||
if (!lora || Boolean(id in loras)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const disabled = currentMainModel?.base_model !== lora.base_model;
|
||||
|
||||
data.push({
|
||||
value: id,
|
||||
label: lora.name,
|
||||
description: lora.description,
|
||||
disabled,
|
||||
group: MODEL_TYPE_MAP[lora.base_model],
|
||||
tooltip: disabled
|
||||
? `Incompatible base model: ${lora.base_model}`
|
||||
: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
return data;
|
||||
}, [loras, lorasQueryData]);
|
||||
return data.sort((a, b) => (a.disabled && !b.disabled ? 1 : -1));
|
||||
}, [loras, lorasQueryData, currentMainModel?.base_model]);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(v: string[]) => {
|
||||
@ -78,10 +85,10 @@ const ParamLoraSelect = () => {
|
||||
data={data}
|
||||
maxDropdownHeight={400}
|
||||
nothingFound="No matching LoRAs"
|
||||
itemComponent={SelectItem}
|
||||
itemComponent={IAIMantineSelectItemWithTooltip}
|
||||
disabled={data.length === 0}
|
||||
filter={(value, selected, item: LoraSelectItem) =>
|
||||
item.label.toLowerCase().includes(value.toLowerCase().trim()) ||
|
||||
filter={(value, selected, item: SelectItem) =>
|
||||
item.label?.toLowerCase().includes(value.toLowerCase().trim()) ||
|
||||
item.value.toLowerCase().includes(value.toLowerCase().trim())
|
||||
}
|
||||
onChange={handleChange}
|
||||
@ -89,29 +96,4 @@ const ParamLoraSelect = () => {
|
||||
);
|
||||
};
|
||||
|
||||
interface ItemProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||
value: string;
|
||||
label: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
const SelectItem = forwardRef<HTMLDivElement, ItemProps>(
|
||||
({ label, description, ...others }: ItemProps, ref) => {
|
||||
return (
|
||||
<div ref={ref} {...others}>
|
||||
<div>
|
||||
<Text>{label}</Text>
|
||||
{description && (
|
||||
<Text size="xs" color="base.600">
|
||||
{description}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
SelectItem.displayName = 'SelectItem';
|
||||
|
||||
export default ParamLoraSelect;
|
||||
|
@ -1,18 +1,21 @@
|
||||
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
|
||||
import { LoRAModelParam } from 'features/parameters/store/parameterZodSchemas';
|
||||
import { LoRAModelConfigEntity } from 'services/api/endpoints/models';
|
||||
import { BaseModelType } from 'services/api/types';
|
||||
|
||||
export type Lora = {
|
||||
id: string;
|
||||
base_model: BaseModelType;
|
||||
name: string;
|
||||
weight: number;
|
||||
};
|
||||
|
||||
export const defaultLoRAConfig: Omit<Lora, 'id' | 'name'> = {
|
||||
export const defaultLoRAConfig = {
|
||||
weight: 0.75,
|
||||
};
|
||||
|
||||
export type LoraState = {
|
||||
loras: Record<string, Lora>;
|
||||
loras: Record<string, LoRAModelParam & { weight: number }>;
|
||||
};
|
||||
|
||||
export const intialLoraState: LoraState = {
|
||||
@ -24,13 +27,16 @@ export const loraSlice = createSlice({
|
||||
initialState: intialLoraState,
|
||||
reducers: {
|
||||
loraAdded: (state, action: PayloadAction<LoRAModelConfigEntity>) => {
|
||||
const { name, id } = action.payload;
|
||||
state.loras[id] = { id, name, ...defaultLoRAConfig };
|
||||
const { name, id, base_model } = action.payload;
|
||||
state.loras[id] = { id, name, base_model, ...defaultLoRAConfig };
|
||||
},
|
||||
loraRemoved: (state, action: PayloadAction<string>) => {
|
||||
const id = action.payload;
|
||||
delete state.loras[id];
|
||||
},
|
||||
lorasCleared: (state) => {
|
||||
state.loras = {};
|
||||
},
|
||||
loraWeightChanged: (
|
||||
state,
|
||||
action: PayloadAction<{ id: string; weight: number }>
|
||||
@ -45,7 +51,12 @@ export const loraSlice = createSlice({
|
||||
},
|
||||
});
|
||||
|
||||
export const { loraAdded, loraRemoved, loraWeightChanged, loraWeightReset } =
|
||||
loraSlice.actions;
|
||||
export const {
|
||||
loraAdded,
|
||||
loraRemoved,
|
||||
loraWeightChanged,
|
||||
loraWeightReset,
|
||||
lorasCleared,
|
||||
} = loraSlice.actions;
|
||||
|
||||
export default loraSlice.reducer;
|
||||
|
@ -4,6 +4,7 @@ import { forEach, size } from 'lodash-es';
|
||||
import { LoraLoaderInvocation } from 'services/api/types';
|
||||
import { modelIdToLoRAModelField } from '../modelIdToLoRAName';
|
||||
import {
|
||||
CLIP_SKIP,
|
||||
LORA_LOADER,
|
||||
MAIN_MODEL_LOADER,
|
||||
NEGATIVE_CONDITIONING,
|
||||
@ -27,14 +28,19 @@ export const addLoRAsToGraph = (
|
||||
const loraCount = size(loras);
|
||||
|
||||
if (loraCount > 0) {
|
||||
// remove any existing connections from main model loader, we need to insert the lora nodes
|
||||
// Remove MAIN_MODEL_LOADER unet connection to feed it to LoRAs
|
||||
graph.edges = graph.edges.filter(
|
||||
(e) =>
|
||||
!(
|
||||
e.source.node_id === MAIN_MODEL_LOADER &&
|
||||
['unet', 'clip'].includes(e.source.field)
|
||||
['unet'].includes(e.source.field)
|
||||
)
|
||||
);
|
||||
// Remove CLIP_SKIP connections to conditionings to feed it through LoRAs
|
||||
graph.edges = graph.edges.filter(
|
||||
(e) =>
|
||||
!(e.source.node_id === CLIP_SKIP && ['clip'].includes(e.source.field))
|
||||
);
|
||||
}
|
||||
|
||||
// we need to remember the last lora so we can chain from it
|
||||
@ -73,7 +79,7 @@ export const addLoRAsToGraph = (
|
||||
|
||||
graph.edges.push({
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
|
@ -16,10 +16,12 @@ export const addVAEToGraph = (
|
||||
graph: NonNullableGraph,
|
||||
state: RootState
|
||||
): void => {
|
||||
const { vae: vaeId } = state.generation;
|
||||
const vae_model = modelIdToVAEModelField(vaeId);
|
||||
const { vae } = state.generation;
|
||||
const vae_model = modelIdToVAEModelField(vae?.id || '');
|
||||
|
||||
if (vaeId !== 'auto') {
|
||||
const isAutoVae = !vae;
|
||||
|
||||
if (!isAutoVae) {
|
||||
graph.nodes[VAE_LOADER] = {
|
||||
type: 'vae_loader',
|
||||
id: VAE_LOADER,
|
||||
@ -30,7 +32,7 @@ export const addVAEToGraph = (
|
||||
if (graph.id === TEXT_TO_IMAGE_GRAPH || graph.id === IMAGE_TO_IMAGE_GRAPH) {
|
||||
graph.edges.push({
|
||||
source: {
|
||||
node_id: vaeId === 'auto' ? MAIN_MODEL_LOADER : VAE_LOADER,
|
||||
node_id: isAutoVae ? MAIN_MODEL_LOADER : VAE_LOADER,
|
||||
field: 'vae',
|
||||
},
|
||||
destination: {
|
||||
@ -43,7 +45,7 @@ export const addVAEToGraph = (
|
||||
if (graph.id === IMAGE_TO_IMAGE_GRAPH) {
|
||||
graph.edges.push({
|
||||
source: {
|
||||
node_id: vaeId === 'auto' ? MAIN_MODEL_LOADER : VAE_LOADER,
|
||||
node_id: isAutoVae ? MAIN_MODEL_LOADER : VAE_LOADER,
|
||||
field: 'vae',
|
||||
},
|
||||
destination: {
|
||||
@ -56,7 +58,7 @@ export const addVAEToGraph = (
|
||||
if (graph.id === INPAINT_GRAPH) {
|
||||
graph.edges.push({
|
||||
source: {
|
||||
node_id: vaeId === 'auto' ? MAIN_MODEL_LOADER : VAE_LOADER,
|
||||
node_id: isAutoVae ? MAIN_MODEL_LOADER : VAE_LOADER,
|
||||
field: 'vae',
|
||||
},
|
||||
destination: {
|
||||
|
@ -12,6 +12,7 @@ import { addDynamicPromptsToGraph } from './addDynamicPromptsToGraph';
|
||||
import { addLoRAsToGraph } from './addLoRAsToGraph';
|
||||
import { addVAEToGraph } from './addVAEToGraph';
|
||||
import {
|
||||
CLIP_SKIP,
|
||||
IMAGE_TO_IMAGE_GRAPH,
|
||||
IMAGE_TO_LATENTS,
|
||||
LATENTS_TO_IMAGE,
|
||||
@ -35,11 +36,12 @@ export const buildCanvasImageToImageGraph = (
|
||||
const {
|
||||
positivePrompt,
|
||||
negativePrompt,
|
||||
model: modelId,
|
||||
model: currentModel,
|
||||
cfgScale: cfg_scale,
|
||||
scheduler,
|
||||
steps,
|
||||
img2imgStrength: strength,
|
||||
clipSkip,
|
||||
iterations,
|
||||
seed,
|
||||
shouldRandomizeSeed,
|
||||
@ -48,7 +50,7 @@ export const buildCanvasImageToImageGraph = (
|
||||
// The bounding box determines width and height, not the width and height params
|
||||
const { width, height } = state.canvas.boundingBoxDimensions;
|
||||
|
||||
const model = modelIdToMainModelField(modelId);
|
||||
const model = modelIdToMainModelField(currentModel?.id || '');
|
||||
|
||||
/**
|
||||
* The easiest way to build linear graphs is to do it in the node editor, then copy and paste the
|
||||
@ -82,6 +84,11 @@ export const buildCanvasImageToImageGraph = (
|
||||
id: MAIN_MODEL_LOADER,
|
||||
model,
|
||||
},
|
||||
[CLIP_SKIP]: {
|
||||
type: 'clip_skip',
|
||||
id: CLIP_SKIP,
|
||||
skipped_layers: clipSkip,
|
||||
},
|
||||
[LATENTS_TO_IMAGE]: {
|
||||
type: 'l2i',
|
||||
id: LATENTS_TO_IMAGE,
|
||||
@ -109,6 +116,16 @@ export const buildCanvasImageToImageGraph = (
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: POSITIVE_CONDITIONING,
|
||||
field: 'clip',
|
||||
@ -116,7 +133,7 @@ export const buildCanvasImageToImageGraph = (
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
|
@ -11,6 +11,7 @@ import { modelIdToMainModelField } from '../modelIdToMainModelField';
|
||||
import { addLoRAsToGraph } from './addLoRAsToGraph';
|
||||
import { addVAEToGraph } from './addVAEToGraph';
|
||||
import {
|
||||
CLIP_SKIP,
|
||||
INPAINT,
|
||||
INPAINT_GRAPH,
|
||||
ITERATE,
|
||||
@ -34,7 +35,7 @@ export const buildCanvasInpaintGraph = (
|
||||
const {
|
||||
positivePrompt,
|
||||
negativePrompt,
|
||||
model: modelId,
|
||||
model: currentModel,
|
||||
cfgScale: cfg_scale,
|
||||
scheduler,
|
||||
steps,
|
||||
@ -49,6 +50,7 @@ export const buildCanvasInpaintGraph = (
|
||||
seamStrength,
|
||||
tileSize,
|
||||
infillMethod,
|
||||
clipSkip,
|
||||
} = state.generation;
|
||||
|
||||
// The bounding box determines width and height, not the width and height params
|
||||
@ -57,7 +59,7 @@ export const buildCanvasInpaintGraph = (
|
||||
// We may need to set the inpaint width and height to scale the image
|
||||
const { scaledBoundingBoxDimensions, boundingBoxScaleMethod } = state.canvas;
|
||||
|
||||
const model = modelIdToMainModelField(modelId);
|
||||
const model = modelIdToMainModelField(currentModel?.id || '');
|
||||
|
||||
const graph: NonNullableGraph = {
|
||||
id: INPAINT_GRAPH,
|
||||
@ -108,6 +110,11 @@ export const buildCanvasInpaintGraph = (
|
||||
id: MAIN_MODEL_LOADER,
|
||||
model,
|
||||
},
|
||||
[CLIP_SKIP]: {
|
||||
type: 'clip_skip',
|
||||
id: CLIP_SKIP,
|
||||
skipped_layers: clipSkip,
|
||||
},
|
||||
[RANGE_OF_SIZE]: {
|
||||
type: 'range_of_size',
|
||||
id: RANGE_OF_SIZE,
|
||||
@ -122,6 +129,46 @@ export const buildCanvasInpaintGraph = (
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'unet',
|
||||
},
|
||||
destination: {
|
||||
node_id: INPAINT,
|
||||
field: 'unet',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: POSITIVE_CONDITIONING,
|
||||
field: 'clip',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: NEGATIVE_CONDITIONING,
|
||||
field: 'clip',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: NEGATIVE_CONDITIONING,
|
||||
@ -142,36 +189,6 @@ export const buildCanvasInpaintGraph = (
|
||||
field: 'positive_conditioning',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: POSITIVE_CONDITIONING,
|
||||
field: 'clip',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: NEGATIVE_CONDITIONING,
|
||||
field: 'clip',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'unet',
|
||||
},
|
||||
destination: {
|
||||
node_id: INPAINT,
|
||||
field: 'unet',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: RANGE_OF_SIZE,
|
||||
|
@ -6,6 +6,7 @@ import { addDynamicPromptsToGraph } from './addDynamicPromptsToGraph';
|
||||
import { addLoRAsToGraph } from './addLoRAsToGraph';
|
||||
import { addVAEToGraph } from './addVAEToGraph';
|
||||
import {
|
||||
CLIP_SKIP,
|
||||
LATENTS_TO_IMAGE,
|
||||
MAIN_MODEL_LOADER,
|
||||
NEGATIVE_CONDITIONING,
|
||||
@ -24,10 +25,11 @@ export const buildCanvasTextToImageGraph = (
|
||||
const {
|
||||
positivePrompt,
|
||||
negativePrompt,
|
||||
model: modelId,
|
||||
model: currentModel,
|
||||
cfgScale: cfg_scale,
|
||||
scheduler,
|
||||
steps,
|
||||
clipSkip,
|
||||
iterations,
|
||||
seed,
|
||||
shouldRandomizeSeed,
|
||||
@ -36,7 +38,7 @@ export const buildCanvasTextToImageGraph = (
|
||||
// The bounding box determines width and height, not the width and height params
|
||||
const { width, height } = state.canvas.boundingBoxDimensions;
|
||||
|
||||
const model = modelIdToMainModelField(modelId);
|
||||
const model = modelIdToMainModelField(currentModel?.id || '');
|
||||
|
||||
/**
|
||||
* The easiest way to build linear graphs is to do it in the node editor, then copy and paste the
|
||||
@ -79,6 +81,11 @@ export const buildCanvasTextToImageGraph = (
|
||||
id: MAIN_MODEL_LOADER,
|
||||
model,
|
||||
},
|
||||
[CLIP_SKIP]: {
|
||||
type: 'clip_skip',
|
||||
id: CLIP_SKIP,
|
||||
skipped_layers: clipSkip,
|
||||
},
|
||||
[LATENTS_TO_IMAGE]: {
|
||||
type: 'l2i',
|
||||
id: LATENTS_TO_IMAGE,
|
||||
@ -110,6 +117,16 @@ export const buildCanvasTextToImageGraph = (
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: POSITIVE_CONDITIONING,
|
||||
field: 'clip',
|
||||
@ -117,7 +134,7 @@ export const buildCanvasTextToImageGraph = (
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
|
@ -13,6 +13,7 @@ import { addDynamicPromptsToGraph } from './addDynamicPromptsToGraph';
|
||||
import { addLoRAsToGraph } from './addLoRAsToGraph';
|
||||
import { addVAEToGraph } from './addVAEToGraph';
|
||||
import {
|
||||
CLIP_SKIP,
|
||||
IMAGE_COLLECTION,
|
||||
IMAGE_COLLECTION_ITERATE,
|
||||
IMAGE_TO_IMAGE_GRAPH,
|
||||
@ -37,7 +38,7 @@ export const buildLinearImageToImageGraph = (
|
||||
const {
|
||||
positivePrompt,
|
||||
negativePrompt,
|
||||
model: modelId,
|
||||
model: currentModel,
|
||||
cfgScale: cfg_scale,
|
||||
scheduler,
|
||||
steps,
|
||||
@ -46,6 +47,7 @@ export const buildLinearImageToImageGraph = (
|
||||
shouldFitToWidthHeight,
|
||||
width,
|
||||
height,
|
||||
clipSkip,
|
||||
} = state.generation;
|
||||
|
||||
const {
|
||||
@ -71,12 +73,22 @@ export const buildLinearImageToImageGraph = (
|
||||
throw new Error('No initial image found in state');
|
||||
}
|
||||
|
||||
const model = modelIdToMainModelField(modelId);
|
||||
const model = modelIdToMainModelField(currentModel?.id || '');
|
||||
|
||||
// copy-pasted graph from node editor, filled in with state values & friendly node ids
|
||||
const graph: NonNullableGraph = {
|
||||
id: IMAGE_TO_IMAGE_GRAPH,
|
||||
nodes: {
|
||||
[MAIN_MODEL_LOADER]: {
|
||||
type: 'main_model_loader',
|
||||
id: MAIN_MODEL_LOADER,
|
||||
model,
|
||||
},
|
||||
[CLIP_SKIP]: {
|
||||
type: 'clip_skip',
|
||||
id: CLIP_SKIP,
|
||||
skipped_layers: clipSkip,
|
||||
},
|
||||
[POSITIVE_CONDITIONING]: {
|
||||
type: 'compel',
|
||||
id: POSITIVE_CONDITIONING,
|
||||
@ -91,11 +103,6 @@ export const buildLinearImageToImageGraph = (
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
},
|
||||
[MAIN_MODEL_LOADER]: {
|
||||
type: 'main_model_loader',
|
||||
id: MAIN_MODEL_LOADER,
|
||||
model,
|
||||
},
|
||||
[LATENTS_TO_IMAGE]: {
|
||||
type: 'l2i',
|
||||
id: LATENTS_TO_IMAGE,
|
||||
@ -121,6 +128,26 @@ export const buildLinearImageToImageGraph = (
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'unet',
|
||||
},
|
||||
destination: {
|
||||
node_id: LATENTS_TO_LATENTS,
|
||||
field: 'unet',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
@ -130,7 +157,7 @@ export const buildLinearImageToImageGraph = (
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
@ -168,17 +195,6 @@ export const buildLinearImageToImageGraph = (
|
||||
field: 'noise',
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'unet',
|
||||
},
|
||||
destination: {
|
||||
node_id: LATENTS_TO_LATENTS,
|
||||
field: 'unet',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: NEGATIVE_CONDITIONING,
|
||||
|
@ -6,6 +6,7 @@ import { addDynamicPromptsToGraph } from './addDynamicPromptsToGraph';
|
||||
import { addLoRAsToGraph } from './addLoRAsToGraph';
|
||||
import { addVAEToGraph } from './addVAEToGraph';
|
||||
import {
|
||||
CLIP_SKIP,
|
||||
LATENTS_TO_IMAGE,
|
||||
MAIN_MODEL_LOADER,
|
||||
NEGATIVE_CONDITIONING,
|
||||
@ -21,15 +22,16 @@ export const buildLinearTextToImageGraph = (
|
||||
const {
|
||||
positivePrompt,
|
||||
negativePrompt,
|
||||
model: modelId,
|
||||
model: currentModel,
|
||||
cfgScale: cfg_scale,
|
||||
scheduler,
|
||||
steps,
|
||||
width,
|
||||
height,
|
||||
clipSkip,
|
||||
} = state.generation;
|
||||
|
||||
const model = modelIdToMainModelField(modelId);
|
||||
const model = modelIdToMainModelField(currentModel?.id || '');
|
||||
|
||||
/**
|
||||
* The easiest way to build linear graphs is to do it in the node editor, then copy and paste the
|
||||
@ -44,6 +46,16 @@ export const buildLinearTextToImageGraph = (
|
||||
const graph: NonNullableGraph = {
|
||||
id: TEXT_TO_IMAGE_GRAPH,
|
||||
nodes: {
|
||||
[MAIN_MODEL_LOADER]: {
|
||||
type: 'main_model_loader',
|
||||
id: MAIN_MODEL_LOADER,
|
||||
model,
|
||||
},
|
||||
[CLIP_SKIP]: {
|
||||
type: 'clip_skip',
|
||||
id: CLIP_SKIP,
|
||||
skipped_layers: clipSkip,
|
||||
},
|
||||
[POSITIVE_CONDITIONING]: {
|
||||
type: 'compel',
|
||||
id: POSITIVE_CONDITIONING,
|
||||
@ -67,11 +79,6 @@ export const buildLinearTextToImageGraph = (
|
||||
scheduler,
|
||||
steps,
|
||||
},
|
||||
[MAIN_MODEL_LOADER]: {
|
||||
type: 'main_model_loader',
|
||||
id: MAIN_MODEL_LOADER,
|
||||
model,
|
||||
},
|
||||
[LATENTS_TO_IMAGE]: {
|
||||
type: 'l2i',
|
||||
id: LATENTS_TO_IMAGE,
|
||||
@ -80,12 +87,42 @@ export const buildLinearTextToImageGraph = (
|
||||
edges: [
|
||||
{
|
||||
source: {
|
||||
node_id: NEGATIVE_CONDITIONING,
|
||||
field: 'conditioning',
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'unet',
|
||||
},
|
||||
destination: {
|
||||
node_id: TEXT_TO_LATENTS,
|
||||
field: 'negative_conditioning',
|
||||
field: 'unet',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: POSITIVE_CONDITIONING,
|
||||
field: 'clip',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: CLIP_SKIP,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: NEGATIVE_CONDITIONING,
|
||||
field: 'clip',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -100,32 +137,12 @@ export const buildLinearTextToImageGraph = (
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: POSITIVE_CONDITIONING,
|
||||
field: 'clip',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'clip',
|
||||
},
|
||||
destination: {
|
||||
node_id: NEGATIVE_CONDITIONING,
|
||||
field: 'clip',
|
||||
},
|
||||
},
|
||||
{
|
||||
source: {
|
||||
node_id: MAIN_MODEL_LOADER,
|
||||
field: 'unet',
|
||||
field: 'conditioning',
|
||||
},
|
||||
destination: {
|
||||
node_id: TEXT_TO_LATENTS,
|
||||
field: 'unet',
|
||||
field: 'negative_conditioning',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -10,6 +10,7 @@ export const ITERATE = 'iterate';
|
||||
export const MAIN_MODEL_LOADER = 'main_model_loader';
|
||||
export const VAE_LOADER = 'vae_loader';
|
||||
export const LORA_LOADER = 'lora_loader';
|
||||
export const CLIP_SKIP = 'clip_skip';
|
||||
export const IMAGE_TO_LATENTS = 'image_to_latents';
|
||||
export const LATENTS_TO_LATENTS = 'latents_to_latents';
|
||||
export const RESIZE = 'resize_image';
|
||||
|
@ -0,0 +1,34 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { RootState, stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import ParamClipSkip from './ParamClipSkip';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state: RootState) => {
|
||||
const clipSkip = state.generation.clipSkip;
|
||||
return {
|
||||
activeLabel: clipSkip > 0 ? 'Clip Skip' : undefined,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
export default function ParamAdvancedCollapse() {
|
||||
const { activeLabel } = useAppSelector(selector);
|
||||
const shouldShowAdvancedOptions = useAppSelector(
|
||||
(state: RootState) => state.ui.shouldShowAdvancedOptions
|
||||
);
|
||||
return (
|
||||
shouldShowAdvancedOptions && (
|
||||
<IAICollapse label={'Advanced'} activeLabel={activeLabel}>
|
||||
<Flex sx={{ flexDir: 'column', gap: 2 }}>
|
||||
<ParamClipSkip />
|
||||
</Flex>
|
||||
</IAICollapse>
|
||||
)
|
||||
);
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
import { setClipSkip } from 'features/parameters/store/generationSlice';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const clipSkipMap = {
|
||||
'sd-1': {
|
||||
maxClip: 12,
|
||||
markers: [0, 1, 2, 3, 4, 8, 12],
|
||||
},
|
||||
'sd-2': {
|
||||
maxClip: 24,
|
||||
markers: [0, 1, 2, 3, 5, 10, 15, 20, 24],
|
||||
},
|
||||
};
|
||||
|
||||
export default function ParamClipSkip() {
|
||||
const clipSkip = useAppSelector(
|
||||
(state: RootState) => state.generation.clipSkip
|
||||
);
|
||||
|
||||
const { model } = useAppSelector((state: RootState) => state.generation);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleClipSkipChange = useCallback(
|
||||
(v: number) => {
|
||||
dispatch(setClipSkip(v));
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const handleClipSkipReset = useCallback(() => {
|
||||
dispatch(setClipSkip(0));
|
||||
}, [dispatch]);
|
||||
|
||||
const max = useMemo(() => {
|
||||
if (!model) {
|
||||
return clipSkipMap['sd-1'].maxClip;
|
||||
}
|
||||
return clipSkipMap[model.base_model].maxClip;
|
||||
}, [model]);
|
||||
|
||||
const sliderMarks = useMemo(() => {
|
||||
if (!model) {
|
||||
return clipSkipMap['sd-1'].markers;
|
||||
}
|
||||
return clipSkipMap[model.base_model].markers;
|
||||
}, [model]);
|
||||
|
||||
return (
|
||||
<IAISlider
|
||||
label={t('parameters.clipSkip')}
|
||||
aria-label={t('parameters.clipSkip')}
|
||||
min={0}
|
||||
max={max}
|
||||
step={1}
|
||||
value={clipSkip}
|
||||
onChange={handleClipSkipChange}
|
||||
withSliderMarks
|
||||
sliderMarks={sliderMarks}
|
||||
withInput
|
||||
withReset
|
||||
handleReset={handleClipSkipReset}
|
||||
/>
|
||||
);
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
import { Box, Flex } from '@chakra-ui/react';
|
||||
import ModelSelect from 'features/system/components/ModelSelect';
|
||||
import VAESelect from 'features/system/components/VAESelect';
|
||||
import { memo } from 'react';
|
||||
|
||||
const ParamModelandVAE = () => {
|
||||
return (
|
||||
<Flex gap={3} w="full">
|
||||
<Box w="full">
|
||||
<ModelSelect />
|
||||
</Box>
|
||||
<Box w="full">
|
||||
<VAESelect />
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(ParamModelandVAE);
|
@ -0,0 +1,31 @@
|
||||
import { Box, Flex } from '@chakra-ui/react';
|
||||
import ModelSelect from 'features/system/components/ModelSelect';
|
||||
import VAESelect from 'features/system/components/VAESelect';
|
||||
import { memo } from 'react';
|
||||
import { useFeatureStatus } from '../../../../system/hooks/useFeatureStatus';
|
||||
import ParamScheduler from './ParamScheduler';
|
||||
|
||||
const ParamModelandVAEandScheduler = () => {
|
||||
const isVaeEnabled = useFeatureStatus('vae').isFeatureEnabled;
|
||||
|
||||
return (
|
||||
<Flex gap={3} w="full" flexWrap={isVaeEnabled ? 'wrap' : 'nowrap'}>
|
||||
<Flex gap={3} w="full">
|
||||
<Box w="full">
|
||||
<ModelSelect />
|
||||
</Box>
|
||||
|
||||
{isVaeEnabled && (
|
||||
<Box w="full">
|
||||
<VAESelect />
|
||||
</Box>
|
||||
)}
|
||||
</Flex>
|
||||
<Box w="full">
|
||||
<ParamScheduler />
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(ParamModelandVAEandScheduler);
|
@ -8,6 +8,7 @@ import { setNegativePrompt } from 'features/parameters/store/generationSlice';
|
||||
import { ChangeEvent, KeyboardEvent, useCallback, useRef } from 'react';
|
||||
import { flushSync } from 'react-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useFeatureStatus } from '../../../../system/hooks/useFeatureStatus';
|
||||
|
||||
const ParamNegativeConditioning = () => {
|
||||
const negativePrompt = useAppSelector(
|
||||
@ -71,6 +72,8 @@ const ParamNegativeConditioning = () => {
|
||||
[dispatch, onClose, negativePrompt]
|
||||
);
|
||||
|
||||
const isEmbeddingEnabled = useFeatureStatus('embedding').isFeatureEnabled;
|
||||
|
||||
return (
|
||||
<FormControl>
|
||||
<ParamEmbeddingPopover
|
||||
@ -85,13 +88,13 @@ const ParamNegativeConditioning = () => {
|
||||
value={negativePrompt}
|
||||
placeholder={t('parameters.negativePromptPlaceholder')}
|
||||
onChange={handleChangePrompt}
|
||||
onKeyDown={handleKeyDown}
|
||||
resize="vertical"
|
||||
fontSize="sm"
|
||||
minH={16}
|
||||
{...(isEmbeddingEnabled && { onKeyDown: handleKeyDown })}
|
||||
/>
|
||||
</ParamEmbeddingPopover>
|
||||
{!isOpen && (
|
||||
{!isOpen && isEmbeddingEnabled && (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
|
@ -1,11 +1,10 @@
|
||||
import { Box, FormControl, useDisclosure } from '@chakra-ui/react';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { ChangeEvent, KeyboardEvent, useCallback, useRef } from 'react';
|
||||
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import {
|
||||
GenerationState,
|
||||
clampSymmetrySteps,
|
||||
setPositivePrompt,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
@ -20,12 +19,14 @@ import { isEqual } from 'lodash-es';
|
||||
import { flushSync } from 'react-dom';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useFeatureStatus } from '../../../../system/hooks/useFeatureStatus';
|
||||
|
||||
const promptInputSelector = createSelector(
|
||||
[(state: RootState) => state.generation, activeTabNameSelector],
|
||||
(parameters: GenerationState, activeTabName) => {
|
||||
[stateSelector, activeTabNameSelector],
|
||||
({ generation, ui }, activeTabName) => {
|
||||
return {
|
||||
prompt: parameters.positivePrompt,
|
||||
shouldPinParametersPanel: ui.shouldPinParametersPanel,
|
||||
prompt: generation.positivePrompt,
|
||||
activeTabName,
|
||||
};
|
||||
},
|
||||
@ -41,7 +42,8 @@ const promptInputSelector = createSelector(
|
||||
*/
|
||||
const ParamPositiveConditioning = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { prompt, activeTabName } = useAppSelector(promptInputSelector);
|
||||
const { prompt, shouldPinParametersPanel, activeTabName } =
|
||||
useAppSelector(promptInputSelector);
|
||||
const isReady = useIsReadyToInvoke();
|
||||
const promptRef = useRef<HTMLTextAreaElement>(null);
|
||||
const { isOpen, onClose, onOpen } = useDisclosure();
|
||||
@ -100,6 +102,8 @@ const ParamPositiveConditioning = () => {
|
||||
[dispatch, onClose, prompt]
|
||||
);
|
||||
|
||||
const isEmbeddingEnabled = useFeatureStatus('embedding').isFeatureEnabled;
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
if (e.key === 'Enter' && e.shiftKey === false && isReady) {
|
||||
@ -107,11 +111,11 @@ const ParamPositiveConditioning = () => {
|
||||
dispatch(clampSymmetrySteps());
|
||||
dispatch(userInvoked(activeTabName));
|
||||
}
|
||||
if (e.key === '<') {
|
||||
if (isEmbeddingEnabled && e.key === '<') {
|
||||
onOpen();
|
||||
}
|
||||
},
|
||||
[isReady, dispatch, activeTabName, onOpen]
|
||||
[isReady, dispatch, activeTabName, onOpen, isEmbeddingEnabled]
|
||||
);
|
||||
|
||||
// const handleSelect = (e: MouseEvent<HTMLTextAreaElement>) => {
|
||||
@ -120,7 +124,7 @@ const ParamPositiveConditioning = () => {
|
||||
// };
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Box position="relative">
|
||||
<FormControl>
|
||||
<ParamEmbeddingPopover
|
||||
isOpen={isOpen}
|
||||
@ -140,11 +144,11 @@ const ParamPositiveConditioning = () => {
|
||||
/>
|
||||
</ParamEmbeddingPopover>
|
||||
</FormControl>
|
||||
{!isOpen && (
|
||||
{!isOpen && isEmbeddingEnabled && (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 6,
|
||||
top: shouldPinParametersPanel ? 6 : 0,
|
||||
insetInlineEnd: 0,
|
||||
}}
|
||||
>
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { useAppToaster } from 'app/components/Toaster';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { isImageField } from 'services/api/guards';
|
||||
import { ImageDTO } from 'services/api/types';
|
||||
import { initialImageSelected, modelSelected } from '../store/actions';
|
||||
import {
|
||||
modelSelected,
|
||||
setCfgScale,
|
||||
setHeight,
|
||||
setImg2imgStrength,
|
||||
@ -13,14 +16,10 @@ import {
|
||||
setSteps,
|
||||
setWidth,
|
||||
} from '../store/generationSlice';
|
||||
import { isImageField } from 'services/api/guards';
|
||||
import { initialImageSelected } from '../store/actions';
|
||||
import { useAppToaster } from 'app/components/Toaster';
|
||||
import { ImageDTO } from 'services/api/types';
|
||||
import {
|
||||
isValidCfgScale,
|
||||
isValidHeight,
|
||||
isValidModel,
|
||||
isValidMainModel,
|
||||
isValidNegativePrompt,
|
||||
isValidPositivePrompt,
|
||||
isValidScheduler,
|
||||
@ -159,11 +158,11 @@ export const useRecallParameters = () => {
|
||||
*/
|
||||
const recallModel = useCallback(
|
||||
(model: unknown) => {
|
||||
if (!isValidModel(model)) {
|
||||
if (!isValidMainModel(model)) {
|
||||
parameterNotSetToast();
|
||||
return;
|
||||
}
|
||||
dispatch(modelSelected(model));
|
||||
dispatch(modelSelected(model?.id || ''));
|
||||
parameterSetToast();
|
||||
},
|
||||
[dispatch, parameterSetToast, parameterNotSetToast]
|
||||
@ -296,7 +295,7 @@ export const useRecallParameters = () => {
|
||||
if (isValidCfgScale(cfg_scale)) {
|
||||
dispatch(setCfgScale(cfg_scale));
|
||||
}
|
||||
if (isValidModel(model)) {
|
||||
if (isValidMainModel(model)) {
|
||||
dispatch(modelSelected(model));
|
||||
}
|
||||
if (isValidPositivePrompt(positive_conditioning)) {
|
||||
|
@ -4,3 +4,5 @@ import { ImageDTO } from 'services/api/types';
|
||||
export const initialImageSelected = createAction<ImageDTO | string | undefined>(
|
||||
'generation/initialImageSelected'
|
||||
);
|
||||
|
||||
export const modelSelected = createAction<string>('generation/modelSelected');
|
||||
|
@ -2,20 +2,23 @@ import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import { DEFAULT_SCHEDULER_NAME } from 'app/constants';
|
||||
import { configChanged } from 'features/system/store/configSlice';
|
||||
import { setShouldShowAdvancedOptions } from 'features/ui/store/uiSlice';
|
||||
import { clamp } from 'lodash-es';
|
||||
import { ImageDTO } from 'services/api/types';
|
||||
import { clipSkipMap } from '../components/Parameters/Advanced/ParamClipSkip';
|
||||
import {
|
||||
CfgScaleParam,
|
||||
HeightParam,
|
||||
ModelParam,
|
||||
MainModelParam,
|
||||
NegativePromptParam,
|
||||
PositivePromptParam,
|
||||
SchedulerParam,
|
||||
SeedParam,
|
||||
StepsParam,
|
||||
StrengthParam,
|
||||
VAEParam,
|
||||
VaeModelParam,
|
||||
WidthParam,
|
||||
zMainModel,
|
||||
} from './parameterZodSchemas';
|
||||
|
||||
export interface GenerationState {
|
||||
@ -47,10 +50,11 @@ export interface GenerationState {
|
||||
shouldUseSymmetry: boolean;
|
||||
horizontalSymmetrySteps: number;
|
||||
verticalSymmetrySteps: number;
|
||||
model: ModelParam;
|
||||
vae: VAEParam;
|
||||
model: MainModelParam | null;
|
||||
vae: VaeModelParam | null;
|
||||
seamlessXAxis: boolean;
|
||||
seamlessYAxis: boolean;
|
||||
clipSkip: number;
|
||||
}
|
||||
|
||||
export const initialGenerationState: GenerationState = {
|
||||
@ -81,10 +85,11 @@ export const initialGenerationState: GenerationState = {
|
||||
shouldUseSymmetry: false,
|
||||
horizontalSymmetrySteps: 0,
|
||||
verticalSymmetrySteps: 0,
|
||||
model: '',
|
||||
vae: '',
|
||||
model: null,
|
||||
vae: null,
|
||||
seamlessXAxis: false,
|
||||
seamlessYAxis: false,
|
||||
clipSkip: 0,
|
||||
};
|
||||
|
||||
const initialState: GenerationState = initialGenerationState;
|
||||
@ -212,19 +217,46 @@ export const generationSlice = createSlice({
|
||||
state.initialImage = { imageName: image_name, width, height };
|
||||
},
|
||||
modelSelected: (state, action: PayloadAction<string>) => {
|
||||
const [base_model, type, name] = action.payload.split('/');
|
||||
|
||||
state.model = zMainModel.parse({
|
||||
id: action.payload,
|
||||
base_model,
|
||||
name,
|
||||
type,
|
||||
});
|
||||
|
||||
// Clamp ClipSkip Based On Selected Model
|
||||
const { maxClip } = clipSkipMap[state.model.base_model];
|
||||
state.clipSkip = clamp(state.clipSkip, 0, maxClip);
|
||||
},
|
||||
modelChanged: (state, action: PayloadAction<MainModelParam>) => {
|
||||
state.model = action.payload;
|
||||
},
|
||||
vaeSelected: (state, action: PayloadAction<string>) => {
|
||||
vaeSelected: (state, action: PayloadAction<VaeModelParam | null>) => {
|
||||
state.vae = action.payload;
|
||||
},
|
||||
setClipSkip: (state, action: PayloadAction<number>) => {
|
||||
state.clipSkip = action.payload;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(configChanged, (state, action) => {
|
||||
const defaultModel = action.payload.sd?.defaultModel;
|
||||
|
||||
if (defaultModel && !state.model) {
|
||||
state.model = defaultModel;
|
||||
const [base_model, model_type, model_name] = defaultModel.split('/');
|
||||
state.model = zMainModel.parse({
|
||||
id: defaultModel,
|
||||
name: model_name,
|
||||
base_model,
|
||||
});
|
||||
}
|
||||
});
|
||||
builder.addCase(setShouldShowAdvancedOptions, (state, action) => {
|
||||
const advancedOptionsStatus = action.payload;
|
||||
if (!advancedOptionsStatus) state.clipSkip = 0;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -260,11 +292,12 @@ export const {
|
||||
setHorizontalSymmetrySteps,
|
||||
setVerticalSymmetrySteps,
|
||||
initialImageChanged,
|
||||
modelSelected,
|
||||
modelChanged,
|
||||
vaeSelected,
|
||||
setShouldUseNoiseSettings,
|
||||
setSeamlessXAxis,
|
||||
setSeamlessYAxis,
|
||||
setClipSkip,
|
||||
} = generationSlice.actions;
|
||||
|
||||
export default generationSlice.reducer;
|
||||
|
@ -126,29 +126,63 @@ export type HeightParam = z.infer<typeof zHeight>;
|
||||
export const isValidHeight = (val: unknown): val is HeightParam =>
|
||||
zHeight.safeParse(val).success;
|
||||
|
||||
const zBaseModel = z.enum(['sd-1', 'sd-2']);
|
||||
|
||||
export type BaseModelParam = z.infer<typeof zBaseModel>;
|
||||
|
||||
/**
|
||||
* Zod schema for model parameter
|
||||
* TODO: Make this a dynamically generated enum?
|
||||
*/
|
||||
export const zModel = z.string();
|
||||
export const zMainModel = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
base_model: zBaseModel,
|
||||
});
|
||||
|
||||
/**
|
||||
* Type alias for model parameter, inferred from its zod schema
|
||||
*/
|
||||
export type ModelParam = z.infer<typeof zModel>;
|
||||
/**
|
||||
* Zod schema for VAE parameter
|
||||
* TODO: Make this a dynamically generated enum?
|
||||
*/
|
||||
export const zVAE = z.string();
|
||||
/**
|
||||
* Type alias for model parameter, inferred from its zod schema
|
||||
*/
|
||||
export type VAEParam = z.infer<typeof zVAE>;
|
||||
export type MainModelParam = z.infer<typeof zMainModel>;
|
||||
/**
|
||||
* Validates/type-guards a value as a model parameter
|
||||
*/
|
||||
export const isValidModel = (val: unknown): val is ModelParam =>
|
||||
zModel.safeParse(val).success;
|
||||
export const isValidMainModel = (val: unknown): val is MainModelParam =>
|
||||
zMainModel.safeParse(val).success;
|
||||
/**
|
||||
* Zod schema for VAE parameter
|
||||
*/
|
||||
export const zVaeModel = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
base_model: zBaseModel,
|
||||
});
|
||||
/**
|
||||
* Type alias for model parameter, inferred from its zod schema
|
||||
*/
|
||||
export type VaeModelParam = z.infer<typeof zVaeModel>;
|
||||
/**
|
||||
* Validates/type-guards a value as a model parameter
|
||||
*/
|
||||
export const isValidVaeModel = (val: unknown): val is VaeModelParam =>
|
||||
zVaeModel.safeParse(val).success;
|
||||
/**
|
||||
* Zod schema for LoRA
|
||||
*/
|
||||
export const zLoRAModel = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
base_model: zBaseModel,
|
||||
});
|
||||
/**
|
||||
* Type alias for model parameter, inferred from its zod schema
|
||||
*/
|
||||
export type LoRAModelParam = z.infer<typeof zLoRAModel>;
|
||||
/**
|
||||
* Validates/type-guards a value as a model parameter
|
||||
*/
|
||||
export const isValidLoRAModel = (val: unknown): val is LoRAModelParam =>
|
||||
zLoRAModel.safeParse(val).success;
|
||||
|
||||
/**
|
||||
* Zod schema for l2l strength parameter
|
||||
|
@ -3,10 +3,10 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIMantineSelect from 'common/components/IAIMantineSelect';
|
||||
import { modelSelected } from 'features/parameters/store/generationSlice';
|
||||
|
||||
import { SelectItem } from '@mantine/core';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { modelSelected } from 'features/parameters/store/actions';
|
||||
import { forEach, isString } from 'lodash-es';
|
||||
import { useGetMainModelsQuery } from 'services/api/endpoints/models';
|
||||
|
||||
@ -19,7 +19,7 @@ const ModelSelect = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const selectedModelId = useAppSelector(
|
||||
const currentModel = useAppSelector(
|
||||
(state: RootState) => state.generation.model
|
||||
);
|
||||
|
||||
@ -48,8 +48,8 @@ const ModelSelect = () => {
|
||||
}, [mainModels]);
|
||||
|
||||
const selectedModel = useMemo(
|
||||
() => mainModels?.entities[selectedModelId],
|
||||
[mainModels?.entities, selectedModelId]
|
||||
() => mainModels?.entities[currentModel?.id || ''],
|
||||
[mainModels?.entities, currentModel]
|
||||
);
|
||||
|
||||
const handleChangeModel = useCallback(
|
||||
@ -63,7 +63,13 @@ const ModelSelect = () => {
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedModelId && mainModels?.ids.includes(selectedModelId)) {
|
||||
if (isLoading) {
|
||||
// return early here to avoid resetting model selection before we've loaded the available models
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedModel && mainModels?.ids.includes(selectedModel?.id)) {
|
||||
// the selected model is an available model, no need to change it
|
||||
return;
|
||||
}
|
||||
|
||||
@ -74,7 +80,7 @@ const ModelSelect = () => {
|
||||
}
|
||||
|
||||
handleChangeModel(firstModel);
|
||||
}, [handleChangeModel, mainModels?.ids, selectedModelId]);
|
||||
}, [handleChangeModel, isLoading, mainModels?.ids, selectedModel]);
|
||||
|
||||
return isLoading ? (
|
||||
<IAIMantineSelect
|
||||
@ -87,7 +93,7 @@ const ModelSelect = () => {
|
||||
<IAIMantineSelect
|
||||
tooltip={selectedModel?.description}
|
||||
label={t('modelManager.model')}
|
||||
value={selectedModelId}
|
||||
value={selectedModel?.id}
|
||||
placeholder={data.length > 0 ? 'Select a model' : 'No models detected!'}
|
||||
data={data}
|
||||
error={data.length === 0}
|
||||
|
@ -30,6 +30,7 @@ import {
|
||||
} from 'features/system/store/systemSlice';
|
||||
import { uiSelector } from 'features/ui/store/uiSelectors';
|
||||
import {
|
||||
setShouldShowAdvancedOptions,
|
||||
setShouldShowProgressInViewer,
|
||||
setShouldUseCanvasBetaLayout,
|
||||
setShouldUseSliders,
|
||||
@ -64,6 +65,7 @@ const selector = createSelector(
|
||||
shouldUseCanvasBetaLayout,
|
||||
shouldUseSliders,
|
||||
shouldShowProgressInViewer,
|
||||
shouldShowAdvancedOptions,
|
||||
} = ui;
|
||||
|
||||
return {
|
||||
@ -76,6 +78,7 @@ const selector = createSelector(
|
||||
consoleLogLevel,
|
||||
shouldLogToConsole,
|
||||
shouldAntialiasProgressImage,
|
||||
shouldShowAdvancedOptions,
|
||||
};
|
||||
},
|
||||
{
|
||||
@ -87,6 +90,7 @@ type ConfigOptions = {
|
||||
shouldShowDeveloperSettings: boolean;
|
||||
shouldShowResetWebUiText: boolean;
|
||||
shouldShowBetaLayout: boolean;
|
||||
shouldShowAdvancedOptionsSettings: boolean;
|
||||
};
|
||||
|
||||
type SettingsModalProps = {
|
||||
@ -103,6 +107,8 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
||||
const shouldShowDeveloperSettings =
|
||||
config?.shouldShowDeveloperSettings ?? true;
|
||||
const shouldShowResetWebUiText = config?.shouldShowResetWebUiText ?? true;
|
||||
const shouldShowAdvancedOptionsSettings =
|
||||
config?.shouldShowAdvancedOptionsSettings ?? true;
|
||||
|
||||
useEffect(() => {
|
||||
if (!shouldShowDeveloperSettings) {
|
||||
@ -132,6 +138,7 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
||||
consoleLogLevel,
|
||||
shouldLogToConsole,
|
||||
shouldAntialiasProgressImage,
|
||||
shouldShowAdvancedOptions,
|
||||
} = useAppSelector(selector);
|
||||
|
||||
const handleClickResetWebUI = useCallback(() => {
|
||||
@ -189,6 +196,15 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
||||
dispatch(setShouldConfirmOnDelete(e.target.checked))
|
||||
}
|
||||
/>
|
||||
{shouldShowAdvancedOptionsSettings && (
|
||||
<IAISwitch
|
||||
label={t('settings.showAdvancedOptions')}
|
||||
isChecked={shouldShowAdvancedOptions}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
dispatch(setShouldShowAdvancedOptions(e.target.checked))
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</StyledFlex>
|
||||
|
||||
<StyledFlex>
|
||||
|
@ -9,7 +9,9 @@ import { forEach } from 'lodash-es';
|
||||
import { useGetVaeModelsQuery } from 'services/api/endpoints/models';
|
||||
|
||||
import { RootState } from 'app/store/store';
|
||||
import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
|
||||
import { vaeSelected } from 'features/parameters/store/generationSlice';
|
||||
import { zVaeModel } from 'features/parameters/store/parameterZodSchemas';
|
||||
import { MODEL_TYPE_MAP } from './ModelSelect';
|
||||
|
||||
const VAESelect = () => {
|
||||
@ -18,7 +20,11 @@ const VAESelect = () => {
|
||||
|
||||
const { data: vaeModels } = useGetVaeModelsQuery();
|
||||
|
||||
const selectedModelId = useAppSelector(
|
||||
const currentMainModel = useAppSelector(
|
||||
(state: RootState) => state.generation.model
|
||||
);
|
||||
|
||||
const selectedVae = useAppSelector(
|
||||
(state: RootState) => state.generation.vae
|
||||
);
|
||||
|
||||
@ -29,8 +35,8 @@ const VAESelect = () => {
|
||||
|
||||
const data: SelectItem[] = [
|
||||
{
|
||||
value: 'auto',
|
||||
label: 'Automatic',
|
||||
value: 'default',
|
||||
label: 'Default',
|
||||
group: 'Default',
|
||||
},
|
||||
];
|
||||
@ -40,46 +46,65 @@ const VAESelect = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const disabled = currentMainModel?.base_model !== model.base_model;
|
||||
|
||||
data.push({
|
||||
value: id,
|
||||
label: model.name,
|
||||
group: MODEL_TYPE_MAP[model.base_model],
|
||||
disabled,
|
||||
tooltip: disabled
|
||||
? `Incompatible base model: ${model.base_model}`
|
||||
: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
return data;
|
||||
}, [vaeModels]);
|
||||
return data.sort((a, b) => (a.disabled && !b.disabled ? 1 : -1));
|
||||
}, [vaeModels, currentMainModel?.base_model]);
|
||||
|
||||
const selectedModel = useMemo(
|
||||
() => vaeModels?.entities[selectedModelId],
|
||||
[vaeModels?.entities, selectedModelId]
|
||||
const selectedVaeModel = useMemo(
|
||||
() => (selectedVae?.id ? vaeModels?.entities[selectedVae?.id] : null),
|
||||
[vaeModels?.entities, selectedVae]
|
||||
);
|
||||
|
||||
const handleChangeModel = useCallback(
|
||||
(v: string | null) => {
|
||||
if (!v) {
|
||||
if (!v || v === 'default') {
|
||||
dispatch(vaeSelected(null));
|
||||
return;
|
||||
}
|
||||
dispatch(vaeSelected(v));
|
||||
|
||||
const [base_model, type, name] = v.split('/');
|
||||
|
||||
const model = zVaeModel.parse({
|
||||
id: v,
|
||||
name,
|
||||
base_model,
|
||||
});
|
||||
|
||||
dispatch(vaeSelected(model));
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedModelId && vaeModels?.ids.includes(selectedModelId)) {
|
||||
if (selectedVae && vaeModels?.ids.includes(selectedVae.id)) {
|
||||
return;
|
||||
}
|
||||
handleChangeModel('auto');
|
||||
}, [handleChangeModel, vaeModels?.ids, selectedModelId]);
|
||||
dispatch(vaeSelected(null));
|
||||
}, [handleChangeModel, vaeModels?.ids, selectedVae, dispatch]);
|
||||
|
||||
return (
|
||||
<IAIMantineSelect
|
||||
tooltip={selectedModel?.description}
|
||||
itemComponent={IAIMantineSelectItemWithTooltip}
|
||||
tooltip={selectedVaeModel?.description}
|
||||
label={t('modelManager.vae')}
|
||||
value={selectedModelId}
|
||||
placeholder="Pick one"
|
||||
value={selectedVae?.id ?? 'default'}
|
||||
placeholder="Default"
|
||||
data={data}
|
||||
onChange={handleChangeModel}
|
||||
disabled={data.length === 0}
|
||||
clearable
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -33,12 +33,21 @@ const PinParametersPanelButton = (props: PinParametersPanelButtonProps) => {
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
sx={{
|
||||
color: 'base.700',
|
||||
color: 'base.500',
|
||||
_hover: {
|
||||
color: 'base.550',
|
||||
color: 'base.600',
|
||||
},
|
||||
_active: {
|
||||
color: 'base.700',
|
||||
},
|
||||
_dark: {
|
||||
color: 'base.500',
|
||||
_hover: {
|
||||
color: 'base.400',
|
||||
},
|
||||
_active: {
|
||||
color: 'base.300',
|
||||
},
|
||||
},
|
||||
...sx,
|
||||
}}
|
||||
|
@ -6,8 +6,7 @@ import IAICollapse from 'common/components/IAICollapse';
|
||||
import ParamCFGScale from 'features/parameters/components/Parameters/Core/ParamCFGScale';
|
||||
import ParamHeight from 'features/parameters/components/Parameters/Core/ParamHeight';
|
||||
import ParamIterations from 'features/parameters/components/Parameters/Core/ParamIterations';
|
||||
import ParamModelandVAE from 'features/parameters/components/Parameters/Core/ParamModelandVAE';
|
||||
import ParamScheduler from 'features/parameters/components/Parameters/Core/ParamScheduler';
|
||||
import ParamModelandVAEandScheduler from 'features/parameters/components/Parameters/Core/ParamModelandVAEandScheduler';
|
||||
import ParamSteps from 'features/parameters/components/Parameters/Core/ParamSteps';
|
||||
import ParamWidth from 'features/parameters/components/Parameters/Core/ParamWidth';
|
||||
import ImageToImageFit from 'features/parameters/components/Parameters/ImageToImage/ImageToImageFit';
|
||||
@ -48,7 +47,7 @@ const ImageToImageTabCoreParameters = () => {
|
||||
>
|
||||
{shouldUseSliders ? (
|
||||
<>
|
||||
<ParamModelandVAE />
|
||||
<ParamModelandVAEandScheduler />
|
||||
<Box pt={2}>
|
||||
<ParamSeedFull />
|
||||
</Box>
|
||||
@ -65,8 +64,7 @@ const ImageToImageTabCoreParameters = () => {
|
||||
<ParamSteps />
|
||||
<ParamCFGScale />
|
||||
</Flex>
|
||||
<ParamModelandVAE />
|
||||
<ParamScheduler />
|
||||
<ParamModelandVAEandScheduler />
|
||||
<Box pt={2}>
|
||||
<ParamSeedFull />
|
||||
</Box>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import ParamDynamicPromptsCollapse from 'features/dynamicPrompts/components/ParamDynamicPromptsCollapse';
|
||||
import ParamLoraCollapse from 'features/lora/components/ParamLoraCollapse';
|
||||
import ParamAdvancedCollapse from 'features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse';
|
||||
import ParamControlNetCollapse from 'features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse';
|
||||
import ParamNegativeConditioning from 'features/parameters/components/Parameters/Core/ParamNegativeConditioning';
|
||||
import ParamPositiveConditioning from 'features/parameters/components/Parameters/Core/ParamPositiveConditioning';
|
||||
@ -25,6 +26,7 @@ const ImageToImageTabParameters = () => {
|
||||
<ParamNoiseCollapse />
|
||||
<ParamSymmetryCollapse />
|
||||
<ParamSeamlessCollapse />
|
||||
<ParamAdvancedCollapse />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -7,8 +7,7 @@ import IAICollapse from 'common/components/IAICollapse';
|
||||
import ParamCFGScale from 'features/parameters/components/Parameters/Core/ParamCFGScale';
|
||||
import ParamHeight from 'features/parameters/components/Parameters/Core/ParamHeight';
|
||||
import ParamIterations from 'features/parameters/components/Parameters/Core/ParamIterations';
|
||||
import ParamModelandVAE from 'features/parameters/components/Parameters/Core/ParamModelandVAE';
|
||||
import ParamScheduler from 'features/parameters/components/Parameters/Core/ParamScheduler';
|
||||
import ParamModelandVAEandScheduler from 'features/parameters/components/Parameters/Core/ParamModelandVAEandScheduler';
|
||||
import ParamSteps from 'features/parameters/components/Parameters/Core/ParamSteps';
|
||||
import ParamWidth from 'features/parameters/components/Parameters/Core/ParamWidth';
|
||||
import ParamSeedFull from 'features/parameters/components/Parameters/Seed/ParamSeedFull';
|
||||
@ -44,7 +43,7 @@ const TextToImageTabCoreParameters = () => {
|
||||
>
|
||||
{shouldUseSliders ? (
|
||||
<>
|
||||
<ParamModelandVAE />
|
||||
<ParamModelandVAEandScheduler />
|
||||
<Box pt={2}>
|
||||
<ParamSeedFull />
|
||||
</Box>
|
||||
@ -61,8 +60,7 @@ const TextToImageTabCoreParameters = () => {
|
||||
<ParamSteps />
|
||||
<ParamCFGScale />
|
||||
</Flex>
|
||||
<ParamModelandVAE />
|
||||
<ParamScheduler />
|
||||
<ParamModelandVAEandScheduler />
|
||||
<Box pt={2}>
|
||||
<ParamSeedFull />
|
||||
</Box>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import ParamDynamicPromptsCollapse from 'features/dynamicPrompts/components/ParamDynamicPromptsCollapse';
|
||||
import ParamLoraCollapse from 'features/lora/components/ParamLoraCollapse';
|
||||
import ParamAdvancedCollapse from 'features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse';
|
||||
import ParamControlNetCollapse from 'features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse';
|
||||
import ParamNegativeConditioning from 'features/parameters/components/Parameters/Core/ParamNegativeConditioning';
|
||||
import ParamPositiveConditioning from 'features/parameters/components/Parameters/Core/ParamPositiveConditioning';
|
||||
@ -27,6 +28,7 @@ const TextToImageTabParameters = () => {
|
||||
<ParamSymmetryCollapse />
|
||||
<ParamHiresCollapse />
|
||||
<ParamSeamlessCollapse />
|
||||
<ParamAdvancedCollapse />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -8,8 +8,7 @@ import ParamBoundingBoxHeight from 'features/parameters/components/Parameters/Ca
|
||||
import ParamBoundingBoxWidth from 'features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxWidth';
|
||||
import ParamCFGScale from 'features/parameters/components/Parameters/Core/ParamCFGScale';
|
||||
import ParamIterations from 'features/parameters/components/Parameters/Core/ParamIterations';
|
||||
import ParamModelandVAE from 'features/parameters/components/Parameters/Core/ParamModelandVAE';
|
||||
import ParamScheduler from 'features/parameters/components/Parameters/Core/ParamScheduler';
|
||||
import ParamModelandVAEandScheduler from 'features/parameters/components/Parameters/Core/ParamModelandVAEandScheduler';
|
||||
import ParamSteps from 'features/parameters/components/Parameters/Core/ParamSteps';
|
||||
import ImageToImageStrength from 'features/parameters/components/Parameters/ImageToImage/ImageToImageStrength';
|
||||
import ParamSeedFull from 'features/parameters/components/Parameters/Seed/ParamSeedFull';
|
||||
@ -45,7 +44,7 @@ const UnifiedCanvasCoreParameters = () => {
|
||||
>
|
||||
{shouldUseSliders ? (
|
||||
<>
|
||||
<ParamModelandVAE />
|
||||
<ParamModelandVAEandScheduler />
|
||||
<Box pt={2}>
|
||||
<ParamSeedFull />
|
||||
</Box>
|
||||
@ -62,8 +61,7 @@ const UnifiedCanvasCoreParameters = () => {
|
||||
<ParamSteps />
|
||||
<ParamCFGScale />
|
||||
</Flex>
|
||||
<ParamModelandVAE />
|
||||
<ParamScheduler />
|
||||
<ParamModelandVAEandScheduler />
|
||||
<Box pt={2}>
|
||||
<ParamSeedFull />
|
||||
</Box>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import ParamDynamicPromptsCollapse from 'features/dynamicPrompts/components/ParamDynamicPromptsCollapse';
|
||||
import ParamLoraCollapse from 'features/lora/components/ParamLoraCollapse';
|
||||
import ParamAdvancedCollapse from 'features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse';
|
||||
import ParamInfillAndScalingCollapse from 'features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamInfillAndScalingCollapse';
|
||||
import ParamSeamCorrectionCollapse from 'features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamCorrectionCollapse';
|
||||
import ParamControlNetCollapse from 'features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse';
|
||||
@ -25,6 +26,7 @@ const UnifiedCanvasParameters = () => {
|
||||
<ParamSymmetryCollapse />
|
||||
<ParamSeamCorrectionCollapse />
|
||||
<ParamInfillAndScalingCollapse />
|
||||
<ParamAdvancedCollapse />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -20,6 +20,7 @@ export const initialUIState: UIState = {
|
||||
shouldHidePreview: false,
|
||||
shouldShowProgressInViewer: true,
|
||||
shouldShowEmbeddingPicker: false,
|
||||
shouldShowAdvancedOptions: false,
|
||||
favoriteSchedulers: [],
|
||||
};
|
||||
|
||||
@ -100,6 +101,9 @@ export const uiSlice = createSlice({
|
||||
toggleEmbeddingPicker: (state) => {
|
||||
state.shouldShowEmbeddingPicker = !state.shouldShowEmbeddingPicker;
|
||||
},
|
||||
setShouldShowAdvancedOptions: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldShowAdvancedOptions = action.payload;
|
||||
},
|
||||
},
|
||||
extraReducers(builder) {
|
||||
builder.addCase(initialImageChanged, (state) => {
|
||||
@ -127,6 +131,7 @@ export const {
|
||||
setShouldShowProgressInViewer,
|
||||
favoriteSchedulersChanged,
|
||||
toggleEmbeddingPicker,
|
||||
setShouldShowAdvancedOptions,
|
||||
} = uiSlice.actions;
|
||||
|
||||
export default uiSlice.reducer;
|
||||
|
@ -28,5 +28,6 @@ export interface UIState {
|
||||
shouldShowGallery: boolean;
|
||||
shouldShowProgressInViewer: boolean;
|
||||
shouldShowEmbeddingPicker: boolean;
|
||||
shouldShowAdvancedOptions: boolean;
|
||||
favoriteSchedulers: SchedulerParam[];
|
||||
}
|
||||
|
473
invokeai/frontend/web/src/services/api/schema.d.ts
vendored
473
invokeai/frontend/web/src/services/api/schema.d.ts
vendored
@ -75,25 +75,37 @@ export type paths = {
|
||||
* @description Gets a list of models
|
||||
*/
|
||||
get: operations["list_models"];
|
||||
/**
|
||||
* Update Model
|
||||
* @description Add Model
|
||||
*/
|
||||
post: operations["update_model"];
|
||||
};
|
||||
"/api/v1/models/import": {
|
||||
/**
|
||||
* Import Model
|
||||
* @description Add a model using its local path, repo_id, or remote URL
|
||||
*/
|
||||
post: operations["import_model"];
|
||||
};
|
||||
"/api/v1/models/{model_name}": {
|
||||
"/api/v1/models/{base_model}/{model_type}/{model_name}": {
|
||||
/**
|
||||
* Delete Model
|
||||
* @description Delete Model
|
||||
*/
|
||||
delete: operations["del_model"];
|
||||
/**
|
||||
* Update Model
|
||||
* @description Add Model
|
||||
*/
|
||||
patch: operations["update_model"];
|
||||
};
|
||||
"/api/v1/models/convert/{base_model}/{model_type}/{model_name}": {
|
||||
/**
|
||||
* Convert Model
|
||||
* @description Convert a checkpoint model into a diffusers model
|
||||
*/
|
||||
put: operations["convert_model"];
|
||||
};
|
||||
"/api/v1/models/merge/{base_model}": {
|
||||
/**
|
||||
* Merge Models
|
||||
* @description Convert a checkpoint model into a diffusers model
|
||||
*/
|
||||
put: operations["merge_models"];
|
||||
};
|
||||
"/api/v1/images/": {
|
||||
/**
|
||||
@ -234,23 +246,6 @@ export type components = {
|
||||
*/
|
||||
b?: number;
|
||||
};
|
||||
/** AddModelResult */
|
||||
AddModelResult: {
|
||||
/**
|
||||
* Name
|
||||
* @description The name of the model after import
|
||||
*/
|
||||
name: string;
|
||||
/** @description The type of model */
|
||||
model_type: components["schemas"]["ModelType"];
|
||||
/** @description The base model */
|
||||
base_model: components["schemas"]["BaseModelType"];
|
||||
/**
|
||||
* Config
|
||||
* @description The configuration of the model
|
||||
*/
|
||||
config: components["schemas"]["ModelConfigBase"];
|
||||
};
|
||||
/**
|
||||
* BaseModelType
|
||||
* @description An enumeration.
|
||||
@ -324,6 +319,48 @@ export type components = {
|
||||
*/
|
||||
image_name: string;
|
||||
};
|
||||
/** Body_import_model */
|
||||
Body_import_model: {
|
||||
/**
|
||||
* Location
|
||||
* @description A model path, repo_id or URL to import
|
||||
*/
|
||||
location: string;
|
||||
/**
|
||||
* Prediction Type
|
||||
* @description Prediction type for SDv2 checkpoint files
|
||||
* @default v_prediction
|
||||
* @enum {string}
|
||||
*/
|
||||
prediction_type?: "v_prediction" | "epsilon" | "sample";
|
||||
};
|
||||
/** Body_merge_models */
|
||||
Body_merge_models: {
|
||||
/**
|
||||
* Model Names
|
||||
* @description model name
|
||||
*/
|
||||
model_names: (string)[];
|
||||
/**
|
||||
* Merged Model Name
|
||||
* @description Name of destination model
|
||||
*/
|
||||
merged_model_name: string;
|
||||
/**
|
||||
* Alpha
|
||||
* @description Alpha weighting strength to apply to 2d and 3d models
|
||||
* @default 0.5
|
||||
*/
|
||||
alpha?: number;
|
||||
/** @description Interpolation method */
|
||||
interp: components["schemas"]["MergeInterpolationMethod"];
|
||||
/**
|
||||
* Force
|
||||
* @description Force merging of models created with different versions of diffusers
|
||||
* @default false
|
||||
*/
|
||||
force?: boolean;
|
||||
};
|
||||
/** Body_remove_board_image */
|
||||
Body_remove_board_image: {
|
||||
/**
|
||||
@ -343,7 +380,7 @@ export type components = {
|
||||
* File
|
||||
* Format: binary
|
||||
*/
|
||||
file: string;
|
||||
file: Blob;
|
||||
};
|
||||
/**
|
||||
* CannyImageProcessorInvocation
|
||||
@ -385,55 +422,6 @@ export type components = {
|
||||
*/
|
||||
high_threshold?: number;
|
||||
};
|
||||
/** CkptModelInfo */
|
||||
CkptModelInfo: {
|
||||
/**
|
||||
* Description
|
||||
* @description A description of the model
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* Model Name
|
||||
* @description The name of the model
|
||||
*/
|
||||
model_name: string;
|
||||
/**
|
||||
* Model Type
|
||||
* @description The type of the model
|
||||
*/
|
||||
model_type: string;
|
||||
/**
|
||||
* Format
|
||||
* @default ckpt
|
||||
* @enum {string}
|
||||
*/
|
||||
format?: "ckpt";
|
||||
/**
|
||||
* Config
|
||||
* @description The path to the model config
|
||||
*/
|
||||
config: string;
|
||||
/**
|
||||
* Weights
|
||||
* @description The path to the model weights
|
||||
*/
|
||||
weights: string;
|
||||
/**
|
||||
* Vae
|
||||
* @description The path to the model VAE
|
||||
*/
|
||||
vae: string;
|
||||
/**
|
||||
* Width
|
||||
* @description The width of the model
|
||||
*/
|
||||
width?: number;
|
||||
/**
|
||||
* Height
|
||||
* @description The height of the model
|
||||
*/
|
||||
height?: number;
|
||||
};
|
||||
/** ClipField */
|
||||
ClipField: {
|
||||
/**
|
||||
@ -446,12 +434,68 @@ export type components = {
|
||||
* @description Info to load text_encoder submodel
|
||||
*/
|
||||
text_encoder: components["schemas"]["ModelInfo"];
|
||||
/**
|
||||
* Skipped Layers
|
||||
* @description Number of skipped layers in text_encoder
|
||||
*/
|
||||
skipped_layers: number;
|
||||
/**
|
||||
* Loras
|
||||
* @description Loras to apply on model loading
|
||||
*/
|
||||
loras: (components["schemas"]["LoraInfo"])[];
|
||||
};
|
||||
/**
|
||||
* ClipSkipInvocation
|
||||
* @description Skip layers in clip text_encoder model.
|
||||
*/
|
||||
ClipSkipInvocation: {
|
||||
/**
|
||||
* Id
|
||||
* @description The id of this node. Must be unique among all nodes.
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Is Intermediate
|
||||
* @description Whether or not this node is an intermediate node.
|
||||
* @default false
|
||||
*/
|
||||
is_intermediate?: boolean;
|
||||
/**
|
||||
* Type
|
||||
* @default clip_skip
|
||||
* @enum {string}
|
||||
*/
|
||||
type?: "clip_skip";
|
||||
/**
|
||||
* Clip
|
||||
* @description Clip to use
|
||||
*/
|
||||
clip?: components["schemas"]["ClipField"];
|
||||
/**
|
||||
* Skipped Layers
|
||||
* @description Number of layers to skip in text_encoder
|
||||
* @default 0
|
||||
*/
|
||||
skipped_layers?: number;
|
||||
};
|
||||
/**
|
||||
* ClipSkipInvocationOutput
|
||||
* @description Clip skip node output
|
||||
*/
|
||||
ClipSkipInvocationOutput: {
|
||||
/**
|
||||
* Type
|
||||
* @default clip_skip_output
|
||||
* @enum {string}
|
||||
*/
|
||||
type?: "clip_skip_output";
|
||||
/**
|
||||
* Clip
|
||||
* @description Clip with skipped layers
|
||||
*/
|
||||
clip?: components["schemas"]["ClipField"];
|
||||
};
|
||||
/**
|
||||
* CollectInvocation
|
||||
* @description Collects values into a collection
|
||||
@ -780,19 +824,6 @@ export type components = {
|
||||
*/
|
||||
control?: components["schemas"]["ControlField"];
|
||||
};
|
||||
/** CreateModelRequest */
|
||||
CreateModelRequest: {
|
||||
/**
|
||||
* Name
|
||||
* @description The name of the model
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Info
|
||||
* @description The model info
|
||||
*/
|
||||
info: components["schemas"]["CkptModelInfo"] | components["schemas"]["DiffusersModelInfo"];
|
||||
};
|
||||
/**
|
||||
* CvInpaintInvocation
|
||||
* @description Simple inpaint using opencv.
|
||||
@ -826,45 +857,6 @@ export type components = {
|
||||
*/
|
||||
mask?: components["schemas"]["ImageField"];
|
||||
};
|
||||
/** DiffusersModelInfo */
|
||||
DiffusersModelInfo: {
|
||||
/**
|
||||
* Description
|
||||
* @description A description of the model
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* Model Name
|
||||
* @description The name of the model
|
||||
*/
|
||||
model_name: string;
|
||||
/**
|
||||
* Model Type
|
||||
* @description The type of the model
|
||||
*/
|
||||
model_type: string;
|
||||
/**
|
||||
* Format
|
||||
* @default folder
|
||||
* @enum {string}
|
||||
*/
|
||||
format?: "folder";
|
||||
/**
|
||||
* Vae
|
||||
* @description The VAE repo to use for this model
|
||||
*/
|
||||
vae?: components["schemas"]["VaeRepo"];
|
||||
/**
|
||||
* Repo Id
|
||||
* @description The repo ID to use for this model
|
||||
*/
|
||||
repo_id?: string;
|
||||
/**
|
||||
* Path
|
||||
* @description The path to the model
|
||||
*/
|
||||
path?: string;
|
||||
};
|
||||
/**
|
||||
* DivideInvocation
|
||||
* @description Divides two numbers
|
||||
@ -1054,7 +1046,7 @@ export type components = {
|
||||
* @description The nodes in this graph
|
||||
*/
|
||||
nodes?: {
|
||||
[key: string]: (components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]) | undefined;
|
||||
[key: string]: (components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]) | undefined;
|
||||
};
|
||||
/**
|
||||
* Edges
|
||||
@ -1097,7 +1089,7 @@ export type components = {
|
||||
* @description The results of node executions
|
||||
*/
|
||||
results: {
|
||||
[key: string]: (components["schemas"]["ImageOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["LoraLoaderOutput"] | components["schemas"]["VaeLoaderOutput"] | components["schemas"]["PromptOutput"] | components["schemas"]["PromptCollectionOutput"] | components["schemas"]["CompelOutput"] | components["schemas"]["IntOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["IntCollectionOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["GraphInvocationOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["CollectInvocationOutput"]) | undefined;
|
||||
[key: string]: (components["schemas"]["ImageOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["LoraLoaderOutput"] | components["schemas"]["VaeLoaderOutput"] | components["schemas"]["PromptOutput"] | components["schemas"]["PromptCollectionOutput"] | components["schemas"]["CompelOutput"] | components["schemas"]["ClipSkipInvocationOutput"] | components["schemas"]["IntOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["IntCollectionOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["GraphInvocationOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["CollectInvocationOutput"]) | undefined;
|
||||
};
|
||||
/**
|
||||
* Errors
|
||||
@ -1999,24 +1991,6 @@ export type components = {
|
||||
*/
|
||||
thumbnail_url: string;
|
||||
};
|
||||
/** ImportModelResponse */
|
||||
ImportModelResponse: {
|
||||
/**
|
||||
* Name
|
||||
* @description The name of the imported model
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Info
|
||||
* @description The model info
|
||||
*/
|
||||
info: components["schemas"]["AddModelResult"];
|
||||
/**
|
||||
* Status
|
||||
* @description The status of the API response
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
/**
|
||||
* InfillColorInvocation
|
||||
* @description Infills transparent areas of an image with a solid color
|
||||
@ -2964,6 +2938,12 @@ export type components = {
|
||||
*/
|
||||
min_confidence?: number;
|
||||
};
|
||||
/**
|
||||
* MergeInterpolationMethod
|
||||
* @description An enumeration.
|
||||
* @enum {string}
|
||||
*/
|
||||
MergeInterpolationMethod: "weighted_sum" | "sigmoid" | "inv_sigmoid" | "add_difference";
|
||||
/**
|
||||
* MidasDepthImageProcessorInvocation
|
||||
* @description Applies Midas depth processing to image
|
||||
@ -3056,16 +3036,6 @@ export type components = {
|
||||
*/
|
||||
thr_d?: number;
|
||||
};
|
||||
/** ModelConfigBase */
|
||||
ModelConfigBase: {
|
||||
/** Path */
|
||||
path: string;
|
||||
/** Description */
|
||||
description?: string;
|
||||
/** Model Format */
|
||||
model_format?: string;
|
||||
error?: components["schemas"]["ModelError"];
|
||||
};
|
||||
/**
|
||||
* ModelError
|
||||
* @description An enumeration.
|
||||
@ -3128,7 +3098,7 @@ export type components = {
|
||||
/** ModelsList */
|
||||
ModelsList: {
|
||||
/** Models */
|
||||
models: (components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"])[];
|
||||
models: (components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"])[];
|
||||
};
|
||||
/**
|
||||
* MultiplyInvocation
|
||||
@ -4406,24 +4376,6 @@ export type components = {
|
||||
* @enum {string}
|
||||
*/
|
||||
VaeModelFormat: "checkpoint" | "diffusers";
|
||||
/** VaeRepo */
|
||||
VaeRepo: {
|
||||
/**
|
||||
* Repo Id
|
||||
* @description The repo ID to use for this VAE
|
||||
*/
|
||||
repo_id: string;
|
||||
/**
|
||||
* Path
|
||||
* @description The path to the VAE
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
* Subfolder
|
||||
* @description The subfolder to use for this VAE
|
||||
*/
|
||||
subfolder?: string;
|
||||
};
|
||||
/** ValidationError */
|
||||
ValidationError: {
|
||||
/** Location */
|
||||
@ -4461,18 +4413,18 @@ export type components = {
|
||||
*/
|
||||
image?: components["schemas"]["ImageField"];
|
||||
};
|
||||
/**
|
||||
* StableDiffusion1ModelFormat
|
||||
* @description An enumeration.
|
||||
* @enum {string}
|
||||
*/
|
||||
StableDiffusion1ModelFormat: "checkpoint" | "diffusers";
|
||||
/**
|
||||
* StableDiffusion2ModelFormat
|
||||
* @description An enumeration.
|
||||
* @enum {string}
|
||||
*/
|
||||
StableDiffusion2ModelFormat: "checkpoint" | "diffusers";
|
||||
/**
|
||||
* StableDiffusion1ModelFormat
|
||||
* @description An enumeration.
|
||||
* @enum {string}
|
||||
*/
|
||||
StableDiffusion1ModelFormat: "checkpoint" | "diffusers";
|
||||
};
|
||||
responses: never;
|
||||
parameters: never;
|
||||
@ -4583,7 +4535,7 @@ export type operations = {
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"];
|
||||
"application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
@ -4620,7 +4572,7 @@ export type operations = {
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"];
|
||||
"application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
@ -4839,59 +4791,35 @@ export type operations = {
|
||||
};
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Update Model
|
||||
* @description Add Model
|
||||
*/
|
||||
update_model: {
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["CreateModelRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": unknown;
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Import Model
|
||||
* @description Add a model using its local path, repo_id, or remote URL
|
||||
*/
|
||||
import_model: {
|
||||
parameters: {
|
||||
query: {
|
||||
/** @description A model path, repo_id or URL to import */
|
||||
name: string;
|
||||
/** @description Prediction type for SDv2 checkpoint files */
|
||||
prediction_type?: "v_prediction" | "epsilon" | "sample";
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["Body_import_model"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description The model imported successfully */
|
||||
201: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ImportModelResponse"];
|
||||
"application/json": components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"];
|
||||
};
|
||||
};
|
||||
/** @description The model could not be found */
|
||||
404: never;
|
||||
/** @description There is already a model corresponding to this path or repo_id */
|
||||
409: never;
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
/** @description The model appeared to import successfully, but could not be found in the model manager */
|
||||
424: never;
|
||||
};
|
||||
};
|
||||
/**
|
||||
@ -4901,6 +4829,11 @@ export type operations = {
|
||||
del_model: {
|
||||
parameters: {
|
||||
path: {
|
||||
/** @description Base model */
|
||||
base_model: components["schemas"]["BaseModelType"];
|
||||
/** @description The type of model */
|
||||
model_type: components["schemas"]["ModelType"];
|
||||
/** @description model name */
|
||||
model_name: string;
|
||||
};
|
||||
};
|
||||
@ -4923,6 +4856,114 @@ export type operations = {
|
||||
};
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Update Model
|
||||
* @description Add Model
|
||||
*/
|
||||
update_model: {
|
||||
parameters: {
|
||||
path: {
|
||||
/** @description Base model */
|
||||
base_model: components["schemas"]["BaseModelType"];
|
||||
/** @description The type of model */
|
||||
model_type: components["schemas"]["ModelType"];
|
||||
/** @description model name */
|
||||
model_name: string;
|
||||
};
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description The model was updated successfully */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"];
|
||||
};
|
||||
};
|
||||
/** @description Bad request */
|
||||
400: never;
|
||||
/** @description The model could not be found */
|
||||
404: never;
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Convert Model
|
||||
* @description Convert a checkpoint model into a diffusers model
|
||||
*/
|
||||
convert_model: {
|
||||
parameters: {
|
||||
path: {
|
||||
/** @description Base model */
|
||||
base_model: components["schemas"]["BaseModelType"];
|
||||
/** @description The type of model */
|
||||
model_type: components["schemas"]["ModelType"];
|
||||
/** @description model name */
|
||||
model_name: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Model converted successfully */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"];
|
||||
};
|
||||
};
|
||||
/** @description Bad request */
|
||||
400: never;
|
||||
/** @description Model not found */
|
||||
404: never;
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Merge Models
|
||||
* @description Convert a checkpoint model into a diffusers model
|
||||
*/
|
||||
merge_models: {
|
||||
parameters: {
|
||||
path: {
|
||||
/** @description Base model */
|
||||
base_model: components["schemas"]["BaseModelType"];
|
||||
};
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["Body_merge_models"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Model converted successfully */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"];
|
||||
};
|
||||
};
|
||||
/** @description Incompatible models */
|
||||
400: never;
|
||||
/** @description One or more models not found */
|
||||
404: never;
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/**
|
||||
* List Images With Metadata
|
||||
* @description Gets a list of images
|
||||
|
@ -157,8 +157,6 @@ export const imageUploaded = createAppAsyncThunk<
|
||||
session_id,
|
||||
} = arg;
|
||||
const { post } = $client.get();
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
const { data, error, response } = await post('/api/v1/images/', {
|
||||
params: {
|
||||
query: {
|
||||
@ -167,10 +165,12 @@ export const imageUploaded = createAppAsyncThunk<
|
||||
session_id,
|
||||
},
|
||||
},
|
||||
// TODO: Proper handling of `multipart/form-data` is coming soon, will fix type issues
|
||||
// https://github.com/drwpow/openapi-typescript/issues/1123
|
||||
// @ts-ignore
|
||||
body: formData,
|
||||
body: { file },
|
||||
bodySerializer: (body) => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', body.file);
|
||||
return formData;
|
||||
},
|
||||
});
|
||||
|
||||
if (error) {
|
||||
|
@ -23,5 +23,11 @@
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "*.d.ts"],
|
||||
"exclude": ["src/services/fixtures/*", "node_modules", "dist"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
"references": [{ "path": "./tsconfig.node.json" }],
|
||||
"ts-node": {
|
||||
"compilerOptions": {
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"esm": true
|
||||
}
|
||||
}
|
||||
|
@ -5386,10 +5386,10 @@ open@^8.4.0:
|
||||
is-docker "^2.1.1"
|
||||
is-wsl "^2.2.0"
|
||||
|
||||
openapi-fetch@0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/openapi-fetch/-/openapi-fetch-0.4.0.tgz#45c368321ba6c15bc2e168e7dc3fbf322e9cca6d"
|
||||
integrity sha512-4lzZtH5J1ZH9EXfmpcmKi0gOgjy0hc6BAcucAdCmLHY6jZopMeGP51vD3Cd4rE1nTFMfJzmYDc8ar0+364gBVw==
|
||||
openapi-fetch@^0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/openapi-fetch/-/openapi-fetch-0.6.1.tgz#90d785ead213b82beb8f094a756ad9320ba28b32"
|
||||
integrity sha512-CGWPqqtL31uC2e4eEU9NHoqYMXnJ7Jk4H/4Yguil4tO22MIZi91hlQJ/51E8CiaKdSTODh03yF4ndjIOABVHUw==
|
||||
|
||||
openapi-types@^12.1.3:
|
||||
version "12.1.3"
|
||||
|
Loading…
Reference in New Issue
Block a user