InvokeAI/invokeai/app/services/shared
psychedelicious 0ad904d2b3 feat(nodes): JIT graph nodes validation
We use pydantic to validate a union of valid invocations when instantiating a graph.

Previously, we constructed the union while creating the `Graph` class. This introduces a dependency on the order of imports.

For example, consider a setup where we have 3 invocations in the app:

- Python executes the module where `FirstInvocation` is defined, registering `FirstInvocation`.
- Python executes the module where `SecondInvocation` is defined, registering `SecondInvocation`.
- Python executes the module where `Graph` is defined. A union of invocations is created and used to define the `Graph.nodes` field. The union contains `FirstInvocation` and `SecondInvocation`.
- Python executes the module where `ThirdInvocation` is defined, registering `ThirdInvocation`.
- A graph is created that includes `ThirdInvocation`. Pydantic validates the graph using the union, which does not know about `ThirdInvocation`, raising a `ValidationError` about an unknown invocation type.

This scenario has been particularly problematic in tests, where we may create invocations dynamically. The test files have to be structured in such a way that the imports happen in the right order. It's a major pain.

This PR refactors the validation of graph nodes to resolve this issue:

- `BaseInvocation` gets a new method `get_typeadapter`. This builds a pydantic `TypeAdapter` for the union of all registered invocations, caching it after the first call.
- `Graph.nodes`'s type is widened to `dict[str, BaseInvocation]`. This actually is a nice bonus, because we get better type hints whenever we reference `some_graph.nodes`.
- A "plain" field validator takes over the validation logic for `Graph.nodes`. "Plain" validators totally override pydantic's own validation logic. The validator grabs the `TypeAdapter` from `BaseInvocation`, then validates each node with it. The validation is identical to the previous implementation - we get the same errors.

`BaseInvocationOutput` gets the same treatment.
2024-02-29 13:28:20 -05:00
..
sqlite model loading and conversion implemented for vaes 2024-02-29 13:16:36 -05:00
sqlite_migrator make model manager v2 ready for PR review 2024-02-29 13:16:37 -05:00
__init__.py feat(backend): organise service dependencies 2023-10-12 12:15:06 -04:00
default_graphs.py chore: ruff check - fix flake8-comprensions 2023-11-11 10:55:23 +11:00
graph.py feat(nodes): JIT graph nodes validation 2024-02-29 13:28:20 -05:00
invocation_context.py chore: ruff formatting 2024-02-29 13:28:20 -05:00
pagination.py feat(api): chore: pydantic & fastapi upgrade 2023-10-17 14:59:25 +11:00