diff --git a/invokeai/app/api/routers/images.py b/invokeai/app/api/routers/images.py index f462437700..625fb3c43b 100644 --- a/invokeai/app/api/routers/images.py +++ b/invokeai/app/api/routers/images.py @@ -7,11 +7,14 @@ from fastapi.routing import APIRouter from PIL import Image from pydantic import BaseModel, Field, ValidationError -from invokeai.app.invocations.baseinvocation import MetadataField, type_adapter_MetadataField +from invokeai.app.invocations.baseinvocation import ( + MetadataField, + type_adapter_MetadataField, + type_adapter_WorkflowField, +) from invokeai.app.services.image_records.image_records_common import ImageCategory, ImageRecordChanges, ResourceOrigin from invokeai.app.services.images.images_common import ImageDTO, ImageUrlsDTO from invokeai.app.services.shared.pagination import OffsetPaginatedResults -from invokeai.app.services.workflow_records.workflow_records_common import type_adapter_WorkflowField from ..dependencies import ApiDependencies diff --git a/invokeai/app/api/routers/workflows.py b/invokeai/app/api/routers/workflows.py index 57a33fe73f..36de31fb51 100644 --- a/invokeai/app/api/routers/workflows.py +++ b/invokeai/app/api/routers/workflows.py @@ -1,7 +1,7 @@ from fastapi import APIRouter, Path from invokeai.app.api.dependencies import ApiDependencies -from invokeai.app.services.workflow_records.workflow_records_common import WorkflowField +from invokeai.app.invocations.baseinvocation import WorkflowField workflows_router = APIRouter(prefix="/v1/workflows", tags=["workflows"]) diff --git a/invokeai/app/invocations/baseinvocation.py b/invokeai/app/invocations/baseinvocation.py index 162b22b28d..50ce8de7d3 100644 --- a/invokeai/app/invocations/baseinvocation.py +++ b/invokeai/app/invocations/baseinvocation.py @@ -15,7 +15,6 @@ from pydantic.fields import _Unset from pydantic_core import PydanticUndefined from invokeai.app.services.config.config_default import InvokeAIAppConfig -from invokeai.app.services.workflow_records.workflow_records_common import WorkflowField from invokeai.app.util.misc import uuid_string if TYPE_CHECKING: @@ -813,22 +812,29 @@ def invocation_output( return wrapper +class WorkflowField(RootModel): + """ + Pydantic model for workflows with custom root of type dict[str, Any]. + Workflows are stored without a strict schema. + """ + + root: dict[str, Any] = Field(description="The workflow") + + +type_adapter_WorkflowField = TypeAdapter(WorkflowField) + + class WithWorkflow(BaseModel): workflow: Optional[WorkflowField] = InputField(default=None, description=FieldDescriptions.workflow) -class MetadataItemField(BaseModel): - label: str = Field(description=FieldDescriptions.metadata_item_label) - value: Any = Field(description=FieldDescriptions.metadata_item_value) - - class MetadataField(RootModel): """ Pydantic model for metadata with custom root of type dict[str, Any]. Metadata is stored without a strict schema. """ - root: dict[str, Any] = Field(description="A dictionary of metadata, shape of which is arbitrary") + root: dict[str, Any] = Field(description="The metadata") type_adapter_MetadataField = TypeAdapter(MetadataField) diff --git a/invokeai/app/invocations/metadata.py b/invokeai/app/invocations/metadata.py index 205dbef814..98f5f0e830 100644 --- a/invokeai/app/invocations/metadata.py +++ b/invokeai/app/invocations/metadata.py @@ -9,7 +9,6 @@ from invokeai.app.invocations.baseinvocation import ( InputField, InvocationContext, MetadataField, - MetadataItemField, OutputField, UIType, invocation, @@ -24,6 +23,11 @@ from invokeai.app.invocations.t2i_adapter import T2IAdapterField from ...version import __version__ +class MetadataItemField(BaseModel): + label: str = Field(description=FieldDescriptions.metadata_item_label) + value: Any = Field(description=FieldDescriptions.metadata_item_value) + + class LoRAMetadataField(BaseModel): """LoRA Metadata Field""" diff --git a/invokeai/app/services/image_files/image_files_base.py b/invokeai/app/services/image_files/image_files_base.py index 3f6e797225..91e18f30fc 100644 --- a/invokeai/app/services/image_files/image_files_base.py +++ b/invokeai/app/services/image_files/image_files_base.py @@ -4,8 +4,7 @@ from typing import Optional from PIL.Image import Image as PILImageType -from invokeai.app.invocations.metadata import MetadataField -from invokeai.app.services.workflow_records.workflow_records_common import WorkflowField +from invokeai.app.invocations.baseinvocation import MetadataField, WorkflowField class ImageFileStorageBase(ABC): diff --git a/invokeai/app/services/image_files/image_files_disk.py b/invokeai/app/services/image_files/image_files_disk.py index 57c05562d5..e8a733d619 100644 --- a/invokeai/app/services/image_files/image_files_disk.py +++ b/invokeai/app/services/image_files/image_files_disk.py @@ -7,9 +7,8 @@ from PIL import Image, PngImagePlugin from PIL.Image import Image as PILImageType from send2trash import send2trash -from invokeai.app.invocations.metadata import MetadataField +from invokeai.app.invocations.baseinvocation import MetadataField, WorkflowField from invokeai.app.services.invoker import Invoker -from invokeai.app.services.workflow_records.workflow_records_common import WorkflowField from invokeai.app.util.thumbnails import get_thumbnail_name, make_thumbnail from .image_files_base import ImageFileStorageBase diff --git a/invokeai/app/services/images/images_base.py b/invokeai/app/services/images/images_base.py index ebb40424bc..50a3a5fb82 100644 --- a/invokeai/app/services/images/images_base.py +++ b/invokeai/app/services/images/images_base.py @@ -3,7 +3,7 @@ from typing import Callable, Optional from PIL.Image import Image as PILImageType -from invokeai.app.invocations.metadata import MetadataField +from invokeai.app.invocations.baseinvocation import MetadataField, WorkflowField from invokeai.app.services.image_records.image_records_common import ( ImageCategory, ImageRecord, @@ -12,7 +12,6 @@ from invokeai.app.services.image_records.image_records_common import ( ) from invokeai.app.services.images.images_common import ImageDTO from invokeai.app.services.shared.pagination import OffsetPaginatedResults -from invokeai.app.services.workflow_records.workflow_records_common import WorkflowField class ImageServiceABC(ABC): diff --git a/invokeai/app/services/images/images_default.py b/invokeai/app/services/images/images_default.py index e466e809b1..a0d59470fc 100644 --- a/invokeai/app/services/images/images_default.py +++ b/invokeai/app/services/images/images_default.py @@ -2,10 +2,9 @@ from typing import Optional from PIL.Image import Image as PILImageType -from invokeai.app.invocations.metadata import MetadataField +from invokeai.app.invocations.baseinvocation import MetadataField, WorkflowField from invokeai.app.services.invoker import Invoker from invokeai.app.services.shared.pagination import OffsetPaginatedResults -from invokeai.app.services.workflow_records.workflow_records_common import WorkflowField from ..image_files.image_files_common import ( ImageFileDeleteException, diff --git a/invokeai/app/services/workflow_records/workflow_records_base.py b/invokeai/app/services/workflow_records/workflow_records_base.py index 97f7cfe3c0..d5a4b25ce4 100644 --- a/invokeai/app/services/workflow_records/workflow_records_base.py +++ b/invokeai/app/services/workflow_records/workflow_records_base.py @@ -1,6 +1,6 @@ from abc import ABC, abstractmethod -from invokeai.app.services.workflow_records.workflow_records_common import WorkflowField +from invokeai.app.invocations.baseinvocation import WorkflowField class WorkflowRecordsStorageBase(ABC): diff --git a/invokeai/app/services/workflow_records/workflow_records_common.py b/invokeai/app/services/workflow_records/workflow_records_common.py index 32046328bb..3a2b13f565 100644 --- a/invokeai/app/services/workflow_records/workflow_records_common.py +++ b/invokeai/app/services/workflow_records/workflow_records_common.py @@ -1,19 +1,2 @@ -from typing import Any - -from pydantic import Field, RootModel, TypeAdapter - - class WorkflowNotFoundError(Exception): """Raised when a workflow is not found""" - - -class WorkflowField(RootModel): - """ - Pydantic model for workflows with custom root of type dict[str, Any]. - Workflows are stored without a strict schema. - """ - - root: dict[str, Any] = Field(description="Workflow dict") - - -type_adapter_WorkflowField = TypeAdapter(WorkflowField) diff --git a/invokeai/app/services/workflow_records/workflow_records_sqlite.py b/invokeai/app/services/workflow_records/workflow_records_sqlite.py index 2b284ac03f..e3c11cfa4b 100644 --- a/invokeai/app/services/workflow_records/workflow_records_sqlite.py +++ b/invokeai/app/services/workflow_records/workflow_records_sqlite.py @@ -1,14 +1,11 @@ import sqlite3 import threading +from invokeai.app.invocations.baseinvocation import WorkflowField, type_adapter_WorkflowField from invokeai.app.services.invoker import Invoker from invokeai.app.services.shared.sqlite import SqliteDatabase from invokeai.app.services.workflow_records.workflow_records_base import WorkflowRecordsStorageBase -from invokeai.app.services.workflow_records.workflow_records_common import ( - WorkflowField, - WorkflowNotFoundError, - type_adapter_WorkflowField, -) +from invokeai.app.services.workflow_records.workflow_records_common import WorkflowNotFoundError from invokeai.app.util.misc import uuid_string