2023-01-17 10:00:02 +08:00
|
|
|
[build-system]
|
2024-10-08 07:55:49 +08:00
|
|
|
requires = ["setuptools", "pip", "wheel"]
|
2023-01-17 10:00:02 +08:00
|
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
|
|
|
|
[project]
|
|
|
|
name = "InvokeAI"
|
|
|
|
description = "An implementation of Stable Diffusion which provides various new features and options to aid the image generation process"
|
2023-09-28 21:28:41 +08:00
|
|
|
requires-python = ">=3.10, <3.12"
|
2023-01-17 10:00:02 +08:00
|
|
|
readme = { content-type = "text/markdown", file = "README.md" }
|
|
|
|
keywords = ["stable-diffusion", "AI"]
|
|
|
|
dynamic = ["version"]
|
|
|
|
license = { file = "LICENSE" }
|
|
|
|
authors = [{ name = "The InvokeAI Project", email = "lincoln.stein@gmail.com" }]
|
|
|
|
classifiers = [
|
|
|
|
'Development Status :: 4 - Beta',
|
|
|
|
'Environment :: GPU',
|
|
|
|
'Environment :: GPU :: NVIDIA CUDA',
|
|
|
|
'Environment :: MacOS X',
|
|
|
|
'Intended Audience :: End Users/Desktop',
|
|
|
|
'Intended Audience :: Developers',
|
|
|
|
'License :: OSI Approved :: MIT License',
|
|
|
|
'Operating System :: POSIX :: Linux',
|
|
|
|
'Operating System :: MacOS',
|
|
|
|
'Operating System :: Microsoft :: Windows',
|
|
|
|
'Programming Language :: Python :: 3 :: Only',
|
|
|
|
'Programming Language :: Python :: 3.10',
|
|
|
|
'Topic :: Artistic Software',
|
|
|
|
'Topic :: Internet :: WWW/HTTP :: WSGI :: Application',
|
|
|
|
'Topic :: Internet :: WWW/HTTP :: WSGI :: Server',
|
|
|
|
'Topic :: Multimedia :: Graphics',
|
|
|
|
'Topic :: Scientific/Engineering :: Artificial Intelligence',
|
|
|
|
'Topic :: Scientific/Engineering :: Image Processing',
|
|
|
|
]
|
|
|
|
dependencies = [
|
2024-01-10 12:46:07 +08:00
|
|
|
# Core generation dependencies, pinned for reproducible builds.
|
2024-10-24 02:09:35 +08:00
|
|
|
"accelerate==1.0.1",
|
2024-08-22 03:48:21 +08:00
|
|
|
"bitsandbytes==0.43.3; sys_platform!='darwin'",
|
2024-05-09 15:11:27 +08:00
|
|
|
"clip_anytorch==2.6.0", # replacing "clip @ https://github.com/openai/CLIP/archive/eaa22acb90a5876642d0507623e859909230a52d.zip",
|
2024-01-10 12:46:07 +08:00
|
|
|
"compel==2.0.2",
|
|
|
|
"controlnet-aux==0.0.7",
|
2024-10-24 02:09:35 +08:00
|
|
|
"diffusers[torch]==0.31.0",
|
2024-09-27 02:54:36 +08:00
|
|
|
"gguf==0.10.0",
|
2024-01-10 12:46:07 +08:00
|
|
|
"invisible-watermark==0.2.0", # needed to install SDXL base and refiner using their repo_ids
|
2024-11-04 22:36:05 +08:00
|
|
|
"mediapipe==0.10.14", # needed for "mediapipeface" controlnet model
|
2024-10-31 03:16:12 +08:00
|
|
|
"numpy<2.0.0",
|
2024-10-12 02:40:22 +08:00
|
|
|
"onnx==1.16.1",
|
|
|
|
"onnxruntime==1.19.2",
|
2024-01-10 12:46:07 +08:00
|
|
|
"opencv-python==4.9.0.80",
|
|
|
|
"pytorch-lightning==2.1.3",
|
2024-05-09 15:11:27 +08:00
|
|
|
"safetensors==0.4.3",
|
2024-08-07 22:18:19 +08:00
|
|
|
# sentencepiece is required to load T5TokenizerFast (used by FLUX).
|
|
|
|
"sentencepiece==0.2.0",
|
2024-06-28 03:17:22 +08:00
|
|
|
"spandrel==0.3.4",
|
2024-01-10 12:46:07 +08:00
|
|
|
"timm==0.6.13", # needed to override timm latest in controlnet_aux, see https://github.com/isl-org/ZoeDepth/issues/26
|
2024-11-01 23:22:44 +08:00
|
|
|
"torch<2.5.0", # torch and related dependencies are loosely pinned, will respect requirement of `diffusers[torch]`
|
2024-10-31 03:16:12 +08:00
|
|
|
"torchmetrics",
|
|
|
|
"torchsde",
|
|
|
|
"torchvision",
|
2024-11-27 23:17:42 +08:00
|
|
|
"transformers==4.46.3",
|
2024-01-10 12:46:07 +08:00
|
|
|
|
|
|
|
# Core application dependencies, pinned for reproducible builds.
|
2024-07-22 11:18:36 +08:00
|
|
|
"fastapi-events==0.11.1",
|
2024-05-29 15:16:33 +08:00
|
|
|
"fastapi==0.111.0",
|
2024-10-24 02:09:35 +08:00
|
|
|
"huggingface-hub==0.26.1",
|
2024-03-10 15:02:01 +08:00
|
|
|
"pydantic-settings==2.2.1",
|
2024-05-29 15:16:33 +08:00
|
|
|
"pydantic==2.7.2",
|
2024-02-09 05:49:07 +08:00
|
|
|
"python-socketio==5.11.1",
|
2024-03-10 15:02:01 +08:00
|
|
|
"uvicorn[standard]==0.28.0",
|
2024-01-10 12:46:07 +08:00
|
|
|
|
|
|
|
# Auxiliary dependencies, pinned only if necessary.
|
2023-01-17 10:00:02 +08:00
|
|
|
"albumentations",
|
2024-02-27 17:51:49 +08:00
|
|
|
"blake3",
|
2023-02-05 11:05:27 +08:00
|
|
|
"click",
|
2023-01-17 10:00:02 +08:00
|
|
|
"datasets",
|
2024-01-14 17:16:51 +08:00
|
|
|
"Deprecated",
|
2024-10-31 03:16:12 +08:00
|
|
|
"dnspython",
|
2023-06-13 20:05:19 +08:00
|
|
|
"dynamicprompts",
|
2023-01-17 10:00:02 +08:00
|
|
|
"einops",
|
|
|
|
"facexlib",
|
2024-08-05 06:29:02 +08:00
|
|
|
# Exclude 3.9.1 which has a problem on windows, see https://github.com/matplotlib/matplotlib/issues/28551
|
|
|
|
"matplotlib!=3.9.1",
|
2023-01-17 10:00:02 +08:00
|
|
|
"npyscreen",
|
|
|
|
"omegaconf",
|
|
|
|
"picklescan",
|
|
|
|
"pillow",
|
2023-01-27 14:20:50 +08:00
|
|
|
"prompt-toolkit",
|
2024-10-31 03:16:12 +08:00
|
|
|
"pympler",
|
2023-01-17 10:00:02 +08:00
|
|
|
"pypatchmatch",
|
2024-10-31 03:16:12 +08:00
|
|
|
"pyperclip",
|
2023-01-17 10:00:02 +08:00
|
|
|
"pyreadline3",
|
2023-07-25 05:13:32 +08:00
|
|
|
"python-multipart",
|
2024-10-31 03:16:12 +08:00
|
|
|
"requests",
|
2023-03-05 10:37:39 +08:00
|
|
|
"rich~=13.3",
|
2024-10-31 03:16:12 +08:00
|
|
|
"scikit-image",
|
2023-09-04 16:11:56 +08:00
|
|
|
"semver~=3.0.1",
|
2024-10-31 03:16:12 +08:00
|
|
|
"test-tube",
|
2023-01-17 10:00:02 +08:00
|
|
|
"windows-curses; sys_platform=='win32'",
|
|
|
|
]
|
|
|
|
|
|
|
|
[project.optional-dependencies]
|
2024-01-10 12:46:07 +08:00
|
|
|
"xformers" = [
|
|
|
|
# Core generation dependencies, pinned for reproducible builds.
|
2024-10-31 03:16:12 +08:00
|
|
|
"xformers>=0.0.28.post1; sys_platform!='darwin'",
|
2024-01-10 12:46:07 +08:00
|
|
|
# Auxiliary dependencies, pinned only if necessary.
|
|
|
|
"triton; sys_platform=='linux'",
|
|
|
|
]
|
|
|
|
"onnx" = ["onnxruntime"]
|
|
|
|
"onnx-cuda" = ["onnxruntime-gpu"]
|
|
|
|
"onnx-directml" = ["onnxruntime-directml"]
|
2023-01-17 10:00:02 +08:00
|
|
|
"dist" = ["pip-tools", "pipdeptree", "twine"]
|
|
|
|
"docs" = [
|
2024-09-22 14:57:25 +08:00
|
|
|
"mkdocs-material>=9.5.36",
|
2023-01-17 10:00:02 +08:00
|
|
|
"mkdocs-git-revision-date-localized-plugin",
|
2024-02-29 19:32:29 +08:00
|
|
|
"mkdocs-redirects",
|
2024-09-22 14:57:25 +08:00
|
|
|
"mkdocstrings[python]>=0.26.1",
|
2023-01-17 10:00:02 +08:00
|
|
|
]
|
2024-01-31 18:51:57 +08:00
|
|
|
"dev" = ["jurigged", "pudb", "snakeviz", "gprof2dot"]
|
2023-08-18 06:45:25 +08:00
|
|
|
"test" = [
|
2024-03-21 09:04:17 +08:00
|
|
|
"ruff>=0.3.3",
|
|
|
|
"ruff-lsp>=0.0.53",
|
feat(api): chore: pydantic & fastapi upgrade
Upgrade pydantic and fastapi to latest.
- pydantic~=2.4.2
- fastapi~=103.2
- fastapi-events~=0.9.1
**Big Changes**
There are a number of logic changes needed to support pydantic v2. Most changes are very simple, like using the new methods to serialized and deserialize models, but there are a few more complex changes.
**Invocations**
The biggest change relates to invocation creation, instantiation and validation.
Because pydantic v2 moves all validation logic into the rust pydantic-core, we may no longer directly stick our fingers into the validation pie.
Previously, we (ab)used models and fields to allow invocation fields to be optional at instantiation, but required when `invoke()` is called. We directly manipulated the fields and invocation models when calling `invoke()`.
With pydantic v2, this is much more involved. Changes to the python wrapper do not propagate down to the rust validation logic - you have to rebuild the model. This causes problem with concurrent access to the invocation classes and is not a free operation.
This logic has been totally refactored and we do not need to change the model any more. The details are in `baseinvocation.py`, in the `InputField` function and `BaseInvocation.invoke_internal()` method.
In the end, this implementation is cleaner.
**Invocation Fields**
In pydantic v2, you can no longer directly add or remove fields from a model.
Previously, we did this to add the `type` field to invocations.
**Invocation Decorators**
With pydantic v2, we instead use the imperative `create_model()` API to create a new model with the additional field. This is done in `baseinvocation.py` in the `invocation()` wrapper.
A similar technique is used for `invocation_output()`.
**Minor Changes**
There are a number of minor changes around the pydantic v2 models API.
**Protected `model_` Namespace**
All models' pydantic-provided methods and attributes are prefixed with `model_` and this is considered a protected namespace. This causes some conflict, because "model" means something to us, and we have a ton of pydantic models with attributes starting with "model_".
Forunately, there are no direct conflicts. However, in any pydantic model where we define an attribute or method that starts with "model_", we must tell set the protected namespaces to an empty tuple.
```py
class IPAdapterModelField(BaseModel):
model_name: str = Field(description="Name of the IP-Adapter model")
base_model: BaseModelType = Field(description="Base model")
model_config = ConfigDict(protected_namespaces=())
```
**Model Serialization**
Pydantic models no longer have `Model.dict()` or `Model.json()`.
Instead, we use `Model.model_dump()` or `Model.model_dump_json()`.
**Model Deserialization**
Pydantic models no longer have `Model.parse_obj()` or `Model.parse_raw()`, and there are no `parse_raw_as()` or `parse_obj_as()` functions.
Instead, you need to create a `TypeAdapter` object to parse python objects or JSON into a model.
```py
adapter_graph = TypeAdapter(Graph)
deserialized_graph_from_json = adapter_graph.validate_json(graph_json)
deserialized_graph_from_dict = adapter_graph.validate_python(graph_dict)
```
**Field Customisation**
Pydantic `Field`s no longer accept arbitrary args.
Now, you must put all additional arbitrary args in a `json_schema_extra` arg on the field.
**Schema Customisation**
FastAPI and pydantic schema generation now follows the OpenAPI version 3.1 spec.
This necessitates two changes:
- Our schema customization logic has been revised
- Schema parsing to build node templates has been revised
The specific aren't important, but this does present additional surface area for bugs.
**Performance Improvements**
Pydantic v2 is a full rewrite with a rust backend. This offers a substantial performance improvement (pydantic claims 5x to 50x depending on the task). We'll notice this the most during serialization and deserialization of sessions/graphs, which happens very very often - a couple times per node.
I haven't done any benchmarks, but anecdotally, graph execution is much faster. Also, very larges graphs - like with massive iterators - are much, much faster.
2023-09-24 16:11:07 +08:00
|
|
|
"mypy",
|
2023-08-20 09:17:44 +08:00
|
|
|
"pre-commit",
|
2023-08-18 06:45:25 +08:00
|
|
|
"pytest>6.0.0",
|
|
|
|
"pytest-cov",
|
2024-02-29 19:34:59 +08:00
|
|
|
"pytest-timeout",
|
2023-08-18 06:45:25 +08:00
|
|
|
"pytest-datadir",
|
2023-12-23 01:35:57 +08:00
|
|
|
"requests_testadapter",
|
2024-01-16 08:11:03 +08:00
|
|
|
"httpx",
|
2023-08-18 06:45:25 +08:00
|
|
|
]
|
2023-01-17 10:00:02 +08:00
|
|
|
|
|
|
|
[project.scripts]
|
feat: single app entrypoint with CLI arg parsing
We have two problems with how argparse is being utilized:
- We parse CLI args as the `api_app.py` file is read. This causes a problem pytest, which has an incompatible set of CLI args. Some tests import the FastAPI app, which triggers the config to parse CLI args, which receives the pytest args and fails.
- We've repeatedly had problems when something that uses the config is imported before the CLI args are parsed. When this happens, the root dir may not be set correctly, so we attempt to operate on incorrect paths.
To resolve these issues, we need to lift CLI arg parsing outside of the application code, but still let the application access the CLI args. We can create a external app entrypoint to do this.
- `InvokeAIArgs` is a simple helper class that parses CLI args and stores the result.
- `run_app()` is the new entrypoint. It first parses CLI args, then runs `invoke_api` to start the app.
The `invokeai-web` project script and `invokeai-web.py` dev script now call `run_app()` instead of `invoke_api()`.
The first time `get_config()` is called to get the singleton config object, it retrieves the args from `InvokeAIArgs`, sets the root dir if provided, then merges settings in from `invokeai.yaml`.
CLI arg parsing is now safely insulated from application code, but still accessible. And we don't need to worry about import order having an impact on anything, because by the time the app is running, we have already parsed CLI args. Whew!
2024-03-15 13:33:52 +08:00
|
|
|
"invokeai-web" = "invokeai.app.run_app:run_app"
|
2023-01-17 10:00:02 +08:00
|
|
|
|
|
|
|
[project.urls]
|
|
|
|
"Homepage" = "https://invoke-ai.github.io/InvokeAI/"
|
|
|
|
"Documentation" = "https://invoke-ai.github.io/InvokeAI/"
|
|
|
|
"Source" = "https://github.com/invoke-ai/InvokeAI/"
|
|
|
|
"Bug Reports" = "https://github.com/invoke-ai/InvokeAI/issues"
|
|
|
|
"Discord" = "https://discord.gg/ZmtBAhwWhy"
|
|
|
|
|
|
|
|
[tool.setuptools.dynamic]
|
2023-03-03 02:28:17 +08:00
|
|
|
version = { attr = "invokeai.version.__version__" }
|
2023-01-17 10:00:02 +08:00
|
|
|
|
|
|
|
[tool.setuptools.packages.find]
|
|
|
|
"where" = ["."]
|
first phase of source tree restructure
This is the first phase of a big shifting of files and directories
in the source tree.
You will need to run `pip install -e .` before the code will work again!
Here's what's in the current commit:
1) Remove a lot of dead code that dealt with checkpoint and safetensor loading.
2) Entire ckpt_generator hierarchy is now gone!
3) ldm.invoke.generator.* => invokeai.generator.*
4) ldm.model.* => invokeai.model.*
5) ldm.invoke.model_manager => invokeai.model.model_manager
6) In addition, a number of frequently-accessed classes can be imported
from the invokeai.model and invokeai.generator modules:
from invokeai.generator import ( Generator, PipelineIntermediateState,
StableDiffusionGeneratorPipeline, infill_methods)
from invokeai.models import ( ModelManager, SDLegacyType
InvokeAIDiffuserComponent, AttentionMapSaver,
DDIMSampler, KSampler, PLMSSampler,
PostprocessingSettings )
2023-02-28 12:52:46 +08:00
|
|
|
"include" = [
|
feat(api): chore: pydantic & fastapi upgrade
Upgrade pydantic and fastapi to latest.
- pydantic~=2.4.2
- fastapi~=103.2
- fastapi-events~=0.9.1
**Big Changes**
There are a number of logic changes needed to support pydantic v2. Most changes are very simple, like using the new methods to serialized and deserialize models, but there are a few more complex changes.
**Invocations**
The biggest change relates to invocation creation, instantiation and validation.
Because pydantic v2 moves all validation logic into the rust pydantic-core, we may no longer directly stick our fingers into the validation pie.
Previously, we (ab)used models and fields to allow invocation fields to be optional at instantiation, but required when `invoke()` is called. We directly manipulated the fields and invocation models when calling `invoke()`.
With pydantic v2, this is much more involved. Changes to the python wrapper do not propagate down to the rust validation logic - you have to rebuild the model. This causes problem with concurrent access to the invocation classes and is not a free operation.
This logic has been totally refactored and we do not need to change the model any more. The details are in `baseinvocation.py`, in the `InputField` function and `BaseInvocation.invoke_internal()` method.
In the end, this implementation is cleaner.
**Invocation Fields**
In pydantic v2, you can no longer directly add or remove fields from a model.
Previously, we did this to add the `type` field to invocations.
**Invocation Decorators**
With pydantic v2, we instead use the imperative `create_model()` API to create a new model with the additional field. This is done in `baseinvocation.py` in the `invocation()` wrapper.
A similar technique is used for `invocation_output()`.
**Minor Changes**
There are a number of minor changes around the pydantic v2 models API.
**Protected `model_` Namespace**
All models' pydantic-provided methods and attributes are prefixed with `model_` and this is considered a protected namespace. This causes some conflict, because "model" means something to us, and we have a ton of pydantic models with attributes starting with "model_".
Forunately, there are no direct conflicts. However, in any pydantic model where we define an attribute or method that starts with "model_", we must tell set the protected namespaces to an empty tuple.
```py
class IPAdapterModelField(BaseModel):
model_name: str = Field(description="Name of the IP-Adapter model")
base_model: BaseModelType = Field(description="Base model")
model_config = ConfigDict(protected_namespaces=())
```
**Model Serialization**
Pydantic models no longer have `Model.dict()` or `Model.json()`.
Instead, we use `Model.model_dump()` or `Model.model_dump_json()`.
**Model Deserialization**
Pydantic models no longer have `Model.parse_obj()` or `Model.parse_raw()`, and there are no `parse_raw_as()` or `parse_obj_as()` functions.
Instead, you need to create a `TypeAdapter` object to parse python objects or JSON into a model.
```py
adapter_graph = TypeAdapter(Graph)
deserialized_graph_from_json = adapter_graph.validate_json(graph_json)
deserialized_graph_from_dict = adapter_graph.validate_python(graph_dict)
```
**Field Customisation**
Pydantic `Field`s no longer accept arbitrary args.
Now, you must put all additional arbitrary args in a `json_schema_extra` arg on the field.
**Schema Customisation**
FastAPI and pydantic schema generation now follows the OpenAPI version 3.1 spec.
This necessitates two changes:
- Our schema customization logic has been revised
- Schema parsing to build node templates has been revised
The specific aren't important, but this does present additional surface area for bugs.
**Performance Improvements**
Pydantic v2 is a full rewrite with a rust backend. This offers a substantial performance improvement (pydantic claims 5x to 50x depending on the task). We'll notice this the most during serialization and deserialization of sessions/graphs, which happens very very often - a couple times per node.
I haven't done any benchmarks, but anecdotally, graph execution is much faster. Also, very larges graphs - like with massive iterators - are much, much faster.
2023-09-24 16:11:07 +08:00
|
|
|
"invokeai.assets.fonts*",
|
|
|
|
"invokeai.version*",
|
|
|
|
"invokeai.generator*",
|
|
|
|
"invokeai.backend*",
|
|
|
|
"invokeai.frontend*",
|
|
|
|
"invokeai.frontend.web.dist*",
|
|
|
|
"invokeai.frontend.web.static*",
|
|
|
|
"invokeai.configs*",
|
|
|
|
"invokeai.app*",
|
2024-01-15 07:48:33 +08:00
|
|
|
"invokeai.invocation_api*",
|
first phase of source tree restructure
This is the first phase of a big shifting of files and directories
in the source tree.
You will need to run `pip install -e .` before the code will work again!
Here's what's in the current commit:
1) Remove a lot of dead code that dealt with checkpoint and safetensor loading.
2) Entire ckpt_generator hierarchy is now gone!
3) ldm.invoke.generator.* => invokeai.generator.*
4) ldm.model.* => invokeai.model.*
5) ldm.invoke.model_manager => invokeai.model.model_manager
6) In addition, a number of frequently-accessed classes can be imported
from the invokeai.model and invokeai.generator modules:
from invokeai.generator import ( Generator, PipelineIntermediateState,
StableDiffusionGeneratorPipeline, infill_methods)
from invokeai.models import ( ModelManager, SDLegacyType
InvokeAIDiffuserComponent, AttentionMapSaver,
DDIMSampler, KSampler, PLMSSampler,
PostprocessingSettings )
2023-02-28 12:52:46 +08:00
|
|
|
]
|
2023-01-17 10:00:02 +08:00
|
|
|
|
|
|
|
[tool.setuptools.package-data]
|
2023-10-20 00:13:36 +08:00
|
|
|
"invokeai.app.assets" = ["**/*.png"]
|
feat: workflow library (#5148)
* chore: bump pydantic to 2.5.2
This release fixes pydantic/pydantic#8175 and allows us to use `JsonValue`
* fix(ui): exclude public/en.json from prettier config
* fix(workflow_records): fix SQLite workflow insertion to ignore duplicates
* feat(backend): update workflows handling
Update workflows handling for Workflow Library.
**Updated Workflow Storage**
"Embedded Workflows" are workflows associated with images, and are now only stored in the image files. "Library Workflows" are not associated with images, and are stored only in DB.
This works out nicely. We have always saved workflows to files, but recently began saving them to the DB in addition to in image files. When that happened, we stopped reading workflows from files, so all the workflows that only existed in images were inaccessible. With this change, access to those workflows is restored, and no workflows are lost.
**Updated Workflow Handling in Nodes**
Prior to this change, workflows were embedded in images by passing the whole workflow JSON to a special workflow field on a node. In the node's `invoke()` function, the node was able to access this workflow and save it with the image. This (inaccurately) models workflows as a property of an image and is rather awkward technically.
A workflow is now a property of a batch/session queue item. It is available in the InvocationContext and therefore available to all nodes during `invoke()`.
**Database Migrations**
Added a `SQLiteMigrator` class to handle database migrations. Migrations were needed to accomodate the DB-related changes in this PR. See the code for details.
The `images`, `workflows` and `session_queue` tables required migrations for this PR, and are using the new migrator. Other tables/services are still creating tables themselves. A followup PR will adapt them to use the migrator.
**Other/Support Changes**
- Add a `has_workflow` column to `images` table to indicate that the image has an embedded workflow.
- Add handling for retrieving the workflow from an image in python. The image file must be fetched, the workflow extracted, and then sent to client, avoiding needing the browser to parse the image file. With the `has_workflow` column, the UI knows if there is a workflow to be fetched, and only fetches when the user requests to load the workflow.
- Add route to get the workflow from an image
- Add CRUD service/routes for the library workflows
- `workflow_images` table and services removed (no longer needed now that embedded workflows are not in the DB)
* feat(ui): updated workflow handling (WIP)
Clientside updates for the backend workflow changes.
Includes roughed-out workflow library UI.
* feat: revert SQLiteMigrator class
Will pursue this in a separate PR.
* feat(nodes): do not overwrite custom node module names
Use a different, simpler method to detect if a node is custom.
* feat(nodes): restore WithWorkflow as no-op class
This class is deprecated and no longer needed. Set its workflow attr value to None (meaning it is now a no-op), and issue a warning when an invocation subclasses it.
* fix(nodes): fix get_workflow from queue item dict func
* feat(backend): add WorkflowRecordListItemDTO
This is the id, name, description, created at and updated at workflow columns/attrs. Used to display lists of workflowsl
* chore(ui): typegen
* feat(ui): add workflow loading, deleting to workflow library UI
* feat(ui): workflow library pagination button styles
* wip
* feat: workflow library WIP
- Save to library
- Duplicate
- Filter/sort
- UI/queries
* feat: workflow library - system graphs - wip
* feat(backend): sync system workflows to db
* fix: merge conflicts
* feat: simplify default workflows
- Rename "system" -> "default"
- Simplify syncing logic
- Update UI to match
* feat(workflows): update default workflows
- Update TextToImage_SD15
- Add TextToImage_SDXL
- Add README
* feat(ui): refine workflow list UI
* fix(workflow_records): typo
* fix(tests): fix tests
* feat(ui): clean up workflow library hooks
* fix(db): fix mis-ordered db cleanup step
It was happening before pruning queue items - should happen afterwards, else you have to restart the app again to free disk space made available by the pruning.
* feat(ui): tweak reset workflow editor translations
* feat(ui): split out workflow redux state
The `nodes` slice is a rather complicated slice. Removing `workflow` makes it a bit more reasonable.
Also helps to flatten state out a bit.
* docs: update default workflows README
* fix: tidy up unused files, unrelated changes
* fix(backend): revert unrelated service organisational changes
* feat(backend): workflow_records.get_many arg "filter_text" -> "query"
* feat(ui): use custom hook in current image buttons
Already in use elsewhere, forgot to use it here.
* fix(ui): remove commented out property
* fix(ui): fix workflow loading
- Different handling for loading from library vs external
- Fix bug where only nodes and edges loaded
* fix(ui): fix save/save-as workflow naming
* fix(ui): fix circular dependency
* fix(db): fix bug with releasing without lock in db.clean()
* fix(db): remove extraneous lock
* chore: bump ruff
* fix(workflow_records): default `category` to `WorkflowCategory.User`
This allows old workflows to validate when reading them from the db or image files.
* hide workflow library buttons if feature is disabled
---------
Co-authored-by: Mary Hipp <maryhipp@Marys-MacBook-Air.local>
2023-12-09 06:48:38 +08:00
|
|
|
"invokeai.app.services.workflow_records.default_workflows" = ["*.json"]
|
2024-08-16 19:12:35 +08:00
|
|
|
"invokeai.app.services.style_preset_records" = ["*.json"]
|
|
|
|
"invokeai.app.services.style_preset_images.default_style_preset_images" = [
|
|
|
|
"*.png",
|
|
|
|
]
|
2023-10-03 20:48:50 +08:00
|
|
|
"invokeai.assets.fonts" = ["**/*.ttf"]
|
2024-11-19 03:47:52 +08:00
|
|
|
"invokeai.backend" = ["**.png", "**/*.icc"]
|
2023-01-31 07:42:17 +08:00
|
|
|
"invokeai.configs" = ["*.example", "**/*.yaml", "*.txt"]
|
2023-03-03 13:02:15 +08:00
|
|
|
"invokeai.frontend.web.dist" = ["**"]
|
2023-05-23 04:48:17 +08:00
|
|
|
"invokeai.frontend.web.static" = ["**"]
|
2023-10-20 12:18:29 +08:00
|
|
|
"invokeai.app.invocations" = ["**"]
|
2023-01-17 10:00:02 +08:00
|
|
|
|
2023-03-06 01:00:08 +08:00
|
|
|
#=== Begin: PyTest and Coverage
|
2023-01-17 10:00:02 +08:00
|
|
|
[tool.pytest.ini_options]
|
2024-03-04 18:12:13 +08:00
|
|
|
addopts = "--cov-report term --cov-report html --cov-report xml --strict-markers -m \"not slow\""
|
2023-09-23 06:44:10 +08:00
|
|
|
markers = [
|
feat(api): chore: pydantic & fastapi upgrade
Upgrade pydantic and fastapi to latest.
- pydantic~=2.4.2
- fastapi~=103.2
- fastapi-events~=0.9.1
**Big Changes**
There are a number of logic changes needed to support pydantic v2. Most changes are very simple, like using the new methods to serialized and deserialize models, but there are a few more complex changes.
**Invocations**
The biggest change relates to invocation creation, instantiation and validation.
Because pydantic v2 moves all validation logic into the rust pydantic-core, we may no longer directly stick our fingers into the validation pie.
Previously, we (ab)used models and fields to allow invocation fields to be optional at instantiation, but required when `invoke()` is called. We directly manipulated the fields and invocation models when calling `invoke()`.
With pydantic v2, this is much more involved. Changes to the python wrapper do not propagate down to the rust validation logic - you have to rebuild the model. This causes problem with concurrent access to the invocation classes and is not a free operation.
This logic has been totally refactored and we do not need to change the model any more. The details are in `baseinvocation.py`, in the `InputField` function and `BaseInvocation.invoke_internal()` method.
In the end, this implementation is cleaner.
**Invocation Fields**
In pydantic v2, you can no longer directly add or remove fields from a model.
Previously, we did this to add the `type` field to invocations.
**Invocation Decorators**
With pydantic v2, we instead use the imperative `create_model()` API to create a new model with the additional field. This is done in `baseinvocation.py` in the `invocation()` wrapper.
A similar technique is used for `invocation_output()`.
**Minor Changes**
There are a number of minor changes around the pydantic v2 models API.
**Protected `model_` Namespace**
All models' pydantic-provided methods and attributes are prefixed with `model_` and this is considered a protected namespace. This causes some conflict, because "model" means something to us, and we have a ton of pydantic models with attributes starting with "model_".
Forunately, there are no direct conflicts. However, in any pydantic model where we define an attribute or method that starts with "model_", we must tell set the protected namespaces to an empty tuple.
```py
class IPAdapterModelField(BaseModel):
model_name: str = Field(description="Name of the IP-Adapter model")
base_model: BaseModelType = Field(description="Base model")
model_config = ConfigDict(protected_namespaces=())
```
**Model Serialization**
Pydantic models no longer have `Model.dict()` or `Model.json()`.
Instead, we use `Model.model_dump()` or `Model.model_dump_json()`.
**Model Deserialization**
Pydantic models no longer have `Model.parse_obj()` or `Model.parse_raw()`, and there are no `parse_raw_as()` or `parse_obj_as()` functions.
Instead, you need to create a `TypeAdapter` object to parse python objects or JSON into a model.
```py
adapter_graph = TypeAdapter(Graph)
deserialized_graph_from_json = adapter_graph.validate_json(graph_json)
deserialized_graph_from_dict = adapter_graph.validate_python(graph_dict)
```
**Field Customisation**
Pydantic `Field`s no longer accept arbitrary args.
Now, you must put all additional arbitrary args in a `json_schema_extra` arg on the field.
**Schema Customisation**
FastAPI and pydantic schema generation now follows the OpenAPI version 3.1 spec.
This necessitates two changes:
- Our schema customization logic has been revised
- Schema parsing to build node templates has been revised
The specific aren't important, but this does present additional surface area for bugs.
**Performance Improvements**
Pydantic v2 is a full rewrite with a rust backend. This offers a substantial performance improvement (pydantic claims 5x to 50x depending on the task). We'll notice this the most during serialization and deserialization of sessions/graphs, which happens very very often - a couple times per node.
I haven't done any benchmarks, but anecdotally, graph execution is much faster. Also, very larges graphs - like with massive iterators - are much, much faster.
2023-09-24 16:11:07 +08:00
|
|
|
"slow: Marks tests as slow. Disabled by default. To run all tests, use -m \"\". To run only slow tests, use -m \"slow\".",
|
2024-03-19 13:54:04 +08:00
|
|
|
"timeout: Marks the timeout override.",
|
2023-09-23 06:44:10 +08:00
|
|
|
]
|
2023-03-06 01:00:08 +08:00
|
|
|
[tool.coverage.run]
|
|
|
|
branch = true
|
|
|
|
source = ["invokeai"]
|
|
|
|
omit = ["*tests*", "*migrations*", ".venv/*", "*.env"]
|
|
|
|
[tool.coverage.report]
|
|
|
|
show_missing = true
|
feat(api): chore: pydantic & fastapi upgrade
Upgrade pydantic and fastapi to latest.
- pydantic~=2.4.2
- fastapi~=103.2
- fastapi-events~=0.9.1
**Big Changes**
There are a number of logic changes needed to support pydantic v2. Most changes are very simple, like using the new methods to serialized and deserialize models, but there are a few more complex changes.
**Invocations**
The biggest change relates to invocation creation, instantiation and validation.
Because pydantic v2 moves all validation logic into the rust pydantic-core, we may no longer directly stick our fingers into the validation pie.
Previously, we (ab)used models and fields to allow invocation fields to be optional at instantiation, but required when `invoke()` is called. We directly manipulated the fields and invocation models when calling `invoke()`.
With pydantic v2, this is much more involved. Changes to the python wrapper do not propagate down to the rust validation logic - you have to rebuild the model. This causes problem with concurrent access to the invocation classes and is not a free operation.
This logic has been totally refactored and we do not need to change the model any more. The details are in `baseinvocation.py`, in the `InputField` function and `BaseInvocation.invoke_internal()` method.
In the end, this implementation is cleaner.
**Invocation Fields**
In pydantic v2, you can no longer directly add or remove fields from a model.
Previously, we did this to add the `type` field to invocations.
**Invocation Decorators**
With pydantic v2, we instead use the imperative `create_model()` API to create a new model with the additional field. This is done in `baseinvocation.py` in the `invocation()` wrapper.
A similar technique is used for `invocation_output()`.
**Minor Changes**
There are a number of minor changes around the pydantic v2 models API.
**Protected `model_` Namespace**
All models' pydantic-provided methods and attributes are prefixed with `model_` and this is considered a protected namespace. This causes some conflict, because "model" means something to us, and we have a ton of pydantic models with attributes starting with "model_".
Forunately, there are no direct conflicts. However, in any pydantic model where we define an attribute or method that starts with "model_", we must tell set the protected namespaces to an empty tuple.
```py
class IPAdapterModelField(BaseModel):
model_name: str = Field(description="Name of the IP-Adapter model")
base_model: BaseModelType = Field(description="Base model")
model_config = ConfigDict(protected_namespaces=())
```
**Model Serialization**
Pydantic models no longer have `Model.dict()` or `Model.json()`.
Instead, we use `Model.model_dump()` or `Model.model_dump_json()`.
**Model Deserialization**
Pydantic models no longer have `Model.parse_obj()` or `Model.parse_raw()`, and there are no `parse_raw_as()` or `parse_obj_as()` functions.
Instead, you need to create a `TypeAdapter` object to parse python objects or JSON into a model.
```py
adapter_graph = TypeAdapter(Graph)
deserialized_graph_from_json = adapter_graph.validate_json(graph_json)
deserialized_graph_from_dict = adapter_graph.validate_python(graph_dict)
```
**Field Customisation**
Pydantic `Field`s no longer accept arbitrary args.
Now, you must put all additional arbitrary args in a `json_schema_extra` arg on the field.
**Schema Customisation**
FastAPI and pydantic schema generation now follows the OpenAPI version 3.1 spec.
This necessitates two changes:
- Our schema customization logic has been revised
- Schema parsing to build node templates has been revised
The specific aren't important, but this does present additional surface area for bugs.
**Performance Improvements**
Pydantic v2 is a full rewrite with a rust backend. This offers a substantial performance improvement (pydantic claims 5x to 50x depending on the task). We'll notice this the most during serialization and deserialization of sessions/graphs, which happens very very often - a couple times per node.
I haven't done any benchmarks, but anecdotally, graph execution is much faster. Also, very larges graphs - like with massive iterators - are much, much faster.
2023-09-24 16:11:07 +08:00
|
|
|
fail_under = 85 # let's set something sensible on Day 1 ...
|
2023-03-06 01:00:08 +08:00
|
|
|
[tool.coverage.json]
|
|
|
|
output = "coverage/coverage.json"
|
|
|
|
pretty_print = true
|
|
|
|
[tool.coverage.html]
|
|
|
|
directory = "coverage/html"
|
|
|
|
[tool.coverage.xml]
|
|
|
|
output = "coverage/index.xml"
|
|
|
|
#=== End: PyTest and Coverage
|
2023-03-03 14:02:00 +08:00
|
|
|
|
2023-11-11 07:06:21 +08:00
|
|
|
#=== Begin: Ruff
|
|
|
|
[tool.ruff]
|
|
|
|
line-length = 120
|
2023-09-16 23:47:05 +08:00
|
|
|
exclude = [
|
|
|
|
".git",
|
|
|
|
"__pycache__",
|
|
|
|
"build",
|
|
|
|
"dist",
|
feat(api): chore: pydantic & fastapi upgrade
Upgrade pydantic and fastapi to latest.
- pydantic~=2.4.2
- fastapi~=103.2
- fastapi-events~=0.9.1
**Big Changes**
There are a number of logic changes needed to support pydantic v2. Most changes are very simple, like using the new methods to serialized and deserialize models, but there are a few more complex changes.
**Invocations**
The biggest change relates to invocation creation, instantiation and validation.
Because pydantic v2 moves all validation logic into the rust pydantic-core, we may no longer directly stick our fingers into the validation pie.
Previously, we (ab)used models and fields to allow invocation fields to be optional at instantiation, but required when `invoke()` is called. We directly manipulated the fields and invocation models when calling `invoke()`.
With pydantic v2, this is much more involved. Changes to the python wrapper do not propagate down to the rust validation logic - you have to rebuild the model. This causes problem with concurrent access to the invocation classes and is not a free operation.
This logic has been totally refactored and we do not need to change the model any more. The details are in `baseinvocation.py`, in the `InputField` function and `BaseInvocation.invoke_internal()` method.
In the end, this implementation is cleaner.
**Invocation Fields**
In pydantic v2, you can no longer directly add or remove fields from a model.
Previously, we did this to add the `type` field to invocations.
**Invocation Decorators**
With pydantic v2, we instead use the imperative `create_model()` API to create a new model with the additional field. This is done in `baseinvocation.py` in the `invocation()` wrapper.
A similar technique is used for `invocation_output()`.
**Minor Changes**
There are a number of minor changes around the pydantic v2 models API.
**Protected `model_` Namespace**
All models' pydantic-provided methods and attributes are prefixed with `model_` and this is considered a protected namespace. This causes some conflict, because "model" means something to us, and we have a ton of pydantic models with attributes starting with "model_".
Forunately, there are no direct conflicts. However, in any pydantic model where we define an attribute or method that starts with "model_", we must tell set the protected namespaces to an empty tuple.
```py
class IPAdapterModelField(BaseModel):
model_name: str = Field(description="Name of the IP-Adapter model")
base_model: BaseModelType = Field(description="Base model")
model_config = ConfigDict(protected_namespaces=())
```
**Model Serialization**
Pydantic models no longer have `Model.dict()` or `Model.json()`.
Instead, we use `Model.model_dump()` or `Model.model_dump_json()`.
**Model Deserialization**
Pydantic models no longer have `Model.parse_obj()` or `Model.parse_raw()`, and there are no `parse_raw_as()` or `parse_obj_as()` functions.
Instead, you need to create a `TypeAdapter` object to parse python objects or JSON into a model.
```py
adapter_graph = TypeAdapter(Graph)
deserialized_graph_from_json = adapter_graph.validate_json(graph_json)
deserialized_graph_from_dict = adapter_graph.validate_python(graph_dict)
```
**Field Customisation**
Pydantic `Field`s no longer accept arbitrary args.
Now, you must put all additional arbitrary args in a `json_schema_extra` arg on the field.
**Schema Customisation**
FastAPI and pydantic schema generation now follows the OpenAPI version 3.1 spec.
This necessitates two changes:
- Our schema customization logic has been revised
- Schema parsing to build node templates has been revised
The specific aren't important, but this does present additional surface area for bugs.
**Performance Improvements**
Pydantic v2 is a full rewrite with a rust backend. This offers a substantial performance improvement (pydantic claims 5x to 50x depending on the task). We'll notice this the most during serialization and deserialization of sessions/graphs, which happens very very often - a couple times per node.
I haven't done any benchmarks, but anecdotally, graph execution is much faster. Also, very larges graphs - like with massive iterators - are much, much faster.
2023-09-24 16:11:07 +08:00
|
|
|
"invokeai/frontend/web/node_modules/",
|
2023-10-31 00:34:30 +08:00
|
|
|
".venv*",
|
2024-08-15 21:33:58 +08:00
|
|
|
"*.ipynb",
|
2024-09-10 18:58:38 +08:00
|
|
|
"invokeai/backend/image_util/mediapipe_face/", # External code
|
2024-09-10 18:59:07 +08:00
|
|
|
"invokeai/backend/image_util/mlsd/", # External code
|
2024-09-10 19:00:43 +08:00
|
|
|
"invokeai/backend/image_util/normal_bae/", # External code
|
2024-09-10 19:01:33 +08:00
|
|
|
"invokeai/backend/image_util/pidi/", # External code
|
2023-09-16 23:47:05 +08:00
|
|
|
]
|
2024-02-10 21:36:54 +08:00
|
|
|
|
|
|
|
[tool.ruff.lint]
|
|
|
|
ignore = [
|
|
|
|
"E501", # https://docs.astral.sh/ruff/rules/line-too-long/
|
|
|
|
"C901", # https://docs.astral.sh/ruff/rules/complex-structure/
|
|
|
|
"B008", # https://docs.astral.sh/ruff/rules/function-call-in-default-argument/
|
|
|
|
"B904", # https://docs.astral.sh/ruff/rules/raise-without-from-inside-except/
|
|
|
|
]
|
2024-07-04 00:04:22 +08:00
|
|
|
select = ["B", "C", "E", "F", "W", "I", "TID"]
|
|
|
|
|
|
|
|
[tool.ruff.lint.flake8-tidy-imports]
|
|
|
|
# Disallow all relative imports.
|
2024-07-04 00:20:35 +08:00
|
|
|
ban-relative-imports = "all"
|
2024-07-04 00:04:22 +08:00
|
|
|
|
2023-11-11 07:06:21 +08:00
|
|
|
#=== End: Ruff
|
2023-07-28 21:46:44 +08:00
|
|
|
|
2023-11-11 07:06:21 +08:00
|
|
|
#=== Begin: MyPy
|
2023-11-21 04:13:17 +08:00
|
|
|
|
|
|
|
# global mypy config
|
feat(api): chore: pydantic & fastapi upgrade
Upgrade pydantic and fastapi to latest.
- pydantic~=2.4.2
- fastapi~=103.2
- fastapi-events~=0.9.1
**Big Changes**
There are a number of logic changes needed to support pydantic v2. Most changes are very simple, like using the new methods to serialized and deserialize models, but there are a few more complex changes.
**Invocations**
The biggest change relates to invocation creation, instantiation and validation.
Because pydantic v2 moves all validation logic into the rust pydantic-core, we may no longer directly stick our fingers into the validation pie.
Previously, we (ab)used models and fields to allow invocation fields to be optional at instantiation, but required when `invoke()` is called. We directly manipulated the fields and invocation models when calling `invoke()`.
With pydantic v2, this is much more involved. Changes to the python wrapper do not propagate down to the rust validation logic - you have to rebuild the model. This causes problem with concurrent access to the invocation classes and is not a free operation.
This logic has been totally refactored and we do not need to change the model any more. The details are in `baseinvocation.py`, in the `InputField` function and `BaseInvocation.invoke_internal()` method.
In the end, this implementation is cleaner.
**Invocation Fields**
In pydantic v2, you can no longer directly add or remove fields from a model.
Previously, we did this to add the `type` field to invocations.
**Invocation Decorators**
With pydantic v2, we instead use the imperative `create_model()` API to create a new model with the additional field. This is done in `baseinvocation.py` in the `invocation()` wrapper.
A similar technique is used for `invocation_output()`.
**Minor Changes**
There are a number of minor changes around the pydantic v2 models API.
**Protected `model_` Namespace**
All models' pydantic-provided methods and attributes are prefixed with `model_` and this is considered a protected namespace. This causes some conflict, because "model" means something to us, and we have a ton of pydantic models with attributes starting with "model_".
Forunately, there are no direct conflicts. However, in any pydantic model where we define an attribute or method that starts with "model_", we must tell set the protected namespaces to an empty tuple.
```py
class IPAdapterModelField(BaseModel):
model_name: str = Field(description="Name of the IP-Adapter model")
base_model: BaseModelType = Field(description="Base model")
model_config = ConfigDict(protected_namespaces=())
```
**Model Serialization**
Pydantic models no longer have `Model.dict()` or `Model.json()`.
Instead, we use `Model.model_dump()` or `Model.model_dump_json()`.
**Model Deserialization**
Pydantic models no longer have `Model.parse_obj()` or `Model.parse_raw()`, and there are no `parse_raw_as()` or `parse_obj_as()` functions.
Instead, you need to create a `TypeAdapter` object to parse python objects or JSON into a model.
```py
adapter_graph = TypeAdapter(Graph)
deserialized_graph_from_json = adapter_graph.validate_json(graph_json)
deserialized_graph_from_dict = adapter_graph.validate_python(graph_dict)
```
**Field Customisation**
Pydantic `Field`s no longer accept arbitrary args.
Now, you must put all additional arbitrary args in a `json_schema_extra` arg on the field.
**Schema Customisation**
FastAPI and pydantic schema generation now follows the OpenAPI version 3.1 spec.
This necessitates two changes:
- Our schema customization logic has been revised
- Schema parsing to build node templates has been revised
The specific aren't important, but this does present additional surface area for bugs.
**Performance Improvements**
Pydantic v2 is a full rewrite with a rust backend. This offers a substantial performance improvement (pydantic claims 5x to 50x depending on the task). We'll notice this the most during serialization and deserialization of sessions/graphs, which happens very very often - a couple times per node.
I haven't done any benchmarks, but anecdotally, graph execution is much faster. Also, very larges graphs - like with massive iterators - are much, much faster.
2023-09-24 16:11:07 +08:00
|
|
|
[tool.mypy]
|
|
|
|
ignore_missing_imports = true # ignores missing types in third-party libraries
|
2023-11-24 12:15:32 +08:00
|
|
|
strict = true
|
2024-01-15 03:54:53 +08:00
|
|
|
plugins = "pydantic.mypy"
|
2023-11-24 12:15:32 +08:00
|
|
|
exclude = ["tests/*"]
|
feat(api): chore: pydantic & fastapi upgrade
Upgrade pydantic and fastapi to latest.
- pydantic~=2.4.2
- fastapi~=103.2
- fastapi-events~=0.9.1
**Big Changes**
There are a number of logic changes needed to support pydantic v2. Most changes are very simple, like using the new methods to serialized and deserialize models, but there are a few more complex changes.
**Invocations**
The biggest change relates to invocation creation, instantiation and validation.
Because pydantic v2 moves all validation logic into the rust pydantic-core, we may no longer directly stick our fingers into the validation pie.
Previously, we (ab)used models and fields to allow invocation fields to be optional at instantiation, but required when `invoke()` is called. We directly manipulated the fields and invocation models when calling `invoke()`.
With pydantic v2, this is much more involved. Changes to the python wrapper do not propagate down to the rust validation logic - you have to rebuild the model. This causes problem with concurrent access to the invocation classes and is not a free operation.
This logic has been totally refactored and we do not need to change the model any more. The details are in `baseinvocation.py`, in the `InputField` function and `BaseInvocation.invoke_internal()` method.
In the end, this implementation is cleaner.
**Invocation Fields**
In pydantic v2, you can no longer directly add or remove fields from a model.
Previously, we did this to add the `type` field to invocations.
**Invocation Decorators**
With pydantic v2, we instead use the imperative `create_model()` API to create a new model with the additional field. This is done in `baseinvocation.py` in the `invocation()` wrapper.
A similar technique is used for `invocation_output()`.
**Minor Changes**
There are a number of minor changes around the pydantic v2 models API.
**Protected `model_` Namespace**
All models' pydantic-provided methods and attributes are prefixed with `model_` and this is considered a protected namespace. This causes some conflict, because "model" means something to us, and we have a ton of pydantic models with attributes starting with "model_".
Forunately, there are no direct conflicts. However, in any pydantic model where we define an attribute or method that starts with "model_", we must tell set the protected namespaces to an empty tuple.
```py
class IPAdapterModelField(BaseModel):
model_name: str = Field(description="Name of the IP-Adapter model")
base_model: BaseModelType = Field(description="Base model")
model_config = ConfigDict(protected_namespaces=())
```
**Model Serialization**
Pydantic models no longer have `Model.dict()` or `Model.json()`.
Instead, we use `Model.model_dump()` or `Model.model_dump_json()`.
**Model Deserialization**
Pydantic models no longer have `Model.parse_obj()` or `Model.parse_raw()`, and there are no `parse_raw_as()` or `parse_obj_as()` functions.
Instead, you need to create a `TypeAdapter` object to parse python objects or JSON into a model.
```py
adapter_graph = TypeAdapter(Graph)
deserialized_graph_from_json = adapter_graph.validate_json(graph_json)
deserialized_graph_from_dict = adapter_graph.validate_python(graph_dict)
```
**Field Customisation**
Pydantic `Field`s no longer accept arbitrary args.
Now, you must put all additional arbitrary args in a `json_schema_extra` arg on the field.
**Schema Customisation**
FastAPI and pydantic schema generation now follows the OpenAPI version 3.1 spec.
This necessitates two changes:
- Our schema customization logic has been revised
- Schema parsing to build node templates has been revised
The specific aren't important, but this does present additional surface area for bugs.
**Performance Improvements**
Pydantic v2 is a full rewrite with a rust backend. This offers a substantial performance improvement (pydantic claims 5x to 50x depending on the task). We'll notice this the most during serialization and deserialization of sessions/graphs, which happens very very often - a couple times per node.
I haven't done any benchmarks, but anecdotally, graph execution is much faster. Also, very larges graphs - like with massive iterators - are much, much faster.
2023-09-24 16:11:07 +08:00
|
|
|
|
2023-11-21 04:13:17 +08:00
|
|
|
# overrides for specific modules
|
feat(api): chore: pydantic & fastapi upgrade
Upgrade pydantic and fastapi to latest.
- pydantic~=2.4.2
- fastapi~=103.2
- fastapi-events~=0.9.1
**Big Changes**
There are a number of logic changes needed to support pydantic v2. Most changes are very simple, like using the new methods to serialized and deserialize models, but there are a few more complex changes.
**Invocations**
The biggest change relates to invocation creation, instantiation and validation.
Because pydantic v2 moves all validation logic into the rust pydantic-core, we may no longer directly stick our fingers into the validation pie.
Previously, we (ab)used models and fields to allow invocation fields to be optional at instantiation, but required when `invoke()` is called. We directly manipulated the fields and invocation models when calling `invoke()`.
With pydantic v2, this is much more involved. Changes to the python wrapper do not propagate down to the rust validation logic - you have to rebuild the model. This causes problem with concurrent access to the invocation classes and is not a free operation.
This logic has been totally refactored and we do not need to change the model any more. The details are in `baseinvocation.py`, in the `InputField` function and `BaseInvocation.invoke_internal()` method.
In the end, this implementation is cleaner.
**Invocation Fields**
In pydantic v2, you can no longer directly add or remove fields from a model.
Previously, we did this to add the `type` field to invocations.
**Invocation Decorators**
With pydantic v2, we instead use the imperative `create_model()` API to create a new model with the additional field. This is done in `baseinvocation.py` in the `invocation()` wrapper.
A similar technique is used for `invocation_output()`.
**Minor Changes**
There are a number of minor changes around the pydantic v2 models API.
**Protected `model_` Namespace**
All models' pydantic-provided methods and attributes are prefixed with `model_` and this is considered a protected namespace. This causes some conflict, because "model" means something to us, and we have a ton of pydantic models with attributes starting with "model_".
Forunately, there are no direct conflicts. However, in any pydantic model where we define an attribute or method that starts with "model_", we must tell set the protected namespaces to an empty tuple.
```py
class IPAdapterModelField(BaseModel):
model_name: str = Field(description="Name of the IP-Adapter model")
base_model: BaseModelType = Field(description="Base model")
model_config = ConfigDict(protected_namespaces=())
```
**Model Serialization**
Pydantic models no longer have `Model.dict()` or `Model.json()`.
Instead, we use `Model.model_dump()` or `Model.model_dump_json()`.
**Model Deserialization**
Pydantic models no longer have `Model.parse_obj()` or `Model.parse_raw()`, and there are no `parse_raw_as()` or `parse_obj_as()` functions.
Instead, you need to create a `TypeAdapter` object to parse python objects or JSON into a model.
```py
adapter_graph = TypeAdapter(Graph)
deserialized_graph_from_json = adapter_graph.validate_json(graph_json)
deserialized_graph_from_dict = adapter_graph.validate_python(graph_dict)
```
**Field Customisation**
Pydantic `Field`s no longer accept arbitrary args.
Now, you must put all additional arbitrary args in a `json_schema_extra` arg on the field.
**Schema Customisation**
FastAPI and pydantic schema generation now follows the OpenAPI version 3.1 spec.
This necessitates two changes:
- Our schema customization logic has been revised
- Schema parsing to build node templates has been revised
The specific aren't important, but this does present additional surface area for bugs.
**Performance Improvements**
Pydantic v2 is a full rewrite with a rust backend. This offers a substantial performance improvement (pydantic claims 5x to 50x depending on the task). We'll notice this the most during serialization and deserialization of sessions/graphs, which happens very very often - a couple times per node.
I haven't done any benchmarks, but anecdotally, graph execution is much faster. Also, very larges graphs - like with massive iterators - are much, much faster.
2023-09-24 16:11:07 +08:00
|
|
|
[[tool.mypy.overrides]]
|
2023-11-21 04:13:17 +08:00
|
|
|
follow_imports = "skip" # skips type checking of the modules listed below
|
feat(api): chore: pydantic & fastapi upgrade
Upgrade pydantic and fastapi to latest.
- pydantic~=2.4.2
- fastapi~=103.2
- fastapi-events~=0.9.1
**Big Changes**
There are a number of logic changes needed to support pydantic v2. Most changes are very simple, like using the new methods to serialized and deserialize models, but there are a few more complex changes.
**Invocations**
The biggest change relates to invocation creation, instantiation and validation.
Because pydantic v2 moves all validation logic into the rust pydantic-core, we may no longer directly stick our fingers into the validation pie.
Previously, we (ab)used models and fields to allow invocation fields to be optional at instantiation, but required when `invoke()` is called. We directly manipulated the fields and invocation models when calling `invoke()`.
With pydantic v2, this is much more involved. Changes to the python wrapper do not propagate down to the rust validation logic - you have to rebuild the model. This causes problem with concurrent access to the invocation classes and is not a free operation.
This logic has been totally refactored and we do not need to change the model any more. The details are in `baseinvocation.py`, in the `InputField` function and `BaseInvocation.invoke_internal()` method.
In the end, this implementation is cleaner.
**Invocation Fields**
In pydantic v2, you can no longer directly add or remove fields from a model.
Previously, we did this to add the `type` field to invocations.
**Invocation Decorators**
With pydantic v2, we instead use the imperative `create_model()` API to create a new model with the additional field. This is done in `baseinvocation.py` in the `invocation()` wrapper.
A similar technique is used for `invocation_output()`.
**Minor Changes**
There are a number of minor changes around the pydantic v2 models API.
**Protected `model_` Namespace**
All models' pydantic-provided methods and attributes are prefixed with `model_` and this is considered a protected namespace. This causes some conflict, because "model" means something to us, and we have a ton of pydantic models with attributes starting with "model_".
Forunately, there are no direct conflicts. However, in any pydantic model where we define an attribute or method that starts with "model_", we must tell set the protected namespaces to an empty tuple.
```py
class IPAdapterModelField(BaseModel):
model_name: str = Field(description="Name of the IP-Adapter model")
base_model: BaseModelType = Field(description="Base model")
model_config = ConfigDict(protected_namespaces=())
```
**Model Serialization**
Pydantic models no longer have `Model.dict()` or `Model.json()`.
Instead, we use `Model.model_dump()` or `Model.model_dump_json()`.
**Model Deserialization**
Pydantic models no longer have `Model.parse_obj()` or `Model.parse_raw()`, and there are no `parse_raw_as()` or `parse_obj_as()` functions.
Instead, you need to create a `TypeAdapter` object to parse python objects or JSON into a model.
```py
adapter_graph = TypeAdapter(Graph)
deserialized_graph_from_json = adapter_graph.validate_json(graph_json)
deserialized_graph_from_dict = adapter_graph.validate_python(graph_dict)
```
**Field Customisation**
Pydantic `Field`s no longer accept arbitrary args.
Now, you must put all additional arbitrary args in a `json_schema_extra` arg on the field.
**Schema Customisation**
FastAPI and pydantic schema generation now follows the OpenAPI version 3.1 spec.
This necessitates two changes:
- Our schema customization logic has been revised
- Schema parsing to build node templates has been revised
The specific aren't important, but this does present additional surface area for bugs.
**Performance Improvements**
Pydantic v2 is a full rewrite with a rust backend. This offers a substantial performance improvement (pydantic claims 5x to 50x depending on the task). We'll notice this the most during serialization and deserialization of sessions/graphs, which happens very very often - a couple times per node.
I haven't done any benchmarks, but anecdotally, graph execution is much faster. Also, very larges graphs - like with massive iterators - are much, much faster.
2023-09-24 16:11:07 +08:00
|
|
|
module = [
|
|
|
|
"invokeai.app.api.routers.models",
|
|
|
|
"invokeai.app.invocations.compel",
|
2024-06-07 01:43:58 +08:00
|
|
|
"invokeai.app.invocations.denoise_latents",
|
feat(api): chore: pydantic & fastapi upgrade
Upgrade pydantic and fastapi to latest.
- pydantic~=2.4.2
- fastapi~=103.2
- fastapi-events~=0.9.1
**Big Changes**
There are a number of logic changes needed to support pydantic v2. Most changes are very simple, like using the new methods to serialized and deserialize models, but there are a few more complex changes.
**Invocations**
The biggest change relates to invocation creation, instantiation and validation.
Because pydantic v2 moves all validation logic into the rust pydantic-core, we may no longer directly stick our fingers into the validation pie.
Previously, we (ab)used models and fields to allow invocation fields to be optional at instantiation, but required when `invoke()` is called. We directly manipulated the fields and invocation models when calling `invoke()`.
With pydantic v2, this is much more involved. Changes to the python wrapper do not propagate down to the rust validation logic - you have to rebuild the model. This causes problem with concurrent access to the invocation classes and is not a free operation.
This logic has been totally refactored and we do not need to change the model any more. The details are in `baseinvocation.py`, in the `InputField` function and `BaseInvocation.invoke_internal()` method.
In the end, this implementation is cleaner.
**Invocation Fields**
In pydantic v2, you can no longer directly add or remove fields from a model.
Previously, we did this to add the `type` field to invocations.
**Invocation Decorators**
With pydantic v2, we instead use the imperative `create_model()` API to create a new model with the additional field. This is done in `baseinvocation.py` in the `invocation()` wrapper.
A similar technique is used for `invocation_output()`.
**Minor Changes**
There are a number of minor changes around the pydantic v2 models API.
**Protected `model_` Namespace**
All models' pydantic-provided methods and attributes are prefixed with `model_` and this is considered a protected namespace. This causes some conflict, because "model" means something to us, and we have a ton of pydantic models with attributes starting with "model_".
Forunately, there are no direct conflicts. However, in any pydantic model where we define an attribute or method that starts with "model_", we must tell set the protected namespaces to an empty tuple.
```py
class IPAdapterModelField(BaseModel):
model_name: str = Field(description="Name of the IP-Adapter model")
base_model: BaseModelType = Field(description="Base model")
model_config = ConfigDict(protected_namespaces=())
```
**Model Serialization**
Pydantic models no longer have `Model.dict()` or `Model.json()`.
Instead, we use `Model.model_dump()` or `Model.model_dump_json()`.
**Model Deserialization**
Pydantic models no longer have `Model.parse_obj()` or `Model.parse_raw()`, and there are no `parse_raw_as()` or `parse_obj_as()` functions.
Instead, you need to create a `TypeAdapter` object to parse python objects or JSON into a model.
```py
adapter_graph = TypeAdapter(Graph)
deserialized_graph_from_json = adapter_graph.validate_json(graph_json)
deserialized_graph_from_dict = adapter_graph.validate_python(graph_dict)
```
**Field Customisation**
Pydantic `Field`s no longer accept arbitrary args.
Now, you must put all additional arbitrary args in a `json_schema_extra` arg on the field.
**Schema Customisation**
FastAPI and pydantic schema generation now follows the OpenAPI version 3.1 spec.
This necessitates two changes:
- Our schema customization logic has been revised
- Schema parsing to build node templates has been revised
The specific aren't important, but this does present additional surface area for bugs.
**Performance Improvements**
Pydantic v2 is a full rewrite with a rust backend. This offers a substantial performance improvement (pydantic claims 5x to 50x depending on the task). We'll notice this the most during serialization and deserialization of sessions/graphs, which happens very very often - a couple times per node.
I haven't done any benchmarks, but anecdotally, graph execution is much faster. Also, very larges graphs - like with massive iterators - are much, much faster.
2023-09-24 16:11:07 +08:00
|
|
|
"invokeai.app.services.invocation_stats.invocation_stats_default",
|
|
|
|
"invokeai.app.services.model_manager.model_manager_base",
|
|
|
|
"invokeai.app.services.model_manager.model_manager_default",
|
2024-02-14 22:36:30 +08:00
|
|
|
"invokeai.app.services.model_manager.store.model_records_sql",
|
feat(api): chore: pydantic & fastapi upgrade
Upgrade pydantic and fastapi to latest.
- pydantic~=2.4.2
- fastapi~=103.2
- fastapi-events~=0.9.1
**Big Changes**
There are a number of logic changes needed to support pydantic v2. Most changes are very simple, like using the new methods to serialized and deserialize models, but there are a few more complex changes.
**Invocations**
The biggest change relates to invocation creation, instantiation and validation.
Because pydantic v2 moves all validation logic into the rust pydantic-core, we may no longer directly stick our fingers into the validation pie.
Previously, we (ab)used models and fields to allow invocation fields to be optional at instantiation, but required when `invoke()` is called. We directly manipulated the fields and invocation models when calling `invoke()`.
With pydantic v2, this is much more involved. Changes to the python wrapper do not propagate down to the rust validation logic - you have to rebuild the model. This causes problem with concurrent access to the invocation classes and is not a free operation.
This logic has been totally refactored and we do not need to change the model any more. The details are in `baseinvocation.py`, in the `InputField` function and `BaseInvocation.invoke_internal()` method.
In the end, this implementation is cleaner.
**Invocation Fields**
In pydantic v2, you can no longer directly add or remove fields from a model.
Previously, we did this to add the `type` field to invocations.
**Invocation Decorators**
With pydantic v2, we instead use the imperative `create_model()` API to create a new model with the additional field. This is done in `baseinvocation.py` in the `invocation()` wrapper.
A similar technique is used for `invocation_output()`.
**Minor Changes**
There are a number of minor changes around the pydantic v2 models API.
**Protected `model_` Namespace**
All models' pydantic-provided methods and attributes are prefixed with `model_` and this is considered a protected namespace. This causes some conflict, because "model" means something to us, and we have a ton of pydantic models with attributes starting with "model_".
Forunately, there are no direct conflicts. However, in any pydantic model where we define an attribute or method that starts with "model_", we must tell set the protected namespaces to an empty tuple.
```py
class IPAdapterModelField(BaseModel):
model_name: str = Field(description="Name of the IP-Adapter model")
base_model: BaseModelType = Field(description="Base model")
model_config = ConfigDict(protected_namespaces=())
```
**Model Serialization**
Pydantic models no longer have `Model.dict()` or `Model.json()`.
Instead, we use `Model.model_dump()` or `Model.model_dump_json()`.
**Model Deserialization**
Pydantic models no longer have `Model.parse_obj()` or `Model.parse_raw()`, and there are no `parse_raw_as()` or `parse_obj_as()` functions.
Instead, you need to create a `TypeAdapter` object to parse python objects or JSON into a model.
```py
adapter_graph = TypeAdapter(Graph)
deserialized_graph_from_json = adapter_graph.validate_json(graph_json)
deserialized_graph_from_dict = adapter_graph.validate_python(graph_dict)
```
**Field Customisation**
Pydantic `Field`s no longer accept arbitrary args.
Now, you must put all additional arbitrary args in a `json_schema_extra` arg on the field.
**Schema Customisation**
FastAPI and pydantic schema generation now follows the OpenAPI version 3.1 spec.
This necessitates two changes:
- Our schema customization logic has been revised
- Schema parsing to build node templates has been revised
The specific aren't important, but this does present additional surface area for bugs.
**Performance Improvements**
Pydantic v2 is a full rewrite with a rust backend. This offers a substantial performance improvement (pydantic claims 5x to 50x depending on the task). We'll notice this the most during serialization and deserialization of sessions/graphs, which happens very very often - a couple times per node.
I haven't done any benchmarks, but anecdotally, graph execution is much faster. Also, very larges graphs - like with massive iterators - are much, much faster.
2023-09-24 16:11:07 +08:00
|
|
|
"invokeai.app.util.controlnet_utils",
|
|
|
|
"invokeai.backend.image_util.txt2mask",
|
|
|
|
"invokeai.backend.image_util.safety_checker",
|
|
|
|
"invokeai.backend.image_util.patchmatch",
|
|
|
|
"invokeai.backend.image_util.invisible_watermark",
|
|
|
|
"invokeai.backend.install.model_install_backend",
|
|
|
|
"invokeai.backend.ip_adapter.ip_adapter",
|
|
|
|
"invokeai.backend.ip_adapter.resampler",
|
|
|
|
"invokeai.backend.ip_adapter.unet_patcher",
|
|
|
|
"invokeai.backend.model_management.convert_ckpt_to_diffusers",
|
|
|
|
"invokeai.backend.model_management.lora",
|
|
|
|
"invokeai.backend.model_management.model_cache",
|
|
|
|
"invokeai.backend.model_management.model_manager",
|
|
|
|
"invokeai.backend.model_management.model_merge",
|
|
|
|
"invokeai.backend.model_management.model_probe",
|
|
|
|
"invokeai.backend.model_management.model_search",
|
|
|
|
"invokeai.backend.model_management.models.*", # this is needed to ignore the module's `__init__.py`
|
|
|
|
"invokeai.backend.model_management.models.base",
|
|
|
|
"invokeai.backend.model_management.models.controlnet",
|
|
|
|
"invokeai.backend.model_management.models.ip_adapter",
|
|
|
|
"invokeai.backend.model_management.models.lora",
|
|
|
|
"invokeai.backend.model_management.models.sdxl",
|
|
|
|
"invokeai.backend.model_management.models.stable_diffusion",
|
|
|
|
"invokeai.backend.model_management.models.vae",
|
|
|
|
"invokeai.backend.model_management.seamless",
|
|
|
|
"invokeai.backend.model_management.util",
|
|
|
|
"invokeai.backend.stable_diffusion.diffusers_pipeline",
|
|
|
|
"invokeai.backend.stable_diffusion.diffusion.shared_invokeai_diffusion",
|
|
|
|
"invokeai.backend.util.hotfixes",
|
|
|
|
"invokeai.backend.util.mps_fixes",
|
|
|
|
"invokeai.backend.util.util",
|
|
|
|
"invokeai.frontend.install.model_install",
|
|
|
|
]
|
2023-11-11 07:06:21 +08:00
|
|
|
#=== End: MyPy
|
2024-01-13 20:23:01 +08:00
|
|
|
|
|
|
|
[tool.pyright]
|
2024-01-16 16:19:49 +08:00
|
|
|
# Start from strict mode
|
|
|
|
typeCheckingMode = "strict"
|
|
|
|
# This errors whenever an import is missing a type stub file - way too noisy
|
|
|
|
reportMissingTypeStubs = "none"
|
|
|
|
# These are the rest of the rules enabled by strict mode - enable them @ warning
|
|
|
|
reportConstantRedefinition = "warning"
|
|
|
|
reportDeprecated = "warning"
|
|
|
|
reportDuplicateImport = "warning"
|
|
|
|
reportIncompleteStub = "warning"
|
|
|
|
reportInconsistentConstructor = "warning"
|
|
|
|
reportInvalidStubStatement = "warning"
|
|
|
|
reportMatchNotExhaustive = "warning"
|
|
|
|
reportMissingParameterType = "warning"
|
|
|
|
reportMissingTypeArgument = "warning"
|
|
|
|
reportPrivateUsage = "warning"
|
|
|
|
reportTypeCommentUsage = "warning"
|
|
|
|
reportUnknownArgumentType = "warning"
|
|
|
|
reportUnknownLambdaType = "warning"
|
|
|
|
reportUnknownMemberType = "warning"
|
|
|
|
reportUnknownParameterType = "warning"
|
|
|
|
reportUnknownVariableType = "warning"
|
|
|
|
reportUnnecessaryCast = "warning"
|
|
|
|
reportUnnecessaryComparison = "warning"
|
|
|
|
reportUnnecessaryContains = "warning"
|
|
|
|
reportUnnecessaryIsInstance = "warning"
|
|
|
|
reportUnusedClass = "warning"
|
|
|
|
reportUnusedImport = "warning"
|
|
|
|
reportUnusedFunction = "warning"
|
|
|
|
reportUnusedVariable = "warning"
|
|
|
|
reportUntypedBaseClass = "warning"
|
|
|
|
reportUntypedClassDecorator = "warning"
|
|
|
|
reportUntypedFunctionDecorator = "warning"
|
|
|
|
reportUntypedNamedTuple = "warning"
|