InvokeAI/invokeai/app/services
psychedelicious 69539a0472 feat(nodes): depth-first execution
There was an issue where for graphs w/ iterations, your images were output all at once, at the very end of processing. So if you canceled halfway through an execution of 10 nodes, you wouldn't get any images - even though you'd completed 5 images' worth of inference.

## Cause

Because graphs executed breadth-first (i.e. depth-by-depth), leaf nodes were necessarily processed last. For image generation graphs, your `LatentsToImage` will be leaf nodes, and be the last depth to be executed.

For example, a `TextToLatents` graph w/ 3 iterations would execute all 3 `TextToLatents` nodes fully before moving to the next depth, where the `LatentsToImage` nodes produce output images, resulting in a node execution order like this:

1. TextToLatents
2. TextToLatents
3. TextToLatents
4. LatentsToImage
5. LatentsToImage
6. LatentsToImage

## Solution

This PR makes a two changes to graph execution to execute as deeply as it can along each branch of the graph.

### Eager node preparation

We now prepare as many nodes as possible, instead of just a single node at a time.

We also need to change the conditions in which nodes are prepared. Previously, nodes were prepared only when all of their direct ancestors were executed.

The updated logic prepares nodes that:
- are *not* `Iterate` nodes whose inputs have *not* been executed
- do *not* have any unexecuted `Iterate` ancestor nodes

This results in graphs always being maximally prepared.

### Always execute the deepest prepared node

We now choose the next node to execute by traversing from the bottom of the graph instead of the top, choosing the first node whose inputs are all executed.

This means we always execute the deepest node possible.

## Result

Graphs now execute depth-first, so instead of an execution order like this:

1. TextToLatents
2. TextToLatents
3. TextToLatents
4. LatentsToImage
5. LatentsToImage
6. LatentsToImage

... we get an execution order like this:

1. TextToLatents
2. LatentsToImage
3. TextToLatents
4. LatentsToImage
5. TextToLatents
6. LatentsToImage

Immediately after inference, the image is decoded and sent to the gallery.

fixes #3400
2023-06-09 14:53:45 +10:00
..
models feat(nodes): make list images route use offset pagination 2023-05-28 20:19:56 -04:00
__init__.py all files migrated; tweaks needed 2023-03-03 00:02:15 -05:00
config.py merge with main 2023-06-05 22:03:44 -04:00
default_graphs.py fix(nodes): temporarily disable librarygraphs 2023-05-12 22:33:49 +10:00
events.py feat(nodes): refactor image types 2023-05-28 20:19:56 -04:00
graph.py feat(nodes): depth-first execution 2023-06-09 14:53:45 +10:00
image_file_storage.py feat(nodes): refactor image types 2023-05-28 20:19:56 -04:00
image_record_storage.py fix(nodes): fix images service update() for is_intermediate 2023-05-28 20:19:56 -04:00
images.py feat(nodes): make list images route use offset pagination 2023-05-28 20:19:56 -04:00
invocation_queue.py nodes: invocation queue item - make more pydantic 2023-04-16 09:39:33 -04:00
invocation_services.py fix(nodes): use forward declarations for InvocationServices 2023-05-25 12:12:31 +10:00
invoker.py fix(nodes): fix duplicate Invoker start/stop events 2023-05-01 18:24:37 -04:00
item_storage.py revert and disable auto-formatting of invocations 2023-03-03 14:59:17 -05:00
latent_storage.py feat(nodes): wip image storage implementation 2023-05-24 11:30:47 -04:00
metadata.py feat(nodes): improve metadata service comments 2023-05-24 11:30:47 -04:00
model_manager_initializer.py remove globals, args, generate and the legacy CLI 2023-05-03 23:36:51 -04:00
processor.py chore(nodes): remove unused imports 2023-05-25 12:12:31 +10:00
resource_name.py feat(nodes): add nameservice 2023-05-28 20:19:56 -04:00
restoration_services.py logger is a interchangeable service 2023-04-29 10:48:50 -04:00
sqlite.py fix potential race condition in config system 2023-05-25 20:41:26 -04:00
urls.py feat(nodes): refactor image types 2023-05-28 20:19:56 -04:00