[Frontend] Add MiniMax-H3 references and Ref2VA workflow (#7483)
Signed-off-by: Linze-Shi <linzeshi0@gmail.com>
This commit is contained in:
1 parent
5f7f62e13c
commit
e78a5d01f7
9 files changed
+1235
-66
No files matched your search
@@ -0,0 +1,115 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
|
||||
|
||||
import json
|
||||
from graphlib import TopologicalSorter
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from comfyui_vllm_omni import nodes as omni_nodes
|
||||
|
||||
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
|
||||
|
||||
WORKFLOW = (
|
||||
Path(__file__).resolve().parents[4]
|
||||
/ "apps/ComfyUI-vLLM-Omni/example_workflows/vLLM-Omni MiniMax-H3 Reference to Video.json"
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def workflow():
|
||||
return json.loads(WORKFLOW.read_text())
|
||||
|
||||
|
||||
def test_reference_workflow_connections(workflow):
|
||||
nodes = {node["id"]: node for node in workflow["nodes"]}
|
||||
links = {link[0]: link for link in workflow["links"]}
|
||||
assert len(nodes) == len(workflow["nodes"])
|
||||
assert len(links) == len(workflow["links"])
|
||||
graph: dict[int, set[int]] = {node_id: set() for node_id in nodes}
|
||||
for link_id, source, output_slot, target, input_slot, kind in links.values():
|
||||
output = nodes[source]["outputs"][output_slot]
|
||||
input_ = nodes[target]["inputs"][input_slot]
|
||||
assert output["type"] == input_["type"] == kind
|
||||
assert link_id in output["links"]
|
||||
assert input_["link"] == link_id
|
||||
graph[target].add(source)
|
||||
assert len(tuple(TopologicalSorter(graph).static_order())) == len(nodes)
|
||||
for node in nodes.values():
|
||||
for slot, input_ in enumerate(node.get("inputs", [])):
|
||||
if input_["link"] is not None:
|
||||
assert links[input_["link"]][3:5] == [node["id"], slot]
|
||||
for slot, output in enumerate(node.get("outputs", [])):
|
||||
for link_id in output.get("links") or []:
|
||||
assert links[link_id][1:3] == [node["id"], slot]
|
||||
|
||||
|
||||
def test_reference_workflow_matches_omni_node_interfaces(workflow):
|
||||
for node in workflow["nodes"]:
|
||||
if not node["type"].startswith("VLLMOmni"):
|
||||
continue
|
||||
cls = getattr(omni_nodes, node["type"])
|
||||
schema = cls.INPUT_TYPES()
|
||||
inputs = {**schema.get("required", {}), **schema.get("optional", {})}
|
||||
for input_ in node["inputs"]:
|
||||
assert input_["type"] == inputs[input_["name"]][0]
|
||||
assert tuple(output["type"] for output in node["outputs"]) == cls.RETURN_TYPES
|
||||
expected_widgets = len(schema.get("required", {}))
|
||||
if "seed" in schema.get("required", {}):
|
||||
expected_widgets += 1
|
||||
assert len(node["widgets_values"]) == expected_widgets
|
||||
refs = next(node for node in workflow["nodes"] if node["type"] == "VLLMOmniVideoReferences")
|
||||
assert [input_["name"] for input_ in refs["inputs"]] == list(
|
||||
omni_nodes.VLLMOmniVideoReferences.INPUT_TYPES()["optional"]
|
||||
)
|
||||
|
||||
|
||||
def test_reference_workflow_default_route_and_output(workflow):
|
||||
nodes = {node["id"]: node for node in workflow["nodes"]}
|
||||
links = {link[0]: link for link in workflow["links"]}
|
||||
generate = next(node for node in nodes.values() if node["type"] == "VLLMOmniGenerateVideo")
|
||||
inputs = {input_["name"]: input_["link"] for input_ in generate["inputs"]}
|
||||
assert inputs["frame"] is None
|
||||
assert inputs["lora"] is None
|
||||
for name, kind in (
|
||||
("references", "VLLMOmniVideoReferences"),
|
||||
("sampling_params", "VLLMOmniDiffusionSampling"),
|
||||
("model_params", "VLLMOmniMiniMaxH3Params"),
|
||||
):
|
||||
assert nodes[links[inputs[name]][1]]["type"] == kind
|
||||
save = next(node for node in nodes.values() if node["type"] == "SaveVideo")
|
||||
assert links[save["inputs"][0]["link"]][1] == generate["id"]
|
||||
assert save["widgets_values"] == ["video/MiniMax-H3-Ref2VA", "mp4", "h264"]
|
||||
|
||||
|
||||
def test_reference_workflow_defaults_and_portable_assets(workflow):
|
||||
by_type = {node["type"]: node for node in workflow["nodes"]}
|
||||
values = by_type["VLLMOmniGenerateVideo"]["widgets_values"]
|
||||
assert values[0] == "http://localhost:8000/v1"
|
||||
assert values[1] == "MiniMaxAI/MiniMax-H3"
|
||||
assert "<Picture 1>" in values[2]
|
||||
assert values[4:8] == [1344, 768, 24, 5.167]
|
||||
num_frames = round(values[7] * values[6])
|
||||
assert num_frames == 124
|
||||
assert values[3] == ""
|
||||
assert (num_frames - 5) % 17 == 0
|
||||
assert 4 <= values[7] <= 15
|
||||
assert by_type["VLLMOmniDiffusionSampling"]["widgets_values"] == [1, 50, 1.0, 1.0, False, False, 42, "fixed"]
|
||||
assert by_type["VLLMOmniMiniMaxH3Params"]["widgets_values"] == [3.0, 12.0]
|
||||
assert by_type["VLLMOmniRemoteLoRA"]["widgets_values"][0] == ""
|
||||
for kind in ("LoadImage", "LoadVideo", "LoadAudio"):
|
||||
filename = by_type[kind]["widgets_values"][0]
|
||||
assert filename and Path(filename).name == filename
|
||||
assert ":" not in filename and "\\" not in filename
|
||||
assert set(by_type) == {
|
||||
"LoadImage",
|
||||
"LoadVideo",
|
||||
"LoadAudio",
|
||||
"SaveVideo",
|
||||
"MarkdownNote",
|
||||
"VLLMOmniVideoReferences",
|
||||
"VLLMOmniGenerateVideo",
|
||||
"VLLMOmniDiffusionSampling",
|
||||
"VLLMOmniMiniMaxH3Params",
|
||||
"VLLMOmniRemoteLoRA",
|
||||
}
|
||||
Reference in new issue
Block a user