Complete node pack with ZeroCLIP-A through ZeroCLIP-D conditioning nodes, shared utilities, core modules, vocab files, and example workflows. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
88 lines
2.7 KiB
Python
88 lines
2.7 KiB
Python
"""Shared utilities for ZeroClip-nodes."""
|
|
|
|
import torch
|
|
import numpy as np
|
|
|
|
# Custom type aliases for ComfyUI graph edges
|
|
ZEROCLIP_SEED_TYPE = "ZEROCLIP_SEED"
|
|
ZEROCLIP_A_ANCHORS_TYPE = "ZEROCLIP_A_ANCHORS"
|
|
ZEROCLIP_B_MODEL_TYPE = "ZEROCLIP_B_MODEL"
|
|
ZEROCLIP_C_PROJECTION_TYPE = "ZEROCLIP_C_PROJECTION"
|
|
ZEROCLIP_D_ANCHORS_TYPE = "ZEROCLIP_D_ANCHORS"
|
|
|
|
SEQ_LEN = 77 # CLIP sequence length
|
|
|
|
|
|
def numpy_vec_to_conditioning(vec: np.ndarray) -> list:
|
|
"""Convert a [D] numpy conditioning vector to ComfyUI CONDITIONING format.
|
|
|
|
Args:
|
|
vec: L2-normalized float32 array of shape [D].
|
|
|
|
Returns:
|
|
ComfyUI CONDITIONING: [(tensor_of_shape(1, 77, D), {})]
|
|
"""
|
|
t = torch.from_numpy(vec).float() # [D]
|
|
t = t.unsqueeze(0).unsqueeze(0).expand(1, SEQ_LEN, -1) # [1, 77, D]
|
|
t = t.clone() # materialize the expand (ComfyUI needs contiguous)
|
|
return [(t, {})]
|
|
|
|
|
|
def numpy_vec_to_sdxl_conditioning(
|
|
seq_vec: np.ndarray,
|
|
pooled_vec: np.ndarray,
|
|
) -> list:
|
|
"""Convert sequence + pooled vectors to SDXL CONDITIONING format.
|
|
|
|
Args:
|
|
seq_vec: L2-normalized float32 array of shape [D_seq] (typically 2048).
|
|
pooled_vec: L2-normalized float32 array of shape [D_pooled] (typically 1280).
|
|
|
|
Returns:
|
|
ComfyUI CONDITIONING: [(tensor[1,77,D_seq], {"pooled_output": tensor[1,D_pooled]})]
|
|
"""
|
|
t_seq = torch.from_numpy(seq_vec).float()
|
|
t_seq = t_seq.unsqueeze(0).unsqueeze(0).expand(1, SEQ_LEN, -1).clone()
|
|
|
|
t_pooled = torch.from_numpy(pooled_vec).float().unsqueeze(0) # [1, D_pooled]
|
|
|
|
return [(t_seq, {"pooled_output": t_pooled})]
|
|
|
|
|
|
def numpy_batch_to_conditioning(vecs: np.ndarray) -> list:
|
|
"""Convert a batch of [B, D] numpy vectors to ComfyUI CONDITIONING format.
|
|
|
|
Args:
|
|
vecs: float32 array of shape [B, D].
|
|
|
|
Returns:
|
|
ComfyUI CONDITIONING: [(tensor[B, 77, D], {})]
|
|
"""
|
|
t = torch.from_numpy(vecs).float() # [B, D]
|
|
t = t.unsqueeze(1).expand(-1, SEQ_LEN, -1).clone() # [B, 77, D]
|
|
return [(t, {})]
|
|
|
|
|
|
def zero_conditioning(D: int) -> list:
|
|
"""Produce zero-vector conditioning (for negative/uncond input).
|
|
|
|
Args:
|
|
D: Embedding dimension (768 for SD1.x, 1024 for SD2.x).
|
|
|
|
Returns:
|
|
ComfyUI CONDITIONING: [(zeros_tensor(1, 77, D), {})]
|
|
"""
|
|
t = torch.zeros(1, SEQ_LEN, D, dtype=torch.float32)
|
|
return [(t, {})]
|
|
|
|
|
|
def zero_sdxl_conditioning(D_seq: int = 2048, D_pooled: int = 1280) -> list:
|
|
"""Produce zero-vector SDXL conditioning.
|
|
|
|
Returns:
|
|
ComfyUI CONDITIONING: [(zeros[1,77,D_seq], {"pooled_output": zeros[1,D_pooled]})]
|
|
"""
|
|
t_seq = torch.zeros(1, SEQ_LEN, D_seq, dtype=torch.float32)
|
|
t_pooled = torch.zeros(1, D_pooled, dtype=torch.float32)
|
|
return [(t_seq, {"pooled_output": t_pooled})]
|