initial commit
variety of nodes to support many things including a start on alpha channel support for comfyui
This commit is contained in:
+48
@@ -0,0 +1,48 @@
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.latent import LatentInterpolation
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import PadToMatch
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import StackImages
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import ImageBC
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import RGBA_MOD
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import rgba_lower_clip
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import rgba_upper_clip
|
||||
|
||||
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import rgba_merge
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import rgba_split
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import select_from_batch
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import Quantize
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import SelectFromRGBSimilarity
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import LoadImage
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import PromptTemplate
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import ExecWidget
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import TinyTxtToImg
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import ImageDistanceMask
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.image import PreviewImageTest
|
||||
|
||||
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.nlp import NODE_CLASS_MAPPINGS as NLP_NODE_CLASS_MAPPINGS
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"Interpolation": LatentInterpolation,
|
||||
"Image Pad To Match": PadToMatch,
|
||||
"Image Stack": StackImages,
|
||||
"Image B/C": ImageBC,
|
||||
"Image RGBA Mod": RGBA_MOD,
|
||||
"Image RGBA Lower Clip": rgba_lower_clip,
|
||||
"Image RGBA Upper Clip": rgba_upper_clip,
|
||||
"Image RGBA Merge": rgba_merge,
|
||||
"Image RGBA Split": rgba_split,
|
||||
"Select From Batch": select_from_batch,
|
||||
"Quantize": Quantize,
|
||||
"Select From RGB Similarity": SelectFromRGBSimilarity,
|
||||
"Load Layered Image": LoadImage,
|
||||
"Prompt Template": PromptTemplate,
|
||||
"Eval Widget": ExecWidget,
|
||||
"Tiny Txt 2 Img":TinyTxtToImg,
|
||||
"Image Distance Mask":ImageDistanceMask,
|
||||
"Preview Image Test":PreviewImageTest,
|
||||
}
|
||||
|
||||
for k,v in NLP_NODE_CLASS_MAPPINGS.items():
|
||||
NODE_CLASS_MAPPINGS[k] = v
|
||||
@@ -0,0 +1,13 @@
|
||||
import sys
|
||||
|
||||
FLOAT = ("FLOAT", {"default": 1,
|
||||
"min": -sys.float_info.max,
|
||||
"max": sys.float_info.max,
|
||||
"step": 0.01})
|
||||
BOOL = ("BOOL", {"default": False})
|
||||
INT = ("INT", {"default": 1,
|
||||
"min": -sys.maxsize,
|
||||
"max": sys.maxsize,
|
||||
"step": 1})
|
||||
STRING = ("STRING", {"default": ""})
|
||||
STRING_ML = ("STRING", {"multiline": True})
|
||||
@@ -0,0 +1,22 @@
|
||||
def get_latent_size(LATENT, ORIGINAL_VALUES=False):
|
||||
lc = LATENT.copy()
|
||||
size = lc["samples"].shape[3], lc["samples"].shape[2]
|
||||
if ORIGINAL_VALUES == False:
|
||||
size = size[0] * 8, size[1] * 8
|
||||
return size
|
||||
|
||||
|
||||
def get_image_size(IMAGE):
|
||||
samples = IMAGE.movedim(-1, 1)
|
||||
size = samples.shape[3], samples.shape[2]
|
||||
# size = size.movedim(1, -1)
|
||||
return size
|
||||
|
||||
|
||||
def get_conditioning_size(CONDITIONING):
|
||||
size = CONDITIONING["area"]
|
||||
width = size[1]
|
||||
height = size[0]
|
||||
x_offs = size[3]
|
||||
y_offs = size[2]
|
||||
return ({"w": width, "h": height}, {"x": x_offs, "y": y_offs})
|
||||
@@ -0,0 +1,22 @@
|
||||
TREE_MAIN = "EternalKernelNodes"
|
||||
|
||||
TREE_VARIABLE = TREE_MAIN + "/Variables"
|
||||
TREE_TUPLES = TREE_MAIN + "/Tuples"
|
||||
TREE_MATH = TREE_MAIN + "/Math"
|
||||
TREE_FUNCTIONS = TREE_MAIN + "/Functions"
|
||||
TREE_MODDED = TREE_MAIN + "/Modded nodes"
|
||||
|
||||
TREE_CONVERTERS = TREE_FUNCTIONS + "/Converters"
|
||||
|
||||
TREE_TRIGONOMETRY = TREE_MATH + "/Trigonometry"
|
||||
|
||||
TREE_TUPLE_MODDED = TREE_TUPLES + "/Modded nodes"
|
||||
|
||||
TREE_TUPLE_LATENTS = TREE_TUPLE_MODDED + "/Latents"
|
||||
TREE_TUPLE_CONDITIONING = TREE_TUPLE_MODDED + "/Conditioning"
|
||||
|
||||
TREE_COND = TREE_MODDED + "/Conditions"
|
||||
TREE_IMAGES = TREE_MODDED + "/Image"
|
||||
TREE_LATENTS = TREE_MODDED + "/Latent"
|
||||
|
||||
TREE_DEBUG = TREE_MAIN + "/Debug"
|
||||
@@ -0,0 +1,77 @@
|
||||
#from nodes import MAX_RESOLUTION
|
||||
import torch
|
||||
|
||||
from custom_nodes.EternalKernelLiteGraphNodes.components import fields as field
|
||||
|
||||
|
||||
class LatentInterpolation:
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"latent1": ("LATENT",),
|
||||
"latent2": ("LATENT",),
|
||||
"t": field.FLOAT,
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LATENT",)
|
||||
FUNCTION = "interpolate"
|
||||
CATEGORY = "EternalKernelNodes"
|
||||
|
||||
def interpolate(self, latent1, latent2, t):
|
||||
# Ensure that the latents are dictionaries
|
||||
if not (isinstance(latent1, dict) and isinstance(latent2, dict)):
|
||||
raise ValueError("Latent values must be dictionaries.")
|
||||
|
||||
# Ensure that both latents have the same keys
|
||||
if set(latent1.keys()) != set(latent2.keys()):
|
||||
raise ValueError("Latent dictionaries must have the same keys.")
|
||||
|
||||
inter_latent = {}
|
||||
for key in latent1:
|
||||
if isinstance(latent1[key], (list, tuple)):
|
||||
inter_latent[key] = [(1 - t) * l1_val + t * l2_val for l1_val, l2_val in
|
||||
zip(latent1[key], latent2[key])]
|
||||
elif isinstance(latent1[key], torch.Tensor):
|
||||
inter_latent[key] = (1 - t) * latent1[key] + t * latent2[key]
|
||||
else:
|
||||
raise ValueError(f"Unsupported value type for key '{key}' in latent dictionaries.")
|
||||
|
||||
return (inter_latent,)
|
||||
|
||||
|
||||
def test_latent_interpolation():
|
||||
import torch
|
||||
# Create an instance of the LatentInterpolation class
|
||||
li = LatentInterpolation()
|
||||
|
||||
# Define test cases for the interpolate method
|
||||
# latents are at least 4 diminsional
|
||||
# latents are of the same length
|
||||
test_cases = [
|
||||
{
|
||||
"input": {
|
||||
"latent1": torch.tensor([[[[1.0, 2.0], [3.0, 4.0]]]]),
|
||||
"latent2": torch.tensor([[[[5.0, 6.0], [7.0, 8.0]]]]),
|
||||
"t": 0.5,
|
||||
|
||||
},
|
||||
"expected": torch.tensor([[[[3.0, 4.0], [5.0, 6.0]]]]),
|
||||
},
|
||||
]
|
||||
|
||||
# Run the test cases
|
||||
for test_case in test_cases:
|
||||
result = li.interpolate(**test_case["input"])
|
||||
if not (result[0][0] == test_case["expected"]).all().item():
|
||||
print(f"Expected {test_case['expected']} but got {result}")
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_latent_interpolation()
|
||||
@@ -0,0 +1,105 @@
|
||||
import comfy.samplers
|
||||
import custom_nodes.Derfuu_ComfyUI_ModdedNodes.components.fields as field
|
||||
import PIL.Image
|
||||
import torch
|
||||
import torchvision
|
||||
import PIL.Image as Image
|
||||
from nodes import CLIPTextEncode, VAEEncode, VAEDecode, KSampler, CheckpointLoaderSimple, EmptyLatentImage
|
||||
import doctest
|
||||
# make sure to import ABC
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
import os
|
||||
import openai
|
||||
|
||||
|
||||
class Config:
|
||||
api_key = os.environ.get('OPENAI_API_KEY')
|
||||
organization = os.environ.get('OPENAI_ORG')
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {}
|
||||
|
||||
openai.organization = Config.organization
|
||||
openai.api_key = Config.api_key
|
||||
|
||||
|
||||
class SimpleTextWidget:
|
||||
"""base class for simple construction"""
|
||||
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
|
||||
|
||||
@classmethod
|
||||
def register(self, name):
|
||||
global NODE_CLASS_MAPPINGS
|
||||
|
||||
# register the widget
|
||||
NODE_CLASS_MAPPINGS[name] = self
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {"required":
|
||||
{
|
||||
"text": ("STRING", {"multiline": True}),
|
||||
"Display": ("SERVER_STRING", {"multiline": True}),
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
CATEGORY = "text"
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "handler"
|
||||
|
||||
def handler(self, text,Display):
|
||||
ret = self.func(text)
|
||||
return (ret,)
|
||||
|
||||
|
||||
try:
|
||||
import folder_paths
|
||||
except:
|
||||
pass
|
||||
|
||||
import os
|
||||
import numpy as np
|
||||
import hashlib
|
||||
|
||||
### info for code completion AI ###
|
||||
"""
|
||||
all of these classes are plugins for comfyui and follow the same pattern
|
||||
all of the images are torch tensors and it is unknown and unimportant if they are on the cpu or gpu
|
||||
all image inputs are (B,W,H,C)
|
||||
|
||||
avoid numpy and PIL as much as possible
|
||||
"""
|
||||
|
||||
|
||||
class LLMCompletion(SimpleTextWidget):
|
||||
"""uses the input text to call the specified LLM model and returns the output string"""
|
||||
|
||||
def OAI_completion(self, text):
|
||||
out_message = [{"role": "user", "content": text}]
|
||||
|
||||
response = openai.ChatCompletion.create(
|
||||
model="gpt-3.5-turbo",
|
||||
messages=out_message
|
||||
)
|
||||
gpt_message = response["choices"][0]["message"]["content"].strip()
|
||||
self.server_strings[self.SSID] = gpt_message
|
||||
return gpt_message
|
||||
|
||||
def __init__(self):
|
||||
self.func = self.OAI_completion
|
||||
super().__init__(self.func)
|
||||
import uuid
|
||||
self.SSID = str(uuid.uuid4())
|
||||
from main import server_obj_holder
|
||||
self.server_strings = server_obj_holder[0].server_strings
|
||||
self.server_strings["self.SSID"] = "empty"
|
||||
|
||||
|
||||
|
||||
|
||||
LLMCompletion.register("LLM_Completion")
|
||||
Reference in New Issue
Block a user