initial commit

variety of nodes to support many things including a start on alpha channel support for comfyui
This commit is contained in:
Tasha Upchurch
2023-05-25 12:55:40 -04:00
parent 5aefcd5a4b
commit 9807e12198
8 changed files with 1479 additions and 0 deletions
+48
View File
@@ -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
View File
+13
View File
@@ -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})
+22
View File
@@ -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})
+22
View File
@@ -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"
+1192
View File
File diff suppressed because it is too large Load Diff
+77
View File
@@ -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()
+105
View File
@@ -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")