Files
82dfce256f feat: new tests for nunchaku comfyui from lmxyy & ttio2tech, tested and verified on comfyui 0.3.63 upstream and 0.3.60 LTS (#641) (#650)
* bump requires-python

* model patcher now implements everything it needs for comfyui

* index

* Support LTS and Vanilla ComfyUI

* Fix version string when installed as package (not material)

* style: make linter happy

* update init.py

* Update nunchaku index

* Bump dependencies, include config and workflows when installed using pip/uv

* Update installation instructions to include ComfyUI LTS

* Update requirements for nunchaku>=1.0.1

* Fix torch210 key

* Fix pep 508 spec

* Improve tests (still more to go)

* Fix comfyui_controlnet_aux flaws

* Update tests (all should pass)

* Organize the tests in this runner

* Update contribution guide

* Install uv

* Dependencies now resolve with correct conflicts with uv's most stringent resolution

* Mediapipe hasn't been built for 3.13 yet, so we can't use it here

* Remove controlnet-aux dep

* make linter happy

* make the linter happy

* optimize the loading

* update installation

* update

* update contribution guide

* update qwenimage

* need to figure out why the toml parsing doesn't owk

* update

* update

* update

* style: make linter happy

* update

* add pulid requirement

* update docs

* update

* update

* update

* update

* update

* organize the pyproject.toml

* update

* update

* update

* passing all tests

* update

* update

* update

* update

* update

* remove a useless class

* update

* update

* fix a typo

---------

Co-authored-by: doctorpangloss <@hiddenswitch.com>
Co-authored-by: doctorpangloss <2229300+doctorpangloss@users.noreply.github.com>
2025-10-14 00:46:20 -04:00

58 lines
2.1 KiB
Python

import json
import logging
from pathlib import Path
import pytest
import pytest_asyncio
import torch
from comfy.api.components.schema.prompt import Prompt
from comfy.cli_args_types import Configuration
from comfy.client.embedded_comfy_client import Comfy
from nunchaku.utils import get_precision, is_turing
from .case import Case, cases, ids
from .utils import compute_metrics, prepare_inputs, prepare_models, set_nested_value
logger = logging.getLogger(__name__)
precision = get_precision()
torch_dtype = torch.float16 if is_turing() else torch.bfloat16
dtype_str = "fp16" if torch_dtype == torch.float16 else "bf16"
@pytest_asyncio.fixture(scope="module", autouse=False)
async def inputs(tmp_path_factory):
config = Configuration()
input_path = config.input_directory = str(tmp_path_factory.mktemp("nunchaku_input"))
prepare_inputs(input_path)
yield config
@pytest_asyncio.fixture(scope="function", autouse=False)
async def client(tmp_path_factory, inputs) -> Comfy:
async with Comfy(inputs) as client_instance:
prepare_models()
yield client_instance
@pytest.mark.asyncio
@pytest.mark.parametrize("case", cases, ids=ids)
async def test(case: Case, client: Comfy):
api_file = Path(__file__).parent / "workflows" / case.workflow_name / "api.json"
# Read and parse the workflow file
workflow = json.loads(api_file.read_text(encoding="utf8"))
for key, value in case.inputs.items():
set_nested_value(workflow, key, value)
prompt = Prompt.validate(workflow)
outputs = await client.queue_prompt(prompt)
save_image_node_id = next(key for key in prompt if prompt[key].class_type == "SaveImage")
path = outputs[save_image_node_id]["images"][0]["abs_path"]
logger.info("Generated image path: %s", path)
clip_iqa, lpips, psnr = compute_metrics(path, case.ref_image_url)
assert clip_iqa >= min(case.expected_clip_iqa[f"{precision}-{dtype_str}"], 1) * 0.9
assert lpips <= max(case.expected_lpips[f"{precision}-{dtype_str}"], 0.1) * 1.15
assert psnr >= min(case.expected_psnr[f"{precision}-{dtype_str}"], 24) * 0.85