Jump latent upscale fallback to spatial split
This commit is contained in:
+10
-1
@@ -150,7 +150,16 @@ class H3ModelInspector:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {"required": {"model": ("MODEL",)}}
|
return {
|
||||||
|
"required": {
|
||||||
|
"model": (
|
||||||
|
"MODEL",
|
||||||
|
{
|
||||||
|
"tooltip": "MiniMax / H3 model to inspect for quantization and tensor format."
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def inspect(self, model):
|
def inspect(self, model):
|
||||||
label, _counts, report = _detect(model)
|
label, _counts, report = _detect(model)
|
||||||
|
|||||||
+12
-10
@@ -521,21 +521,23 @@ def _shrink_model_tile_param(param):
|
|||||||
|
|
||||||
tile_w = int(next_param.get("tile_width", 0) or 0)
|
tile_w = int(next_param.get("tile_width", 0) or 0)
|
||||||
tile_h = int(next_param.get("tile_height", 0) or 0)
|
tile_h = int(next_param.get("tile_height", 0) or 0)
|
||||||
new_w = _halve_32(tile_w)
|
if tile_w <= 0 or tile_h <= 0:
|
||||||
new_h = _halve_32(tile_h)
|
|
||||||
if new_w < 32 or new_h < 32:
|
|
||||||
return None
|
return None
|
||||||
if new_w >= tile_w and new_h >= tile_h:
|
|
||||||
return None
|
# Jump straight from a coarse specific-size tile to a conservative 2x2
|
||||||
next_param["tile_width"] = new_w
|
# equal-grid split. That usually cuts peak VRAM much harder than halving
|
||||||
next_param["tile_height"] = new_h
|
# the tile size through several retries.
|
||||||
next_param["overlap"] = _halve_32(next_param.get("overlap", 0))
|
next_param["tile_size_mode"] = "rows_cols"
|
||||||
|
next_param["grid_rows"] = 2
|
||||||
|
next_param["grid_cols"] = 2
|
||||||
|
next_param["spatial_w_overlap"] = _halve_32(next_param.get("overlap", 0))
|
||||||
|
next_param["spatial_h_overlap"] = _halve_32(next_param.get("overlap", 0))
|
||||||
next_param["fade_width"] = _halve_32(next_param.get("fade_width", 0))
|
next_param["fade_width"] = _halve_32(next_param.get("fade_width", 0))
|
||||||
next_param["fade_height"] = _halve_32(next_param.get("fade_height", 0))
|
next_param["fade_height"] = _halve_32(next_param.get("fade_height", 0))
|
||||||
next_param["min_tile_size"] = min(
|
next_param["min_tile_size"] = min(
|
||||||
_halve_32(next_param.get("min_tile_size", 0)),
|
_halve_32(next_param.get("min_tile_size", 0)),
|
||||||
new_w,
|
max(32, _halve_32(tile_w)),
|
||||||
new_h,
|
max(32, _halve_32(tile_h)),
|
||||||
)
|
)
|
||||||
return next_param
|
return next_param
|
||||||
|
|
||||||
|
|||||||
@@ -39,10 +39,11 @@ class H3ShotLength:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"shot_seconds": ("FLOAT", {"default": 5.0, "min": 0.2, "max": 15.1, "step": 0.5,
|
"shot_seconds": ("FLOAT", {"default": 3.0, "min": 0.2, "max": 15.1, "step": 0.5,
|
||||||
"tooltip": "Length of each shot. Feeds the sampler's shot_seconds AND (as frames) "
|
"tooltip": "Length of each shot. Feeds the sampler's shot_seconds AND (as frames) "
|
||||||
"the preview override. Max ~15s (362 frames)."}),
|
"the preview override. Default 3s matches the common one-beat H3 test shot. Max ~15s (362 frames)."}),
|
||||||
"fps": ("INT", {"default": 24, "min": 1, "max": 60}),
|
"fps": ("INT", {"default": 24, "min": 1, "max": 60,
|
||||||
|
"tooltip": "Frame rate used for the seconds->frames conversion. H3 itself renders at 24fps, so 24 is the realistic default."}),
|
||||||
},
|
},
|
||||||
"optional": {
|
"optional": {
|
||||||
"cap_to_h3_max": ("BOOLEAN", {"default": True,
|
"cap_to_h3_max": ("BOOLEAN", {"default": True,
|
||||||
|
|||||||
+50
-29
@@ -277,7 +277,14 @@ class DumasJSONStringToObjectNode:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_string": ("STRING", {"multiline": True}),
|
"json_string": (
|
||||||
|
"STRING",
|
||||||
|
{
|
||||||
|
"multiline": True,
|
||||||
|
"default": '{\n "shots": [\n {\n "prompt": "Francine stands by the window."\n }\n ]\n}',
|
||||||
|
"tooltip": "Raw JSON text to parse into a structured JSON object."
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +306,14 @@ class DumasStripIterationSuffixNode:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"filename": ("STRING", {"default": "", "multiline": False}),
|
"filename": (
|
||||||
|
"STRING",
|
||||||
|
{
|
||||||
|
"default": "francine_pose_final.png",
|
||||||
|
"multiline": False,
|
||||||
|
"tooltip": "Filename to normalize by removing everything after the first underscore in the stem."
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +330,14 @@ class DumasSlugifyStringNode:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"text": ("STRING", {"default": "", "multiline": False}),
|
"text": (
|
||||||
|
"STRING",
|
||||||
|
{
|
||||||
|
"default": "Francine Coffee Shop",
|
||||||
|
"multiline": False,
|
||||||
|
"tooltip": "Text to slugify into lowercase ASCII words joined with hyphens."
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,8 +355,8 @@ class DumasJSONObjectToStringNode:
|
|||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_object": ("JSON",),
|
"json_object": ("JSON",),
|
||||||
"pretty": ("BOOLEAN", {"default": True}),
|
"pretty": ("BOOLEAN", {"default": True, "tooltip": "Pretty-print the JSON with indentation."}),
|
||||||
"sort_keys": ("BOOLEAN", {"default": False}),
|
"sort_keys": ("BOOLEAN", {"default": False, "tooltip": "Sort object keys alphabetically before serializing."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +376,7 @@ class DumasJSONGetValueNode:
|
|||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_object": ("JSON",),
|
"json_object": ("JSON",),
|
||||||
"path": ("STRING", {"default": "", "multiline": False}),
|
"path": ("STRING", {"default": "shots.0.prompt", "multiline": False, "tooltip": "Dot-path to read, such as 'shots.0.prompt'."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,8 +394,8 @@ class DumasJSONSetValueNode:
|
|||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_object": ("JSON",),
|
"json_object": ("JSON",),
|
||||||
"path": ("STRING", {"default": "", "multiline": False}),
|
"path": ("STRING", {"default": "shots.0.prompt", "multiline": False, "tooltip": "Dot-path to write, such as 'shots.0.prompt' or 'shots.1.duration'."}),
|
||||||
"value_json": ("STRING", {"multiline": True, "default": "null"}),
|
"value_json": ("STRING", {"multiline": True, "default": '"Francine stands by the window."', "tooltip": "JSON value to store at the path. Must be valid JSON, so strings need quotes."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,7 +419,7 @@ class DumasJSONHasKeyNode:
|
|||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_object": ("JSON",),
|
"json_object": ("JSON",),
|
||||||
"path": ("STRING", {"default": "", "multiline": False}),
|
"path": ("STRING", {"default": "shots.0.prompt", "multiline": False, "tooltip": "Dot-path to test for existence."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,7 +437,7 @@ class DumasJSONRemoveKeyNode:
|
|||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_object": ("JSON",),
|
"json_object": ("JSON",),
|
||||||
"path": ("STRING", {"default": "", "multiline": False}),
|
"path": ("STRING", {"default": "shots.0.prompt", "multiline": False, "tooltip": "Dot-path to remove from the object."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,7 +455,7 @@ class DumasJSONPickFieldsNode:
|
|||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_object": ("JSON",),
|
"json_object": ("JSON",),
|
||||||
"paths": ("STRING", {"multiline": True, "default": ""}),
|
"paths": ("STRING", {"multiline": True, "default": "shots.0.prompt\nshots.0.duration", "tooltip": "One dot-path per line. Only those fields are copied into the output object."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,8 +484,8 @@ class DumasJSONMergeObjectsNode:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"base_object": ("JSON",),
|
"base_object": ("JSON", {"tooltip": "Base JSON object to start from."}),
|
||||||
"overlay_object": ("JSON",),
|
"overlay_object": ("JSON", {"tooltip": "Overlay JSON object whose keys replace or merge into the base object."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +503,7 @@ class DumasJSONKeysNode:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_object": ("JSON",),
|
"json_object": ("JSON", {"tooltip": "JSON object whose top-level keys should be listed."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,7 +523,7 @@ class DumasJSONArrayLengthNode:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_array": ("JSON",),
|
"json_array": ("JSON", {"tooltip": "JSON array whose length should be measured."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,8 +542,8 @@ class DumasJSONArrayAppendNode:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_array": ("JSON",),
|
"json_array": ("JSON", {"tooltip": "JSON array to append to."}),
|
||||||
"value_json": ("STRING", {"multiline": True, "default": "null"}),
|
"value_json": ("STRING", {"multiline": True, "default": '{"prompt":"Francine looks toward the door."}', "tooltip": "JSON value to append. Must be valid JSON."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -548,10 +569,10 @@ class DumasJSONArraySliceNode:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_array": ("JSON",),
|
"json_array": ("JSON", {"tooltip": "JSON array to slice."}),
|
||||||
"start": ("INT", {"default": 0, "step": 1}),
|
"start": ("INT", {"default": 0, "step": 1, "tooltip": "Zero-based start index."}),
|
||||||
"end": ("INT", {"default": 0, "step": 1}),
|
"end": ("INT", {"default": 0, "step": 1, "tooltip": "Zero-based end index. Use 0 to mean 'to the end'."}),
|
||||||
"step": ("INT", {"default": 1, "step": 1, "min": 1}),
|
"step": ("INT", {"default": 1, "step": 1, "min": 1, "tooltip": "Slice step size."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -572,9 +593,9 @@ class DumasJSONArrayIteratorNode:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_input": ("JSON",),
|
"json_input": ("JSON", {"tooltip": "JSON array to iterate over."}),
|
||||||
"index": ("INT", {"default": 0, "min": 0, "step": 1}),
|
"index": ("INT", {"default": 0, "min": 0, "step": 1, "tooltip": "Current zero-based index."}),
|
||||||
"mode": (["fixed", "incr", "decr"], {"default": "fixed"}),
|
"mode": (["fixed", "incr", "decr"], {"default": "fixed", "tooltip": "Keep the index fixed, increment it, or decrement it before reading."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,9 +621,9 @@ class DumasJSONObjectIteratorNode:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_input": ("JSON",),
|
"json_input": ("JSON", {"tooltip": "JSON object whose key/value pairs should be iterated in insertion order."}),
|
||||||
"index": ("INT", {"default": 0, "min": 0, "step": 1}),
|
"index": ("INT", {"default": 0, "min": 0, "step": 1, "tooltip": "Current zero-based index into the object's items."}),
|
||||||
"mode": (["fixed", "incr", "decr"], {"default": "fixed"}),
|
"mode": (["fixed", "incr", "decr"], {"default": "fixed", "tooltip": "Keep the index fixed, increment it, or decrement it before reading."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -628,7 +649,7 @@ class DumasJSONFlattenNode:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"json_input": ("JSON",),
|
"json_input": ("JSON", {"tooltip": "Nested JSON value to flatten into dot-path keys."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -645,7 +666,7 @@ class DumasJSONUnflattenNode:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"flat_json_object": ("JSON",),
|
"flat_json_object": ("JSON", {"tooltip": "Flat JSON object whose keys are dot-paths to rebuild into nested JSON."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1172,12 +1172,12 @@ class DumasH3LongVideosHelperTests(unittest.TestCase):
|
|||||||
"fade_height": 32,
|
"fade_height": 32,
|
||||||
})
|
})
|
||||||
self.assertIsNotNone(smaller)
|
self.assertIsNotNone(smaller)
|
||||||
self.assertLess(smaller["tile_width"], 512)
|
self.assertEqual(smaller["tile_size_mode"], "rows_cols")
|
||||||
self.assertLess(smaller["tile_height"], 512)
|
self.assertEqual(smaller["grid_rows"], 2)
|
||||||
|
self.assertEqual(smaller["grid_cols"], 2)
|
||||||
self.assertEqual(smaller["fade_width"] % 32, 0)
|
self.assertEqual(smaller["fade_width"] % 32, 0)
|
||||||
self.assertEqual(smaller["fade_height"] % 32, 0)
|
self.assertEqual(smaller["fade_height"] % 32, 0)
|
||||||
self.assertLessEqual(smaller["min_tile_size"], smaller["tile_width"])
|
self.assertGreaterEqual(smaller["min_tile_size"], 0)
|
||||||
self.assertLessEqual(smaller["min_tile_size"], smaller["tile_height"])
|
|
||||||
|
|
||||||
def test_temporal_segments_split_long_sequences(self):
|
def test_temporal_segments_split_long_sequences(self):
|
||||||
latent = importlib.import_module("dumas_h3_latent_upscale")
|
latent = importlib.import_module("dumas_h3_latent_upscale")
|
||||||
|
|||||||
Reference in New Issue
Block a user