mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-01-20 10:58:06 -05:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c439e9681e | ||
|
|
369963791e | ||
|
|
0d94bed9f8 | ||
|
|
cec8ad57a5 | ||
|
|
003c2c28c9 | ||
|
|
661b3056ed | ||
|
|
20f7e448c3 |
@@ -7,6 +7,7 @@ from fastapi.routing import APIRouter
|
|||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
from invokeai.app.invocations.upscale import ESRGAN_MODELS
|
from invokeai.app.invocations.upscale import ESRGAN_MODELS
|
||||||
|
from invokeai.app.services.invocation_cache.invocation_cache_common import InvocationCacheStatus
|
||||||
from invokeai.backend.image_util.invisible_watermark import InvisibleWatermark
|
from invokeai.backend.image_util.invisible_watermark import InvisibleWatermark
|
||||||
from invokeai.backend.image_util.patchmatch import PatchMatch
|
from invokeai.backend.image_util.patchmatch import PatchMatch
|
||||||
from invokeai.backend.image_util.safety_checker import SafetyChecker
|
from invokeai.backend.image_util.safety_checker import SafetyChecker
|
||||||
@@ -113,3 +114,33 @@ async def set_log_level(
|
|||||||
async def clear_invocation_cache() -> None:
|
async def clear_invocation_cache() -> None:
|
||||||
"""Clears the invocation cache"""
|
"""Clears the invocation cache"""
|
||||||
ApiDependencies.invoker.services.invocation_cache.clear()
|
ApiDependencies.invoker.services.invocation_cache.clear()
|
||||||
|
|
||||||
|
|
||||||
|
@app_router.put(
|
||||||
|
"/invocation_cache/enable",
|
||||||
|
operation_id="enable_invocation_cache",
|
||||||
|
responses={200: {"description": "The operation was successful"}},
|
||||||
|
)
|
||||||
|
async def enable_invocation_cache() -> None:
|
||||||
|
"""Clears the invocation cache"""
|
||||||
|
ApiDependencies.invoker.services.invocation_cache.enable()
|
||||||
|
|
||||||
|
|
||||||
|
@app_router.put(
|
||||||
|
"/invocation_cache/disable",
|
||||||
|
operation_id="disable_invocation_cache",
|
||||||
|
responses={200: {"description": "The operation was successful"}},
|
||||||
|
)
|
||||||
|
async def disable_invocation_cache() -> None:
|
||||||
|
"""Clears the invocation cache"""
|
||||||
|
ApiDependencies.invoker.services.invocation_cache.disable()
|
||||||
|
|
||||||
|
|
||||||
|
@app_router.get(
|
||||||
|
"/invocation_cache/status",
|
||||||
|
operation_id="get_invocation_cache_status",
|
||||||
|
responses={200: {"model": InvocationCacheStatus}},
|
||||||
|
)
|
||||||
|
async def get_invocation_cache_status() -> InvocationCacheStatus:
|
||||||
|
"""Clears the invocation cache"""
|
||||||
|
return ApiDependencies.invoker.services.invocation_cache.get_status()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from abc import ABC, abstractmethod
|
|||||||
from typing import Optional, Union
|
from typing import Optional, Union
|
||||||
|
|
||||||
from invokeai.app.invocations.baseinvocation import BaseInvocation, BaseInvocationOutput
|
from invokeai.app.invocations.baseinvocation import BaseInvocation, BaseInvocationOutput
|
||||||
|
from invokeai.app.services.invocation_cache.invocation_cache_common import InvocationCacheStatus
|
||||||
|
|
||||||
|
|
||||||
class InvocationCacheBase(ABC):
|
class InvocationCacheBase(ABC):
|
||||||
@@ -32,7 +33,7 @@ class InvocationCacheBase(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def delete(self, key: Union[int, str]) -> None:
|
def delete(self, key: Union[int, str]) -> None:
|
||||||
"""Deleteds an invocation output from the cache"""
|
"""Deletes an invocation output from the cache"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
@@ -44,3 +45,18 @@ class InvocationCacheBase(ABC):
|
|||||||
def create_key(self, invocation: BaseInvocation) -> int:
|
def create_key(self, invocation: BaseInvocation) -> int:
|
||||||
"""Gets the key for the invocation's cache item"""
|
"""Gets the key for the invocation's cache item"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def disable(self) -> None:
|
||||||
|
"""Disables the cache, overriding the max cache size"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def enable(self) -> None:
|
||||||
|
"""Enables the cache, letting the the max cache size take effect"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_status(self) -> InvocationCacheStatus:
|
||||||
|
"""Returns the status of the cache"""
|
||||||
|
pass
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
|
class InvocationCacheStatus(BaseModel):
|
||||||
|
size: int = Field(description="The current size of the invocation cache")
|
||||||
|
hits: int = Field(description="The number of cache hits")
|
||||||
|
misses: int = Field(description="The number of cache misses")
|
||||||
|
enabled: bool = Field(description="Whether the invocation cache is enabled")
|
||||||
|
max_size: int = Field(description="The maximum size of the invocation cache")
|
||||||
@@ -3,18 +3,25 @@ from typing import Optional, Union
|
|||||||
|
|
||||||
from invokeai.app.invocations.baseinvocation import BaseInvocation, BaseInvocationOutput
|
from invokeai.app.invocations.baseinvocation import BaseInvocation, BaseInvocationOutput
|
||||||
from invokeai.app.services.invocation_cache.invocation_cache_base import InvocationCacheBase
|
from invokeai.app.services.invocation_cache.invocation_cache_base import InvocationCacheBase
|
||||||
|
from invokeai.app.services.invocation_cache.invocation_cache_common import InvocationCacheStatus
|
||||||
from invokeai.app.services.invoker import Invoker
|
from invokeai.app.services.invoker import Invoker
|
||||||
|
|
||||||
|
|
||||||
class MemoryInvocationCache(InvocationCacheBase):
|
class MemoryInvocationCache(InvocationCacheBase):
|
||||||
__cache: dict[Union[int, str], tuple[BaseInvocationOutput, str]]
|
__cache: dict[Union[int, str], tuple[BaseInvocationOutput, str]]
|
||||||
__max_cache_size: int
|
__max_cache_size: int
|
||||||
|
__disabled: bool
|
||||||
|
__hits: int
|
||||||
|
__misses: int
|
||||||
__cache_ids: Queue
|
__cache_ids: Queue
|
||||||
__invoker: Invoker
|
__invoker: Invoker
|
||||||
|
|
||||||
def __init__(self, max_cache_size: int = 0) -> None:
|
def __init__(self, max_cache_size: int = 0) -> None:
|
||||||
self.__cache = dict()
|
self.__cache = dict()
|
||||||
self.__max_cache_size = max_cache_size
|
self.__max_cache_size = max_cache_size
|
||||||
|
self.__disabled = False
|
||||||
|
self.__hits = 0
|
||||||
|
self.__misses = 0
|
||||||
self.__cache_ids = Queue()
|
self.__cache_ids = Queue()
|
||||||
|
|
||||||
def start(self, invoker: Invoker) -> None:
|
def start(self, invoker: Invoker) -> None:
|
||||||
@@ -25,15 +32,17 @@ class MemoryInvocationCache(InvocationCacheBase):
|
|||||||
self.__invoker.services.latents.on_deleted(self._delete_by_match)
|
self.__invoker.services.latents.on_deleted(self._delete_by_match)
|
||||||
|
|
||||||
def get(self, key: Union[int, str]) -> Optional[BaseInvocationOutput]:
|
def get(self, key: Union[int, str]) -> Optional[BaseInvocationOutput]:
|
||||||
if self.__max_cache_size == 0:
|
if self.__max_cache_size == 0 or self.__disabled:
|
||||||
return
|
return
|
||||||
|
|
||||||
item = self.__cache.get(key, None)
|
item = self.__cache.get(key, None)
|
||||||
if item is not None:
|
if item is not None:
|
||||||
|
self.__hits += 1
|
||||||
return item[0]
|
return item[0]
|
||||||
|
self.__misses += 1
|
||||||
|
|
||||||
def save(self, key: Union[int, str], invocation_output: BaseInvocationOutput) -> None:
|
def save(self, key: Union[int, str], invocation_output: BaseInvocationOutput) -> None:
|
||||||
if self.__max_cache_size == 0:
|
if self.__max_cache_size == 0 or self.__disabled:
|
||||||
return
|
return
|
||||||
|
|
||||||
if key not in self.__cache:
|
if key not in self.__cache:
|
||||||
@@ -47,25 +56,46 @@ class MemoryInvocationCache(InvocationCacheBase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def delete(self, key: Union[int, str]) -> None:
|
def delete(self, key: Union[int, str]) -> None:
|
||||||
if self.__max_cache_size == 0:
|
if self.__max_cache_size == 0 or self.__disabled:
|
||||||
return
|
return
|
||||||
|
|
||||||
if key in self.__cache:
|
if key in self.__cache:
|
||||||
del self.__cache[key]
|
del self.__cache[key]
|
||||||
|
|
||||||
def clear(self, *args, **kwargs) -> None:
|
def clear(self, *args, **kwargs) -> None:
|
||||||
if self.__max_cache_size == 0:
|
if self.__max_cache_size == 0 or self.__disabled:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.__cache.clear()
|
self.__cache.clear()
|
||||||
self.__cache_ids = Queue()
|
self.__cache_ids = Queue()
|
||||||
|
self.__misses = 0
|
||||||
|
self.__hits = 0
|
||||||
|
|
||||||
def create_key(self, invocation: BaseInvocation) -> int:
|
def create_key(self, invocation: BaseInvocation) -> int:
|
||||||
return hash(invocation.json(exclude={"id"}))
|
return hash(invocation.json(exclude={"id"}))
|
||||||
|
|
||||||
def _delete_by_match(self, to_match: str) -> None:
|
def disable(self) -> None:
|
||||||
if self.__max_cache_size == 0:
|
if self.__max_cache_size == 0:
|
||||||
return
|
return
|
||||||
|
self.__disabled = True
|
||||||
|
|
||||||
|
def enable(self) -> None:
|
||||||
|
if self.__max_cache_size == 0:
|
||||||
|
return
|
||||||
|
self.__disabled = False
|
||||||
|
|
||||||
|
def get_status(self) -> InvocationCacheStatus:
|
||||||
|
return InvocationCacheStatus(
|
||||||
|
hits=self.__hits,
|
||||||
|
misses=self.__misses,
|
||||||
|
enabled=not self.__disabled and self.__max_cache_size > 0,
|
||||||
|
size=len(self.__cache),
|
||||||
|
max_size=self.__max_cache_size,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _delete_by_match(self, to_match: str) -> None:
|
||||||
|
if self.__max_cache_size == 0 or self.__disabled:
|
||||||
|
return
|
||||||
|
|
||||||
keys_to_delete = set()
|
keys_to_delete = set()
|
||||||
for key, value_tuple in self.__cache.items():
|
for key, value_tuple in self.__cache.items():
|
||||||
|
|||||||
@@ -162,15 +162,15 @@ class SessionQueueItemWithoutGraph(BaseModel):
|
|||||||
session_id: str = Field(
|
session_id: str = Field(
|
||||||
description="The ID of the session associated with this queue item. The session doesn't exist in graph_executions until the queue item is executed."
|
description="The ID of the session associated with this queue item. The session doesn't exist in graph_executions until the queue item is executed."
|
||||||
)
|
)
|
||||||
field_values: Optional[list[NodeFieldValue]] = Field(
|
|
||||||
default=None, description="The field values that were used for this queue item"
|
|
||||||
)
|
|
||||||
queue_id: str = Field(description="The id of the queue with which this item is associated")
|
|
||||||
error: Optional[str] = Field(default=None, description="The error message if this queue item errored")
|
error: Optional[str] = Field(default=None, description="The error message if this queue item errored")
|
||||||
created_at: Union[datetime.datetime, str] = Field(description="When this queue item was created")
|
created_at: Union[datetime.datetime, str] = Field(description="When this queue item was created")
|
||||||
updated_at: Union[datetime.datetime, str] = Field(description="When this queue item was updated")
|
updated_at: Union[datetime.datetime, str] = Field(description="When this queue item was updated")
|
||||||
started_at: Optional[Union[datetime.datetime, str]] = Field(description="When this queue item was started")
|
started_at: Optional[Union[datetime.datetime, str]] = Field(description="When this queue item was started")
|
||||||
completed_at: Optional[Union[datetime.datetime, str]] = Field(description="When this queue item was completed")
|
completed_at: Optional[Union[datetime.datetime, str]] = Field(description="When this queue item was completed")
|
||||||
|
queue_id: str = Field(description="The id of the queue with which this item is associated")
|
||||||
|
field_values: Optional[list[NodeFieldValue]] = Field(
|
||||||
|
default=None, description="The field values that were used for this queue item"
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, queue_item_dict: dict) -> "SessionQueueItemDTO":
|
def from_dict(cls, queue_item_dict: dict) -> "SessionQueueItemDTO":
|
||||||
|
|||||||
169
invokeai/frontend/web/dist/assets/App-61ae6f9e.js
vendored
Normal file
169
invokeai/frontend/web/dist/assets/App-61ae6f9e.js
vendored
Normal file
File diff suppressed because one or more lines are too long
169
invokeai/frontend/web/dist/assets/App-dbf8f111.js
vendored
169
invokeai/frontend/web/dist/assets/App-dbf8f111.js
vendored
File diff suppressed because one or more lines are too long
310
invokeai/frontend/web/dist/assets/ThemeLocaleProvider-9f721f69.js
vendored
Normal file
310
invokeai/frontend/web/dist/assets/ThemeLocaleProvider-9f721f69.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
128
invokeai/frontend/web/dist/assets/index-eac60e23.js
vendored
Normal file
128
invokeai/frontend/web/dist/assets/index-eac60e23.js
vendored
Normal file
File diff suppressed because one or more lines are too long
128
invokeai/frontend/web/dist/assets/index-f6c3f475.js
vendored
128
invokeai/frontend/web/dist/assets/index-f6c3f475.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
invokeai/frontend/web/dist/assets/menu-f40e1624.js
vendored
Normal file
1
invokeai/frontend/web/dist/assets/menu-f40e1624.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
invokeai/frontend/web/dist/index.html
vendored
2
invokeai/frontend/web/dist/index.html
vendored
@@ -12,7 +12,7 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script type="module" crossorigin src="./assets/index-f6c3f475.js"></script>
|
<script type="module" crossorigin src="./assets/index-eac60e23.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body dir="ltr">
|
<body dir="ltr">
|
||||||
|
|||||||
254
invokeai/frontend/web/dist/locales/en.json
vendored
254
invokeai/frontend/web/dist/locales/en.json
vendored
@@ -13,14 +13,15 @@
|
|||||||
"reset": "Reset",
|
"reset": "Reset",
|
||||||
"rotateClockwise": "Rotate Clockwise",
|
"rotateClockwise": "Rotate Clockwise",
|
||||||
"rotateCounterClockwise": "Rotate Counter-Clockwise",
|
"rotateCounterClockwise": "Rotate Counter-Clockwise",
|
||||||
"showGallery": "Show Gallery",
|
"showGalleryPanel": "Show Gallery Panel",
|
||||||
"showOptionsPanel": "Show Side Panel",
|
"showOptionsPanel": "Show Side Panel",
|
||||||
"toggleAutoscroll": "Toggle autoscroll",
|
"toggleAutoscroll": "Toggle autoscroll",
|
||||||
"toggleLogViewer": "Toggle Log Viewer",
|
"toggleLogViewer": "Toggle Log Viewer",
|
||||||
"uploadImage": "Upload Image",
|
"uploadImage": "Upload Image",
|
||||||
"useThisParameter": "Use this parameter",
|
"useThisParameter": "Use this parameter",
|
||||||
"zoomIn": "Zoom In",
|
"zoomIn": "Zoom In",
|
||||||
"zoomOut": "Zoom Out"
|
"zoomOut": "Zoom Out",
|
||||||
|
"loadMore": "Load More"
|
||||||
},
|
},
|
||||||
"boards": {
|
"boards": {
|
||||||
"addBoard": "Add Board",
|
"addBoard": "Add Board",
|
||||||
@@ -110,6 +111,7 @@
|
|||||||
"statusModelChanged": "Model Changed",
|
"statusModelChanged": "Model Changed",
|
||||||
"statusModelConverted": "Model Converted",
|
"statusModelConverted": "Model Converted",
|
||||||
"statusPreparing": "Preparing",
|
"statusPreparing": "Preparing",
|
||||||
|
"statusProcessing": "Processing",
|
||||||
"statusProcessingCanceled": "Processing Canceled",
|
"statusProcessingCanceled": "Processing Canceled",
|
||||||
"statusProcessingComplete": "Processing Complete",
|
"statusProcessingComplete": "Processing Complete",
|
||||||
"statusRestoringFaces": "Restoring Faces",
|
"statusRestoringFaces": "Restoring Faces",
|
||||||
@@ -203,6 +205,81 @@
|
|||||||
"incompatibleModel": "Incompatible base model:",
|
"incompatibleModel": "Incompatible base model:",
|
||||||
"noMatchingEmbedding": "No matching Embeddings"
|
"noMatchingEmbedding": "No matching Embeddings"
|
||||||
},
|
},
|
||||||
|
"queue": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"queueFront": "Add to Front of Queue",
|
||||||
|
"queueBack": "Add to Queue",
|
||||||
|
"queueCountPrediction": "Add {{predicted}} to Queue",
|
||||||
|
"queueMaxExceeded": "Max of {{max_queue_size}} exceeded, would skip {{skip}}",
|
||||||
|
"queuedCount": "{{pending}} Pending",
|
||||||
|
"queueTotal": "{{total}} Total",
|
||||||
|
"queueEmpty": "Queue Empty",
|
||||||
|
"enqueueing": "Queueing Batch",
|
||||||
|
"resume": "Resume",
|
||||||
|
"resumeTooltip": "Resume Processor",
|
||||||
|
"resumeSucceeded": "Processor Resumed",
|
||||||
|
"resumeFailed": "Problem Resuming Processor",
|
||||||
|
"pause": "Pause",
|
||||||
|
"pauseTooltip": "Pause Processor",
|
||||||
|
"pauseSucceeded": "Processor Paused",
|
||||||
|
"pauseFailed": "Problem Pausing Processor",
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"cancelTooltip": "Cancel Current Item",
|
||||||
|
"cancelSucceeded": "Item Canceled",
|
||||||
|
"cancelFailed": "Problem Canceling Item",
|
||||||
|
"prune": "Prune",
|
||||||
|
"pruneTooltip": "Prune {{item_count}} Completed Items",
|
||||||
|
"pruneSucceeded": "Pruned {{item_count}} Completed Items from Queue",
|
||||||
|
"pruneFailed": "Problem Pruning Queue",
|
||||||
|
"clear": "Clear",
|
||||||
|
"clearTooltip": "Cancel and Clear All Items",
|
||||||
|
"clearSucceeded": "Queue Cleared",
|
||||||
|
"clearFailed": "Problem Clearing Queue",
|
||||||
|
"cancelBatch": "Cancel Batch",
|
||||||
|
"cancelItem": "Cancel Item",
|
||||||
|
"cancelBatchSucceeded": "Batch Canceled",
|
||||||
|
"cancelBatchFailed": "Problem Canceling Batch",
|
||||||
|
"clearQueueAlertDialog": "Clearing the queue immediately cancels any processing items and clears the queue entirely.",
|
||||||
|
"clearQueueAlertDialog2": "Are you sure you want to clear the queue?",
|
||||||
|
"current": "Current",
|
||||||
|
"next": "Next",
|
||||||
|
"status": "Status",
|
||||||
|
"total": "Total",
|
||||||
|
"pending": "Pending",
|
||||||
|
"in_progress": "In Progress",
|
||||||
|
"completed": "Completed",
|
||||||
|
"failed": "Failed",
|
||||||
|
"canceled": "Canceled",
|
||||||
|
"completedIn": "Completed in",
|
||||||
|
"batch": "Batch",
|
||||||
|
"item": "Item",
|
||||||
|
"session": "Session",
|
||||||
|
"batchValues": "Batch Values",
|
||||||
|
"notReady": "Unable to Queue",
|
||||||
|
"batchQueued": "Batch Queued",
|
||||||
|
"batchQueuedDesc": "Added {{item_count}} sessions to {{direction}} of queue",
|
||||||
|
"front": "front",
|
||||||
|
"back": "back",
|
||||||
|
"batchFailedToQueue": "Failed to Queue Batch",
|
||||||
|
"graphQueued": "Graph queued",
|
||||||
|
"graphFailedToQueue": "Failed to queue graph"
|
||||||
|
},
|
||||||
|
"invocationCache": {
|
||||||
|
"invocationCache": "Invocation Cache",
|
||||||
|
"cacheSize": "Cache Size",
|
||||||
|
"maxCacheSize": "Max Cache Size",
|
||||||
|
"hits": "Cache Hits",
|
||||||
|
"misses": "Cache Misses",
|
||||||
|
"clear": "Clear",
|
||||||
|
"clearSucceeded": "Invocation Cache Cleared",
|
||||||
|
"clearFailed": "Problem Clearing Invocation Cache",
|
||||||
|
"enable": "Enable",
|
||||||
|
"enableSucceeded": "Invocation Cache Enabled",
|
||||||
|
"enableFailed": "Problem Enabling Invocation Cache",
|
||||||
|
"disable": "Disable",
|
||||||
|
"disableSucceeded": "Invocation Cache Disabled",
|
||||||
|
"disableFailed": "Problem Disabling Invocation Cache"
|
||||||
|
},
|
||||||
"gallery": {
|
"gallery": {
|
||||||
"allImagesLoaded": "All Images Loaded",
|
"allImagesLoaded": "All Images Loaded",
|
||||||
"assets": "Assets",
|
"assets": "Assets",
|
||||||
@@ -641,7 +718,8 @@
|
|||||||
"collectionItemDescription": "TODO",
|
"collectionItemDescription": "TODO",
|
||||||
"colorCodeEdges": "Color-Code Edges",
|
"colorCodeEdges": "Color-Code Edges",
|
||||||
"colorCodeEdgesHelp": "Color-code edges according to their connected fields",
|
"colorCodeEdgesHelp": "Color-code edges according to their connected fields",
|
||||||
"colorCollectionDescription": "A collection of colors.",
|
"colorCollection": "A collection of colors.",
|
||||||
|
"colorCollectionDescription": "TODO",
|
||||||
"colorField": "Color",
|
"colorField": "Color",
|
||||||
"colorFieldDescription": "A RGBA color.",
|
"colorFieldDescription": "A RGBA color.",
|
||||||
"colorPolymorphic": "Color Polymorphic",
|
"colorPolymorphic": "Color Polymorphic",
|
||||||
@@ -688,7 +766,8 @@
|
|||||||
"imageFieldDescription": "Images may be passed between nodes.",
|
"imageFieldDescription": "Images may be passed between nodes.",
|
||||||
"imagePolymorphic": "Image Polymorphic",
|
"imagePolymorphic": "Image Polymorphic",
|
||||||
"imagePolymorphicDescription": "A collection of images.",
|
"imagePolymorphicDescription": "A collection of images.",
|
||||||
"inputFields": "Input Feilds",
|
"inputField": "Input Field",
|
||||||
|
"inputFields": "Input Fields",
|
||||||
"inputMayOnlyHaveOneConnection": "Input may only have one connection",
|
"inputMayOnlyHaveOneConnection": "Input may only have one connection",
|
||||||
"inputNode": "Input Node",
|
"inputNode": "Input Node",
|
||||||
"integer": "Integer",
|
"integer": "Integer",
|
||||||
@@ -706,6 +785,7 @@
|
|||||||
"latentsPolymorphicDescription": "Latents may be passed between nodes.",
|
"latentsPolymorphicDescription": "Latents may be passed between nodes.",
|
||||||
"loadingNodes": "Loading Nodes...",
|
"loadingNodes": "Loading Nodes...",
|
||||||
"loadWorkflow": "Load Workflow",
|
"loadWorkflow": "Load Workflow",
|
||||||
|
"noWorkflow": "No Workflow",
|
||||||
"loRAModelField": "LoRA",
|
"loRAModelField": "LoRA",
|
||||||
"loRAModelFieldDescription": "TODO",
|
"loRAModelFieldDescription": "TODO",
|
||||||
"mainModelField": "Model",
|
"mainModelField": "Model",
|
||||||
@@ -727,14 +807,15 @@
|
|||||||
"noImageFoundState": "No initial image found in state",
|
"noImageFoundState": "No initial image found in state",
|
||||||
"noMatchingNodes": "No matching nodes",
|
"noMatchingNodes": "No matching nodes",
|
||||||
"noNodeSelected": "No node selected",
|
"noNodeSelected": "No node selected",
|
||||||
"noOpacity": "Node Opacity",
|
"nodeOpacity": "Node Opacity",
|
||||||
"noOutputRecorded": "No outputs recorded",
|
"noOutputRecorded": "No outputs recorded",
|
||||||
"noOutputSchemaName": "No output schema name found in ref object",
|
"noOutputSchemaName": "No output schema name found in ref object",
|
||||||
"notes": "Notes",
|
"notes": "Notes",
|
||||||
"notesDescription": "Add notes about your workflow",
|
"notesDescription": "Add notes about your workflow",
|
||||||
"oNNXModelField": "ONNX Model",
|
"oNNXModelField": "ONNX Model",
|
||||||
"oNNXModelFieldDescription": "ONNX model field.",
|
"oNNXModelFieldDescription": "ONNX model field.",
|
||||||
"outputFields": "Output Feilds",
|
"outputField": "Output Field",
|
||||||
|
"outputFields": "Output Fields",
|
||||||
"outputNode": "Output node",
|
"outputNode": "Output node",
|
||||||
"outputSchemaNotFound": "Output schema not found",
|
"outputSchemaNotFound": "Output schema not found",
|
||||||
"pickOne": "Pick One",
|
"pickOne": "Pick One",
|
||||||
@@ -783,6 +864,7 @@
|
|||||||
"unknownNode": "Unknown Node",
|
"unknownNode": "Unknown Node",
|
||||||
"unknownTemplate": "Unknown Template",
|
"unknownTemplate": "Unknown Template",
|
||||||
"unkownInvocation": "Unknown Invocation type",
|
"unkownInvocation": "Unknown Invocation type",
|
||||||
|
"updateNode": "Update Node",
|
||||||
"updateApp": "Update App",
|
"updateApp": "Update App",
|
||||||
"vaeField": "Vae",
|
"vaeField": "Vae",
|
||||||
"vaeFieldDescription": "Vae submodel.",
|
"vaeFieldDescription": "Vae submodel.",
|
||||||
@@ -819,6 +901,7 @@
|
|||||||
},
|
},
|
||||||
"cfgScale": "CFG Scale",
|
"cfgScale": "CFG Scale",
|
||||||
"clipSkip": "CLIP Skip",
|
"clipSkip": "CLIP Skip",
|
||||||
|
"clipSkipWithLayerCount": "CLIP Skip {{layerCount}}",
|
||||||
"closeViewer": "Close Viewer",
|
"closeViewer": "Close Viewer",
|
||||||
"codeformerFidelity": "Fidelity",
|
"codeformerFidelity": "Fidelity",
|
||||||
"coherenceMode": "Mode",
|
"coherenceMode": "Mode",
|
||||||
@@ -857,6 +940,7 @@
|
|||||||
"noInitialImageSelected": "No initial image selected",
|
"noInitialImageSelected": "No initial image selected",
|
||||||
"noModelForControlNet": "ControlNet {{index}} has no model selected.",
|
"noModelForControlNet": "ControlNet {{index}} has no model selected.",
|
||||||
"noModelSelected": "No model selected",
|
"noModelSelected": "No model selected",
|
||||||
|
"noPrompts": "No prompts generated",
|
||||||
"noNodesInGraph": "No nodes in graph",
|
"noNodesInGraph": "No nodes in graph",
|
||||||
"readyToInvoke": "Ready to Invoke",
|
"readyToInvoke": "Ready to Invoke",
|
||||||
"systemBusy": "System busy",
|
"systemBusy": "System busy",
|
||||||
@@ -875,7 +959,12 @@
|
|||||||
"perlinNoise": "Perlin Noise",
|
"perlinNoise": "Perlin Noise",
|
||||||
"positivePromptPlaceholder": "Positive Prompt",
|
"positivePromptPlaceholder": "Positive Prompt",
|
||||||
"randomizeSeed": "Randomize Seed",
|
"randomizeSeed": "Randomize Seed",
|
||||||
|
"manualSeed": "Manual Seed",
|
||||||
|
"randomSeed": "Random Seed",
|
||||||
"restoreFaces": "Restore Faces",
|
"restoreFaces": "Restore Faces",
|
||||||
|
"iterations": "Iterations",
|
||||||
|
"iterationsWithCount_one": "{{count}} Iteration",
|
||||||
|
"iterationsWithCount_other": "{{count}} Iterations",
|
||||||
"scale": "Scale",
|
"scale": "Scale",
|
||||||
"scaleBeforeProcessing": "Scale Before Processing",
|
"scaleBeforeProcessing": "Scale Before Processing",
|
||||||
"scaledHeight": "Scaled H",
|
"scaledHeight": "Scaled H",
|
||||||
@@ -886,13 +975,17 @@
|
|||||||
"seamlessTiling": "Seamless Tiling",
|
"seamlessTiling": "Seamless Tiling",
|
||||||
"seamlessXAxis": "X Axis",
|
"seamlessXAxis": "X Axis",
|
||||||
"seamlessYAxis": "Y Axis",
|
"seamlessYAxis": "Y Axis",
|
||||||
|
"seamlessX": "Seamless X",
|
||||||
|
"seamlessY": "Seamless Y",
|
||||||
|
"seamlessX&Y": "Seamless X & Y",
|
||||||
"seamLowThreshold": "Low",
|
"seamLowThreshold": "Low",
|
||||||
"seed": "Seed",
|
"seed": "Seed",
|
||||||
"seedWeights": "Seed Weights",
|
"seedWeights": "Seed Weights",
|
||||||
|
"imageActions": "Image Actions",
|
||||||
"sendTo": "Send to",
|
"sendTo": "Send to",
|
||||||
"sendToImg2Img": "Send to Image to Image",
|
"sendToImg2Img": "Send to Image to Image",
|
||||||
"sendToUnifiedCanvas": "Send To Unified Canvas",
|
"sendToUnifiedCanvas": "Send To Unified Canvas",
|
||||||
"showOptionsPanel": "Show Options Panel",
|
"showOptionsPanel": "Show Side Panel (O or T)",
|
||||||
"showPreview": "Show Preview",
|
"showPreview": "Show Preview",
|
||||||
"shuffle": "Shuffle Seed",
|
"shuffle": "Shuffle Seed",
|
||||||
"steps": "Steps",
|
"steps": "Steps",
|
||||||
@@ -901,11 +994,13 @@
|
|||||||
"tileSize": "Tile Size",
|
"tileSize": "Tile Size",
|
||||||
"toggleLoopback": "Toggle Loopback",
|
"toggleLoopback": "Toggle Loopback",
|
||||||
"type": "Type",
|
"type": "Type",
|
||||||
"upscale": "Upscale",
|
"upscale": "Upscale (Shift + U)",
|
||||||
"upscaleImage": "Upscale Image",
|
"upscaleImage": "Upscale Image",
|
||||||
"upscaling": "Upscaling",
|
"upscaling": "Upscaling",
|
||||||
"useAll": "Use All",
|
"useAll": "Use All",
|
||||||
"useCpuNoise": "Use CPU Noise",
|
"useCpuNoise": "Use CPU Noise",
|
||||||
|
"cpuNoise": "CPU Noise",
|
||||||
|
"gpuNoise": "GPU Noise",
|
||||||
"useInitImg": "Use Initial Image",
|
"useInitImg": "Use Initial Image",
|
||||||
"usePrompt": "Use Prompt",
|
"usePrompt": "Use Prompt",
|
||||||
"useSeed": "Use Seed",
|
"useSeed": "Use Seed",
|
||||||
@@ -914,11 +1009,20 @@
|
|||||||
"vSymmetryStep": "V Symmetry Step",
|
"vSymmetryStep": "V Symmetry Step",
|
||||||
"width": "Width"
|
"width": "Width"
|
||||||
},
|
},
|
||||||
"prompt": {
|
"dynamicPrompts": {
|
||||||
"combinatorial": "Combinatorial Generation",
|
"combinatorial": "Combinatorial Generation",
|
||||||
"dynamicPrompts": "Dynamic Prompts",
|
"dynamicPrompts": "Dynamic Prompts",
|
||||||
"enableDynamicPrompts": "Enable Dynamic Prompts",
|
"enableDynamicPrompts": "Enable Dynamic Prompts",
|
||||||
"maxPrompts": "Max Prompts"
|
"maxPrompts": "Max Prompts",
|
||||||
|
"promptsWithCount_one": "{{count}} Prompt",
|
||||||
|
"promptsWithCount_other": "{{count}} Prompts",
|
||||||
|
"seedBehaviour": {
|
||||||
|
"label": "Seed Behaviour",
|
||||||
|
"perIterationLabel": "Seed per Iteration",
|
||||||
|
"perIterationDesc": "Use a different seed for each iteration",
|
||||||
|
"perPromptLabel": "Seed per Prompt",
|
||||||
|
"perPromptDesc": "Use a different seed for each prompt"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"sdxl": {
|
"sdxl": {
|
||||||
"cfgScale": "CFG Scale",
|
"cfgScale": "CFG Scale",
|
||||||
@@ -1066,6 +1170,136 @@
|
|||||||
"variations": "Try a variation with a value between 0.1 and 1.0 to change the result for a given seed. Interesting variations of the seed are between 0.1 and 0.3."
|
"variations": "Try a variation with a value between 0.1 and 1.0 to change the result for a given seed. Interesting variations of the seed are between 0.1 and 0.3."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"popovers": {
|
||||||
|
"clipSkip": {
|
||||||
|
"heading": "CLIP Skip",
|
||||||
|
"paragraph": "Choose how many layers of the CLIP model to skip. Certain models are better suited to be used with CLIP Skip."
|
||||||
|
},
|
||||||
|
"compositingBlur": {
|
||||||
|
"heading": "Blur",
|
||||||
|
"paragraph": "The blur radius of the mask."
|
||||||
|
},
|
||||||
|
"compositingBlurMethod": {
|
||||||
|
"heading": "Blur Method",
|
||||||
|
"paragraph": "The method of blur applied to the masked area."
|
||||||
|
},
|
||||||
|
"compositingCoherencePass": {
|
||||||
|
"heading": "Coherence Pass",
|
||||||
|
"paragraph": "Composite the Inpainted/Outpainted images."
|
||||||
|
},
|
||||||
|
"compositingCoherenceMode": {
|
||||||
|
"heading": "Mode",
|
||||||
|
"paragraph": "The mode of the Coherence Pass."
|
||||||
|
},
|
||||||
|
"compositingCoherenceSteps": {
|
||||||
|
"heading": "Steps",
|
||||||
|
"paragraph": "Number of steps in the Coherence Pass. Similar to Denoising Steps."
|
||||||
|
},
|
||||||
|
"compositingStrength": {
|
||||||
|
"heading": "Strength",
|
||||||
|
"paragraph": "Amount of noise added for the Coherence Pass. Similar to Denoising Strength."
|
||||||
|
},
|
||||||
|
"compositingMaskAdjustments": {
|
||||||
|
"heading": "Mask Adjustments",
|
||||||
|
"paragraph": "Adjust the mask."
|
||||||
|
},
|
||||||
|
"controlNetBeginEnd": {
|
||||||
|
"heading": "Begin / End Step Percentage",
|
||||||
|
"paragraph": "Which parts of the denoising process will have the ControlNet applied. ControlNets applied at the start of the process guide composition, and ControlNets applied at the end guide details."
|
||||||
|
},
|
||||||
|
"controlNetControlMode": {
|
||||||
|
"heading": "Control Mode",
|
||||||
|
"paragraph": "Lends more weight to either the prompt or ControlNet."
|
||||||
|
},
|
||||||
|
"controlNetResizeMode": {
|
||||||
|
"heading": "Resize Mode",
|
||||||
|
"paragraph": "How the ControlNet image will be fit to the image generation Ratio"
|
||||||
|
},
|
||||||
|
"controlNetToggle": {
|
||||||
|
"heading": "Enable ControlNet",
|
||||||
|
"paragraph": "ControlNets provide guidance to the generation process, helping create images with controlled composition, structure, or style, depending on the model selected."
|
||||||
|
},
|
||||||
|
"controlNetWeight": {
|
||||||
|
"heading": "Weight",
|
||||||
|
"paragraph": "How strongly the ControlNet will impact the generated image."
|
||||||
|
},
|
||||||
|
"dynamicPromptsToggle": {
|
||||||
|
"heading": "Enable Dynamic Prompts",
|
||||||
|
"paragraph": "Dynamic prompts allow multiple options within a prompt. Dynamic prompts can be used by: {option1|option2|option3}. Combinations of prompts will be randomly generated until the “Images” number has been reached."
|
||||||
|
},
|
||||||
|
"dynamicPromptsCombinatorial": {
|
||||||
|
"heading": "Combinatorial Generation",
|
||||||
|
"paragraph": "Generate an image for every possible combination of Dynamic Prompts until the Max Prompts is reached."
|
||||||
|
},
|
||||||
|
"infillMethod": {
|
||||||
|
"heading": "Infill Method",
|
||||||
|
"paragraph": "Method to infill the selected area."
|
||||||
|
},
|
||||||
|
"lora": {
|
||||||
|
"heading": "LoRA Weight",
|
||||||
|
"paragraph": "Weight of the LoRA. Higher weight will lead to larger impacts on the final image."
|
||||||
|
},
|
||||||
|
"noiseEnable": {
|
||||||
|
"heading": "Enable Noise Settings",
|
||||||
|
"paragraph": "Advanced control over noise generation."
|
||||||
|
},
|
||||||
|
"noiseUseCPU": {
|
||||||
|
"heading": "Use CPU Noise",
|
||||||
|
"paragraph": "Uses the CPU to generate random noise."
|
||||||
|
},
|
||||||
|
"paramCFGScale": {
|
||||||
|
"heading": "CFG Scale",
|
||||||
|
"paragraph": "Controls how much your prompt influences the generation process."
|
||||||
|
},
|
||||||
|
"paramDenoisingStrength": {
|
||||||
|
"heading": "Denoising Strength",
|
||||||
|
"paragraph": "How much noise is added to the input image. 0 will result in an identical image, while 1 will result in a completely new image."
|
||||||
|
},
|
||||||
|
"paramIterations": {
|
||||||
|
"heading": "Iterations",
|
||||||
|
"paragraph": "The number of images to generate. If Dynamic Prompts is enabled, each of the prompts will be generated this many times."
|
||||||
|
},
|
||||||
|
"paramModel": {
|
||||||
|
"heading": "Model",
|
||||||
|
"paragraph": "Model used for the denoising steps. Different models are trained to specialize in producing different aesthetic results and content."
|
||||||
|
},
|
||||||
|
"paramNegativeConditioning": {
|
||||||
|
"heading": "Negative Prompt",
|
||||||
|
"paragraph": "The generation process avoids the concepts in the negative prompt. Use this to exclude qualities or objects from the output. Supports Compel syntax and embeddings."
|
||||||
|
},
|
||||||
|
"paramPositiveConditioning": {
|
||||||
|
"heading": "Positive Prompt",
|
||||||
|
"paragraph": "Guides the generation process. You may use any words or phrases. Supports Compel and Dynamic Prompts syntaxes and embeddings."
|
||||||
|
},
|
||||||
|
"paramRatio": {
|
||||||
|
"heading": "Ratio",
|
||||||
|
"paragraph": "The ratio of the dimensions of the image generated. An image size (in number of pixels) equivalent to 512x512 is recommended for SD1.5 models and a size equivalent to 1024x1024 is recommended for SDXL models."
|
||||||
|
},
|
||||||
|
"paramScheduler": {
|
||||||
|
"heading": "Scheduler",
|
||||||
|
"paragraph": "Scheduler defines how to iteratively add noise to an image or how to update a sample based on a model's output."
|
||||||
|
},
|
||||||
|
"paramSeed": {
|
||||||
|
"heading": "Seed",
|
||||||
|
"paragraph": "Controls the starting noise used for generation. Disable “Random Seed” to produce identical results with the same generation settings."
|
||||||
|
},
|
||||||
|
"paramSteps": {
|
||||||
|
"heading": "Steps",
|
||||||
|
"paragraph": "Number of steps that will be performed in each generation. Higher step counts will typically create better images but will require more generation time."
|
||||||
|
},
|
||||||
|
"paramVAE": {
|
||||||
|
"heading": "VAE",
|
||||||
|
"paragraph": "Model used for translating AI output into the final image."
|
||||||
|
},
|
||||||
|
"paramVAEPrecision": {
|
||||||
|
"heading": "VAE Precision",
|
||||||
|
"paragraph": "The precision used during VAE encoding and decoding. Fp16/Half precision is more efficient, at the expense of minor image variations."
|
||||||
|
},
|
||||||
|
"scaleBeforeProcessing": {
|
||||||
|
"heading": "Scale Before Processing",
|
||||||
|
"paragraph": "Scales the selected area to the size best suited for the model before the image generation process."
|
||||||
|
}
|
||||||
|
},
|
||||||
"ui": {
|
"ui": {
|
||||||
"hideProgressImages": "Hide Progress Images",
|
"hideProgressImages": "Hide Progress Images",
|
||||||
"lockRatio": "Lock Ratio",
|
"lockRatio": "Lock Ratio",
|
||||||
|
|||||||
@@ -264,6 +264,22 @@
|
|||||||
"graphQueued": "Graph queued",
|
"graphQueued": "Graph queued",
|
||||||
"graphFailedToQueue": "Failed to queue graph"
|
"graphFailedToQueue": "Failed to queue graph"
|
||||||
},
|
},
|
||||||
|
"invocationCache": {
|
||||||
|
"invocationCache": "Invocation Cache",
|
||||||
|
"cacheSize": "Cache Size",
|
||||||
|
"maxCacheSize": "Max Cache Size",
|
||||||
|
"hits": "Cache Hits",
|
||||||
|
"misses": "Cache Misses",
|
||||||
|
"clear": "Clear",
|
||||||
|
"clearSucceeded": "Invocation Cache Cleared",
|
||||||
|
"clearFailed": "Problem Clearing Invocation Cache",
|
||||||
|
"enable": "Enable",
|
||||||
|
"enableSucceeded": "Invocation Cache Enabled",
|
||||||
|
"enableFailed": "Problem Enabling Invocation Cache",
|
||||||
|
"disable": "Disable",
|
||||||
|
"disableSucceeded": "Invocation Cache Disabled",
|
||||||
|
"disableFailed": "Problem Disabling Invocation Cache"
|
||||||
|
},
|
||||||
"gallery": {
|
"gallery": {
|
||||||
"allImagesLoaded": "All Images Loaded",
|
"allImagesLoaded": "All Images Loaded",
|
||||||
"assets": "Assets",
|
"assets": "Assets",
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ export type AppFeature =
|
|||||||
| 'multiselect'
|
| 'multiselect'
|
||||||
| 'pauseQueue'
|
| 'pauseQueue'
|
||||||
| 'resumeQueue'
|
| 'resumeQueue'
|
||||||
| 'prependQueue';
|
| 'prependQueue'
|
||||||
|
| 'invocationCache';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A disable-able Stable Diffusion feature
|
* A disable-able Stable Diffusion feature
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ const NodeEditorPanelGroup = () => {
|
|||||||
<PanelGroup
|
<PanelGroup
|
||||||
ref={panelGroupRef}
|
ref={panelGroupRef}
|
||||||
id="workflow-panel-group"
|
id="workflow-panel-group"
|
||||||
|
autoSaveId="workflow-panel-group"
|
||||||
direction="vertical"
|
direction="vertical"
|
||||||
style={{ height: '100%', width: '100%' }}
|
style={{ height: '100%', width: '100%' }}
|
||||||
storage={panelStorage}
|
storage={panelStorage}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||||
import { cloneDeep, forEach, isEqual, map, uniqBy } from 'lodash-es';
|
import { cloneDeep, forEach, isEqual, uniqBy } from 'lodash-es';
|
||||||
import {
|
import {
|
||||||
addEdge,
|
addEdge,
|
||||||
applyEdgeChanges,
|
applyEdgeChanges,
|
||||||
@@ -19,7 +19,6 @@ import {
|
|||||||
XYPosition,
|
XYPosition,
|
||||||
} from 'reactflow';
|
} from 'reactflow';
|
||||||
import { receivedOpenAPISchema } from 'services/api/thunks/schema';
|
import { receivedOpenAPISchema } from 'services/api/thunks/schema';
|
||||||
import { sessionCanceled, sessionInvoked } from 'services/api/thunks/session';
|
|
||||||
import { ImageField } from 'services/api/types';
|
import { ImageField } from 'services/api/types';
|
||||||
import {
|
import {
|
||||||
appSocketGeneratorProgress,
|
appSocketGeneratorProgress,
|
||||||
@@ -869,28 +868,10 @@ const nodesSlice = createSlice({
|
|||||||
node.progressImage = progress_image ?? null;
|
node.progressImage = progress_image ?? null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
builder.addCase(sessionInvoked.fulfilled, (state) => {
|
|
||||||
forEach(state.nodeExecutionStates, (nes) => {
|
|
||||||
nes.status = NodeStatus.PENDING;
|
|
||||||
nes.error = null;
|
|
||||||
nes.progress = null;
|
|
||||||
nes.progressImage = null;
|
|
||||||
nes.outputs = [];
|
|
||||||
});
|
|
||||||
});
|
|
||||||
builder.addCase(sessionCanceled.fulfilled, (state) => {
|
|
||||||
map(state.nodeExecutionStates, (nes) => {
|
|
||||||
if (nes.status === NodeStatus.IN_PROGRESS) {
|
|
||||||
nes.status = NodeStatus.PENDING;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
builder.addCase(appSocketQueueItemStatusChanged, (state, action) => {
|
builder.addCase(appSocketQueueItemStatusChanged, (state, action) => {
|
||||||
if (
|
if (['in_progress'].includes(action.payload.data.status)) {
|
||||||
['completed', 'canceled', 'failed'].includes(action.payload.data.status)
|
|
||||||
) {
|
|
||||||
forEach(state.nodeExecutionStates, (nes) => {
|
forEach(state.nodeExecutionStates, (nes) => {
|
||||||
nes.status = NodeStatus.PENDING;
|
nes.status = NodeStatus.IN_PROGRESS;
|
||||||
nes.error = null;
|
nes.error = null;
|
||||||
nes.progress = null;
|
nes.progress = null;
|
||||||
nes.progressImage = null;
|
nes.progressImage = null;
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import IAIButton from 'common/components/IAIButton';
|
||||||
|
import { memo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useClearInvocationCache } from '../hooks/useClearInvocationCache';
|
||||||
|
|
||||||
|
const ClearInvocationCacheButton = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { clearInvocationCache, isDisabled, isLoading } =
|
||||||
|
useClearInvocationCache();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IAIButton
|
||||||
|
isDisabled={isDisabled}
|
||||||
|
isLoading={isLoading}
|
||||||
|
onClick={clearInvocationCache}
|
||||||
|
>
|
||||||
|
{t('invocationCache.clear')}
|
||||||
|
</IAIButton>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(ClearInvocationCacheButton);
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import { ButtonGroup } from '@chakra-ui/react';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { memo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useGetInvocationCacheStatusQuery } from 'services/api/endpoints/appInfo';
|
||||||
|
import { useGetQueueStatusQuery } from 'services/api/endpoints/queue';
|
||||||
|
import ClearInvocationCacheButton from './ClearInvocationCacheButton';
|
||||||
|
import ToggleInvocationCacheButton from './ToggleInvocationCacheButton';
|
||||||
|
import StatusStatGroup from './common/StatusStatGroup';
|
||||||
|
import StatusStatItem from './common/StatusStatItem';
|
||||||
|
|
||||||
|
const InvocationCacheStatus = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const isConnected = useAppSelector((state) => state.system.isConnected);
|
||||||
|
const { data: queueStatus } = useGetQueueStatusQuery(undefined);
|
||||||
|
const { data: cacheStatus } = useGetInvocationCacheStatusQuery(undefined, {
|
||||||
|
pollingInterval:
|
||||||
|
isConnected &&
|
||||||
|
queueStatus?.processor.is_started &&
|
||||||
|
queueStatus?.queue.pending > 0
|
||||||
|
? 5000
|
||||||
|
: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StatusStatGroup>
|
||||||
|
<StatusStatItem
|
||||||
|
isDisabled={!cacheStatus?.enabled}
|
||||||
|
label={t('invocationCache.cacheSize')}
|
||||||
|
value={cacheStatus?.size ?? 0}
|
||||||
|
/>
|
||||||
|
<StatusStatItem
|
||||||
|
isDisabled={!cacheStatus?.enabled}
|
||||||
|
label={t('invocationCache.hits')}
|
||||||
|
value={cacheStatus?.hits ?? 0}
|
||||||
|
/>
|
||||||
|
<StatusStatItem
|
||||||
|
isDisabled={!cacheStatus?.enabled}
|
||||||
|
label={t('invocationCache.misses')}
|
||||||
|
value={cacheStatus?.misses ?? 0}
|
||||||
|
/>
|
||||||
|
<StatusStatItem
|
||||||
|
isDisabled={!cacheStatus?.enabled}
|
||||||
|
label={t('invocationCache.maxCacheSize')}
|
||||||
|
value={cacheStatus?.max_size ?? 0}
|
||||||
|
/>
|
||||||
|
<ButtonGroup w={24} orientation="vertical" size="xs">
|
||||||
|
<ClearInvocationCacheButton />
|
||||||
|
<ToggleInvocationCacheButton />
|
||||||
|
</ButtonGroup>
|
||||||
|
</StatusStatGroup>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(InvocationCacheStatus);
|
||||||
@@ -1,38 +1,39 @@
|
|||||||
import { Stat, StatGroup, StatLabel, StatNumber } from '@chakra-ui/react';
|
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useGetQueueStatusQuery } from 'services/api/endpoints/queue';
|
import { useGetQueueStatusQuery } from 'services/api/endpoints/queue';
|
||||||
|
import StatusStatGroup from './common/StatusStatGroup';
|
||||||
|
import StatusStatItem from './common/StatusStatItem';
|
||||||
|
|
||||||
const QueueStatus = () => {
|
const QueueStatus = () => {
|
||||||
const { data: queueStatus } = useGetQueueStatusQuery();
|
const { data: queueStatus } = useGetQueueStatusQuery();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<StatGroup alignItems="center" justifyContent="center" w="full" h="full">
|
<StatusStatGroup>
|
||||||
<Stat w={24}>
|
<StatusStatItem
|
||||||
<StatLabel>{t('queue.in_progress')}</StatLabel>
|
label={t('queue.in_progress')}
|
||||||
<StatNumber>{queueStatus?.queue.in_progress ?? 0}</StatNumber>
|
value={queueStatus?.queue.in_progress ?? 0}
|
||||||
</Stat>
|
/>
|
||||||
<Stat w={24}>
|
<StatusStatItem
|
||||||
<StatLabel>{t('queue.pending')}</StatLabel>
|
label={t('queue.pending')}
|
||||||
<StatNumber>{queueStatus?.queue.pending ?? 0}</StatNumber>
|
value={queueStatus?.queue.pending ?? 0}
|
||||||
</Stat>
|
/>
|
||||||
<Stat w={24}>
|
<StatusStatItem
|
||||||
<StatLabel>{t('queue.completed')}</StatLabel>
|
label={t('queue.completed')}
|
||||||
<StatNumber>{queueStatus?.queue.completed ?? 0}</StatNumber>
|
value={queueStatus?.queue.completed ?? 0}
|
||||||
</Stat>
|
/>
|
||||||
<Stat w={24}>
|
<StatusStatItem
|
||||||
<StatLabel>{t('queue.failed')}</StatLabel>
|
label={t('queue.failed')}
|
||||||
<StatNumber>{queueStatus?.queue.failed ?? 0}</StatNumber>
|
value={queueStatus?.queue.failed ?? 0}
|
||||||
</Stat>
|
/>
|
||||||
<Stat w={24}>
|
<StatusStatItem
|
||||||
<StatLabel>{t('queue.canceled')}</StatLabel>
|
label={t('queue.canceled')}
|
||||||
<StatNumber>{queueStatus?.queue.canceled ?? 0}</StatNumber>
|
value={queueStatus?.queue.canceled ?? 0}
|
||||||
</Stat>
|
/>
|
||||||
<Stat w={24}>
|
<StatusStatItem
|
||||||
<StatLabel>{t('queue.total')}</StatLabel>
|
label={t('queue.total')}
|
||||||
<StatNumber>{queueStatus?.queue.total}</StatNumber>
|
value={queueStatus?.queue.total ?? 0}
|
||||||
</Stat>
|
/>
|
||||||
</StatGroup>
|
</StatusStatGroup>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
import { Box, ButtonGroup, Flex } from '@chakra-ui/react';
|
import { Box, Flex } from '@chakra-ui/react';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import ClearQueueButton from './ClearQueueButton';
|
import { useFeatureStatus } from '../../system/hooks/useFeatureStatus';
|
||||||
import PauseProcessorButton from './PauseProcessorButton';
|
import InvocationCacheStatus from './InvocationCacheStatus';
|
||||||
import PruneQueueButton from './PruneQueueButton';
|
|
||||||
import QueueList from './QueueList/QueueList';
|
import QueueList from './QueueList/QueueList';
|
||||||
import QueueStatus from './QueueStatus';
|
import QueueStatus from './QueueStatus';
|
||||||
import ResumeProcessorButton from './ResumeProcessorButton';
|
import QueueTabQueueControls from './QueueTabQueueControls';
|
||||||
import { useFeatureStatus } from '../../system/hooks/useFeatureStatus';
|
|
||||||
|
|
||||||
const QueueTabContent = () => {
|
const QueueTabContent = () => {
|
||||||
const isPauseEnabled = useFeatureStatus('pauseQueue').isFeatureEnabled;
|
const isInvocationCacheEnabled =
|
||||||
const isResumeEnabled = useFeatureStatus('resumeQueue').isFeatureEnabled;
|
useFeatureStatus('invocationCache').isFeatureEnabled;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
@@ -23,33 +21,9 @@ const QueueTabContent = () => {
|
|||||||
gap={2}
|
gap={2}
|
||||||
>
|
>
|
||||||
<Flex gap={2} w="full">
|
<Flex gap={2} w="full">
|
||||||
<Flex layerStyle="second" borderRadius="base" p={2} gap={2}>
|
<QueueTabQueueControls />
|
||||||
{isPauseEnabled || isResumeEnabled ? (
|
<QueueStatus />
|
||||||
<ButtonGroup w={28} orientation="vertical" isAttached size="sm">
|
{isInvocationCacheEnabled && <InvocationCacheStatus />}
|
||||||
{isResumeEnabled ? <ResumeProcessorButton /> : <></>}
|
|
||||||
{isPauseEnabled ? <PauseProcessorButton /> : <></>}
|
|
||||||
</ButtonGroup>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
<ButtonGroup w={28} orientation="vertical" isAttached size="sm">
|
|
||||||
<PruneQueueButton />
|
|
||||||
<ClearQueueButton />
|
|
||||||
</ButtonGroup>
|
|
||||||
</Flex>
|
|
||||||
<Flex
|
|
||||||
layerStyle="second"
|
|
||||||
borderRadius="base"
|
|
||||||
flexDir="column"
|
|
||||||
py={2}
|
|
||||||
px={3}
|
|
||||||
gap={2}
|
|
||||||
>
|
|
||||||
<QueueStatus />
|
|
||||||
</Flex>
|
|
||||||
{/* <QueueStatusCard />
|
|
||||||
<CurrentQueueItemCard />
|
|
||||||
<NextQueueItemCard /> */}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
<Box layerStyle="second" p={2} borderRadius="base" w="full" h="full">
|
<Box layerStyle="second" p={2} borderRadius="base" w="full" h="full">
|
||||||
<QueueList />
|
<QueueList />
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { ButtonGroup, Flex } from '@chakra-ui/react';
|
||||||
|
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||||
|
import { memo } from 'react';
|
||||||
|
import ClearQueueButton from './ClearQueueButton';
|
||||||
|
import PauseProcessorButton from './PauseProcessorButton';
|
||||||
|
import PruneQueueButton from './PruneQueueButton';
|
||||||
|
import ResumeProcessorButton from './ResumeProcessorButton';
|
||||||
|
|
||||||
|
const QueueTabQueueControls = () => {
|
||||||
|
const isPauseEnabled = useFeatureStatus('pauseQueue').isFeatureEnabled;
|
||||||
|
const isResumeEnabled = useFeatureStatus('resumeQueue').isFeatureEnabled;
|
||||||
|
return (
|
||||||
|
<Flex layerStyle="second" borderRadius="base" p={2} gap={2}>
|
||||||
|
{isPauseEnabled || isResumeEnabled ? (
|
||||||
|
<ButtonGroup w={28} orientation="vertical" isAttached size="sm">
|
||||||
|
{isResumeEnabled ? <ResumeProcessorButton /> : <></>}
|
||||||
|
{isPauseEnabled ? <PauseProcessorButton /> : <></>}
|
||||||
|
</ButtonGroup>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
<ButtonGroup w={28} orientation="vertical" isAttached size="sm">
|
||||||
|
<PruneQueueButton />
|
||||||
|
<ClearQueueButton />
|
||||||
|
</ButtonGroup>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(QueueTabQueueControls);
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import IAIButton from 'common/components/IAIButton';
|
||||||
|
import { memo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useGetInvocationCacheStatusQuery } from 'services/api/endpoints/appInfo';
|
||||||
|
import { useDisableInvocationCache } from '../hooks/useDisableInvocationCache';
|
||||||
|
import { useEnableInvocationCache } from '../hooks/useEnableInvocationCache';
|
||||||
|
|
||||||
|
const ToggleInvocationCacheButton = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { data: cacheStatus } = useGetInvocationCacheStatusQuery();
|
||||||
|
|
||||||
|
const {
|
||||||
|
enableInvocationCache,
|
||||||
|
isDisabled: isEnableDisabled,
|
||||||
|
isLoading: isEnableLoading,
|
||||||
|
} = useEnableInvocationCache();
|
||||||
|
|
||||||
|
const {
|
||||||
|
disableInvocationCache,
|
||||||
|
isDisabled: isDisableDisabled,
|
||||||
|
isLoading: isDisableLoading,
|
||||||
|
} = useDisableInvocationCache();
|
||||||
|
|
||||||
|
if (cacheStatus?.enabled) {
|
||||||
|
return (
|
||||||
|
<IAIButton
|
||||||
|
isDisabled={isDisableDisabled}
|
||||||
|
isLoading={isDisableLoading}
|
||||||
|
onClick={disableInvocationCache}
|
||||||
|
>
|
||||||
|
{t('invocationCache.disable')}
|
||||||
|
</IAIButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IAIButton
|
||||||
|
isDisabled={isEnableDisabled}
|
||||||
|
isLoading={isEnableLoading}
|
||||||
|
onClick={enableInvocationCache}
|
||||||
|
>
|
||||||
|
{t('invocationCache.enable')}
|
||||||
|
</IAIButton>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(ToggleInvocationCacheButton);
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import { ButtonGroup, ButtonGroupProps, Flex } from '@chakra-ui/react';
|
|
||||||
import { memo } from 'react';
|
|
||||||
import ClearQueueButton from './ClearQueueButton';
|
|
||||||
import PauseProcessorButton from './PauseProcessorButton';
|
|
||||||
import PruneQueueButton from './PruneQueueButton';
|
|
||||||
import ResumeProcessorButton from './ResumeProcessorButton';
|
|
||||||
|
|
||||||
type Props = ButtonGroupProps & {
|
|
||||||
asIconButtons?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
const VerticalQueueControls = ({ asIconButtons, ...rest }: Props) => {
|
|
||||||
return (
|
|
||||||
<Flex flexDir="column" gap={2}>
|
|
||||||
<ButtonGroup w="full" isAttached {...rest}>
|
|
||||||
<ResumeProcessorButton asIconButton={asIconButtons} />
|
|
||||||
<PauseProcessorButton asIconButton={asIconButtons} />
|
|
||||||
</ButtonGroup>
|
|
||||||
<ButtonGroup w="full" isAttached {...rest}>
|
|
||||||
<PruneQueueButton asIconButton={asIconButtons} />
|
|
||||||
<ClearQueueButton asIconButton={asIconButtons} />
|
|
||||||
</ButtonGroup>
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(VerticalQueueControls);
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { StatGroup, StatGroupProps } from '@chakra-ui/react';
|
||||||
|
import { memo } from 'react';
|
||||||
|
|
||||||
|
const StatusStatGroup = ({ children, ...rest }: StatGroupProps) => (
|
||||||
|
<StatGroup
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
w="full"
|
||||||
|
h="full"
|
||||||
|
layerStyle="second"
|
||||||
|
borderRadius="base"
|
||||||
|
py={2}
|
||||||
|
px={3}
|
||||||
|
gap={6}
|
||||||
|
flexWrap="nowrap"
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</StatGroup>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default memo(StatusStatGroup);
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import {
|
||||||
|
ChakraProps,
|
||||||
|
Stat,
|
||||||
|
StatLabel,
|
||||||
|
StatNumber,
|
||||||
|
StatProps,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import { memo } from 'react';
|
||||||
|
|
||||||
|
const sx: ChakraProps['sx'] = {
|
||||||
|
'&[aria-disabled="true"]': {
|
||||||
|
color: 'base.400',
|
||||||
|
_dark: {
|
||||||
|
color: 'base.500',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
type Props = Omit<StatProps, 'children'> & {
|
||||||
|
label: string;
|
||||||
|
value: string | number;
|
||||||
|
isDisabled?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StatusStatItem = ({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
isDisabled = false,
|
||||||
|
...rest
|
||||||
|
}: Props) => (
|
||||||
|
<Stat
|
||||||
|
flexGrow={1}
|
||||||
|
textOverflow="ellipsis"
|
||||||
|
overflow="hidden"
|
||||||
|
whiteSpace="nowrap"
|
||||||
|
aria-disabled={isDisabled}
|
||||||
|
sx={sx}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
<StatLabel textOverflow="ellipsis" overflow="hidden" whiteSpace="nowrap">
|
||||||
|
{label}
|
||||||
|
</StatLabel>
|
||||||
|
<StatNumber>{value}</StatNumber>
|
||||||
|
</Stat>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default memo(StatusStatItem);
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { addToast } from 'features/system/store/systemSlice';
|
||||||
|
import { useCallback, useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import {
|
||||||
|
useClearInvocationCacheMutation,
|
||||||
|
useGetInvocationCacheStatusQuery,
|
||||||
|
} from 'services/api/endpoints/appInfo';
|
||||||
|
|
||||||
|
export const useClearInvocationCache = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { data: cacheStatus } = useGetInvocationCacheStatusQuery();
|
||||||
|
const isConnected = useAppSelector((state) => state.system.isConnected);
|
||||||
|
const [trigger, { isLoading }] = useClearInvocationCacheMutation({
|
||||||
|
fixedCacheKey: 'clearInvocationCache',
|
||||||
|
});
|
||||||
|
|
||||||
|
const isDisabled = useMemo(
|
||||||
|
() => !cacheStatus?.size || !isConnected,
|
||||||
|
[cacheStatus?.size, isConnected]
|
||||||
|
);
|
||||||
|
|
||||||
|
const clearInvocationCache = useCallback(async () => {
|
||||||
|
if (isDisabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await trigger().unwrap();
|
||||||
|
dispatch(
|
||||||
|
addToast({
|
||||||
|
title: t('invocationCache.clearSucceeded'),
|
||||||
|
status: 'success',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} catch {
|
||||||
|
dispatch(
|
||||||
|
addToast({
|
||||||
|
title: t('invocationCache.clearFailed'),
|
||||||
|
status: 'error',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [isDisabled, trigger, dispatch, t]);
|
||||||
|
|
||||||
|
return { clearInvocationCache, isLoading, cacheStatus, isDisabled };
|
||||||
|
};
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { addToast } from 'features/system/store/systemSlice';
|
||||||
|
import { useCallback, useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import {
|
||||||
|
useDisableInvocationCacheMutation,
|
||||||
|
useGetInvocationCacheStatusQuery,
|
||||||
|
} from 'services/api/endpoints/appInfo';
|
||||||
|
|
||||||
|
export const useDisableInvocationCache = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { data: cacheStatus } = useGetInvocationCacheStatusQuery();
|
||||||
|
const isConnected = useAppSelector((state) => state.system.isConnected);
|
||||||
|
const [trigger, { isLoading }] = useDisableInvocationCacheMutation({
|
||||||
|
fixedCacheKey: 'disableInvocationCache',
|
||||||
|
});
|
||||||
|
|
||||||
|
const isDisabled = useMemo(
|
||||||
|
() => !cacheStatus?.enabled || !isConnected || cacheStatus?.max_size === 0,
|
||||||
|
[cacheStatus?.enabled, cacheStatus?.max_size, isConnected]
|
||||||
|
);
|
||||||
|
|
||||||
|
const disableInvocationCache = useCallback(async () => {
|
||||||
|
if (isDisabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await trigger().unwrap();
|
||||||
|
dispatch(
|
||||||
|
addToast({
|
||||||
|
title: t('invocationCache.disableSucceeded'),
|
||||||
|
status: 'success',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} catch {
|
||||||
|
dispatch(
|
||||||
|
addToast({
|
||||||
|
title: t('invocationCache.disableFailed'),
|
||||||
|
status: 'error',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [isDisabled, trigger, dispatch, t]);
|
||||||
|
|
||||||
|
return { disableInvocationCache, isLoading, cacheStatus, isDisabled };
|
||||||
|
};
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { addToast } from 'features/system/store/systemSlice';
|
||||||
|
import { useCallback, useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import {
|
||||||
|
useEnableInvocationCacheMutation,
|
||||||
|
useGetInvocationCacheStatusQuery,
|
||||||
|
} from 'services/api/endpoints/appInfo';
|
||||||
|
|
||||||
|
export const useEnableInvocationCache = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { data: cacheStatus } = useGetInvocationCacheStatusQuery();
|
||||||
|
const isConnected = useAppSelector((state) => state.system.isConnected);
|
||||||
|
const [trigger, { isLoading }] = useEnableInvocationCacheMutation({
|
||||||
|
fixedCacheKey: 'enableInvocationCache',
|
||||||
|
});
|
||||||
|
|
||||||
|
const isDisabled = useMemo(
|
||||||
|
() => cacheStatus?.enabled || !isConnected || cacheStatus?.max_size === 0,
|
||||||
|
[cacheStatus?.enabled, cacheStatus?.max_size, isConnected]
|
||||||
|
);
|
||||||
|
|
||||||
|
const enableInvocationCache = useCallback(async () => {
|
||||||
|
if (isDisabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await trigger().unwrap();
|
||||||
|
dispatch(
|
||||||
|
addToast({
|
||||||
|
title: t('invocationCache.enableSucceeded'),
|
||||||
|
status: 'success',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} catch {
|
||||||
|
dispatch(
|
||||||
|
addToast({
|
||||||
|
title: t('invocationCache.enableFailed'),
|
||||||
|
status: 'error',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [isDisabled, trigger, dispatch, t]);
|
||||||
|
|
||||||
|
return { enableInvocationCache, isLoading, cacheStatus, isDisabled };
|
||||||
|
};
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { api } from '..';
|
import { api } from '..';
|
||||||
|
import { paths } from '../schema';
|
||||||
import { AppConfig, AppVersion } from '../types';
|
import { AppConfig, AppVersion } from '../types';
|
||||||
|
|
||||||
export const appInfoApi = api.injectEndpoints({
|
export const appInfoApi = api.injectEndpoints({
|
||||||
@@ -19,7 +20,45 @@ export const appInfoApi = api.injectEndpoints({
|
|||||||
providesTags: ['AppConfig'],
|
providesTags: ['AppConfig'],
|
||||||
keepUnusedDataFor: 86400000, // 1 day
|
keepUnusedDataFor: 86400000, // 1 day
|
||||||
}),
|
}),
|
||||||
|
getInvocationCacheStatus: build.query<
|
||||||
|
paths['/api/v1/app/invocation_cache/status']['get']['responses']['200']['content']['application/json'],
|
||||||
|
void
|
||||||
|
>({
|
||||||
|
query: () => ({
|
||||||
|
url: `app/invocation_cache/status`,
|
||||||
|
method: 'GET',
|
||||||
|
}),
|
||||||
|
providesTags: ['InvocationCacheStatus'],
|
||||||
|
}),
|
||||||
|
clearInvocationCache: build.mutation<void, void>({
|
||||||
|
query: () => ({
|
||||||
|
url: `app/invocation_cache`,
|
||||||
|
method: 'DELETE',
|
||||||
|
}),
|
||||||
|
invalidatesTags: ['InvocationCacheStatus'],
|
||||||
|
}),
|
||||||
|
enableInvocationCache: build.mutation<void, void>({
|
||||||
|
query: () => ({
|
||||||
|
url: `app/invocation_cache/enable`,
|
||||||
|
method: 'PUT',
|
||||||
|
}),
|
||||||
|
invalidatesTags: ['InvocationCacheStatus'],
|
||||||
|
}),
|
||||||
|
disableInvocationCache: build.mutation<void, void>({
|
||||||
|
query: () => ({
|
||||||
|
url: `app/invocation_cache/disable`,
|
||||||
|
method: 'PUT',
|
||||||
|
}),
|
||||||
|
invalidatesTags: ['InvocationCacheStatus'],
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { useGetAppVersionQuery, useGetAppConfigQuery } = appInfoApi;
|
export const {
|
||||||
|
useGetAppVersionQuery,
|
||||||
|
useGetAppConfigQuery,
|
||||||
|
useClearInvocationCacheMutation,
|
||||||
|
useDisableInvocationCacheMutation,
|
||||||
|
useEnableInvocationCacheMutation,
|
||||||
|
useGetInvocationCacheStatusQuery,
|
||||||
|
} = appInfoApi;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export const tagTypes = [
|
|||||||
'SessionQueueStatus',
|
'SessionQueueStatus',
|
||||||
'SessionProcessorStatus',
|
'SessionProcessorStatus',
|
||||||
'BatchStatus',
|
'BatchStatus',
|
||||||
|
'InvocationCacheStatus',
|
||||||
];
|
];
|
||||||
export type ApiTagDescription = TagDescription<(typeof tagTypes)[number]>;
|
export type ApiTagDescription = TagDescription<(typeof tagTypes)[number]>;
|
||||||
export const LIST_TAG = 'LIST';
|
export const LIST_TAG = 'LIST';
|
||||||
|
|||||||
175
invokeai/frontend/web/src/services/api/schema.d.ts
vendored
175
invokeai/frontend/web/src/services/api/schema.d.ts
vendored
@@ -317,6 +317,34 @@ export type paths = {
|
|||||||
*/
|
*/
|
||||||
post: operations["set_log_level"];
|
post: operations["set_log_level"];
|
||||||
};
|
};
|
||||||
|
"/api/v1/app/invocation_cache": {
|
||||||
|
/**
|
||||||
|
* Clear Invocation Cache
|
||||||
|
* @description Clears the invocation cache
|
||||||
|
*/
|
||||||
|
delete: operations["clear_invocation_cache"];
|
||||||
|
};
|
||||||
|
"/api/v1/app/invocation_cache/enable": {
|
||||||
|
/**
|
||||||
|
* Enable Invocation Cache
|
||||||
|
* @description Clears the invocation cache
|
||||||
|
*/
|
||||||
|
put: operations["enable_invocation_cache"];
|
||||||
|
};
|
||||||
|
"/api/v1/app/invocation_cache/disable": {
|
||||||
|
/**
|
||||||
|
* Disable Invocation Cache
|
||||||
|
* @description Clears the invocation cache
|
||||||
|
*/
|
||||||
|
put: operations["disable_invocation_cache"];
|
||||||
|
};
|
||||||
|
"/api/v1/app/invocation_cache/status": {
|
||||||
|
/**
|
||||||
|
* Get Invocation Cache Status
|
||||||
|
* @description Clears the invocation cache
|
||||||
|
*/
|
||||||
|
get: operations["get_invocation_cache_status"];
|
||||||
|
};
|
||||||
"/api/v1/queue/{queue_id}/enqueue_graph": {
|
"/api/v1/queue/{queue_id}/enqueue_graph": {
|
||||||
/**
|
/**
|
||||||
* Enqueue Graph
|
* Enqueue Graph
|
||||||
@@ -1259,11 +1287,6 @@ export type components = {
|
|||||||
* @default true
|
* @default true
|
||||||
*/
|
*/
|
||||||
use_cache?: boolean;
|
use_cache?: boolean;
|
||||||
/**
|
|
||||||
* CLIP
|
|
||||||
* @description CLIP (tokenizer, text encoder, LoRAs) and skipped layer count
|
|
||||||
*/
|
|
||||||
clip?: components["schemas"]["ClipField"];
|
|
||||||
/**
|
/**
|
||||||
* Skipped Layers
|
* Skipped Layers
|
||||||
* @description Number of layers to skip in text encoder
|
* @description Number of layers to skip in text encoder
|
||||||
@@ -1276,6 +1299,11 @@ export type components = {
|
|||||||
* @enum {string}
|
* @enum {string}
|
||||||
*/
|
*/
|
||||||
type: "clip_skip";
|
type: "clip_skip";
|
||||||
|
/**
|
||||||
|
* CLIP
|
||||||
|
* @description CLIP (tokenizer, text encoder, LoRAs) and skipped layer count
|
||||||
|
*/
|
||||||
|
clip?: components["schemas"]["ClipField"];
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* ClipSkipInvocationOutput
|
* ClipSkipInvocationOutput
|
||||||
@@ -2020,7 +2048,7 @@ export type components = {
|
|||||||
* Clip Skip
|
* Clip Skip
|
||||||
* @description The number of skipped CLIP layers
|
* @description The number of skipped CLIP layers
|
||||||
*/
|
*/
|
||||||
clip_skip: number;
|
clip_skip?: number;
|
||||||
/**
|
/**
|
||||||
* Model
|
* Model
|
||||||
* @description The main model used for inference
|
* @description The main model used for inference
|
||||||
@@ -2309,10 +2337,7 @@ export type components = {
|
|||||||
* @enum {string}
|
* @enum {string}
|
||||||
*/
|
*/
|
||||||
scheduler?: "ddim" | "ddpm" | "deis" | "lms" | "lms_k" | "pndm" | "heun" | "heun_k" | "euler" | "euler_k" | "euler_a" | "kdpm_2" | "kdpm_2_a" | "dpmpp_2s" | "dpmpp_2s_k" | "dpmpp_2m" | "dpmpp_2m_k" | "dpmpp_2m_sde" | "dpmpp_2m_sde_k" | "dpmpp_sde" | "dpmpp_sde_k" | "unipc";
|
scheduler?: "ddim" | "ddpm" | "deis" | "lms" | "lms_k" | "pndm" | "heun" | "heun_k" | "euler" | "euler_k" | "euler_a" | "kdpm_2" | "kdpm_2_a" | "dpmpp_2s" | "dpmpp_2s_k" | "dpmpp_2m" | "dpmpp_2m_k" | "dpmpp_2m_sde" | "dpmpp_2m_sde_k" | "dpmpp_sde" | "dpmpp_sde_k" | "unipc";
|
||||||
/**
|
/** Control */
|
||||||
* Control
|
|
||||||
* @description ControlNet(s) to apply
|
|
||||||
*/
|
|
||||||
control?: components["schemas"]["ControlField"] | components["schemas"]["ControlField"][];
|
control?: components["schemas"]["ControlField"] | components["schemas"]["ControlField"][];
|
||||||
/**
|
/**
|
||||||
* IP-Adapter
|
* IP-Adapter
|
||||||
@@ -4718,6 +4743,34 @@ export type components = {
|
|||||||
*/
|
*/
|
||||||
type: "integer_output";
|
type: "integer_output";
|
||||||
};
|
};
|
||||||
|
/** InvocationCacheStatus */
|
||||||
|
InvocationCacheStatus: {
|
||||||
|
/**
|
||||||
|
* Size
|
||||||
|
* @description The current size of the invocation cache
|
||||||
|
*/
|
||||||
|
size: number;
|
||||||
|
/**
|
||||||
|
* Hits
|
||||||
|
* @description The number of cache hits
|
||||||
|
*/
|
||||||
|
hits: number;
|
||||||
|
/**
|
||||||
|
* Misses
|
||||||
|
* @description The number of cache misses
|
||||||
|
*/
|
||||||
|
misses: number;
|
||||||
|
/**
|
||||||
|
* Enabled
|
||||||
|
* @description Whether the invocation cache is enabled
|
||||||
|
*/
|
||||||
|
enabled: boolean;
|
||||||
|
/**
|
||||||
|
* Max Size
|
||||||
|
* @description The maximum size of the invocation cache
|
||||||
|
*/
|
||||||
|
max_size: number;
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* IterateInvocation
|
* IterateInvocation
|
||||||
* @description Iterates over a list of items
|
* @description Iterates over a list of items
|
||||||
@@ -7497,11 +7550,6 @@ export type components = {
|
|||||||
* @default false
|
* @default false
|
||||||
*/
|
*/
|
||||||
use_cache?: boolean;
|
use_cache?: boolean;
|
||||||
/**
|
|
||||||
* Image
|
|
||||||
* @description The image to load
|
|
||||||
*/
|
|
||||||
image?: components["schemas"]["ImageField"];
|
|
||||||
/**
|
/**
|
||||||
* Metadata
|
* Metadata
|
||||||
* @description Optional core metadata to be written to image
|
* @description Optional core metadata to be written to image
|
||||||
@@ -7513,6 +7561,11 @@ export type components = {
|
|||||||
* @enum {string}
|
* @enum {string}
|
||||||
*/
|
*/
|
||||||
type: "save_image";
|
type: "save_image";
|
||||||
|
/**
|
||||||
|
* Image
|
||||||
|
* @description The image to load
|
||||||
|
*/
|
||||||
|
image?: components["schemas"]["ImageField"];
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Scale Latents
|
* Scale Latents
|
||||||
@@ -9042,18 +9095,6 @@ export type components = {
|
|||||||
/** Ui Order */
|
/** Ui Order */
|
||||||
ui_order?: number;
|
ui_order?: number;
|
||||||
};
|
};
|
||||||
/**
|
|
||||||
* IPAdapterModelFormat
|
|
||||||
* @description An enumeration.
|
|
||||||
* @enum {string}
|
|
||||||
*/
|
|
||||||
IPAdapterModelFormat: "invokeai";
|
|
||||||
/**
|
|
||||||
* ControlNetModelFormat
|
|
||||||
* @description An enumeration.
|
|
||||||
* @enum {string}
|
|
||||||
*/
|
|
||||||
ControlNetModelFormat: "checkpoint" | "diffusers";
|
|
||||||
/**
|
/**
|
||||||
* StableDiffusionOnnxModelFormat
|
* StableDiffusionOnnxModelFormat
|
||||||
* @description An enumeration.
|
* @description An enumeration.
|
||||||
@@ -9066,24 +9107,36 @@ export type components = {
|
|||||||
* @enum {string}
|
* @enum {string}
|
||||||
*/
|
*/
|
||||||
StableDiffusion2ModelFormat: "checkpoint" | "diffusers";
|
StableDiffusion2ModelFormat: "checkpoint" | "diffusers";
|
||||||
/**
|
|
||||||
* StableDiffusion1ModelFormat
|
|
||||||
* @description An enumeration.
|
|
||||||
* @enum {string}
|
|
||||||
*/
|
|
||||||
StableDiffusion1ModelFormat: "checkpoint" | "diffusers";
|
|
||||||
/**
|
/**
|
||||||
* CLIPVisionModelFormat
|
* CLIPVisionModelFormat
|
||||||
* @description An enumeration.
|
* @description An enumeration.
|
||||||
* @enum {string}
|
* @enum {string}
|
||||||
*/
|
*/
|
||||||
CLIPVisionModelFormat: "diffusers";
|
CLIPVisionModelFormat: "diffusers";
|
||||||
|
/**
|
||||||
|
* StableDiffusion1ModelFormat
|
||||||
|
* @description An enumeration.
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
StableDiffusion1ModelFormat: "checkpoint" | "diffusers";
|
||||||
/**
|
/**
|
||||||
* StableDiffusionXLModelFormat
|
* StableDiffusionXLModelFormat
|
||||||
* @description An enumeration.
|
* @description An enumeration.
|
||||||
* @enum {string}
|
* @enum {string}
|
||||||
*/
|
*/
|
||||||
StableDiffusionXLModelFormat: "checkpoint" | "diffusers";
|
StableDiffusionXLModelFormat: "checkpoint" | "diffusers";
|
||||||
|
/**
|
||||||
|
* IPAdapterModelFormat
|
||||||
|
* @description An enumeration.
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
IPAdapterModelFormat: "invokeai";
|
||||||
|
/**
|
||||||
|
* ControlNetModelFormat
|
||||||
|
* @description An enumeration.
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
ControlNetModelFormat: "checkpoint" | "diffusers";
|
||||||
};
|
};
|
||||||
responses: never;
|
responses: never;
|
||||||
parameters: never;
|
parameters: never;
|
||||||
@@ -10505,6 +10558,62 @@ export type operations = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* Clear Invocation Cache
|
||||||
|
* @description Clears the invocation cache
|
||||||
|
*/
|
||||||
|
clear_invocation_cache: {
|
||||||
|
responses: {
|
||||||
|
/** @description The operation was successful */
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
"application/json": unknown;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Enable Invocation Cache
|
||||||
|
* @description Clears the invocation cache
|
||||||
|
*/
|
||||||
|
enable_invocation_cache: {
|
||||||
|
responses: {
|
||||||
|
/** @description The operation was successful */
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
"application/json": unknown;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Disable Invocation Cache
|
||||||
|
* @description Clears the invocation cache
|
||||||
|
*/
|
||||||
|
disable_invocation_cache: {
|
||||||
|
responses: {
|
||||||
|
/** @description The operation was successful */
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
"application/json": unknown;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Get Invocation Cache Status
|
||||||
|
* @description Clears the invocation cache
|
||||||
|
*/
|
||||||
|
get_invocation_cache_status: {
|
||||||
|
responses: {
|
||||||
|
/** @description Successful Response */
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["InvocationCacheStatus"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* Enqueue Graph
|
* Enqueue Graph
|
||||||
* @description Enqueues a graph for single execution.
|
* @description Enqueues a graph for single execution.
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__ = "3.1.1"
|
__version__ = "3.2.0rc2"
|
||||||
|
|||||||
Reference in New Issue
Block a user