From fdc444ed616a27f9cd45a7c1dafd83a2583cd115 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Sun, 23 Jul 2023 15:24:04 +1200 Subject: [PATCH 1/8] fix: Fix app crashing when you upload an incorrect JSON to node editor --- invokeai/frontend/web/public/locales/en.json | 2 + .../nodes/components/ui/LoadNodesButton.tsx | 78 ++++++++++++------- 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index 59cf87fbda..ab10276491 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -615,6 +615,8 @@ "initialImageNotSetDesc": "Could not load initial image", "nodesSaved": "Nodes Saved", "nodesLoaded": "Nodes Loaded", + "nodesNotValidGraph": "Not a valid InvokeAI Node Graph", + "nodesNotValidJSON": "Not a valid JSON", "nodesLoadedFailed": "Failed To Load Nodes", "nodesCleared": "Nodes Cleared" }, diff --git a/invokeai/frontend/web/src/features/nodes/components/ui/LoadNodesButton.tsx b/invokeai/frontend/web/src/features/nodes/components/ui/LoadNodesButton.tsx index 706fbd8b31..2aa369bc11 100644 --- a/invokeai/frontend/web/src/features/nodes/components/ui/LoadNodesButton.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/ui/LoadNodesButton.tsx @@ -1,14 +1,28 @@ import { FileButton } from '@mantine/core'; -import { makeToast } from 'features/system/util/makeToast'; import { useAppDispatch } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { loadFileEdges, loadFileNodes } from 'features/nodes/store/nodesSlice'; import { addToast } from 'features/system/store/systemSlice'; +import { makeToast } from 'features/system/util/makeToast'; import { memo, useCallback, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { FaUpload } from 'react-icons/fa'; import { useReactFlow } from 'reactflow'; +interface JsonFile { + [key: string]: unknown; +} + +function validateInvokeAIGraph(jsonFile: JsonFile): boolean { + const keys = ['nodes', 'edges', 'viewport']; + for (const key of keys) { + if (!(key in jsonFile)) { + return false; + } + } + return true; +} + const LoadNodesButton = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); @@ -22,33 +36,45 @@ const LoadNodesButton = () => { const reader = new FileReader(); reader.onload = async () => { const json = reader.result; - const retrievedNodeTree = await JSON.parse(String(json)); - if (!retrievedNodeTree) { - dispatch( - addToast( - makeToast({ - title: t('toast.nodesLoadedFailed'), - status: 'error', - }) - ) - ); + try { + const retrievedNodeTree = await JSON.parse(String(json)); + const isValidNodeTree = validateInvokeAIGraph(retrievedNodeTree); + + if (isValidNodeTree) { + dispatch(loadFileNodes(retrievedNodeTree.nodes)); + dispatch(loadFileEdges(retrievedNodeTree.edges)); + fitView(); + + dispatch( + addToast( + makeToast({ title: t('toast.nodesLoaded'), status: 'success' }) + ) + ); + } else { + dispatch( + addToast( + makeToast({ + title: t('toast.nodesNotValidGraph'), + status: 'error', + }) + ) + ); + } + // Cleanup + reader.abort(); + } catch (error) { + if (error) { + dispatch( + addToast( + makeToast({ + title: t('toast.nodesNotValidJSON'), + status: 'error', + }) + ) + ); + } } - - if (retrievedNodeTree) { - dispatch(loadFileNodes(retrievedNodeTree.nodes)); - dispatch(loadFileEdges(retrievedNodeTree.edges)); - fitView(); - - dispatch( - addToast( - makeToast({ title: t('toast.nodesLoaded'), status: 'success' }) - ) - ); - } - - // Cleanup - reader.abort(); }; reader.readAsText(v); From 225f60855647147e6e4a67461df36c6fc437cf3d Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Sun, 23 Jul 2023 16:49:52 +1200 Subject: [PATCH 2/8] fix: Add more sanity checks & rename buttons to Graphs --- invokeai/frontend/web/public/locales/en.json | 6 ++--- .../components/panels/TopCenterPanel.tsx | 12 ++++----- ...arNodesButton.tsx => ClearGraphButton.tsx} | 16 ++++++------ ...oadNodesButton.tsx => LoadGraphButton.tsx} | 25 +++++++++++++------ ...aveNodesButton.tsx => SaveGraphButton.tsx} | 8 +++--- 5 files changed, 39 insertions(+), 28 deletions(-) rename invokeai/frontend/web/src/features/nodes/components/ui/{ClearNodesButton.tsx => ClearGraphButton.tsx} (87%) rename invokeai/frontend/web/src/features/nodes/components/ui/{LoadNodesButton.tsx => LoadGraphButton.tsx} (82%) rename invokeai/frontend/web/src/features/nodes/components/ui/{SaveNodesButton.tsx => SaveGraphButton.tsx} (90%) diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index ab10276491..404c2013e4 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -702,9 +702,9 @@ }, "nodes": { "reloadSchema": "Reload Schema", - "saveNodes": "Save Nodes", - "loadNodes": "Load Nodes", - "clearNodes": "Clear Nodes", + "saveGraph": "Save Graph", + "loadGraph": "Load Graph (saved from Node Editor) (Do not copy-paste metadata)", + "clearGraph": "Clear Graph", "zoomInNodes": "Zoom In", "zoomOutNodes": "Zoom Out", "fitViewportNodes": "Fit View", diff --git a/invokeai/frontend/web/src/features/nodes/components/panels/TopCenterPanel.tsx b/invokeai/frontend/web/src/features/nodes/components/panels/TopCenterPanel.tsx index 90f8039285..21076e16f5 100644 --- a/invokeai/frontend/web/src/features/nodes/components/panels/TopCenterPanel.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/panels/TopCenterPanel.tsx @@ -2,11 +2,11 @@ import { HStack } from '@chakra-ui/react'; import CancelButton from 'features/parameters/components/ProcessButtons/CancelButton'; import { memo } from 'react'; import { Panel } from 'reactflow'; -import LoadNodesButton from '../ui/LoadNodesButton'; +import ClearGraphButton from '../ui/ClearGraphButton'; +import LoadGraphButton from '../ui/LoadGraphButton'; import NodeInvokeButton from '../ui/NodeInvokeButton'; import ReloadSchemaButton from '../ui/ReloadSchemaButton'; -import SaveNodesButton from '../ui/SaveNodesButton'; -import ClearNodesButton from '../ui/ClearNodesButton'; +import SaveGraphButton from '../ui/SaveGraphButton'; const TopCenterPanel = () => { return ( @@ -15,9 +15,9 @@ const TopCenterPanel = () => { - - - + + + ); diff --git a/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx b/invokeai/frontend/web/src/features/nodes/components/ui/ClearGraphButton.tsx similarity index 87% rename from invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx rename to invokeai/frontend/web/src/features/nodes/components/ui/ClearGraphButton.tsx index 86d9d08a84..88fb60ee0f 100644 --- a/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/ui/ClearGraphButton.tsx @@ -9,17 +9,17 @@ import { Text, useDisclosure, } from '@chakra-ui/react'; -import { makeToast } from 'features/system/util/makeToast'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { nodeEditorReset } from 'features/nodes/store/nodesSlice'; import { addToast } from 'features/system/store/systemSlice'; -import { memo, useRef, useCallback } from 'react'; +import { makeToast } from 'features/system/util/makeToast'; +import { memo, useCallback, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { FaTrash } from 'react-icons/fa'; -const ClearNodesButton = () => { +const ClearGraphButton = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const { isOpen, onOpen, onClose } = useDisclosure(); @@ -46,8 +46,8 @@ const ClearNodesButton = () => { <> } - tooltip={t('nodes.clearNodes')} - aria-label={t('nodes.clearNodes')} + tooltip={t('nodes.clearGraph')} + aria-label={t('nodes.clearGraph')} onClick={onOpen} isDisabled={nodes.length === 0} /> @@ -62,11 +62,11 @@ const ClearNodesButton = () => { - {t('nodes.clearNodes')} + {t('nodes.clearGraph')} - {t('common.clearNodes')} + {t('common.clearGraph')} @@ -83,4 +83,4 @@ const ClearNodesButton = () => { ); }; -export default memo(ClearNodesButton); +export default memo(ClearGraphButton); diff --git a/invokeai/frontend/web/src/features/nodes/components/ui/LoadNodesButton.tsx b/invokeai/frontend/web/src/features/nodes/components/ui/LoadGraphButton.tsx similarity index 82% rename from invokeai/frontend/web/src/features/nodes/components/ui/LoadNodesButton.tsx rename to invokeai/frontend/web/src/features/nodes/components/ui/LoadGraphButton.tsx index 2aa369bc11..437418e18a 100644 --- a/invokeai/frontend/web/src/features/nodes/components/ui/LoadNodesButton.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/ui/LoadGraphButton.tsx @@ -13,17 +13,28 @@ interface JsonFile { [key: string]: unknown; } -function validateInvokeAIGraph(jsonFile: JsonFile): boolean { +function sanityCheckInvokeAIGraph(jsonFile: JsonFile): boolean { const keys = ['nodes', 'edges', 'viewport']; for (const key of keys) { if (!(key in jsonFile)) { return false; } } + + if (!Array.isArray(jsonFile.nodes) || !Array.isArray(jsonFile.edges)) { + return false; + } + + for (const node of jsonFile.nodes) { + if (!('data' in node)) { + return false; + } + } + return true; } -const LoadNodesButton = () => { +const LoadGraphButton = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const { fitView } = useReactFlow(); @@ -39,9 +50,9 @@ const LoadNodesButton = () => { try { const retrievedNodeTree = await JSON.parse(String(json)); - const isValidNodeTree = validateInvokeAIGraph(retrievedNodeTree); + const isSaneNodeTree = sanityCheckInvokeAIGraph(retrievedNodeTree); - if (isValidNodeTree) { + if (isSaneNodeTree) { dispatch(loadFileNodes(retrievedNodeTree.nodes)); dispatch(loadFileEdges(retrievedNodeTree.edges)); fitView(); @@ -93,8 +104,8 @@ const LoadNodesButton = () => { {(props) => ( } - tooltip={t('nodes.loadNodes')} - aria-label={t('nodes.loadNodes')} + tooltip={t('nodes.loadGraph')} + aria-label={t('nodes.loadGraph')} {...props} /> )} @@ -102,4 +113,4 @@ const LoadNodesButton = () => { ); }; -export default memo(LoadNodesButton); +export default memo(LoadGraphButton); diff --git a/invokeai/frontend/web/src/features/nodes/components/ui/SaveNodesButton.tsx b/invokeai/frontend/web/src/features/nodes/components/ui/SaveGraphButton.tsx similarity index 90% rename from invokeai/frontend/web/src/features/nodes/components/ui/SaveNodesButton.tsx rename to invokeai/frontend/web/src/features/nodes/components/ui/SaveGraphButton.tsx index 5833182456..42e545258e 100644 --- a/invokeai/frontend/web/src/features/nodes/components/ui/SaveNodesButton.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/ui/SaveGraphButton.tsx @@ -6,7 +6,7 @@ import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { FaSave } from 'react-icons/fa'; -const SaveNodesButton = () => { +const SaveGraphButton = () => { const { t } = useTranslation(); const editorInstance = useAppSelector( (state: RootState) => state.nodes.editorInstance @@ -37,12 +37,12 @@ const SaveNodesButton = () => { } fontSize={18} - tooltip={t('nodes.saveNodes')} - aria-label={t('nodes.saveNodes')} + tooltip={t('nodes.saveGraph')} + aria-label={t('nodes.saveGraph')} onClick={saveEditorToJSON} isDisabled={nodes.length === 0} /> ); }; -export default memo(SaveNodesButton); +export default memo(SaveGraphButton); From af4579b4d494d37ae1615f94ae61c7631c28bc79 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Sun, 23 Jul 2023 18:12:25 +1200 Subject: [PATCH 3/8] feat: Add more sanity checks for graph loading --- invokeai/frontend/web/public/locales/en.json | 7 +- .../nodes/components/ui/ClearGraphButton.tsx | 2 +- .../nodes/components/ui/LoadGraphButton.tsx | 71 +++++++++++++++---- 3 files changed, 64 insertions(+), 16 deletions(-) diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index 404c2013e4..0640ab9ef0 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -102,8 +102,7 @@ "openInNewTab": "Open in New Tab", "dontAskMeAgain": "Don't ask me again", "areYouSure": "Are you sure?", - "imagePrompt": "Image Prompt", - "clearNodes": "Are you sure you want to clear all nodes?" + "imagePrompt": "Image Prompt" }, "gallery": { "generations": "Generations", @@ -617,6 +616,9 @@ "nodesLoaded": "Nodes Loaded", "nodesNotValidGraph": "Not a valid InvokeAI Node Graph", "nodesNotValidJSON": "Not a valid JSON", + "nodesCorruptedGraph": "Cannot load. Graph seems to be corrupted.", + "nodesUnrecognizedTypes": "Cannot load. Graph has unrecognized types", + "nodesBrokenConnections": "Cannot load. Some connections are broken.", "nodesLoadedFailed": "Failed To Load Nodes", "nodesCleared": "Nodes Cleared" }, @@ -705,6 +707,7 @@ "saveGraph": "Save Graph", "loadGraph": "Load Graph (saved from Node Editor) (Do not copy-paste metadata)", "clearGraph": "Clear Graph", + "clearGraphDesc": "Are you sure you want to clear all nodes?", "zoomInNodes": "Zoom In", "zoomOutNodes": "Zoom Out", "fitViewportNodes": "Fit View", diff --git a/invokeai/frontend/web/src/features/nodes/components/ui/ClearGraphButton.tsx b/invokeai/frontend/web/src/features/nodes/components/ui/ClearGraphButton.tsx index 88fb60ee0f..432675c5cd 100644 --- a/invokeai/frontend/web/src/features/nodes/components/ui/ClearGraphButton.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/ui/ClearGraphButton.tsx @@ -66,7 +66,7 @@ const ClearGraphButton = () => { - {t('common.clearGraph')} + {t('nodes.clearGraphDesc')} diff --git a/invokeai/frontend/web/src/features/nodes/components/ui/LoadGraphButton.tsx b/invokeai/frontend/web/src/features/nodes/components/ui/LoadGraphButton.tsx index 437418e18a..44d93bb8fe 100644 --- a/invokeai/frontend/web/src/features/nodes/components/ui/LoadGraphButton.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/ui/LoadGraphButton.tsx @@ -4,6 +4,7 @@ import IAIIconButton from 'common/components/IAIIconButton'; import { loadFileEdges, loadFileNodes } from 'features/nodes/store/nodesSlice'; import { addToast } from 'features/system/store/systemSlice'; import { makeToast } from 'features/system/util/makeToast'; +import i18n from 'i18n'; import { memo, useCallback, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { FaUpload } from 'react-icons/fa'; @@ -13,25 +14,70 @@ interface JsonFile { [key: string]: unknown; } -function sanityCheckInvokeAIGraph(jsonFile: JsonFile): boolean { +function sanityCheckInvokeAIGraph(jsonFile: JsonFile): { + isValid: boolean; + message: string; +} { + // Check if primary keys exist const keys = ['nodes', 'edges', 'viewport']; for (const key of keys) { if (!(key in jsonFile)) { - return false; + return { + isValid: false, + message: i18n.t('toast.nodesNotValidGraph'), + }; } } + // Check if nodes and edges are arrays if (!Array.isArray(jsonFile.nodes) || !Array.isArray(jsonFile.edges)) { - return false; + return { + isValid: false, + message: i18n.t('toast.nodesNotValidGraph'), + }; } - for (const node of jsonFile.nodes) { - if (!('data' in node)) { - return false; + // Check if data is present in nodes + const nodeKeys = ['data', 'type']; + const nodeTypes = ['invocation', 'progress_image']; + if (jsonFile.nodes.length > 0) { + for (const node of jsonFile.nodes) { + for (const nodeKey of nodeKeys) { + if (!(nodeKey in node)) { + return { + isValid: false, + message: i18n.t('toast.nodesNotValidGraph'), + }; + } + if (nodeKey === 'type' && !nodeTypes.includes(node[nodeKey])) { + return { + isValid: false, + message: i18n.t('toast.nodesUnrecognizedTypes'), + }; + } + } } } - return true; + // Check Edge Object + const edgeKeys = ['source', 'sourceHandle', 'target', 'targetHandle']; + if (jsonFile.edges.length > 0) { + for (const edge of jsonFile.edges) { + for (const edgeKey of edgeKeys) { + if (!(edgeKey in edge)) { + return { + isValid: false, + message: i18n.t('toast.nodesBrokenConnections'), + }; + } + } + } + } + + return { + isValid: true, + message: i18n.t('toast.nodesLoaded'), + }; } const LoadGraphButton = () => { @@ -50,23 +96,22 @@ const LoadGraphButton = () => { try { const retrievedNodeTree = await JSON.parse(String(json)); - const isSaneNodeTree = sanityCheckInvokeAIGraph(retrievedNodeTree); + const { isValid, message } = + sanityCheckInvokeAIGraph(retrievedNodeTree); - if (isSaneNodeTree) { + if (isValid) { dispatch(loadFileNodes(retrievedNodeTree.nodes)); dispatch(loadFileEdges(retrievedNodeTree.edges)); fitView(); dispatch( - addToast( - makeToast({ title: t('toast.nodesLoaded'), status: 'success' }) - ) + addToast(makeToast({ title: message, status: 'success' })) ); } else { dispatch( addToast( makeToast({ - title: t('toast.nodesNotValidGraph'), + title: message, status: 'error', }) ) From 0beec08d3822b398f855ab11ee5064ed5b479bce Mon Sep 17 00:00:00 2001 From: Alexandre Macabies Date: Sun, 23 Jul 2023 14:46:16 +0200 Subject: [PATCH 4/8] Add missing import. --- invokeai/backend/model_management/models/lora.py | 1 + 1 file changed, 1 insertion(+) diff --git a/invokeai/backend/model_management/models/lora.py b/invokeai/backend/model_management/models/lora.py index 5387ade0e5..eb771841ec 100644 --- a/invokeai/backend/model_management/models/lora.py +++ b/invokeai/backend/model_management/models/lora.py @@ -10,6 +10,7 @@ from .base import ( SubModelType, classproperty, InvalidModelException, + ModelNotFoundException, ) # TODO: naming from ..lora import LoRAModel as LoRAModelRaw From d5a75eb83301f89a2240f2ca4a9719d04ef574b5 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 24 Jul 2023 16:34:34 +1000 Subject: [PATCH 5/8] feat: increase seed from int32 to uint32 At some point I typo'd this and set the max seed to signed int32 max. It should be *un*signed int32 max. This restored the seed range to what it was in v2.3. --- invokeai/app/util/misc.py | 2 +- invokeai/frontend/web/src/app/constants.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/invokeai/app/util/misc.py b/invokeai/app/util/misc.py index 7c674674e2..be5b698258 100644 --- a/invokeai/app/util/misc.py +++ b/invokeai/app/util/misc.py @@ -14,7 +14,7 @@ def get_datetime_from_iso_timestamp(iso_timestamp: str) -> datetime.datetime: return datetime.datetime.fromisoformat(iso_timestamp) -SEED_MAX = np.iinfo(np.int32).max +SEED_MAX = np.iinfo(np.uint32).max def get_random_seed(): diff --git a/invokeai/frontend/web/src/app/constants.ts b/invokeai/frontend/web/src/app/constants.ts index 1194ea467b..b8fab16c1c 100644 --- a/invokeai/frontend/web/src/app/constants.ts +++ b/invokeai/frontend/web/src/app/constants.ts @@ -1,2 +1,2 @@ export const NUMPY_RAND_MIN = 0; -export const NUMPY_RAND_MAX = 2147483647; +export const NUMPY_RAND_MAX = 4294967295; From 66cdeba8a1e8ba78f255ea3ca3269c9331a889cf Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 24 Jul 2023 16:44:32 +1000 Subject: [PATCH 6/8] fix(nodes): fix seed modulus operation This was incorect and resulted in the max seed being one less than intended. --- invokeai/app/invocations/noise.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/invokeai/app/invocations/noise.py b/invokeai/app/invocations/noise.py index 442557520a..fff0f29f14 100644 --- a/invokeai/app/invocations/noise.py +++ b/invokeai/app/invocations/noise.py @@ -119,8 +119,8 @@ class NoiseInvocation(BaseInvocation): @validator("seed", pre=True) def modulo_seed(cls, v): - """Returns the seed modulo SEED_MAX to ensure it is within the valid range.""" - return v % SEED_MAX + """Returns the seed modulo (SEED_MAX + 1) to ensure it is within the valid range.""" + return v % (SEED_MAX + 1) def invoke(self, context: InvocationContext) -> NoiseOutput: noise = get_noise( From 0cf7a10c5ccd413b001fb360ff7b0fcb6e961883 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Mon, 24 Jul 2023 18:58:24 +1200 Subject: [PATCH 7/8] fix: Other lora missing type --- invokeai/backend/model_management/lora.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/invokeai/backend/model_management/lora.py b/invokeai/backend/model_management/lora.py index b0481f3cfa..222169afbb 100644 --- a/invokeai/backend/model_management/lora.py +++ b/invokeai/backend/model_management/lora.py @@ -474,7 +474,7 @@ class ModelPatcher: @staticmethod def _lora_forward_hook( - applied_loras: List[Tuple[LoraModel, float]], + applied_loras: List[Tuple[LoRAModel, float]], layer_name: str, ): @@ -519,7 +519,7 @@ class ModelPatcher: def apply_lora( cls, model: torch.nn.Module, - loras: List[Tuple[LoraModel, float]], + loras: List[Tuple[LoRAModel, float]], prefix: str, ): original_weights = dict() From e766ddbcf45b2eca1436fe8b51294e91769a4405 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Mon, 24 Jul 2023 19:38:21 +1200 Subject: [PATCH 8/8] fix: Generate random seed using the generator instead of RandomState --- invokeai/app/util/misc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/invokeai/app/util/misc.py b/invokeai/app/util/misc.py index be5b698258..503f3af4c8 100644 --- a/invokeai/app/util/misc.py +++ b/invokeai/app/util/misc.py @@ -18,4 +18,5 @@ SEED_MAX = np.iinfo(np.uint32).max def get_random_seed(): - return np.random.randint(0, SEED_MAX) + rng = np.random.default_rng(seed=0) + return int(rng.integers(0, SEED_MAX))