Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76d4d8e91e |
+2
-3
@@ -1,6 +1,5 @@
|
|||||||
from . import workflowcheckpointing, orchestration
|
from . import workflowcheckpointing
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {}
|
NODE_CLASS_MAPPINGS = {}
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {}
|
NODE_DISPLAY_NAME_MAPPINGS = {}
|
||||||
WEB_DIRECTORY = "./web"
|
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]
|
||||||
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
|
|
||||||
|
|||||||
+76
-40
@@ -12,9 +12,9 @@ import hashlib
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
import comfy.samplers
|
import comfy.samplers
|
||||||
import execution
|
|
||||||
import server
|
import server
|
||||||
import heapq
|
import heapq
|
||||||
|
import execution
|
||||||
|
|
||||||
SAMPLER_NODES = ["SamplerCustom", "KSampler", "KSamplerAdvanced", "SamplerCustomAdvanced"]
|
SAMPLER_NODES = ["SamplerCustom", "KSampler", "KSamplerAdvanced", "SamplerCustomAdvanced"]
|
||||||
|
|
||||||
@@ -31,6 +31,16 @@ async def get_header():
|
|||||||
SALAD_TOKEN =(await r.json())['jwt']
|
SALAD_TOKEN =(await r.json())['jwt']
|
||||||
return {'Authorization': SALAD_TOKEN}
|
return {'Authorization': SALAD_TOKEN}
|
||||||
|
|
||||||
|
def logError(func):
|
||||||
|
def wrapped(*args, **kwargs):
|
||||||
|
try:
|
||||||
|
func(*args, **kwargs)
|
||||||
|
except:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
raise
|
||||||
|
return func
|
||||||
|
|
||||||
class RequestLoop:
|
class RequestLoop:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.active_request = None
|
self.active_request = None
|
||||||
@@ -328,6 +338,9 @@ async def fetch_remote_files(remote_files, uid=None):
|
|||||||
|
|
||||||
completion_futures = {}
|
completion_futures = {}
|
||||||
def add_future(json_data):
|
def add_future(json_data):
|
||||||
|
if len(completion_futures.keys() == 0):
|
||||||
|
#For debugging, should be changed to assert later
|
||||||
|
return
|
||||||
index = max(completion_futures.keys())
|
index = max(completion_futures.keys())
|
||||||
json_data['extra_data']['completion_future'] = index
|
json_data['extra_data']['completion_future'] = index
|
||||||
return json_data
|
return json_data
|
||||||
@@ -377,14 +390,15 @@ async def post_prompt_remote(request):
|
|||||||
json_output['machineid'] = os.environ.get('SALAD_MACHINE_ID', "local")
|
json_output['machineid'] = os.environ.get('SALAD_MACHINE_ID', "local")
|
||||||
return server.web.Response(body=json.dumps(json_output))
|
return server.web.Response(body=json.dumps(json_output))
|
||||||
#Dangerous
|
#Dangerous
|
||||||
object.__setattr__(prompt_route, 'handler', post_prompt_remote)
|
#object.__setattr__(prompt_route, 'handler', post_prompt_remote)
|
||||||
|
|
||||||
class CheckpointSampler(comfy.samplers.KSAMPLER):
|
class CheckpointSampler(comfy.samplers.KSAMPLER):
|
||||||
def sample(self, *args, **kwargs):
|
def sample(self, *args, **kwargs):
|
||||||
args = list(args)
|
args = list(args)
|
||||||
self.unique_id = server.PromptServer.instance.last_node_id
|
self.unique_id = server.PromptServer.instance.last_node_id
|
||||||
self.step = None
|
self.step = None
|
||||||
data, metadata = checkpoint.get(self.unique_id)
|
#data, metadata = checkpoint.get(self.unique_id)
|
||||||
|
data, metadata = None, None
|
||||||
if metadata is not None and 'step' in metadata:
|
if metadata is not None and 'step' in metadata:
|
||||||
data = data['x']
|
data = data['x']
|
||||||
self.step = int(metadata['step'])
|
self.step = int(metadata['step'])
|
||||||
@@ -411,41 +425,57 @@ class CheckpointSampler(comfy.samplers.KSAMPLER):
|
|||||||
if step == int(os.environ['FORCE_CRASH_AT']):
|
if step == int(os.environ['FORCE_CRASH_AT']):
|
||||||
raise Exception("Simulated Crash")
|
raise Exception("Simulated Crash")
|
||||||
|
|
||||||
original_recursive_execute = execution.execute
|
class CheckpointCache(execution.HierarchicalCache):
|
||||||
def recursive_execute_injection(*args):
|
def __init__(self, key_class):
|
||||||
unique_id = args[3]
|
self.injected = {}
|
||||||
class_type = args[1].get_node(unique_id)['class_type']
|
super().__init__(key_class)
|
||||||
extra_data = args[4]
|
def get(self, node_id):
|
||||||
if class_type in SAMPLER_NODES:
|
try:
|
||||||
data, metadata = checkpoint.get(unique_id)
|
return super().get(node_id)
|
||||||
if metadata is not None and 'step' in metadata:
|
except:
|
||||||
args[1].get_node(unique_id)['inputs']['latent_image'] = ['checkpointed'+unique_id, 0]
|
print("oppsie-woopsi")
|
||||||
args[2].outputs.set('checkpointed'+unique_id, [[{'samples': data['x']}]])
|
if node_id in self.injected:
|
||||||
elif metadata is not None and 'completed' in metadata:
|
return self.injected[node_id]
|
||||||
outputs = json.loads(metadata['completed'])
|
#We don't want real ID. if any looping has occured, subresults must cache independently
|
||||||
for x in range(len(outputs)):
|
node = self.dynprompt.get_node(node_id)
|
||||||
if outputs[x] == 'tensor':
|
if node['class_type'] in SAMPLER_NODES and ('checkpointed'+node_id) not in self.injected:
|
||||||
outputs[x] = list(data[str(x)])
|
data, metadata = checkpoint.get(node_id)
|
||||||
elif outputs[x] == 'latent':
|
if metadata is not None and 'step' in metadata:
|
||||||
outputs[x] = [{'samples': l} for l in data[str(x)]]
|
#TODO: redirect dynprompt and fill cache?
|
||||||
args[2].outputs.set(unique_id, outputs)
|
node = node.copy()
|
||||||
return True, None, None
|
node['inputs'] = node['inputs'].copy()
|
||||||
|
node['inputs']['latent_image'] = ['checkpointed'+node_id, 0]
|
||||||
res = original_recursive_execute(*args)
|
self.dynprompt.ephemeral_prompt[node_id] = node
|
||||||
#Conditionally save node output
|
self.injected['checkpointed'+node_id] = [[{'samples': data['x']}]]
|
||||||
#TODO: determine which non-sampler nodes are worth saving
|
elif metadata is not None and 'completed' in metadata:
|
||||||
if class_type in SAMPLER_NODES and args[2].outputs.get(unique_id) is not None:
|
outputs = json.loads(metadata['completed'])
|
||||||
data = {}
|
for x in range(len(outputs)):
|
||||||
outputs = args[2].outputs.get(unique_id).copy()
|
if outputs[x] == 'tensor':
|
||||||
for x in range(len(outputs)):
|
outputs[x] = list(data[str(x)])
|
||||||
if isinstance(outputs[x][0], torch.Tensor):
|
elif outputs[x] == 'latent':
|
||||||
data[str(x)] = torch.stack(outputs[x])
|
outputs[x] = [{'samples': l} for l in data[str(x)]]
|
||||||
outputs[x] = 'tensor'
|
return outputs
|
||||||
elif isinstance(outputs[x][0], dict):
|
return super().get(node_id)
|
||||||
data[str(x)] = torch.stack([l['samples'] for l in outputs[x]])
|
def set(self, node_id, value):
|
||||||
outputs[x] = 'latent'
|
try:
|
||||||
checkpoint.store(unique_id, data, {'completed': json.dumps(outputs)}, priority=1)
|
node = self.dynprompt.get_node(node_id)
|
||||||
return res
|
if node['class_type'] in SAMPLER_NODES:
|
||||||
|
print(node_id, value)
|
||||||
|
return super().set(node_id, value)
|
||||||
|
breakpoint()
|
||||||
|
data = {}
|
||||||
|
for x in range(len(value)):
|
||||||
|
if isinstance(value[x][0], torch.Tensor):
|
||||||
|
data[str(x)] = torch.stack(value[x])
|
||||||
|
value[x] = 'tensor'
|
||||||
|
elif isinstance(value[x][0], dict):
|
||||||
|
data[str(x)] = torch.stack([l['samples'] for l in value[x]])
|
||||||
|
value[x] = 'latent'
|
||||||
|
checkpoint.store(node_id, data, {'completed': json.dumps(outputs)}, priority=1)
|
||||||
|
except:
|
||||||
|
breakpoint()
|
||||||
|
print("oopsie")
|
||||||
|
return super().set(node_id, value)
|
||||||
original_execute = execution.PromptExecutor.execute
|
original_execute = execution.PromptExecutor.execute
|
||||||
def execute_injection(*args, **kwargs):
|
def execute_injection(*args, **kwargs):
|
||||||
metadata = checkpoint.get('prompt')[1]
|
metadata = checkpoint.get('prompt')[1]
|
||||||
@@ -467,9 +497,15 @@ def execute_injection(*args, **kwargs):
|
|||||||
if 'completion_future' in args[3]:
|
if 'completion_future' in args[3]:
|
||||||
completion_futures[args[3]['completion_future']].set_result(outputs)
|
completion_futures[args[3]['completion_future']].set_result(outputs)
|
||||||
|
|
||||||
comfy.samplers.KSAMPLER = CheckpointSampler
|
orig_reset = execution.PromptExecutor.reset
|
||||||
execution.execute = recursive_execute_injection
|
def reset(self):
|
||||||
|
checkpoint.reset()
|
||||||
|
orig_reset(self)
|
||||||
|
|
||||||
|
execution.PromptExecutor.reset = reset
|
||||||
execution.PromptExecutor.execute = execute_injection
|
execution.PromptExecutor.execute = execute_injection
|
||||||
|
execution.HierarchicalCache = CheckpointCache
|
||||||
|
comfy.samplers.KSAMPLER = CheckpointSampler
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {}
|
NODE_CLASS_MAPPINGS = {}
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {}
|
NODE_DISPLAY_NAME_MAPPINGS = {}
|
||||||
|
|||||||
Reference in New Issue
Block a user