feat(ml): auto-commit con 11 cambios

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-24 01:39:30 +02:00
parent d7245efa59
commit d3f05a19a5
11 changed files with 1148 additions and 12 deletions
@@ -0,0 +1,80 @@
"""Tests de estructura para comfyui_build_textured_3d_multiview_workflow (pura)."""
import os
import sys
import pytest
sys.path.insert(0, os.path.dirname(__file__))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))
from ml.comfyui_build_textured_3d_multiview_workflow import (
comfyui_build_textured_3d_multiview_workflow,
)
from _comfyui_wf_assert import assert_api_format, class_types, node_by_ct
def test_estructura_shape_paint_y_upscale():
wf = comfyui_build_textured_3d_multiview_workflow("ref.png", views=6)
assert_api_format(wf)
cts = class_types(wf)
# Fase shape (geometria) + fase paint (textura multi-vista) + upscale Remacri.
for ct in (
"LoadImage",
"Hy3DModelLoader",
"Hy3DGenerateMesh",
"Hy3DVAEDecode",
"Hy3DPostprocessMesh",
"Hy3DMeshUVWrap",
"DownloadAndLoadHy3DPaintModel",
"DownloadAndLoadHy3DDelightModel",
"Hy3DCameraConfig",
"Hy3DRenderMultiView",
"Hy3DDelightImage",
"Hy3DSampleMultiView",
"UpscaleModelLoader",
"ImageUpscaleWithModel",
"ImageResize+",
"Hy3DBakeFromMultiview",
"Hy3DApplyTexture",
"Hy3DExportMesh",
):
assert ct in cts, f"falta {ct}"
def test_params_imagen_ckpt_octree_faces():
wf = comfyui_build_textured_3d_multiview_workflow(
"robot.png", ckpt="custom-mv.safetensors", octree=256, max_faces=40000
)
assert node_by_ct(wf, "LoadImage")["inputs"]["image"] == "robot.png"
assert node_by_ct(wf, "Hy3DModelLoader")["inputs"]["model"] == "custom-mv.safetensors"
assert node_by_ct(wf, "Hy3DVAEDecode")["inputs"]["octree_resolution"] == 256
assert node_by_ct(wf, "Hy3DPostprocessMesh")["inputs"]["max_facenum"] == 40000
def test_6_vistas_configura_camara():
wf = comfyui_build_textured_3d_multiview_workflow("ref.png", views=6)
cam = node_by_ct(wf, "Hy3DCameraConfig")["inputs"]
# 6 azimuths/elevations (front/left/back/right + top/bottom).
assert len(cam["camera_azimuths"].split(",")) == 6
assert len(cam["camera_elevations"].split(",")) == 6
def test_4_vistas_configura_camara():
wf = comfyui_build_textured_3d_multiview_workflow("ref.png", views=4)
cam = node_by_ct(wf, "Hy3DCameraConfig")["inputs"]
assert len(cam["camera_azimuths"].split(",")) == 4
def test_sin_upscale_omite_nodos_remacri():
wf = comfyui_build_textured_3d_multiview_workflow("ref.png", upscale_model="")
cts = class_types(wf)
assert "UpscaleModelLoader" not in cts
assert "ImageUpscaleWithModel" not in cts
# El bake toma las vistas directas del sample multi-vista (nodo 12).
assert node_by_ct(wf, "Hy3DBakeFromMultiview")["inputs"]["images"] == ["12", 0]
def test_views_invalido_lanza_valueerror():
with pytest.raises(ValueError):
comfyui_build_textured_3d_multiview_workflow("ref.png", views=3)
@@ -0,0 +1,91 @@
"""Tests de estructura para comfyui_build_video_workflow (funcion pura)."""
import os
import sys
import pytest
sys.path.insert(0, os.path.dirname(__file__))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))
from ml.comfyui_build_video_workflow import comfyui_build_video_workflow
from _comfyui_wf_assert import assert_api_format, class_types, node_by_ct
def test_ltx_estructura_y_nodos():
wf = comfyui_build_video_workflow("a fox running", model="ltx")
assert_api_format(wf)
cts = class_types(wf)
# Nodos clave del camino LTX presentes.
for ct in (
"CLIPLoader",
"CheckpointLoaderSimple",
"EmptyLTXVLatentVideo",
"LTXVScheduler",
"KSamplerSelect",
"LTXVConditioning",
"SamplerCustom",
"CreateVideo",
"SaveVideo",
):
assert ct in cts, f"falta {ct} en LTX"
# El CLIPLoader de LTX usa el text encoder t5xxl fp8 con type=ltxv.
clip = node_by_ct(wf, "CLIPLoader")["inputs"]
assert clip["type"] == "ltxv"
assert clip["clip_name"] == "t5xxl_fp8_e4m3fn_scaled.safetensors"
assert node_by_ct(wf, "CheckpointLoaderSimple")["inputs"]["ckpt_name"] == (
"ltx-video-2b-v0.9.5.safetensors"
)
def test_wan_estructura_y_nodos():
wf = comfyui_build_video_workflow("a fox running", model="wan")
assert_api_format(wf)
cts = class_types(wf)
# Wan usa UNETLoader + VAELoader aparte + ModelSamplingSD3 + KSampler nativo.
for ct in (
"UNETLoader",
"CLIPLoader",
"VAELoader",
"ModelSamplingSD3",
"EmptyHunyuanLatentVideo",
"KSampler",
"CreateVideo",
"SaveVideo",
):
assert ct in cts, f"falta {ct} en Wan"
assert node_by_ct(wf, "UNETLoader")["inputs"]["unet_name"] == (
"wan2.1_t2v_1.3B_fp16.safetensors"
)
assert node_by_ct(wf, "CLIPLoader")["inputs"]["type"] == "wan"
assert node_by_ct(wf, "VAELoader")["inputs"]["vae_name"] == "wan_2.1_vae.safetensors"
def test_params_se_reflejan_ltx():
wf = comfyui_build_video_workflow(
"POS", model="ltx", negative="NEG", width=640, height=384,
num_frames=49, steps=18, seed=7, fps=30,
)
lat = node_by_ct(wf, "EmptyLTXVLatentVideo")["inputs"]
assert lat["width"] == 640 and lat["height"] == 384 and lat["length"] == 49
assert node_by_ct(wf, "LTXVScheduler")["inputs"]["steps"] == 18
assert node_by_ct(wf, "SamplerCustom")["inputs"]["noise_seed"] == 7
assert node_by_ct(wf, "CreateVideo")["inputs"]["fps"] == 30
textos = sorted(
n["inputs"]["text"] for n in wf.values() if n["class_type"] == "CLIPTextEncode"
)
assert textos == ["NEG", "POS"]
def test_params_se_reflejan_wan():
wf = comfyui_build_video_workflow(
"POS", model="wan", num_frames=33, steps=15, seed=99,
)
assert node_by_ct(wf, "EmptyHunyuanLatentVideo")["inputs"]["length"] == 33
ks = node_by_ct(wf, "KSampler")["inputs"]
assert ks["steps"] == 15 and ks["seed"] == 99
def test_model_invalido_lanza_valueerror():
with pytest.raises(ValueError):
comfyui_build_video_workflow("x", model="sora")