mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Compare commits
3 Commits
v4.0.4
...
feat/nodes
Author | SHA1 | Date | |
---|---|---|---|
b9ebce9bdd | |||
56254b74e2 | |||
593604bbba |
@ -9,6 +9,7 @@ from invokeai.app.services.boards import BoardService, BoardServiceDependencies
|
||||
from invokeai.app.services.config import InvokeAIAppConfig
|
||||
from invokeai.app.services.image_record_storage import SqliteImageRecordStorage
|
||||
from invokeai.app.services.images import ImageService, ImageServiceDependencies
|
||||
from invokeai.app.services.invocation_cache.invocation_cache_memory import MemoryInvocationCache
|
||||
from invokeai.app.services.resource_name import SimpleNameService
|
||||
from invokeai.app.services.urls import LocalUrlService
|
||||
from invokeai.backend.util.logging import InvokeAILogger
|
||||
@ -126,6 +127,7 @@ class ApiDependencies:
|
||||
configuration=config,
|
||||
performance_statistics=InvocationStatsService(graph_execution_manager),
|
||||
logger=logger,
|
||||
invocation_cache=MemoryInvocationCache(max_cache_size=config.node_cache_size),
|
||||
)
|
||||
|
||||
create_system_graphs(services.graph_library)
|
||||
|
@ -1,5 +1,7 @@
|
||||
# Copyright (c) 2022 Kyle Schouviller (https://github.com/kyle0654)
|
||||
|
||||
from invokeai.app.services.invocation_cache.invocation_cache_memory import MemoryInvocationCache
|
||||
|
||||
from .services.config import InvokeAIAppConfig
|
||||
|
||||
# parse_args() must be called before any other imports. if it is not called first, consumers of the config
|
||||
@ -309,6 +311,7 @@ def invoke_cli():
|
||||
performance_statistics=InvocationStatsService(graph_execution_manager),
|
||||
logger=logger,
|
||||
configuration=config,
|
||||
invocation_cache=MemoryInvocationCache(max_cache_size=config.node_cache_size),
|
||||
)
|
||||
|
||||
system_graphs = create_system_graphs(services.graph_library)
|
||||
|
@ -568,7 +568,24 @@ class BaseInvocation(ABC, BaseModel):
|
||||
raise RequiredConnectionException(self.__fields__["type"].default, field_name)
|
||||
elif _input == Input.Any:
|
||||
raise MissingInputException(self.__fields__["type"].default, field_name)
|
||||
return self.invoke(context)
|
||||
output: BaseInvocationOutput
|
||||
if self.use_cache:
|
||||
key = context.services.invocation_cache.create_key(self)
|
||||
cached_value = context.services.invocation_cache.get(key)
|
||||
if cached_value is None:
|
||||
context.services.logger.debug(f'Invocation cache miss for type "{self.get_type()}": {self.id}')
|
||||
output = self.invoke(context)
|
||||
context.services.invocation_cache.save(key, output)
|
||||
return output
|
||||
else:
|
||||
context.services.logger.debug(f'Invocation cache hit for type "{self.get_type()}": {self.id}')
|
||||
return cached_value
|
||||
else:
|
||||
context.services.logger.debug(f'Skipping invocation cache for "{self.get_type()}": {self.id}')
|
||||
return self.invoke(context)
|
||||
|
||||
def get_type(self) -> str:
|
||||
return self.__fields__["type"].default
|
||||
|
||||
id: str = Field(
|
||||
description="The id of this instance of an invocation. Must be unique among all instances of invocations."
|
||||
@ -581,6 +598,7 @@ class BaseInvocation(ABC, BaseModel):
|
||||
description="The workflow to save with the image",
|
||||
ui_type=UIType.WorkflowField,
|
||||
)
|
||||
use_cache: bool = InputField(default=True, description="Whether or not to use the cache")
|
||||
|
||||
@validator("workflow", pre=True)
|
||||
def validate_workflow_is_json(cls, v):
|
||||
@ -604,6 +622,7 @@ def invocation(
|
||||
tags: Optional[list[str]] = None,
|
||||
category: Optional[str] = None,
|
||||
version: Optional[str] = None,
|
||||
use_cache: Optional[bool] = True,
|
||||
) -> Callable[[Type[GenericBaseInvocation]], Type[GenericBaseInvocation]]:
|
||||
"""
|
||||
Adds metadata to an invocation.
|
||||
@ -636,6 +655,8 @@ def invocation(
|
||||
except ValueError as e:
|
||||
raise InvalidVersionError(f'Invalid version string for node "{invocation_type}": "{version}"') from e
|
||||
cls.UIConfig.version = version
|
||||
if use_cache is not None:
|
||||
cls.__fields__["use_cache"].default = use_cache
|
||||
|
||||
# Add the invocation type to the pydantic model of the invocation
|
||||
invocation_type_annotation = Literal[invocation_type] # type: ignore
|
||||
|
@ -56,6 +56,7 @@ class RangeOfSizeInvocation(BaseInvocation):
|
||||
tags=["range", "integer", "random", "collection"],
|
||||
category="collections",
|
||||
version="1.0.0",
|
||||
use_cache=False,
|
||||
)
|
||||
class RandomRangeInvocation(BaseInvocation):
|
||||
"""Creates a collection of random numbers"""
|
||||
|
@ -965,3 +965,42 @@ class ImageChannelMultiplyInvocation(BaseInvocation):
|
||||
width=image_dto.width,
|
||||
height=image_dto.height,
|
||||
)
|
||||
|
||||
|
||||
@invocation(
|
||||
"save_image",
|
||||
title="Save Image",
|
||||
tags=["primitives", "image"],
|
||||
category="primitives",
|
||||
version="1.0.0",
|
||||
use_cache=False,
|
||||
)
|
||||
class SaveImageInvocation(BaseInvocation):
|
||||
"""Saves an image. Unlike an image primitive, this invocation stores a copy of the image."""
|
||||
|
||||
image: ImageField = InputField(description="The image to load")
|
||||
metadata: CoreMetadata = InputField(
|
||||
default=None,
|
||||
description=FieldDescriptions.core_metadata,
|
||||
ui_hidden=True,
|
||||
)
|
||||
|
||||
def invoke(self, context: InvocationContext) -> ImageOutput:
|
||||
image = context.services.images.get_pil_image(self.image.image_name)
|
||||
|
||||
image_dto = context.services.images.create(
|
||||
image=image,
|
||||
image_origin=ResourceOrigin.INTERNAL,
|
||||
image_category=ImageCategory.GENERAL,
|
||||
node_id=self.id,
|
||||
session_id=context.graph_execution_state_id,
|
||||
is_intermediate=self.is_intermediate,
|
||||
metadata=self.metadata.dict() if self.metadata else None,
|
||||
workflow=self.workflow,
|
||||
)
|
||||
|
||||
return ImageOutput(
|
||||
image=ImageField(image_name=image_dto.image_name),
|
||||
width=image_dto.width,
|
||||
height=image_dto.height,
|
||||
)
|
||||
|
@ -54,7 +54,14 @@ class DivideInvocation(BaseInvocation):
|
||||
return IntegerOutput(value=int(self.a / self.b))
|
||||
|
||||
|
||||
@invocation("rand_int", title="Random Integer", tags=["math", "random"], category="math", version="1.0.0")
|
||||
@invocation(
|
||||
"rand_int",
|
||||
title="Random Integer",
|
||||
tags=["math", "random"],
|
||||
category="math",
|
||||
version="1.0.0",
|
||||
use_cache=False,
|
||||
)
|
||||
class RandomIntInvocation(BaseInvocation):
|
||||
"""Outputs a single random integer."""
|
||||
|
||||
|
@ -10,7 +10,14 @@ from invokeai.app.invocations.primitives import StringCollectionOutput
|
||||
from .baseinvocation import BaseInvocation, InputField, InvocationContext, UIComponent, invocation
|
||||
|
||||
|
||||
@invocation("dynamic_prompt", title="Dynamic Prompt", tags=["prompt", "collection"], category="prompt", version="1.0.0")
|
||||
@invocation(
|
||||
"dynamic_prompt",
|
||||
title="Dynamic Prompt",
|
||||
tags=["prompt", "collection"],
|
||||
category="prompt",
|
||||
version="1.0.0",
|
||||
use_cache=False,
|
||||
)
|
||||
class DynamicPromptInvocation(BaseInvocation):
|
||||
"""Parses a prompt using adieyal/dynamicprompts' random or combinatorial generator"""
|
||||
|
||||
|
@ -253,6 +253,7 @@ class InvokeAIAppConfig(InvokeAISettings):
|
||||
attention_type : Literal[tuple(["auto", "normal", "xformers", "sliced", "torch-sdp"])] = Field(default="auto", description="Attention type", category="Generation", )
|
||||
attention_slice_size: Literal[tuple(["auto", "balanced", "max", 1, 2, 3, 4, 5, 6, 7, 8])] = Field(default="auto", description='Slice size, valid when attention_type=="sliced"', category="Generation", )
|
||||
force_tiled_decode: bool = Field(default=False, description="Whether to enable tiled VAE decode (reduces memory consumption with some performance penalty)", category="Generation",)
|
||||
node_cache_size : int = Field(default=512, description="How many cached nodes to keep in memory", category="Generation", )
|
||||
|
||||
# NODES
|
||||
allow_nodes : Optional[List[str]] = Field(default=None, description="List of nodes to allow. Omit to allow all.", category="Nodes")
|
||||
|
0
invokeai/app/services/invocation_cache/__init__.py
Normal file
0
invokeai/app/services/invocation_cache/__init__.py
Normal file
@ -0,0 +1,29 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional, Union
|
||||
|
||||
from invokeai.app.invocations.baseinvocation import BaseInvocation, BaseInvocationOutput
|
||||
|
||||
|
||||
class InvocationCacheBase(ABC):
|
||||
"""Base class for invocation caches."""
|
||||
|
||||
@abstractmethod
|
||||
def get(self, key: Union[int, str]) -> Optional[BaseInvocationOutput]:
|
||||
"""Retrieves and invocation output from the cache"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def save(self, key: Union[int, str], value: BaseInvocationOutput) -> None:
|
||||
"""Stores an invocation output in the cache"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def delete(self, key: Union[int, str]) -> None:
|
||||
"""Deleted an invocation output from the cache"""
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def create_key(cls, value: BaseInvocation) -> Union[int, str]:
|
||||
"""Creates the cache key for an invocation"""
|
||||
pass
|
@ -0,0 +1,34 @@
|
||||
from queue import Queue
|
||||
from typing import Optional, Union
|
||||
|
||||
from invokeai.app.invocations.baseinvocation import BaseInvocation, BaseInvocationOutput
|
||||
from invokeai.app.services.invocation_cache.invocation_cache_base import InvocationCacheBase
|
||||
|
||||
|
||||
class MemoryInvocationCache(InvocationCacheBase):
|
||||
__cache: dict[Union[int, str], BaseInvocationOutput]
|
||||
__max_cache_size: int
|
||||
__cache_ids: Queue
|
||||
|
||||
def __init__(self, max_cache_size: int = 512) -> None:
|
||||
self.__cache = dict()
|
||||
self.__max_cache_size = max_cache_size
|
||||
self.__cache_ids = Queue()
|
||||
|
||||
def get(self, key: Union[int, str]) -> Optional[BaseInvocationOutput]:
|
||||
return self.__cache.get(key, None)
|
||||
|
||||
def save(self, key: Union[int, str], value: BaseInvocationOutput) -> None:
|
||||
if key not in self.__cache:
|
||||
self.__cache[key] = value
|
||||
self.__cache_ids.put(key)
|
||||
if self.__cache_ids.qsize() > self.__max_cache_size:
|
||||
self.__cache.pop(self.__cache_ids.get())
|
||||
|
||||
def delete(self, key: Union[int, str]) -> None:
|
||||
if key in self.__cache:
|
||||
del self.__cache[key]
|
||||
|
||||
@classmethod
|
||||
def create_key(cls, value: BaseInvocation) -> Union[int, str]:
|
||||
return hash(value.json(exclude={"id"}))
|
@ -12,6 +12,7 @@ if TYPE_CHECKING:
|
||||
from invokeai.app.services.events import EventServiceBase
|
||||
from invokeai.app.services.graph import GraphExecutionState, LibraryGraph
|
||||
from invokeai.app.services.images import ImageServiceABC
|
||||
from invokeai.app.services.invocation_cache.invocation_cache_base import InvocationCacheBase
|
||||
from invokeai.app.services.invocation_queue import InvocationQueueABC
|
||||
from invokeai.app.services.invocation_stats import InvocationStatsServiceBase
|
||||
from invokeai.app.services.invoker import InvocationProcessorABC
|
||||
@ -37,6 +38,7 @@ class InvocationServices:
|
||||
processor: "InvocationProcessorABC"
|
||||
performance_statistics: "InvocationStatsServiceBase"
|
||||
queue: "InvocationQueueABC"
|
||||
invocation_cache: "InvocationCacheBase"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -53,6 +55,7 @@ class InvocationServices:
|
||||
processor: "InvocationProcessorABC",
|
||||
performance_statistics: "InvocationStatsServiceBase",
|
||||
queue: "InvocationQueueABC",
|
||||
invocation_cache: "InvocationCacheBase",
|
||||
):
|
||||
self.board_images = board_images
|
||||
self.boards = boards
|
||||
@ -68,3 +71,4 @@ class InvocationServices:
|
||||
self.processor = processor
|
||||
self.performance_statistics = performance_statistics
|
||||
self.queue = queue
|
||||
self.invocation_cache = invocation_cache
|
||||
|
5
invokeai/frontend/web/src/app/store/nanostores/store.ts
Normal file
5
invokeai/frontend/web/src/app/store/nanostores/store.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { Store } from '@reduxjs/toolkit';
|
||||
import { atom } from 'nanostores';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const $store = atom<Store<any> | undefined>();
|
@ -31,6 +31,7 @@ import { actionSanitizer } from './middleware/devtools/actionSanitizer';
|
||||
import { actionsDenylist } from './middleware/devtools/actionsDenylist';
|
||||
import { stateSanitizer } from './middleware/devtools/stateSanitizer';
|
||||
import { listenerMiddleware } from './middleware/listenerMiddleware';
|
||||
import { $store } from './nanostores/store';
|
||||
|
||||
const allReducers = {
|
||||
canvas: canvasReducer,
|
||||
@ -121,3 +122,4 @@ export type RootState = ReturnType<typeof store.getState>;
|
||||
export type AppThunkDispatch = ThunkDispatch<RootState, any, AnyAction>;
|
||||
export type AppDispatch = typeof store.dispatch;
|
||||
export const stateSelector = (state: RootState) => state;
|
||||
$store.set(store);
|
||||
|
@ -27,7 +27,7 @@ const EmbedWorkflowCheckbox = ({ nodeId }: { nodeId: string }) => {
|
||||
|
||||
return (
|
||||
<FormControl as={Flex} sx={{ alignItems: 'center', gap: 2, w: 'auto' }}>
|
||||
<FormLabel sx={{ fontSize: 'xs', mb: '1px' }}>Embed Workflow</FormLabel>
|
||||
<FormLabel sx={{ fontSize: 'xs', mb: '1px' }}>Workflow</FormLabel>
|
||||
<Checkbox
|
||||
className="nopan"
|
||||
size="sm"
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { Flex, Grid, GridItem } from '@chakra-ui/react';
|
||||
import { useAnyOrDirectInputFieldNames } from 'features/nodes/hooks/useAnyOrDirectInputFieldNames';
|
||||
import { useConnectionInputFieldNames } from 'features/nodes/hooks/useConnectionInputFieldNames';
|
||||
import { useOutputFieldNames } from 'features/nodes/hooks/useOutputFieldNames';
|
||||
import { memo } from 'react';
|
||||
import NodeWrapper from '../common/NodeWrapper';
|
||||
import InvocationNodeFooter from './InvocationNodeFooter';
|
||||
import InvocationNodeHeader from './InvocationNodeHeader';
|
||||
import NodeWrapper from '../common/NodeWrapper';
|
||||
import OutputField from './fields/OutputField';
|
||||
import InputField from './fields/InputField';
|
||||
import { useOutputFieldNames } from 'features/nodes/hooks/useOutputFieldNames';
|
||||
import { useWithFooter } from 'features/nodes/hooks/useWithFooter';
|
||||
import { useConnectionInputFieldNames } from 'features/nodes/hooks/useConnectionInputFieldNames';
|
||||
import { useAnyOrDirectInputFieldNames } from 'features/nodes/hooks/useAnyOrDirectInputFieldNames';
|
||||
import OutputField from './fields/OutputField';
|
||||
|
||||
type Props = {
|
||||
nodeId: string;
|
||||
@ -22,7 +21,6 @@ const InvocationNode = ({ nodeId, isOpen, label, type, selected }: Props) => {
|
||||
const inputConnectionFieldNames = useConnectionInputFieldNames(nodeId);
|
||||
const inputAnyOrDirectFieldNames = useAnyOrDirectInputFieldNames(nodeId);
|
||||
const outputFieldNames = useOutputFieldNames(nodeId);
|
||||
const withFooter = useWithFooter(nodeId);
|
||||
|
||||
return (
|
||||
<NodeWrapper nodeId={nodeId} selected={selected}>
|
||||
@ -43,7 +41,7 @@ const InvocationNode = ({ nodeId, isOpen, label, type, selected }: Props) => {
|
||||
h: 'full',
|
||||
py: 2,
|
||||
gap: 1,
|
||||
borderBottomRadius: withFooter ? 0 : 'base',
|
||||
borderBottomRadius: 0,
|
||||
}}
|
||||
>
|
||||
<Flex sx={{ flexDir: 'column', px: 2, w: 'full', h: 'full' }}>
|
||||
@ -76,7 +74,7 @@ const InvocationNode = ({ nodeId, isOpen, label, type, selected }: Props) => {
|
||||
))}
|
||||
</Flex>
|
||||
</Flex>
|
||||
{withFooter && <InvocationNodeFooter nodeId={nodeId} />}
|
||||
<InvocationNodeFooter nodeId={nodeId} />
|
||||
</>
|
||||
)}
|
||||
</NodeWrapper>
|
||||
|
@ -3,12 +3,15 @@ import { DRAG_HANDLE_CLASSNAME } from 'features/nodes/types/constants';
|
||||
import { memo } from 'react';
|
||||
import EmbedWorkflowCheckbox from './EmbedWorkflowCheckbox';
|
||||
import SaveToGalleryCheckbox from './SaveToGalleryCheckbox';
|
||||
import UseCacheCheckbox from './UseCacheCheckbox';
|
||||
import { useHasImageOutput } from 'features/nodes/hooks/useHasImageOutput';
|
||||
|
||||
type Props = {
|
||||
nodeId: string;
|
||||
};
|
||||
|
||||
const InvocationNodeFooter = ({ nodeId }: Props) => {
|
||||
const hasImageOutput = useHasImageOutput(nodeId);
|
||||
return (
|
||||
<Flex
|
||||
className={DRAG_HANDLE_CLASSNAME}
|
||||
@ -22,8 +25,9 @@ const InvocationNodeFooter = ({ nodeId }: Props) => {
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<EmbedWorkflowCheckbox nodeId={nodeId} />
|
||||
<SaveToGalleryCheckbox nodeId={nodeId} />
|
||||
{hasImageOutput && <EmbedWorkflowCheckbox nodeId={nodeId} />}
|
||||
<UseCacheCheckbox nodeId={nodeId} />
|
||||
{hasImageOutput && <SaveToGalleryCheckbox nodeId={nodeId} />}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
@ -0,0 +1,35 @@
|
||||
import { Checkbox, Flex, FormControl, FormLabel } from '@chakra-ui/react';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { useUseCache } from 'features/nodes/hooks/useUseCache';
|
||||
import { nodeUseCacheChanged } from 'features/nodes/store/nodesSlice';
|
||||
import { ChangeEvent, memo, useCallback } from 'react';
|
||||
|
||||
const UseCacheCheckbox = ({ nodeId }: { nodeId: string }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const useCache = useUseCache(nodeId);
|
||||
const handleChange = useCallback(
|
||||
(e: ChangeEvent<HTMLInputElement>) => {
|
||||
dispatch(
|
||||
nodeUseCacheChanged({
|
||||
nodeId,
|
||||
useCache: e.target.checked,
|
||||
})
|
||||
);
|
||||
},
|
||||
[dispatch, nodeId]
|
||||
);
|
||||
|
||||
return (
|
||||
<FormControl as={Flex} sx={{ alignItems: 'center', gap: 2, w: 'auto' }}>
|
||||
<FormLabel sx={{ fontSize: 'xs', mb: '1px' }}>Use Cache</FormLabel>
|
||||
<Checkbox
|
||||
className="nopan"
|
||||
size="sm"
|
||||
onChange={handleChange}
|
||||
isChecked={useCache}
|
||||
/>
|
||||
</FormControl>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(UseCacheCheckbox);
|
@ -146,6 +146,7 @@ export const useBuildNodeData = () => {
|
||||
isIntermediate: true,
|
||||
inputs,
|
||||
outputs,
|
||||
useCache: template.useCache,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,29 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { useMemo } from 'react';
|
||||
import { isInvocationNode } from '../types/types';
|
||||
|
||||
export const useUseCache = (nodeId: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
stateSelector,
|
||||
({ nodes }) => {
|
||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||
if (!isInvocationNode(node)) {
|
||||
return false;
|
||||
}
|
||||
// cast to boolean to support older workflows that didn't have useCache
|
||||
// TODO: handle this better somehow
|
||||
return node.data.useCache;
|
||||
},
|
||||
defaultSelectorOptions
|
||||
),
|
||||
[nodeId]
|
||||
);
|
||||
|
||||
const useCache = useAppSelector(selector);
|
||||
return useCache;
|
||||
};
|
@ -7,7 +7,7 @@ import { useMemo } from 'react';
|
||||
import { FOOTER_FIELDS } from '../types/constants';
|
||||
import { isInvocationNode } from '../types/types';
|
||||
|
||||
export const useWithFooter = (nodeId: string) => {
|
||||
export const useHasImageOutputs = (nodeId: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
|
@ -260,6 +260,20 @@ const nodesSlice = createSlice({
|
||||
}
|
||||
node.data.embedWorkflow = embedWorkflow;
|
||||
},
|
||||
nodeUseCacheChanged: (
|
||||
state,
|
||||
action: PayloadAction<{ nodeId: string; useCache: boolean }>
|
||||
) => {
|
||||
const { nodeId, useCache } = action.payload;
|
||||
const nodeIndex = state.nodes.findIndex((n) => n.id === nodeId);
|
||||
|
||||
const node = state.nodes?.[nodeIndex];
|
||||
|
||||
if (!isInvocationNode(node)) {
|
||||
return;
|
||||
}
|
||||
node.data.useCache = useCache;
|
||||
},
|
||||
nodeIsIntermediateChanged: (
|
||||
state,
|
||||
action: PayloadAction<{ nodeId: string; isIntermediate: boolean }>
|
||||
@ -904,6 +918,7 @@ export const {
|
||||
nodeIsIntermediateChanged,
|
||||
mouseOverNodeChanged,
|
||||
nodeExclusivelySelected,
|
||||
nodeUseCacheChanged,
|
||||
} = nodesSlice.actions;
|
||||
|
||||
export default nodesSlice.reducer;
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { $store } from 'app/store/nanostores/store';
|
||||
import {
|
||||
SchedulerParam,
|
||||
zBaseModel,
|
||||
@ -7,7 +8,8 @@ import {
|
||||
zSDXLRefinerModel,
|
||||
zScheduler,
|
||||
} from 'features/parameters/types/parameterSchemas';
|
||||
import { keyBy } from 'lodash-es';
|
||||
import i18n from 'i18next';
|
||||
import { has, keyBy } from 'lodash-es';
|
||||
import { OpenAPIV3 } from 'openapi-types';
|
||||
import { RgbaColor } from 'react-colorful';
|
||||
import { Node } from 'reactflow';
|
||||
@ -20,7 +22,6 @@ import {
|
||||
import { O } from 'ts-toolbelt';
|
||||
import { JsonObject } from 'type-fest';
|
||||
import { z } from 'zod';
|
||||
import i18n from 'i18next';
|
||||
|
||||
export type NonNullableGraph = O.Required<Graph, 'nodes' | 'edges'>;
|
||||
|
||||
@ -57,6 +58,10 @@ export type InvocationTemplate = {
|
||||
* The invocation's version.
|
||||
*/
|
||||
version?: string;
|
||||
/**
|
||||
* Whether or not this node should use the cache
|
||||
*/
|
||||
useCache: boolean;
|
||||
};
|
||||
|
||||
export type FieldUIConfig = {
|
||||
@ -976,6 +981,9 @@ export type InvocationSchemaExtra = {
|
||||
type: Omit<OpenAPIV3.SchemaObject, 'default'> & {
|
||||
default: AnyInvocationType;
|
||||
};
|
||||
use_cache: Omit<OpenAPIV3.SchemaObject, 'default'> & {
|
||||
default: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@ -1139,9 +1147,37 @@ export const zInvocationNodeData = z.object({
|
||||
version: zSemVer.optional(),
|
||||
});
|
||||
|
||||
export const zInvocationNodeDataV2 = z.preprocess(
|
||||
(arg) => {
|
||||
try {
|
||||
const data = zInvocationNodeData.parse(arg);
|
||||
if (!has(data, 'useCache')) {
|
||||
const nodeTemplates = $store.get()?.getState().nodes.nodeTemplates as
|
||||
| Record<string, InvocationTemplate>
|
||||
| undefined;
|
||||
|
||||
const template = nodeTemplates?.[data.type];
|
||||
|
||||
let useCache = true;
|
||||
if (template) {
|
||||
useCache = template.useCache;
|
||||
}
|
||||
|
||||
Object.assign(data, { useCache });
|
||||
}
|
||||
return data;
|
||||
} catch {
|
||||
return arg;
|
||||
}
|
||||
},
|
||||
zInvocationNodeData.extend({
|
||||
useCache: z.boolean(),
|
||||
})
|
||||
);
|
||||
|
||||
// Massage this to get better type safety while developing
|
||||
export type InvocationNodeData = Omit<
|
||||
z.infer<typeof zInvocationNodeData>,
|
||||
z.infer<typeof zInvocationNodeDataV2>,
|
||||
'type'
|
||||
> & {
|
||||
type: AnyInvocationType;
|
||||
@ -1169,7 +1205,7 @@ const zDimension = z.number().gt(0).nullish();
|
||||
export const zWorkflowInvocationNode = z.object({
|
||||
id: z.string().trim().min(1),
|
||||
type: z.literal('invocation'),
|
||||
data: zInvocationNodeData,
|
||||
data: zInvocationNodeDataV2,
|
||||
width: zDimension,
|
||||
height: zDimension,
|
||||
position: zPosition,
|
||||
@ -1231,6 +1267,8 @@ export type WorkflowWarning = {
|
||||
data: JsonObject;
|
||||
};
|
||||
|
||||
const CURRENT_WORKFLOW_VERSION = '1.0.0';
|
||||
|
||||
export const zWorkflow = z.object({
|
||||
name: z.string().default(''),
|
||||
author: z.string().default(''),
|
||||
@ -1246,7 +1284,7 @@ export const zWorkflow = z.object({
|
||||
.object({
|
||||
version: zSemVer,
|
||||
})
|
||||
.default({ version: '1.0.0' }),
|
||||
.default({ version: CURRENT_WORKFLOW_VERSION }),
|
||||
});
|
||||
|
||||
export const zValidatedWorkflow = zWorkflow.transform((workflow) => {
|
||||
|
@ -1,46 +1,32 @@
|
||||
import { RootState } from 'app/store/store';
|
||||
import { NonNullableGraph } from 'features/nodes/types/types';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import {
|
||||
ImageNSFWBlurInvocation,
|
||||
LatentsToImageInvocation,
|
||||
MetadataAccumulatorInvocation,
|
||||
} from 'services/api/types';
|
||||
import {
|
||||
LATENTS_TO_IMAGE,
|
||||
METADATA_ACCUMULATOR,
|
||||
NSFW_CHECKER,
|
||||
} from './constants';
|
||||
import { LATENTS_TO_IMAGE, NSFW_CHECKER } from './constants';
|
||||
|
||||
export const addNSFWCheckerToGraph = (
|
||||
state: RootState,
|
||||
graph: NonNullableGraph,
|
||||
nodeIdToAddTo = LATENTS_TO_IMAGE
|
||||
): void => {
|
||||
const activeTabName = activeTabNameSelector(state);
|
||||
|
||||
const is_intermediate =
|
||||
activeTabName === 'unifiedCanvas' ? !state.canvas.shouldAutoSave : false;
|
||||
|
||||
const nodeToAddTo = graph.nodes[nodeIdToAddTo] as
|
||||
| LatentsToImageInvocation
|
||||
| undefined;
|
||||
|
||||
const metadataAccumulator = graph.nodes[METADATA_ACCUMULATOR] as
|
||||
| MetadataAccumulatorInvocation
|
||||
| undefined;
|
||||
|
||||
if (!nodeToAddTo) {
|
||||
// something has gone terribly awry
|
||||
return;
|
||||
}
|
||||
|
||||
nodeToAddTo.is_intermediate = true;
|
||||
nodeToAddTo.use_cache = true;
|
||||
|
||||
const nsfwCheckerNode: ImageNSFWBlurInvocation = {
|
||||
id: NSFW_CHECKER,
|
||||
type: 'img_nsfw',
|
||||
is_intermediate,
|
||||
is_intermediate: true,
|
||||
};
|
||||
|
||||
graph.nodes[NSFW_CHECKER] = nsfwCheckerNode as ImageNSFWBlurInvocation;
|
||||
@ -54,17 +40,4 @@ export const addNSFWCheckerToGraph = (
|
||||
field: 'image',
|
||||
},
|
||||
});
|
||||
|
||||
if (metadataAccumulator) {
|
||||
graph.edges.push({
|
||||
source: {
|
||||
node_id: METADATA_ACCUMULATOR,
|
||||
field: 'metadata',
|
||||
},
|
||||
destination: {
|
||||
node_id: NSFW_CHECKER,
|
||||
field: 'metadata',
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -0,0 +1,92 @@
|
||||
import { NonNullableGraph } from 'features/nodes/types/types';
|
||||
import {
|
||||
CANVAS_OUTPUT,
|
||||
LATENTS_TO_IMAGE,
|
||||
METADATA_ACCUMULATOR,
|
||||
NSFW_CHECKER,
|
||||
SAVE_IMAGE,
|
||||
WATERMARKER,
|
||||
} from './constants';
|
||||
import {
|
||||
MetadataAccumulatorInvocation,
|
||||
SaveImageInvocation,
|
||||
} from 'services/api/types';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
|
||||
/**
|
||||
* Set the `use_cache` field on the linear/canvas graph's final image output node to False.
|
||||
*/
|
||||
export const addSaveImageNode = (
|
||||
state: RootState,
|
||||
graph: NonNullableGraph
|
||||
): void => {
|
||||
const activeTabName = activeTabNameSelector(state);
|
||||
const is_intermediate =
|
||||
activeTabName === 'unifiedCanvas' ? !state.canvas.shouldAutoSave : false;
|
||||
|
||||
const saveImageNode: SaveImageInvocation = {
|
||||
id: SAVE_IMAGE,
|
||||
type: 'save_image',
|
||||
is_intermediate,
|
||||
use_cache: false,
|
||||
};
|
||||
|
||||
graph.nodes[SAVE_IMAGE] = saveImageNode;
|
||||
|
||||
const metadataAccumulator = graph.nodes[METADATA_ACCUMULATOR] as
|
||||
| MetadataAccumulatorInvocation
|
||||
| undefined;
|
||||
|
||||
if (metadataAccumulator) {
|
||||
graph.edges.push({
|
||||
source: {
|
||||
node_id: METADATA_ACCUMULATOR,
|
||||
field: 'metadata',
|
||||
},
|
||||
destination: {
|
||||
node_id: SAVE_IMAGE,
|
||||
field: 'metadata',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const destination = {
|
||||
node_id: SAVE_IMAGE,
|
||||
field: 'image',
|
||||
};
|
||||
|
||||
if (WATERMARKER in graph.nodes) {
|
||||
graph.edges.push({
|
||||
source: {
|
||||
node_id: WATERMARKER,
|
||||
field: 'image',
|
||||
},
|
||||
destination,
|
||||
});
|
||||
} else if (NSFW_CHECKER in graph.nodes) {
|
||||
graph.edges.push({
|
||||
source: {
|
||||
node_id: NSFW_CHECKER,
|
||||
field: 'image',
|
||||
},
|
||||
destination,
|
||||
});
|
||||
} else if (CANVAS_OUTPUT in graph.nodes) {
|
||||
graph.edges.push({
|
||||
source: {
|
||||
node_id: CANVAS_OUTPUT,
|
||||
field: 'image',
|
||||
},
|
||||
destination,
|
||||
});
|
||||
} else if (LATENTS_TO_IMAGE in graph.nodes) {
|
||||
graph.edges.push({
|
||||
source: {
|
||||
node_id: LATENTS_TO_IMAGE,
|
||||
field: 'image',
|
||||
},
|
||||
destination,
|
||||
});
|
||||
}
|
||||
};
|
@ -51,6 +51,7 @@ export const addWatermarkerToGraph = (
|
||||
|
||||
// no matter the situation, we want the l2i node to be intermediate
|
||||
nodeToAddTo.is_intermediate = true;
|
||||
nodeToAddTo.use_cache = true;
|
||||
|
||||
if (nsfwCheckerNode) {
|
||||
// if we are using NSFW checker, we need to "disable" it output by marking it intermediate,
|
||||
|
@ -25,6 +25,7 @@ import {
|
||||
POSITIVE_CONDITIONING,
|
||||
SEAMLESS,
|
||||
} from './constants';
|
||||
import { addSaveImageNode } from './addSaveImageNode';
|
||||
|
||||
/**
|
||||
* Builds the Canvas tab's Image to Image graph.
|
||||
@ -53,14 +54,10 @@ export const buildCanvasImageToImageGraph = (
|
||||
// The bounding box determines width and height, not the width and height params
|
||||
const { width, height } = state.canvas.boundingBoxDimensions;
|
||||
|
||||
const {
|
||||
scaledBoundingBoxDimensions,
|
||||
boundingBoxScaleMethod,
|
||||
shouldAutoSave,
|
||||
} = state.canvas;
|
||||
const { scaledBoundingBoxDimensions, boundingBoxScaleMethod } = state.canvas;
|
||||
|
||||
const fp32 = vaePrecision === 'fp32';
|
||||
|
||||
const is_intermediate = true;
|
||||
const isUsingScaledDimensions = ['auto', 'manual'].includes(
|
||||
boundingBoxScaleMethod
|
||||
);
|
||||
@ -92,31 +89,31 @@ export const buildCanvasImageToImageGraph = (
|
||||
[modelLoaderNodeId]: {
|
||||
type: 'main_model_loader',
|
||||
id: modelLoaderNodeId,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
model,
|
||||
},
|
||||
[CLIP_SKIP]: {
|
||||
type: 'clip_skip',
|
||||
id: CLIP_SKIP,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
skipped_layers: clipSkip,
|
||||
},
|
||||
[POSITIVE_CONDITIONING]: {
|
||||
type: 'compel',
|
||||
id: POSITIVE_CONDITIONING,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
prompt: positivePrompt,
|
||||
},
|
||||
[NEGATIVE_CONDITIONING]: {
|
||||
type: 'compel',
|
||||
id: NEGATIVE_CONDITIONING,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
prompt: negativePrompt,
|
||||
},
|
||||
[NOISE]: {
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
use_cpu,
|
||||
width: !isUsingScaledDimensions
|
||||
? width
|
||||
@ -128,12 +125,12 @@ export const buildCanvasImageToImageGraph = (
|
||||
[IMAGE_TO_LATENTS]: {
|
||||
type: 'i2l',
|
||||
id: IMAGE_TO_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[DENOISE_LATENTS]: {
|
||||
type: 'denoise_latents',
|
||||
id: DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
cfg_scale,
|
||||
scheduler,
|
||||
steps,
|
||||
@ -143,7 +140,7 @@ export const buildCanvasImageToImageGraph = (
|
||||
[CANVAS_OUTPUT]: {
|
||||
type: 'l2i',
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate: !shouldAutoSave,
|
||||
is_intermediate,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
@ -238,7 +235,7 @@ export const buildCanvasImageToImageGraph = (
|
||||
graph.nodes[IMG2IMG_RESIZE] = {
|
||||
id: IMG2IMG_RESIZE,
|
||||
type: 'img_resize',
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
image: initialImage,
|
||||
width: scaledBoundingBoxDimensions.width,
|
||||
height: scaledBoundingBoxDimensions.height,
|
||||
@ -246,13 +243,13 @@ export const buildCanvasImageToImageGraph = (
|
||||
graph.nodes[LATENTS_TO_IMAGE] = {
|
||||
id: LATENTS_TO_IMAGE,
|
||||
type: 'l2i',
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
};
|
||||
graph.nodes[CANVAS_OUTPUT] = {
|
||||
id: CANVAS_OUTPUT,
|
||||
type: 'img_resize',
|
||||
is_intermediate: !shouldAutoSave,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
@ -293,7 +290,7 @@ export const buildCanvasImageToImageGraph = (
|
||||
graph.nodes[CANVAS_OUTPUT] = {
|
||||
type: 'l2i',
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate: !shouldAutoSave,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
};
|
||||
|
||||
@ -337,17 +334,6 @@ export const buildCanvasImageToImageGraph = (
|
||||
init_image: initialImage.image_name,
|
||||
};
|
||||
|
||||
graph.edges.push({
|
||||
source: {
|
||||
node_id: METADATA_ACCUMULATOR,
|
||||
field: 'metadata',
|
||||
},
|
||||
destination: {
|
||||
node_id: CANVAS_OUTPUT,
|
||||
field: 'metadata',
|
||||
},
|
||||
});
|
||||
|
||||
// Add Seamless To Graph
|
||||
if (seamlessXAxis || seamlessYAxis) {
|
||||
addSeamlessToLinearGraph(state, graph, modelLoaderNodeId);
|
||||
@ -377,5 +363,7 @@ export const buildCanvasImageToImageGraph = (
|
||||
addWatermarkerToGraph(state, graph, CANVAS_OUTPUT);
|
||||
}
|
||||
|
||||
addSaveImageNode(state, graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
@ -44,6 +44,7 @@ import {
|
||||
RANGE_OF_SIZE,
|
||||
SEAMLESS,
|
||||
} from './constants';
|
||||
import { addSaveImageNode } from './addSaveImageNode';
|
||||
|
||||
/**
|
||||
* Builds the Canvas tab's Inpaint graph.
|
||||
@ -87,12 +88,8 @@ export const buildCanvasInpaintGraph = (
|
||||
const { width, height } = state.canvas.boundingBoxDimensions;
|
||||
|
||||
// We may need to set the inpaint width and height to scale the image
|
||||
const {
|
||||
scaledBoundingBoxDimensions,
|
||||
boundingBoxScaleMethod,
|
||||
shouldAutoSave,
|
||||
} = state.canvas;
|
||||
|
||||
const { scaledBoundingBoxDimensions, boundingBoxScaleMethod } = state.canvas;
|
||||
const is_intermediate = true;
|
||||
const fp32 = vaePrecision === 'fp32';
|
||||
|
||||
const isUsingScaledDimensions = ['auto', 'manual'].includes(
|
||||
@ -111,56 +108,56 @@ export const buildCanvasInpaintGraph = (
|
||||
[modelLoaderNodeId]: {
|
||||
type: 'main_model_loader',
|
||||
id: modelLoaderNodeId,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
model,
|
||||
},
|
||||
[CLIP_SKIP]: {
|
||||
type: 'clip_skip',
|
||||
id: CLIP_SKIP,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
skipped_layers: clipSkip,
|
||||
},
|
||||
[POSITIVE_CONDITIONING]: {
|
||||
type: 'compel',
|
||||
id: POSITIVE_CONDITIONING,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
prompt: positivePrompt,
|
||||
},
|
||||
[NEGATIVE_CONDITIONING]: {
|
||||
type: 'compel',
|
||||
id: NEGATIVE_CONDITIONING,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
prompt: negativePrompt,
|
||||
},
|
||||
[MASK_BLUR]: {
|
||||
type: 'img_blur',
|
||||
id: MASK_BLUR,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
radius: maskBlur,
|
||||
blur_type: maskBlurMethod,
|
||||
},
|
||||
[INPAINT_IMAGE]: {
|
||||
type: 'i2l',
|
||||
id: INPAINT_IMAGE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
},
|
||||
[NOISE]: {
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
use_cpu,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[INPAINT_CREATE_MASK]: {
|
||||
type: 'create_denoise_mask',
|
||||
id: INPAINT_CREATE_MASK,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
},
|
||||
[DENOISE_LATENTS]: {
|
||||
type: 'denoise_latents',
|
||||
id: DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
steps: steps,
|
||||
cfg_scale: cfg_scale,
|
||||
scheduler: scheduler,
|
||||
@ -171,18 +168,18 @@ export const buildCanvasInpaintGraph = (
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
use_cpu,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[CANVAS_COHERENCE_NOISE_INCREMENT]: {
|
||||
type: 'add',
|
||||
id: CANVAS_COHERENCE_NOISE_INCREMENT,
|
||||
b: 1,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[CANVAS_COHERENCE_DENOISE_LATENTS]: {
|
||||
type: 'denoise_latents',
|
||||
id: CANVAS_COHERENCE_DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
steps: canvasCoherenceSteps,
|
||||
cfg_scale: cfg_scale,
|
||||
scheduler: scheduler,
|
||||
@ -192,19 +189,19 @@ export const buildCanvasInpaintGraph = (
|
||||
[LATENTS_TO_IMAGE]: {
|
||||
type: 'l2i',
|
||||
id: LATENTS_TO_IMAGE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
},
|
||||
[CANVAS_OUTPUT]: {
|
||||
type: 'color_correct',
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate: !shouldAutoSave,
|
||||
is_intermediate,
|
||||
reference: canvasInitImage,
|
||||
},
|
||||
[RANGE_OF_SIZE]: {
|
||||
type: 'range_of_size',
|
||||
id: RANGE_OF_SIZE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
// seed - must be connected manually
|
||||
// start: 0,
|
||||
size: iterations,
|
||||
@ -213,7 +210,7 @@ export const buildCanvasInpaintGraph = (
|
||||
[ITERATE]: {
|
||||
type: 'iterate',
|
||||
id: ITERATE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
@ -436,7 +433,7 @@ export const buildCanvasInpaintGraph = (
|
||||
graph.nodes[INPAINT_IMAGE_RESIZE_UP] = {
|
||||
type: 'img_resize',
|
||||
id: INPAINT_IMAGE_RESIZE_UP,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: scaledWidth,
|
||||
height: scaledHeight,
|
||||
image: canvasInitImage,
|
||||
@ -444,7 +441,7 @@ export const buildCanvasInpaintGraph = (
|
||||
graph.nodes[MASK_RESIZE_UP] = {
|
||||
type: 'img_resize',
|
||||
id: MASK_RESIZE_UP,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: scaledWidth,
|
||||
height: scaledHeight,
|
||||
image: canvasMaskImage,
|
||||
@ -452,14 +449,14 @@ export const buildCanvasInpaintGraph = (
|
||||
graph.nodes[INPAINT_IMAGE_RESIZE_DOWN] = {
|
||||
type: 'img_resize',
|
||||
id: INPAINT_IMAGE_RESIZE_DOWN,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
graph.nodes[MASK_RESIZE_DOWN] = {
|
||||
type: 'img_resize',
|
||||
id: MASK_RESIZE_DOWN,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
@ -597,7 +594,7 @@ export const buildCanvasInpaintGraph = (
|
||||
graph.nodes[CANVAS_COHERENCE_INPAINT_CREATE_MASK] = {
|
||||
type: 'create_denoise_mask',
|
||||
id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
};
|
||||
|
||||
@ -650,7 +647,7 @@ export const buildCanvasInpaintGraph = (
|
||||
graph.nodes[CANVAS_COHERENCE_MASK_EDGE] = {
|
||||
type: 'mask_edge',
|
||||
id: CANVAS_COHERENCE_MASK_EDGE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
edge_blur: maskBlur,
|
||||
edge_size: maskBlur * 2,
|
||||
low_threshold: 100,
|
||||
@ -747,5 +744,7 @@ export const buildCanvasInpaintGraph = (
|
||||
addWatermarkerToGraph(state, graph, CANVAS_OUTPUT);
|
||||
}
|
||||
|
||||
addSaveImageNode(state, graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
@ -46,6 +46,7 @@ import {
|
||||
RANGE_OF_SIZE,
|
||||
SEAMLESS,
|
||||
} from './constants';
|
||||
import { addSaveImageNode } from './addSaveImageNode';
|
||||
|
||||
/**
|
||||
* Builds the Canvas tab's Outpaint graph.
|
||||
@ -91,14 +92,10 @@ export const buildCanvasOutpaintGraph = (
|
||||
const { width, height } = state.canvas.boundingBoxDimensions;
|
||||
|
||||
// We may need to set the inpaint width and height to scale the image
|
||||
const {
|
||||
scaledBoundingBoxDimensions,
|
||||
boundingBoxScaleMethod,
|
||||
shouldAutoSave,
|
||||
} = state.canvas;
|
||||
const { scaledBoundingBoxDimensions, boundingBoxScaleMethod } = state.canvas;
|
||||
|
||||
const fp32 = vaePrecision === 'fp32';
|
||||
|
||||
const is_intermediate = true;
|
||||
const isUsingScaledDimensions = ['auto', 'manual'].includes(
|
||||
boundingBoxScaleMethod
|
||||
);
|
||||
@ -115,61 +112,61 @@ export const buildCanvasOutpaintGraph = (
|
||||
[modelLoaderNodeId]: {
|
||||
type: 'main_model_loader',
|
||||
id: modelLoaderNodeId,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
model,
|
||||
},
|
||||
[CLIP_SKIP]: {
|
||||
type: 'clip_skip',
|
||||
id: CLIP_SKIP,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
skipped_layers: clipSkip,
|
||||
},
|
||||
[POSITIVE_CONDITIONING]: {
|
||||
type: 'compel',
|
||||
id: POSITIVE_CONDITIONING,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
prompt: positivePrompt,
|
||||
},
|
||||
[NEGATIVE_CONDITIONING]: {
|
||||
type: 'compel',
|
||||
id: NEGATIVE_CONDITIONING,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
prompt: negativePrompt,
|
||||
},
|
||||
[MASK_FROM_ALPHA]: {
|
||||
type: 'tomask',
|
||||
id: MASK_FROM_ALPHA,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
image: canvasInitImage,
|
||||
},
|
||||
[MASK_COMBINE]: {
|
||||
type: 'mask_combine',
|
||||
id: MASK_COMBINE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
mask2: canvasMaskImage,
|
||||
},
|
||||
[INPAINT_IMAGE]: {
|
||||
type: 'i2l',
|
||||
id: INPAINT_IMAGE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
},
|
||||
[NOISE]: {
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
use_cpu,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[INPAINT_CREATE_MASK]: {
|
||||
type: 'create_denoise_mask',
|
||||
id: INPAINT_CREATE_MASK,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
},
|
||||
[DENOISE_LATENTS]: {
|
||||
type: 'denoise_latents',
|
||||
id: DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
steps: steps,
|
||||
cfg_scale: cfg_scale,
|
||||
scheduler: scheduler,
|
||||
@ -180,18 +177,18 @@ export const buildCanvasOutpaintGraph = (
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
use_cpu,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[CANVAS_COHERENCE_NOISE_INCREMENT]: {
|
||||
type: 'add',
|
||||
id: CANVAS_COHERENCE_NOISE_INCREMENT,
|
||||
b: 1,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[CANVAS_COHERENCE_DENOISE_LATENTS]: {
|
||||
type: 'denoise_latents',
|
||||
id: CANVAS_COHERENCE_DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
steps: canvasCoherenceSteps,
|
||||
cfg_scale: cfg_scale,
|
||||
scheduler: scheduler,
|
||||
@ -201,18 +198,18 @@ export const buildCanvasOutpaintGraph = (
|
||||
[LATENTS_TO_IMAGE]: {
|
||||
type: 'l2i',
|
||||
id: LATENTS_TO_IMAGE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
},
|
||||
[CANVAS_OUTPUT]: {
|
||||
type: 'color_correct',
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate: !shouldAutoSave,
|
||||
is_intermediate,
|
||||
},
|
||||
[RANGE_OF_SIZE]: {
|
||||
type: 'range_of_size',
|
||||
id: RANGE_OF_SIZE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
// seed - must be connected manually
|
||||
// start: 0,
|
||||
size: iterations,
|
||||
@ -221,7 +218,7 @@ export const buildCanvasOutpaintGraph = (
|
||||
[ITERATE]: {
|
||||
type: 'iterate',
|
||||
id: ITERATE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
@ -472,7 +469,7 @@ export const buildCanvasOutpaintGraph = (
|
||||
graph.nodes[INPAINT_INFILL] = {
|
||||
type: 'infill_patchmatch',
|
||||
id: INPAINT_INFILL,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
downscale: infillPatchmatchDownscaleSize,
|
||||
};
|
||||
}
|
||||
@ -481,7 +478,7 @@ export const buildCanvasOutpaintGraph = (
|
||||
graph.nodes[INPAINT_INFILL] = {
|
||||
type: 'infill_lama',
|
||||
id: INPAINT_INFILL,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
};
|
||||
}
|
||||
|
||||
@ -489,7 +486,7 @@ export const buildCanvasOutpaintGraph = (
|
||||
graph.nodes[INPAINT_INFILL] = {
|
||||
type: 'infill_cv2',
|
||||
id: INPAINT_INFILL,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
};
|
||||
}
|
||||
|
||||
@ -497,7 +494,7 @@ export const buildCanvasOutpaintGraph = (
|
||||
graph.nodes[INPAINT_INFILL] = {
|
||||
type: 'infill_tile',
|
||||
id: INPAINT_INFILL,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
tile_size: infillTileSize,
|
||||
};
|
||||
}
|
||||
@ -511,7 +508,7 @@ export const buildCanvasOutpaintGraph = (
|
||||
graph.nodes[INPAINT_IMAGE_RESIZE_UP] = {
|
||||
type: 'img_resize',
|
||||
id: INPAINT_IMAGE_RESIZE_UP,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: scaledWidth,
|
||||
height: scaledHeight,
|
||||
image: canvasInitImage,
|
||||
@ -519,28 +516,28 @@ export const buildCanvasOutpaintGraph = (
|
||||
graph.nodes[MASK_RESIZE_UP] = {
|
||||
type: 'img_resize',
|
||||
id: MASK_RESIZE_UP,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: scaledWidth,
|
||||
height: scaledHeight,
|
||||
};
|
||||
graph.nodes[INPAINT_IMAGE_RESIZE_DOWN] = {
|
||||
type: 'img_resize',
|
||||
id: INPAINT_IMAGE_RESIZE_DOWN,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
graph.nodes[INPAINT_INFILL_RESIZE_DOWN] = {
|
||||
type: 'img_resize',
|
||||
id: INPAINT_INFILL_RESIZE_DOWN,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
graph.nodes[MASK_RESIZE_DOWN] = {
|
||||
type: 'img_resize',
|
||||
id: MASK_RESIZE_DOWN,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
@ -699,7 +696,7 @@ export const buildCanvasOutpaintGraph = (
|
||||
graph.nodes[CANVAS_COHERENCE_INPAINT_CREATE_MASK] = {
|
||||
type: 'create_denoise_mask',
|
||||
id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
};
|
||||
|
||||
@ -746,7 +743,7 @@ export const buildCanvasOutpaintGraph = (
|
||||
graph.nodes[CANVAS_COHERENCE_MASK_EDGE] = {
|
||||
type: 'mask_edge',
|
||||
id: CANVAS_COHERENCE_MASK_EDGE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
edge_blur: maskBlur,
|
||||
edge_size: maskBlur * 2,
|
||||
low_threshold: 100,
|
||||
@ -849,5 +846,7 @@ export const buildCanvasOutpaintGraph = (
|
||||
addWatermarkerToGraph(state, graph, CANVAS_OUTPUT);
|
||||
}
|
||||
|
||||
addSaveImageNode(state, graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
@ -27,6 +27,7 @@ import {
|
||||
SEAMLESS,
|
||||
} from './constants';
|
||||
import { craftSDXLStylePrompt } from './helpers/craftSDXLStylePrompt';
|
||||
import { addSaveImageNode } from './addSaveImageNode';
|
||||
|
||||
/**
|
||||
* Builds the Canvas tab's Image to Image graph.
|
||||
@ -61,14 +62,10 @@ export const buildCanvasSDXLImageToImageGraph = (
|
||||
// The bounding box determines width and height, not the width and height params
|
||||
const { width, height } = state.canvas.boundingBoxDimensions;
|
||||
|
||||
const {
|
||||
scaledBoundingBoxDimensions,
|
||||
boundingBoxScaleMethod,
|
||||
shouldAutoSave,
|
||||
} = state.canvas;
|
||||
const { scaledBoundingBoxDimensions, boundingBoxScaleMethod } = state.canvas;
|
||||
|
||||
const fp32 = vaePrecision === 'fp32';
|
||||
|
||||
const is_intermediate = true;
|
||||
const isUsingScaledDimensions = ['auto', 'manual'].includes(
|
||||
boundingBoxScaleMethod
|
||||
);
|
||||
@ -122,7 +119,7 @@ export const buildCanvasSDXLImageToImageGraph = (
|
||||
[NOISE]: {
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
use_cpu,
|
||||
width: !isUsingScaledDimensions
|
||||
? width
|
||||
@ -134,13 +131,13 @@ export const buildCanvasSDXLImageToImageGraph = (
|
||||
[IMAGE_TO_LATENTS]: {
|
||||
type: 'i2l',
|
||||
id: IMAGE_TO_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
},
|
||||
[SDXL_DENOISE_LATENTS]: {
|
||||
type: 'denoise_latents',
|
||||
id: SDXL_DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
cfg_scale,
|
||||
scheduler,
|
||||
steps,
|
||||
@ -251,7 +248,7 @@ export const buildCanvasSDXLImageToImageGraph = (
|
||||
graph.nodes[IMG2IMG_RESIZE] = {
|
||||
id: IMG2IMG_RESIZE,
|
||||
type: 'img_resize',
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
image: initialImage,
|
||||
width: scaledBoundingBoxDimensions.width,
|
||||
height: scaledBoundingBoxDimensions.height,
|
||||
@ -259,13 +256,13 @@ export const buildCanvasSDXLImageToImageGraph = (
|
||||
graph.nodes[LATENTS_TO_IMAGE] = {
|
||||
id: LATENTS_TO_IMAGE,
|
||||
type: 'l2i',
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
};
|
||||
graph.nodes[CANVAS_OUTPUT] = {
|
||||
id: CANVAS_OUTPUT,
|
||||
type: 'img_resize',
|
||||
is_intermediate: !shouldAutoSave,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
@ -306,7 +303,7 @@ export const buildCanvasSDXLImageToImageGraph = (
|
||||
graph.nodes[CANVAS_OUTPUT] = {
|
||||
type: 'l2i',
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate: !shouldAutoSave,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
};
|
||||
|
||||
@ -403,5 +400,7 @@ export const buildCanvasSDXLImageToImageGraph = (
|
||||
addWatermarkerToGraph(state, graph, CANVAS_OUTPUT);
|
||||
}
|
||||
|
||||
addSaveImageNode(state, graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
@ -46,6 +46,7 @@ import {
|
||||
SEAMLESS,
|
||||
} from './constants';
|
||||
import { craftSDXLStylePrompt } from './helpers/craftSDXLStylePrompt';
|
||||
import { addSaveImageNode } from './addSaveImageNode';
|
||||
|
||||
/**
|
||||
* Builds the Canvas tab's Inpaint graph.
|
||||
@ -94,14 +95,10 @@ export const buildCanvasSDXLInpaintGraph = (
|
||||
const { width, height } = state.canvas.boundingBoxDimensions;
|
||||
|
||||
// We may need to set the inpaint width and height to scale the image
|
||||
const {
|
||||
scaledBoundingBoxDimensions,
|
||||
boundingBoxScaleMethod,
|
||||
shouldAutoSave,
|
||||
} = state.canvas;
|
||||
const { scaledBoundingBoxDimensions, boundingBoxScaleMethod } = state.canvas;
|
||||
|
||||
const fp32 = vaePrecision === 'fp32';
|
||||
|
||||
const is_intermediate = true;
|
||||
const isUsingScaledDimensions = ['auto', 'manual'].includes(
|
||||
boundingBoxScaleMethod
|
||||
);
|
||||
@ -139,32 +136,32 @@ export const buildCanvasSDXLInpaintGraph = (
|
||||
[MASK_BLUR]: {
|
||||
type: 'img_blur',
|
||||
id: MASK_BLUR,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
radius: maskBlur,
|
||||
blur_type: maskBlurMethod,
|
||||
},
|
||||
[INPAINT_IMAGE]: {
|
||||
type: 'i2l',
|
||||
id: INPAINT_IMAGE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
},
|
||||
[NOISE]: {
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
use_cpu,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[INPAINT_CREATE_MASK]: {
|
||||
type: 'create_denoise_mask',
|
||||
id: INPAINT_CREATE_MASK,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
},
|
||||
[SDXL_DENOISE_LATENTS]: {
|
||||
type: 'denoise_latents',
|
||||
id: SDXL_DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
steps: steps,
|
||||
cfg_scale: cfg_scale,
|
||||
scheduler: scheduler,
|
||||
@ -177,18 +174,18 @@ export const buildCanvasSDXLInpaintGraph = (
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
use_cpu,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[CANVAS_COHERENCE_NOISE_INCREMENT]: {
|
||||
type: 'add',
|
||||
id: CANVAS_COHERENCE_NOISE_INCREMENT,
|
||||
b: 1,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[CANVAS_COHERENCE_DENOISE_LATENTS]: {
|
||||
type: 'denoise_latents',
|
||||
id: CANVAS_COHERENCE_DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
steps: canvasCoherenceSteps,
|
||||
cfg_scale: cfg_scale,
|
||||
scheduler: scheduler,
|
||||
@ -198,19 +195,19 @@ export const buildCanvasSDXLInpaintGraph = (
|
||||
[LATENTS_TO_IMAGE]: {
|
||||
type: 'l2i',
|
||||
id: LATENTS_TO_IMAGE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
},
|
||||
[CANVAS_OUTPUT]: {
|
||||
type: 'color_correct',
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate: !shouldAutoSave,
|
||||
is_intermediate,
|
||||
reference: canvasInitImage,
|
||||
},
|
||||
[RANGE_OF_SIZE]: {
|
||||
type: 'range_of_size',
|
||||
id: RANGE_OF_SIZE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
// seed - must be connected manually
|
||||
// start: 0,
|
||||
size: iterations,
|
||||
@ -219,7 +216,7 @@ export const buildCanvasSDXLInpaintGraph = (
|
||||
[ITERATE]: {
|
||||
type: 'iterate',
|
||||
id: ITERATE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
@ -451,7 +448,7 @@ export const buildCanvasSDXLInpaintGraph = (
|
||||
graph.nodes[INPAINT_IMAGE_RESIZE_UP] = {
|
||||
type: 'img_resize',
|
||||
id: INPAINT_IMAGE_RESIZE_UP,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: scaledWidth,
|
||||
height: scaledHeight,
|
||||
image: canvasInitImage,
|
||||
@ -459,7 +456,7 @@ export const buildCanvasSDXLInpaintGraph = (
|
||||
graph.nodes[MASK_RESIZE_UP] = {
|
||||
type: 'img_resize',
|
||||
id: MASK_RESIZE_UP,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: scaledWidth,
|
||||
height: scaledHeight,
|
||||
image: canvasMaskImage,
|
||||
@ -467,14 +464,14 @@ export const buildCanvasSDXLInpaintGraph = (
|
||||
graph.nodes[INPAINT_IMAGE_RESIZE_DOWN] = {
|
||||
type: 'img_resize',
|
||||
id: INPAINT_IMAGE_RESIZE_DOWN,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
graph.nodes[MASK_RESIZE_DOWN] = {
|
||||
type: 'img_resize',
|
||||
id: MASK_RESIZE_DOWN,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
@ -612,7 +609,7 @@ export const buildCanvasSDXLInpaintGraph = (
|
||||
graph.nodes[CANVAS_COHERENCE_INPAINT_CREATE_MASK] = {
|
||||
type: 'create_denoise_mask',
|
||||
id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
};
|
||||
|
||||
@ -665,7 +662,7 @@ export const buildCanvasSDXLInpaintGraph = (
|
||||
graph.nodes[CANVAS_COHERENCE_MASK_EDGE] = {
|
||||
type: 'mask_edge',
|
||||
id: CANVAS_COHERENCE_MASK_EDGE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
edge_blur: maskBlur,
|
||||
edge_size: maskBlur * 2,
|
||||
low_threshold: 100,
|
||||
@ -776,5 +773,7 @@ export const buildCanvasSDXLInpaintGraph = (
|
||||
addWatermarkerToGraph(state, graph, CANVAS_OUTPUT);
|
||||
}
|
||||
|
||||
addSaveImageNode(state, graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
@ -48,6 +48,7 @@ import {
|
||||
SEAMLESS,
|
||||
} from './constants';
|
||||
import { craftSDXLStylePrompt } from './helpers/craftSDXLStylePrompt';
|
||||
import { addSaveImageNode } from './addSaveImageNode';
|
||||
|
||||
/**
|
||||
* Builds the Canvas tab's Outpaint graph.
|
||||
@ -98,14 +99,10 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
const { width, height } = state.canvas.boundingBoxDimensions;
|
||||
|
||||
// We may need to set the inpaint width and height to scale the image
|
||||
const {
|
||||
scaledBoundingBoxDimensions,
|
||||
boundingBoxScaleMethod,
|
||||
shouldAutoSave,
|
||||
} = state.canvas;
|
||||
const { scaledBoundingBoxDimensions, boundingBoxScaleMethod } = state.canvas;
|
||||
|
||||
const fp32 = vaePrecision === 'fp32';
|
||||
|
||||
const is_intermediate = true;
|
||||
const isUsingScaledDimensions = ['auto', 'manual'].includes(
|
||||
boundingBoxScaleMethod
|
||||
);
|
||||
@ -143,37 +140,37 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
[MASK_FROM_ALPHA]: {
|
||||
type: 'tomask',
|
||||
id: MASK_FROM_ALPHA,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
image: canvasInitImage,
|
||||
},
|
||||
[MASK_COMBINE]: {
|
||||
type: 'mask_combine',
|
||||
id: MASK_COMBINE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
mask2: canvasMaskImage,
|
||||
},
|
||||
[INPAINT_IMAGE]: {
|
||||
type: 'i2l',
|
||||
id: INPAINT_IMAGE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
},
|
||||
[NOISE]: {
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
use_cpu,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[INPAINT_CREATE_MASK]: {
|
||||
type: 'create_denoise_mask',
|
||||
id: INPAINT_CREATE_MASK,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
},
|
||||
[SDXL_DENOISE_LATENTS]: {
|
||||
type: 'denoise_latents',
|
||||
id: SDXL_DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
steps: steps,
|
||||
cfg_scale: cfg_scale,
|
||||
scheduler: scheduler,
|
||||
@ -186,18 +183,18 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
use_cpu,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[CANVAS_COHERENCE_NOISE_INCREMENT]: {
|
||||
type: 'add',
|
||||
id: CANVAS_COHERENCE_NOISE_INCREMENT,
|
||||
b: 1,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[CANVAS_COHERENCE_DENOISE_LATENTS]: {
|
||||
type: 'denoise_latents',
|
||||
id: CANVAS_COHERENCE_DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
steps: canvasCoherenceSteps,
|
||||
cfg_scale: cfg_scale,
|
||||
scheduler: scheduler,
|
||||
@ -207,18 +204,18 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
[LATENTS_TO_IMAGE]: {
|
||||
type: 'l2i',
|
||||
id: LATENTS_TO_IMAGE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
},
|
||||
[CANVAS_OUTPUT]: {
|
||||
type: 'color_correct',
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate: !shouldAutoSave,
|
||||
is_intermediate,
|
||||
},
|
||||
[RANGE_OF_SIZE]: {
|
||||
type: 'range_of_size',
|
||||
id: RANGE_OF_SIZE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
// seed - must be connected manually
|
||||
// start: 0,
|
||||
size: iterations,
|
||||
@ -227,7 +224,7 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
[ITERATE]: {
|
||||
type: 'iterate',
|
||||
id: ITERATE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
@ -487,7 +484,7 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
graph.nodes[INPAINT_INFILL] = {
|
||||
type: 'infill_patchmatch',
|
||||
id: INPAINT_INFILL,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
downscale: infillPatchmatchDownscaleSize,
|
||||
};
|
||||
}
|
||||
@ -496,7 +493,7 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
graph.nodes[INPAINT_INFILL] = {
|
||||
type: 'infill_lama',
|
||||
id: INPAINT_INFILL,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
};
|
||||
}
|
||||
|
||||
@ -504,7 +501,7 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
graph.nodes[INPAINT_INFILL] = {
|
||||
type: 'infill_cv2',
|
||||
id: INPAINT_INFILL,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
};
|
||||
}
|
||||
|
||||
@ -512,7 +509,7 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
graph.nodes[INPAINT_INFILL] = {
|
||||
type: 'infill_tile',
|
||||
id: INPAINT_INFILL,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
tile_size: infillTileSize,
|
||||
};
|
||||
}
|
||||
@ -526,7 +523,7 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
graph.nodes[INPAINT_IMAGE_RESIZE_UP] = {
|
||||
type: 'img_resize',
|
||||
id: INPAINT_IMAGE_RESIZE_UP,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: scaledWidth,
|
||||
height: scaledHeight,
|
||||
image: canvasInitImage,
|
||||
@ -534,28 +531,28 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
graph.nodes[MASK_RESIZE_UP] = {
|
||||
type: 'img_resize',
|
||||
id: MASK_RESIZE_UP,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: scaledWidth,
|
||||
height: scaledHeight,
|
||||
};
|
||||
graph.nodes[INPAINT_IMAGE_RESIZE_DOWN] = {
|
||||
type: 'img_resize',
|
||||
id: INPAINT_IMAGE_RESIZE_DOWN,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
graph.nodes[INPAINT_INFILL_RESIZE_DOWN] = {
|
||||
type: 'img_resize',
|
||||
id: INPAINT_INFILL_RESIZE_DOWN,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
graph.nodes[MASK_RESIZE_DOWN] = {
|
||||
type: 'img_resize',
|
||||
id: MASK_RESIZE_DOWN,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
@ -715,7 +712,7 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
graph.nodes[CANVAS_COHERENCE_INPAINT_CREATE_MASK] = {
|
||||
type: 'create_denoise_mask',
|
||||
id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
};
|
||||
|
||||
@ -762,7 +759,7 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
graph.nodes[CANVAS_COHERENCE_MASK_EDGE] = {
|
||||
type: 'mask_edge',
|
||||
id: CANVAS_COHERENCE_MASK_EDGE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
edge_blur: maskBlur,
|
||||
edge_size: maskBlur * 2,
|
||||
low_threshold: 100,
|
||||
@ -879,5 +876,7 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
addWatermarkerToGraph(state, graph, CANVAS_OUTPUT);
|
||||
}
|
||||
|
||||
addSaveImageNode(state, graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
@ -29,6 +29,7 @@ import {
|
||||
SEAMLESS,
|
||||
} from './constants';
|
||||
import { craftSDXLStylePrompt } from './helpers/craftSDXLStylePrompt';
|
||||
import { addSaveImageNode } from './addSaveImageNode';
|
||||
|
||||
/**
|
||||
* Builds the Canvas tab's Text to Image graph.
|
||||
@ -55,14 +56,10 @@ export const buildCanvasSDXLTextToImageGraph = (
|
||||
// The bounding box determines width and height, not the width and height params
|
||||
const { width, height } = state.canvas.boundingBoxDimensions;
|
||||
|
||||
const {
|
||||
scaledBoundingBoxDimensions,
|
||||
boundingBoxScaleMethod,
|
||||
shouldAutoSave,
|
||||
} = state.canvas;
|
||||
const { scaledBoundingBoxDimensions, boundingBoxScaleMethod } = state.canvas;
|
||||
|
||||
const fp32 = vaePrecision === 'fp32';
|
||||
|
||||
const is_intermediate = true;
|
||||
const isUsingScaledDimensions = ['auto', 'manual'].includes(
|
||||
boundingBoxScaleMethod
|
||||
);
|
||||
@ -94,7 +91,7 @@ export const buildCanvasSDXLTextToImageGraph = (
|
||||
? {
|
||||
type: 't2l_onnx',
|
||||
id: SDXL_DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
cfg_scale,
|
||||
scheduler,
|
||||
steps,
|
||||
@ -102,7 +99,7 @@ export const buildCanvasSDXLTextToImageGraph = (
|
||||
: {
|
||||
type: 'denoise_latents',
|
||||
id: SDXL_DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
cfg_scale,
|
||||
scheduler,
|
||||
steps,
|
||||
@ -131,27 +128,27 @@ export const buildCanvasSDXLTextToImageGraph = (
|
||||
[modelLoaderNodeId]: {
|
||||
type: modelLoaderNodeType,
|
||||
id: modelLoaderNodeId,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
model,
|
||||
},
|
||||
[POSITIVE_CONDITIONING]: {
|
||||
type: isUsingOnnxModel ? 'prompt_onnx' : 'sdxl_compel_prompt',
|
||||
id: POSITIVE_CONDITIONING,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
prompt: positivePrompt,
|
||||
style: craftedPositiveStylePrompt,
|
||||
},
|
||||
[NEGATIVE_CONDITIONING]: {
|
||||
type: isUsingOnnxModel ? 'prompt_onnx' : 'sdxl_compel_prompt',
|
||||
id: NEGATIVE_CONDITIONING,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
prompt: negativePrompt,
|
||||
style: craftedNegativeStylePrompt,
|
||||
},
|
||||
[NOISE]: {
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: !isUsingScaledDimensions
|
||||
? width
|
||||
: scaledBoundingBoxDimensions.width,
|
||||
@ -253,14 +250,14 @@ export const buildCanvasSDXLTextToImageGraph = (
|
||||
graph.nodes[LATENTS_TO_IMAGE] = {
|
||||
id: LATENTS_TO_IMAGE,
|
||||
type: isUsingOnnxModel ? 'l2i_onnx' : 'l2i',
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
};
|
||||
|
||||
graph.nodes[CANVAS_OUTPUT] = {
|
||||
id: CANVAS_OUTPUT,
|
||||
type: 'img_resize',
|
||||
is_intermediate: !shouldAutoSave,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
@ -291,7 +288,7 @@ export const buildCanvasSDXLTextToImageGraph = (
|
||||
graph.nodes[CANVAS_OUTPUT] = {
|
||||
type: isUsingOnnxModel ? 'l2i_onnx' : 'l2i',
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate: !shouldAutoSave,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
};
|
||||
|
||||
@ -383,5 +380,7 @@ export const buildCanvasSDXLTextToImageGraph = (
|
||||
addWatermarkerToGraph(state, graph, CANVAS_OUTPUT);
|
||||
}
|
||||
|
||||
addSaveImageNode(state, graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
@ -10,6 +10,7 @@ import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
||||
import { addDynamicPromptsToGraph } from './addDynamicPromptsToGraph';
|
||||
import { addLoRAsToGraph } from './addLoRAsToGraph';
|
||||
import { addNSFWCheckerToGraph } from './addNSFWCheckerToGraph';
|
||||
import { addSaveImageNode } from './addSaveImageNode';
|
||||
import { addSeamlessToLinearGraph } from './addSeamlessToLinearGraph';
|
||||
import { addVAEToGraph } from './addVAEToGraph';
|
||||
import { addWatermarkerToGraph } from './addWatermarkerToGraph';
|
||||
@ -53,14 +54,10 @@ export const buildCanvasTextToImageGraph = (
|
||||
// The bounding box determines width and height, not the width and height params
|
||||
const { width, height } = state.canvas.boundingBoxDimensions;
|
||||
|
||||
const {
|
||||
scaledBoundingBoxDimensions,
|
||||
boundingBoxScaleMethod,
|
||||
shouldAutoSave,
|
||||
} = state.canvas;
|
||||
const { scaledBoundingBoxDimensions, boundingBoxScaleMethod } = state.canvas;
|
||||
|
||||
const fp32 = vaePrecision === 'fp32';
|
||||
|
||||
const is_intermediate = true;
|
||||
const isUsingScaledDimensions = ['auto', 'manual'].includes(
|
||||
boundingBoxScaleMethod
|
||||
);
|
||||
@ -89,7 +86,7 @@ export const buildCanvasTextToImageGraph = (
|
||||
? {
|
||||
type: 't2l_onnx',
|
||||
id: DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
cfg_scale,
|
||||
scheduler,
|
||||
steps,
|
||||
@ -97,7 +94,7 @@ export const buildCanvasTextToImageGraph = (
|
||||
: {
|
||||
type: 'denoise_latents',
|
||||
id: DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
cfg_scale,
|
||||
scheduler,
|
||||
steps,
|
||||
@ -122,31 +119,31 @@ export const buildCanvasTextToImageGraph = (
|
||||
[modelLoaderNodeId]: {
|
||||
type: modelLoaderNodeType,
|
||||
id: modelLoaderNodeId,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
model,
|
||||
},
|
||||
[CLIP_SKIP]: {
|
||||
type: 'clip_skip',
|
||||
id: CLIP_SKIP,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
skipped_layers: clipSkip,
|
||||
},
|
||||
[POSITIVE_CONDITIONING]: {
|
||||
type: isUsingOnnxModel ? 'prompt_onnx' : 'compel',
|
||||
id: POSITIVE_CONDITIONING,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
prompt: positivePrompt,
|
||||
},
|
||||
[NEGATIVE_CONDITIONING]: {
|
||||
type: isUsingOnnxModel ? 'prompt_onnx' : 'compel',
|
||||
id: NEGATIVE_CONDITIONING,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
prompt: negativePrompt,
|
||||
},
|
||||
[NOISE]: {
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
width: !isUsingScaledDimensions
|
||||
? width
|
||||
: scaledBoundingBoxDimensions.width,
|
||||
@ -239,14 +236,14 @@ export const buildCanvasTextToImageGraph = (
|
||||
graph.nodes[LATENTS_TO_IMAGE] = {
|
||||
id: LATENTS_TO_IMAGE,
|
||||
type: isUsingOnnxModel ? 'l2i_onnx' : 'l2i',
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
};
|
||||
|
||||
graph.nodes[CANVAS_OUTPUT] = {
|
||||
id: CANVAS_OUTPUT,
|
||||
type: 'img_resize',
|
||||
is_intermediate: !shouldAutoSave,
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
@ -277,7 +274,7 @@ export const buildCanvasTextToImageGraph = (
|
||||
graph.nodes[CANVAS_OUTPUT] = {
|
||||
type: isUsingOnnxModel ? 'l2i_onnx' : 'l2i',
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate: !shouldAutoSave,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
};
|
||||
|
||||
@ -356,5 +353,7 @@ export const buildCanvasTextToImageGraph = (
|
||||
addWatermarkerToGraph(state, graph, CANVAS_OUTPUT);
|
||||
}
|
||||
|
||||
addSaveImageNode(state, graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
@ -27,6 +27,7 @@ import {
|
||||
RESIZE,
|
||||
SEAMLESS,
|
||||
} from './constants';
|
||||
import { addSaveImageNode } from './addSaveImageNode';
|
||||
|
||||
/**
|
||||
* Builds the Image to Image tab graph.
|
||||
@ -85,6 +86,7 @@ export const buildLinearImageToImageGraph = (
|
||||
}
|
||||
|
||||
const fp32 = vaePrecision === 'fp32';
|
||||
const is_intermediate = true;
|
||||
|
||||
let modelLoaderNodeId = MAIN_MODEL_LOADER;
|
||||
|
||||
@ -100,31 +102,37 @@ export const buildLinearImageToImageGraph = (
|
||||
type: 'main_model_loader',
|
||||
id: modelLoaderNodeId,
|
||||
model,
|
||||
is_intermediate,
|
||||
},
|
||||
[CLIP_SKIP]: {
|
||||
type: 'clip_skip',
|
||||
id: CLIP_SKIP,
|
||||
skipped_layers: clipSkip,
|
||||
is_intermediate,
|
||||
},
|
||||
[POSITIVE_CONDITIONING]: {
|
||||
type: 'compel',
|
||||
id: POSITIVE_CONDITIONING,
|
||||
prompt: positivePrompt,
|
||||
is_intermediate,
|
||||
},
|
||||
[NEGATIVE_CONDITIONING]: {
|
||||
type: 'compel',
|
||||
id: NEGATIVE_CONDITIONING,
|
||||
prompt: negativePrompt,
|
||||
is_intermediate,
|
||||
},
|
||||
[NOISE]: {
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
use_cpu,
|
||||
is_intermediate,
|
||||
},
|
||||
[LATENTS_TO_IMAGE]: {
|
||||
type: 'l2i',
|
||||
id: LATENTS_TO_IMAGE,
|
||||
fp32,
|
||||
is_intermediate,
|
||||
},
|
||||
[DENOISE_LATENTS]: {
|
||||
type: 'denoise_latents',
|
||||
@ -134,6 +142,7 @@ export const buildLinearImageToImageGraph = (
|
||||
steps,
|
||||
denoising_start: 1 - strength,
|
||||
denoising_end: 1,
|
||||
is_intermediate,
|
||||
},
|
||||
[IMAGE_TO_LATENTS]: {
|
||||
type: 'i2l',
|
||||
@ -143,6 +152,7 @@ export const buildLinearImageToImageGraph = (
|
||||
// image_name: initialImage.image_name,
|
||||
// },
|
||||
fp32,
|
||||
is_intermediate,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
@ -375,5 +385,7 @@ export const buildLinearImageToImageGraph = (
|
||||
addWatermarkerToGraph(state, graph);
|
||||
}
|
||||
|
||||
addSaveImageNode(state, graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
@ -29,6 +29,7 @@ import {
|
||||
SEAMLESS,
|
||||
} from './constants';
|
||||
import { craftSDXLStylePrompt } from './helpers/craftSDXLStylePrompt';
|
||||
import { addSaveImageNode } from './addSaveImageNode';
|
||||
|
||||
/**
|
||||
* Builds the Image to Image tab graph.
|
||||
@ -85,6 +86,7 @@ export const buildLinearSDXLImageToImageGraph = (
|
||||
}
|
||||
|
||||
const fp32 = vaePrecision === 'fp32';
|
||||
const is_intermediate = true;
|
||||
|
||||
// Model Loader ID
|
||||
let modelLoaderNodeId = SDXL_MODEL_LOADER;
|
||||
@ -105,28 +107,33 @@ export const buildLinearSDXLImageToImageGraph = (
|
||||
type: 'sdxl_model_loader',
|
||||
id: modelLoaderNodeId,
|
||||
model,
|
||||
is_intermediate,
|
||||
},
|
||||
[POSITIVE_CONDITIONING]: {
|
||||
type: 'sdxl_compel_prompt',
|
||||
id: POSITIVE_CONDITIONING,
|
||||
prompt: positivePrompt,
|
||||
style: craftedPositiveStylePrompt,
|
||||
is_intermediate,
|
||||
},
|
||||
[NEGATIVE_CONDITIONING]: {
|
||||
type: 'sdxl_compel_prompt',
|
||||
id: NEGATIVE_CONDITIONING,
|
||||
prompt: negativePrompt,
|
||||
style: craftedNegativeStylePrompt,
|
||||
is_intermediate,
|
||||
},
|
||||
[NOISE]: {
|
||||
type: 'noise',
|
||||
id: NOISE,
|
||||
use_cpu,
|
||||
is_intermediate,
|
||||
},
|
||||
[LATENTS_TO_IMAGE]: {
|
||||
type: 'l2i',
|
||||
id: LATENTS_TO_IMAGE,
|
||||
fp32,
|
||||
is_intermediate,
|
||||
},
|
||||
[SDXL_DENOISE_LATENTS]: {
|
||||
type: 'denoise_latents',
|
||||
@ -138,6 +145,7 @@ export const buildLinearSDXLImageToImageGraph = (
|
||||
? Math.min(refinerStart, 1 - strength)
|
||||
: 1 - strength,
|
||||
denoising_end: shouldUseSDXLRefiner ? refinerStart : 1,
|
||||
is_intermediate,
|
||||
},
|
||||
[IMAGE_TO_LATENTS]: {
|
||||
type: 'i2l',
|
||||
@ -147,6 +155,7 @@ export const buildLinearSDXLImageToImageGraph = (
|
||||
// image_name: initialImage.image_name,
|
||||
// },
|
||||
fp32,
|
||||
is_intermediate,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
@ -398,5 +407,7 @@ export const buildLinearSDXLImageToImageGraph = (
|
||||
addWatermarkerToGraph(state, graph);
|
||||
}
|
||||
|
||||
addSaveImageNode(state, graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
@ -23,6 +23,7 @@ import {
|
||||
SEAMLESS,
|
||||
} from './constants';
|
||||
import { craftSDXLStylePrompt } from './helpers/craftSDXLStylePrompt';
|
||||
import { addSaveImageNode } from './addSaveImageNode';
|
||||
|
||||
export const buildLinearSDXLTextToImageGraph = (
|
||||
state: RootState
|
||||
@ -56,13 +57,13 @@ export const buildLinearSDXLTextToImageGraph = (
|
||||
const use_cpu = shouldUseNoiseSettings
|
||||
? shouldUseCpuNoise
|
||||
: initialGenerationState.shouldUseCpuNoise;
|
||||
|
||||
if (!model) {
|
||||
log.error('No model found in state');
|
||||
throw new Error('No model found in state');
|
||||
}
|
||||
|
||||
const fp32 = vaePrecision === 'fp32';
|
||||
const is_intermediate = true;
|
||||
|
||||
// Construct Style Prompt
|
||||
const { craftedPositiveStylePrompt, craftedNegativeStylePrompt } =
|
||||
@ -88,18 +89,21 @@ export const buildLinearSDXLTextToImageGraph = (
|
||||
type: 'sdxl_model_loader',
|
||||
id: modelLoaderNodeId,
|
||||
model,
|
||||
is_intermediate,
|
||||
},
|
||||
[POSITIVE_CONDITIONING]: {
|
||||
type: 'sdxl_compel_prompt',
|
||||
id: POSITIVE_CONDITIONING,
|
||||
prompt: positivePrompt,
|
||||
style: craftedPositiveStylePrompt,
|
||||
is_intermediate,
|
||||
},
|
||||
[NEGATIVE_CONDITIONING]: {
|
||||
type: 'sdxl_compel_prompt',
|
||||
id: NEGATIVE_CONDITIONING,
|
||||
prompt: negativePrompt,
|
||||
style: craftedNegativeStylePrompt,
|
||||
is_intermediate,
|
||||
},
|
||||
[NOISE]: {
|
||||
type: 'noise',
|
||||
@ -107,6 +111,7 @@ export const buildLinearSDXLTextToImageGraph = (
|
||||
width,
|
||||
height,
|
||||
use_cpu,
|
||||
is_intermediate,
|
||||
},
|
||||
[SDXL_DENOISE_LATENTS]: {
|
||||
type: 'denoise_latents',
|
||||
@ -116,11 +121,13 @@ export const buildLinearSDXLTextToImageGraph = (
|
||||
steps,
|
||||
denoising_start: 0,
|
||||
denoising_end: shouldUseSDXLRefiner ? refinerStart : 1,
|
||||
is_intermediate,
|
||||
},
|
||||
[LATENTS_TO_IMAGE]: {
|
||||
type: 'l2i',
|
||||
id: LATENTS_TO_IMAGE,
|
||||
fp32,
|
||||
is_intermediate,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
@ -291,5 +298,7 @@ export const buildLinearSDXLTextToImageGraph = (
|
||||
addWatermarkerToGraph(state, graph);
|
||||
}
|
||||
|
||||
addSaveImageNode(state, graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
@ -26,6 +26,7 @@ import {
|
||||
SEAMLESS,
|
||||
TEXT_TO_IMAGE_GRAPH,
|
||||
} from './constants';
|
||||
import { addSaveImageNode } from './addSaveImageNode';
|
||||
|
||||
export const buildLinearTextToImageGraph = (
|
||||
state: RootState
|
||||
@ -58,7 +59,7 @@ export const buildLinearTextToImageGraph = (
|
||||
}
|
||||
|
||||
const fp32 = vaePrecision === 'fp32';
|
||||
|
||||
const is_intermediate = true;
|
||||
const isUsingOnnxModel = model.model_type === 'onnx';
|
||||
|
||||
let modelLoaderNodeId = isUsingOnnxModel
|
||||
@ -74,7 +75,7 @@ export const buildLinearTextToImageGraph = (
|
||||
? {
|
||||
type: 't2l_onnx',
|
||||
id: DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
cfg_scale,
|
||||
scheduler,
|
||||
steps,
|
||||
@ -82,7 +83,7 @@ export const buildLinearTextToImageGraph = (
|
||||
: {
|
||||
type: 'denoise_latents',
|
||||
id: DENOISE_LATENTS,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
cfg_scale,
|
||||
scheduler,
|
||||
steps,
|
||||
@ -108,26 +109,26 @@ export const buildLinearTextToImageGraph = (
|
||||
[modelLoaderNodeId]: {
|
||||
type: modelLoaderNodeType,
|
||||
id: modelLoaderNodeId,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
model,
|
||||
},
|
||||
[CLIP_SKIP]: {
|
||||
type: 'clip_skip',
|
||||
id: CLIP_SKIP,
|
||||
skipped_layers: clipSkip,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[POSITIVE_CONDITIONING]: {
|
||||
type: isUsingOnnxModel ? 'prompt_onnx' : 'compel',
|
||||
id: POSITIVE_CONDITIONING,
|
||||
prompt: positivePrompt,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[NEGATIVE_CONDITIONING]: {
|
||||
type: isUsingOnnxModel ? 'prompt_onnx' : 'compel',
|
||||
id: NEGATIVE_CONDITIONING,
|
||||
prompt: negativePrompt,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[NOISE]: {
|
||||
type: 'noise',
|
||||
@ -135,13 +136,14 @@ export const buildLinearTextToImageGraph = (
|
||||
width,
|
||||
height,
|
||||
use_cpu,
|
||||
is_intermediate: true,
|
||||
is_intermediate,
|
||||
},
|
||||
[t2lNode.id]: t2lNode,
|
||||
[LATENTS_TO_IMAGE]: {
|
||||
type: isUsingOnnxModel ? 'l2i_onnx' : 'l2i',
|
||||
id: LATENTS_TO_IMAGE,
|
||||
fp32,
|
||||
is_intermediate,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
@ -293,5 +295,7 @@ export const buildLinearTextToImageGraph = (
|
||||
addWatermarkerToGraph(state, graph);
|
||||
}
|
||||
|
||||
addSaveImageNode(state, graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
@ -55,6 +55,9 @@ export const buildNodesGraph = (nodesState: NodesState): Graph => {
|
||||
{} as Record<Exclude<string, 'id' | 'type'>, unknown>
|
||||
);
|
||||
|
||||
// add reserved use_cache
|
||||
transformedInputs['use_cache'] = node.data.useCache;
|
||||
|
||||
// Build this specific node
|
||||
const graphNode = {
|
||||
type,
|
||||
|
@ -3,6 +3,7 @@ export const POSITIVE_CONDITIONING = 'positive_conditioning';
|
||||
export const NEGATIVE_CONDITIONING = 'negative_conditioning';
|
||||
export const DENOISE_LATENTS = 'denoise_latents';
|
||||
export const LATENTS_TO_IMAGE = 'latents_to_image';
|
||||
export const SAVE_IMAGE = 'save_image';
|
||||
export const NSFW_CHECKER = 'nsfw_checker';
|
||||
export const WATERMARKER = 'invisible_watermark';
|
||||
export const NOISE = 'noise';
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
} from '../types/types';
|
||||
import { buildInputFieldTemplate, getFieldType } from './fieldTemplateBuilders';
|
||||
|
||||
const RESERVED_INPUT_FIELD_NAMES = ['id', 'type', 'metadata'];
|
||||
const RESERVED_INPUT_FIELD_NAMES = ['id', 'type', 'metadata', 'use_cache'];
|
||||
const RESERVED_OUTPUT_FIELD_NAMES = ['type'];
|
||||
const RESERVED_FIELD_TYPES = [
|
||||
'WorkflowField',
|
||||
@ -235,6 +235,8 @@ export const parseSchema = (
|
||||
{} as Record<string, OutputFieldTemplate>
|
||||
);
|
||||
|
||||
const useCache = schema.properties.use_cache.default;
|
||||
|
||||
const invocation: InvocationTemplate = {
|
||||
title,
|
||||
type,
|
||||
@ -244,6 +246,7 @@ export const parseSchema = (
|
||||
outputType,
|
||||
inputs,
|
||||
outputs,
|
||||
useCache,
|
||||
};
|
||||
|
||||
Object.assign(invocationsAccumulator, { [type]: invocation });
|
||||
|
988
invokeai/frontend/web/src/services/api/schema.d.ts
vendored
988
invokeai/frontend/web/src/services/api/schema.d.ts
vendored
File diff suppressed because one or more lines are too long
@ -132,6 +132,7 @@ export type DivideInvocation = s['DivideInvocation'];
|
||||
export type ImageNSFWBlurInvocation = s['ImageNSFWBlurInvocation'];
|
||||
export type ImageWatermarkInvocation = s['ImageWatermarkInvocation'];
|
||||
export type SeamlessModeInvocation = s['SeamlessModeInvocation'];
|
||||
export type SaveImageInvocation = s['SaveImageInvocation'];
|
||||
|
||||
// ControlNet Nodes
|
||||
export type ControlNetInvocation = s['ControlNetInvocation'];
|
||||
|
@ -1,5 +1,9 @@
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
|
||||
from invokeai.app.services.invocation_cache.invocation_cache_memory import MemoryInvocationCache
|
||||
|
||||
# This import must happen before other invoke imports or test in other files(!!) break
|
||||
from .test_nodes import ( # isort: split
|
||||
PromptCollectionTestInvocation,
|
||||
@ -42,7 +46,7 @@ def mock_services() -> InvocationServices:
|
||||
return InvocationServices(
|
||||
model_manager=None, # type: ignore
|
||||
events=TestEventService(),
|
||||
logger=None, # type: ignore
|
||||
logger=logging, # type: ignore
|
||||
images=None, # type: ignore
|
||||
latents=None, # type: ignore
|
||||
boards=None, # type: ignore
|
||||
@ -53,6 +57,7 @@ def mock_services() -> InvocationServices:
|
||||
performance_statistics=InvocationStatsService(graph_execution_manager),
|
||||
processor=DefaultInvocationProcessor(),
|
||||
configuration=None, # type: ignore
|
||||
invocation_cache=MemoryInvocationCache(), # type: ignore
|
||||
)
|
||||
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
|
||||
from invokeai.app.services.graph import Graph, GraphExecutionState, LibraryGraph
|
||||
from invokeai.app.services.invocation_cache.invocation_cache_memory import MemoryInvocationCache
|
||||
from invokeai.app.services.invocation_queue import MemoryInvocationQueue
|
||||
from invokeai.app.services.invocation_services import InvocationServices
|
||||
from invokeai.app.services.invocation_stats import InvocationStatsService
|
||||
@ -39,7 +42,7 @@ def mock_services() -> InvocationServices:
|
||||
return InvocationServices(
|
||||
model_manager=None, # type: ignore
|
||||
events=TestEventService(),
|
||||
logger=None, # type: ignore
|
||||
logger=logging, # type: ignore
|
||||
images=None, # type: ignore
|
||||
latents=None, # type: ignore
|
||||
boards=None, # type: ignore
|
||||
@ -50,6 +53,7 @@ def mock_services() -> InvocationServices:
|
||||
processor=DefaultInvocationProcessor(),
|
||||
performance_statistics=InvocationStatsService(graph_execution_manager),
|
||||
configuration=None, # type: ignore
|
||||
invocation_cache=MemoryInvocationCache(),
|
||||
)
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user