Add New workflows + Add juggernaut flux models + Add support for deepCache and TeaCache + Add Multi Inference
This commit is contained in:
@@ -116,4 +116,4 @@ class bgremoval:
|
||||
|
||||
genResult = rwUtils.inferenecRequest([genConfig])
|
||||
images = rwUtils.convertImageB64List(genResult)
|
||||
return images
|
||||
return (images, )
|
||||
@@ -116,4 +116,4 @@ class controlNetPreprocessor:
|
||||
|
||||
genResult = rwUtils.inferenecRequest(genConfig)
|
||||
images = rwUtils.convertImageB64List(genResult)
|
||||
return images
|
||||
return (images, )
|
||||
@@ -0,0 +1,45 @@
|
||||
class deepCache:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"DeepCache Interval": (
|
||||
"INT",
|
||||
{
|
||||
"tooltip": "Represents the frequency of feature caching, specified as the number of steps between each cache operation.\n\nA larger interval value will make inference faster but may impact quality. A smaller interval prioritizes quality over speed.",
|
||||
"default": 3,
|
||||
"min": 1,
|
||||
"max": 5,
|
||||
"step": 1,
|
||||
},
|
||||
),
|
||||
"DeepCache BranchId": (
|
||||
"INT",
|
||||
{
|
||||
"tooltip": "Determines which branch of the network (ordered from the shallowest to the deepest layer) is responsible for executing the caching processes.\n\nLower branch IDs (e.g., 0) result in more aggressive caching for faster generation, while higher branch IDs produce more conservative caching with potentially higher quality results.",
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 5,
|
||||
"step": 1,
|
||||
},
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
DESCRIPTION = "Can Be connected to Runware Inference to accelerate image generation by reusing past computations.\n\nDeepCache feature, which speeds up diffusion-based image generation by caching internal feature maps from the neural network.\n\nDeepCache can provide significant performance improvements for high-throughput scenarios or when generating multiple similar images."
|
||||
FUNCTION = "deepCache"
|
||||
RETURN_TYPES = ("RUNWAREACCELERATOR",)
|
||||
RETURN_NAMES = ("Runware Accelerator",)
|
||||
CATEGORY = "Runware"
|
||||
|
||||
def deepCache(self, **kwargs):
|
||||
deepCacheInterval = kwargs.get("DeepCache Interval")
|
||||
deepCacheBranchId = kwargs.get("DeepCache BranchId")
|
||||
|
||||
return (
|
||||
{
|
||||
"deepCache": True,
|
||||
# "deepCacheInterval": deepCacheInterval,
|
||||
"deepCacheBranchId": deepCacheBranchId,
|
||||
},
|
||||
)
|
||||
@@ -19,6 +19,12 @@ class txt2img:
|
||||
"placeholder": "Negative Prompt: a text instruction to guide the model on generating the image. It is usually a sentence or a paragraph that provides negative guidance for the task. This parameter helps to avoid certain undesired results.",
|
||||
"tooltip": "Negative Prompt: a text instruction to guide the model on generating the image."
|
||||
}),
|
||||
"Multi Inference Mode": ("BOOLEAN", {
|
||||
"tooltip": "If Enabled the node will skip the image generation process and will only return the Runware Task Object to be used in the Multi Inference Node.",
|
||||
"default": False,
|
||||
"label_on": "Enabled",
|
||||
"label_off": "Disabled",
|
||||
}),
|
||||
"Prompt Weighting": (["Disabled", "sdEmbeds", "Compel"], {
|
||||
"default": "Disabled",
|
||||
"tooltip": "Prompt weighting allows you to adjust how strongly different parts of your prompt influence the generated image.\n\nChoose between \"compel\" notation with advanced weighting operations or \"sdEmbeds\" for simple emphasis adjustments.\n\nCompel Example: \"small+ dog, pixar style\"\n\nsdEmbeds Example: \"(small:2.5) dog, pixar style\"",
|
||||
@@ -101,6 +107,9 @@ class txt2img:
|
||||
}),
|
||||
},
|
||||
"optional": {
|
||||
"Accelerator": ("RUNWAREACCELERATOR", {
|
||||
"tooltip": "Connect a Runware Accelerator Node (TeaCache, DeepCache) to speed up the image generation process.",
|
||||
}),
|
||||
"Lora": ("RUNWARELORA", {
|
||||
"tooltip": "Connect a Runware Lora From Lora Search Node Or Lora Combine For Multiple Lora's Together.",
|
||||
}),
|
||||
@@ -143,15 +152,18 @@ class txt2img:
|
||||
|
||||
DESCRIPTION = "Generates Images Lightning Fast With Runware Image Inference Sonic Engine."
|
||||
FUNCTION = "generateImage"
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_TYPES = ("IMAGE", "RUNWARETASK")
|
||||
RETURN_NAMES = ("IMAGE", "RW-Task")
|
||||
CATEGORY = "Runware"
|
||||
|
||||
def generateImage(self, **kwargs):
|
||||
runwareModel = kwargs.get("Model")
|
||||
positivePrompt = kwargs.get("positivePrompt")
|
||||
negativePrompt = kwargs.get("negativePrompt", None)
|
||||
multiInferenceMode = kwargs.get("Multi Inference Mode", False)
|
||||
promptWeighting = kwargs.get("Prompt Weighting", "Disabled")
|
||||
runwareControlNet = kwargs.get("ControlNet", None)
|
||||
runwareAccelerator = kwargs.get("Accelerator", None)
|
||||
runwareLora = kwargs.get("Lora", None)
|
||||
runwareOutpainting = kwargs.get("Outpainting", None)
|
||||
runwareIPAdapters = kwargs.get("IPAdapters", None)
|
||||
@@ -205,6 +217,8 @@ class txt2img:
|
||||
genConfig[0]["promptWeighting"] = "sdEmbeds"
|
||||
else:
|
||||
genConfig[0]["promptWeighting"] = "compel"
|
||||
if(runwareAccelerator is not None):
|
||||
genConfig[0]["acceleratorOptions"] = runwareAccelerator
|
||||
if (runwareLora is not None):
|
||||
if (isinstance(runwareLora, list)):
|
||||
genConfig[0]["lora"] = runwareLora
|
||||
@@ -238,6 +252,9 @@ class txt2img:
|
||||
if (enableMaskMargin):
|
||||
genConfig[0]["maskMargin"] = maskImageMargin
|
||||
|
||||
genResult = rwUtils.inferenecRequest(genConfig)
|
||||
images = rwUtils.convertImageB64List(genResult)
|
||||
return images
|
||||
if (multiInferenceMode):
|
||||
return (None, genConfig)
|
||||
else:
|
||||
genResult = rwUtils.inferenecRequest(genConfig)
|
||||
images = rwUtils.convertImageB64List(genResult)
|
||||
return (images, None)
|
||||
|
||||
@@ -33,6 +33,8 @@ class modelSearch:
|
||||
"default": "Base Model",
|
||||
}),
|
||||
"ModelList": ([
|
||||
"rundiffusion:110@101 (Juggernaut Lightning Flux by RunDiffusion)",
|
||||
"rundiffusion:130@100 (Juggernaut Pro Flux by RunDiffusion)",
|
||||
"runware:100@1 (Flux Schnell)",
|
||||
"runware:101@1 (Flux Dev)",
|
||||
"runware:5@1 (SD3)",
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
import asyncio
|
||||
from .utils import runwareUtils as rwUtils
|
||||
from comfy_execution.graph import ExecutionBlocker
|
||||
|
||||
|
||||
class multiInference:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"Task 1": (
|
||||
"RUNWARETASK",
|
||||
{
|
||||
"tooltip": "Connect a Runware Task From Any Inference Node.",
|
||||
},
|
||||
),
|
||||
},
|
||||
"optional": {
|
||||
"Task 2": (
|
||||
"RUNWARETASK",
|
||||
{
|
||||
"tooltip": "Connect a Runware Task From Any Inference Node.",
|
||||
},
|
||||
),
|
||||
"Task 3": (
|
||||
"RUNWARETASK",
|
||||
{
|
||||
"tooltip": "Connect a Runware Task From Any Inference Node.",
|
||||
},
|
||||
),
|
||||
"Task 4": (
|
||||
"RUNWARETASK",
|
||||
{
|
||||
"tooltip": "Connect a Runware Task From Any Inference Node.",
|
||||
},
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
DESCRIPTION = "Allows you to Run Multiple Inference Tasks in Parallel."
|
||||
FUNCTION = "multiInference"
|
||||
RETURN_TYPES = ("IMAGE", "IMAGE", "IMAGE", "IMAGE")
|
||||
RETURN_NAMES = ("Result 1", "Result 2", "Result 3", "Result 4")
|
||||
CATEGORY = "Runware"
|
||||
|
||||
def multiInference(self, **kwargs):
|
||||
tasksData = [kwargs.get(f"Task {i}", None) for i in range(1, 5)]
|
||||
validTasks = [task for task in tasksData if task is not None]
|
||||
|
||||
if not validTasks:
|
||||
raise Exception("Error: No valid tasks provided for Multi Inference!")
|
||||
|
||||
taskIncidents = {}
|
||||
|
||||
async def runInference(taskData, taskIndex, oindex):
|
||||
try:
|
||||
print(f"[Debugging] Task {oindex + 1} UUID => {taskData[0]['taskUUID']}")
|
||||
loop = asyncio.get_running_loop()
|
||||
result = await loop.run_in_executor(
|
||||
None, rwUtils.inferenecRequest, taskData
|
||||
)
|
||||
images = rwUtils.convertImageB64List(result)
|
||||
return images
|
||||
except Exception as e:
|
||||
print(f"\n---- Runware Multi Inference Task {oindex + 1} Failed ----")
|
||||
print(f"Task-Type: {taskData[0]['taskType']}")
|
||||
print(f"Task-UUID: {taskData[0]['taskUUID']}")
|
||||
print(f"{e}")
|
||||
print(f"-------------------\n")
|
||||
taskIncidents[taskIndex] = e
|
||||
return ExecutionBlocker(None)
|
||||
|
||||
async def main():
|
||||
coroutines = []
|
||||
valid_indices = [idx for idx, t in enumerate(tasksData) if t is not None]
|
||||
for i, config in enumerate(validTasks):
|
||||
original_index = valid_indices[i]
|
||||
coroutines.append(runInference(config, i, original_index))
|
||||
results = await asyncio.gather(*coroutines, return_exceptions=False)
|
||||
return results
|
||||
|
||||
try:
|
||||
loop = asyncio.get_event_loop()
|
||||
except RuntimeError:
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
|
||||
finalResults = loop.run_until_complete(main())
|
||||
|
||||
optResult = [ExecutionBlocker(None)] * 4
|
||||
rindex = 0
|
||||
workingTasks = 0
|
||||
|
||||
for i, task_config in enumerate(tasksData):
|
||||
if task_config is not None:
|
||||
result = finalResults[rindex]
|
||||
if result is not None and not isinstance(result, ExecutionBlocker):
|
||||
workingTasks += 1
|
||||
optResult[i] = result
|
||||
rindex += 1
|
||||
|
||||
if workingTasks == 0 and len(validTasks) > 0:
|
||||
firstError = min(taskIncidents.keys())
|
||||
raise Exception(
|
||||
f"Error in Task {firstError + 1} => {taskIncidents[firstError]}"
|
||||
)
|
||||
|
||||
return tuple(optResult)
|
||||
@@ -187,4 +187,4 @@ class photoMaker:
|
||||
|
||||
genResult = rwUtils.inferenecRequest(genConfig)
|
||||
images = rwUtils.convertImageB64List(genResult)
|
||||
return images
|
||||
return (images, )
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
class teaCache:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"TeaCache Distance": (
|
||||
"FLOAT",
|
||||
{
|
||||
"tooltip": "Controls the aggressiveness of the TeaCache feature.\n\nValues range from 0.0 (most conservative) to 1.0 (most aggressive).\n\nLower values prioritize quality by being more selective about which computations to reuse, while higher values prioritize speed by reusing more computations.",
|
||||
"default": 0.5,
|
||||
"min": 0.0,
|
||||
"max": 1.0,
|
||||
"step": 0.1,
|
||||
},
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
DESCRIPTION = "Can Be connected to Runware Inference to accelerate image generation by reusing past computations.\n\nTeaCache is specifically designed for transformer-based models such as Flux and SD3, and does not work with UNet models like SDXL or SD1.5."
|
||||
FUNCTION = "teaCache"
|
||||
RETURN_TYPES = ("RUNWAREACCELERATOR",)
|
||||
RETURN_NAMES = ("Runware Accelerator",)
|
||||
CATEGORY = "Runware"
|
||||
|
||||
def teaCache(self, **kwargs):
|
||||
teaCacheDistance = kwargs.get("TeaCache Distance")
|
||||
|
||||
return (
|
||||
{
|
||||
"teaCache": True,
|
||||
"teaCacheDistance": round(teaCacheDistance, 2),
|
||||
},
|
||||
)
|
||||
+1
-1
@@ -40,4 +40,4 @@ class upscaler:
|
||||
|
||||
genResult = rwUtils.inferenecRequest(genConfig)
|
||||
images = rwUtils.convertImageB64List(genResult)
|
||||
return images
|
||||
return (images, )
|
||||
@@ -411,4 +411,4 @@ def convertImageB64List(imageDataObject):
|
||||
generatedImage = convertIMG2Tensor(generatedImage)
|
||||
images += (generatedImage,)
|
||||
images = torch.stack(images, dim=0)
|
||||
return (images,)
|
||||
return images
|
||||
|
||||
Reference in New Issue
Block a user