From f0f22cab081770c9561c7cdc8e6433db97ba381d Mon Sep 17 00:00:00 2001 From: Limitex <76650151+Limitex@users.noreply.github.com> Date: Sun, 2 Nov 2025 23:05:21 +0900 Subject: [PATCH] feat: clip model --- __init__.py | 2 ++ src/domain/model/__init__.py | 2 ++ src/domain/model/_clip.py | 10 ++++++ src/nodes/__init__.py | 3 +- src/nodes/dto/__init__.py | 3 +- src/nodes/dto/_clip.py | 60 ++++++++++++++++++++++++++++++++++++ 6 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 src/domain/model/_clip.py create mode 100644 src/nodes/dto/_clip.py diff --git a/__init__.py b/__init__.py index ca9fa73..a89779d 100644 --- a/__init__.py +++ b/__init__.py @@ -2,6 +2,7 @@ from .src.nodes import ( NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS, ComfyUIAutoencoderDTO, + ComfyUIClipDTO, ComfyUIPipelineDTO, ) @@ -10,4 +11,5 @@ __all__ = [ "NODE_DISPLAY_NAME_MAPPINGS", "ComfyUIPipelineDTO", "ComfyUIAutoencoderDTO", + "ComfyUIClipDTO", ] diff --git a/src/domain/model/__init__.py b/src/domain/model/__init__.py index 3b30e52..8cf9670 100644 --- a/src/domain/model/__init__.py +++ b/src/domain/model/__init__.py @@ -1,7 +1,9 @@ from ._autoencoder import Autoencoder +from ._clip import Clip from ._pipeline import Pipeline __all__ = [ "Pipeline", "Autoencoder", + "Clip", ] diff --git a/src/domain/model/_clip.py b/src/domain/model/_clip.py new file mode 100644 index 0000000..35bd864 --- /dev/null +++ b/src/domain/model/_clip.py @@ -0,0 +1,10 @@ +from dataclasses import dataclass + +from transformers import CLIPTextModel, CLIPTokenizer + + +@dataclass +class Clip: + tokenizer: CLIPTokenizer + text_encoder: CLIPTextModel + path: str diff --git a/src/nodes/__init__.py b/src/nodes/__init__.py index 94eac1b..6803e59 100644 --- a/src/nodes/__init__.py +++ b/src/nodes/__init__.py @@ -1,7 +1,7 @@ from ..di import Container from ._diffusers_pipeline_loader import DiffusersPipelineLoader from ._diffusers_vae_loader import DiffusersVaeLoader -from .dto import ComfyUIAutoencoderDTO, ComfyUIPipelineDTO +from .dto import ComfyUIAutoencoderDTO, ComfyUIClipDTO, ComfyUIPipelineDTO container = Container() container.wire(modules=[__name__]) @@ -20,4 +20,5 @@ __all__ = [ "NODE_DISPLAY_NAME_MAPPINGS", "ComfyUIPipelineDTO", "ComfyUIAutoencoderDTO", + "ComfyUIClipDTO", ] diff --git a/src/nodes/dto/__init__.py b/src/nodes/dto/__init__.py index 9a7ce0a..4853e89 100644 --- a/src/nodes/dto/__init__.py +++ b/src/nodes/dto/__init__.py @@ -1,4 +1,5 @@ from ._autoencoder_dto import ComfyUIAutoencoderDTO +from ._clip import ComfyUIClipDTO from ._pipeline_dto import ComfyUIPipelineDTO -__all__ = ["ComfyUIPipelineDTO", "ComfyUIAutoencoderDTO"] +__all__ = ["ComfyUIPipelineDTO", "ComfyUIAutoencoderDTO", "ComfyUIClipDTO"] diff --git a/src/nodes/dto/_clip.py b/src/nodes/dto/_clip.py new file mode 100644 index 0000000..c7e5463 --- /dev/null +++ b/src/nodes/dto/_clip.py @@ -0,0 +1,60 @@ +from dataclasses import dataclass +from typing import ClassVar + +from transformers import CLIPTextModel, CLIPTokenizer + +from ...domain.model import Clip + + +@dataclass +class ComfyUIClipDTO: + """Data Transfer Object for CLIP (Tokenizer and Text Encoder) in ComfyUI. + + This DTO is designed to be used across different custom nodes. + Other node developers can import and use this type for CLIP operations. + + Attributes: + tokenizer: CLIPTokenizer instance from transformers library + text_encoder: CLIPTextModel instance from transformers library + path: Path to the loaded model directory + + Class Attributes: + COMFY_TYPE: Type name used in ComfyUI's RETURN_TYPES and INPUT_TYPES + + Example: + ```python + from your_node_package.nodes.dto import ComfyUIClipDTO + + class YourCustomNode: + @classmethod + def INPUT_TYPES(cls): + return {"required": {"clip": (ComfyUIClipDTO.COMFY_TYPE,)}} + + RETURN_TYPES = (ComfyUIClipDTO.COMFY_TYPE,) + + def execute(self, clip: ComfyUIClipDTO): + # Use the tokenizer and text encoder + tokens = clip.tokenizer(prompt, return_tensors="pt") + embeddings = clip.text_encoder(**tokens) + return (embeddings,) + ``` + """ + + # ClassVar to avoid being treated as a dataclass field + COMFY_TYPE: ClassVar[str] = "DIFFUSERS_CLIP" + + tokenizer: CLIPTokenizer + text_encoder: CLIPTextModel + path: str + + @classmethod + def from_domain(cls, clip: Clip) -> "ComfyUIClipDTO": + """Create DTO from domain model. + + Args: + clip: Clip from domain layer + + Returns: + ComfyUIClipDTO instance + """ + return cls(tokenizer=clip.tokenizer, text_encoder=clip.text_encoder, path=clip.path)