Rebase the DSL text encoder on comfy.sd1_clip.SDClipModel and comfy.clip_model.CLIPTextModel_, replacing the old HuggingFace transformers CLIPTextModel/CLIPTextTransformer/CLIPTextEmbeddings subclasses (which are no longer how ComfyUI implements CLIP). Structure: - Merge lib/action/ into lib/actions/; drop lib/fun_clip_stuff.py and the bundled clip_config*.json (comfy ships its own) - Convert all custom_nodes.KepPromptLang.* absolute imports to relative imports so installs via Manager work regardless of install directory name Encoder: - PromptLangSDClipModel overrides encode_token_weights to walk the segment/action tree, assemble [B, seq, hidden] embeds, and call self.transformer(None, mask, embeds=..., num_tokens=...) - posScale / postPos are supported without patching the transformer by pre-baking the delta (modified - default) into embeds, so the transformer's inline add yields the modified position embedding - Drop the unused empty-baseline batch that was prepended and then sliced off; halves the per-encode forward pass for single prompts Actions: - Fix copy-pasted broken __repr__ / depth_repr across sum/diff/avg/ slerp that referenced fields that didn't exist - Fix NameError in AverageAction._validate_args (start_arg_token_length) - Fix class-level mutable state in RandAction - Unify _parse_scalar / _parse_scalar_weight / _parse_int into a single parse_numeric_arg helper in action_utils.py - Share add_with_broadcast between SumAction and DiffAction - Convert PostModifiers from TypedDict to dataclass (attribute access catches typos that .get() on string keys hides) Drop the two _exp-pooler / _exp-pooledAvg actions: they recursively invoked the HF CLIPTextTransformer and would need a rework to fit the current CLIPTextModel_ interface. They were experimental and not documented as stable. BuildGif node: - Collapse the 10-positional-arg _save_* helpers onto a small _SaveContext dataclass - Stop mutating the input arg semantics (split_every_val was reassigned to len(images) when -1) Tests: - Add pytest suite covering the parser (grammar, nesting, errors) and every action (embedding math, shape, modifier payloads) - conftest stubs ComfyUI at collection time so tests don't need a real ComfyUI install Drop the broken test_files/ scripts (CI helpers, not a test suite) and regenerate the README from tools/build_docs.py.
24 lines
946 B
Python
24 lines
946 B
Python
import torch
|
|
|
|
|
|
def slerp(val: float, low: torch.Tensor, high: torch.Tensor, epsilon: float = 1e-5) -> torch.Tensor:
|
|
"""Spherical linear interpolation between two tensors along the last dim."""
|
|
val_t = torch.tensor(val, dtype=torch.float32, device=low.device).clamp(0, 1)
|
|
|
|
low_norm = low / torch.norm(low, dim=-1, keepdim=True)
|
|
high_norm = high / torch.norm(high, dim=-1, keepdim=True)
|
|
|
|
dot = (low_norm * high_norm).sum(-1, keepdim=True).clamp(-1, 1)
|
|
omega = torch.acos(dot)
|
|
sin_omega = torch.sin(omega)
|
|
|
|
scale_low = torch.sin((1.0 - val_t) * omega) / (sin_omega + epsilon)
|
|
scale_high = torch.sin(val_t * omega) / (sin_omega + epsilon)
|
|
|
|
# Fall back to linear interp where the angle is too small for stable slerp.
|
|
close = sin_omega < epsilon
|
|
scale_low = torch.where(close, 1.0 - val_t, scale_low)
|
|
scale_high = torch.where(close, val_t, scale_high)
|
|
|
|
return scale_low * low + scale_high * high
|