Add ApplyCosmosReferenceLatent node
simplifying the use of reference images
This commit is contained in:
+62
-15
@@ -18,6 +18,7 @@ class ApplyCosmosReferenceModelPatch:
|
||||
def patch(self, model):
|
||||
m = model.clone()
|
||||
|
||||
# 1. 拦截 extra_conds 以便从 Conditioning 中提取参考图
|
||||
original_extra_conds = m.model.extra_conds
|
||||
|
||||
def custom_extra_conds(self, **kwargs):
|
||||
@@ -25,7 +26,7 @@ class ApplyCosmosReferenceModelPatch:
|
||||
|
||||
ref_latents = kwargs.get("reference_latents", None)
|
||||
if ref_latents is not None:
|
||||
latents =[]
|
||||
latents = []
|
||||
# 遍历传入的参考图,并调用模型内置方法应用 VAE Scale
|
||||
for lat in ref_latents:
|
||||
latents.append(self.process_latent_in(lat))
|
||||
@@ -37,24 +38,32 @@ class ApplyCosmosReferenceModelPatch:
|
||||
bound_extra_conds = types.MethodType(custom_extra_conds, m.model)
|
||||
m.add_object_patch("extra_conds", bound_extra_conds)
|
||||
|
||||
# 2. 应用 UNet 包装器
|
||||
prev_wrapper = m.model_options.get("model_function_wrapper", None)
|
||||
|
||||
def ref_latent_unet_wrapper(model_apply, model_kwargs):
|
||||
c_dict = model_kwargs.get("c", {})
|
||||
|
||||
# 从 extra_conds 传递过来的缩放后的 latent
|
||||
ref_latents = c_dict.get("ref_latents", None)
|
||||
# --- 收集参考图 ---
|
||||
# 来源 A: 来自 extra_conds (Conditioning 注入)
|
||||
ref_from_cond = c_dict.get("ref_latents", [])
|
||||
if not isinstance(ref_from_cond, (list, comfy.conds.CONDList)):
|
||||
ref_from_cond = [ref_from_cond]
|
||||
|
||||
if ref_latents is not None:
|
||||
# 来源 B: 直接从模型对象中获取 (通过 Object Patch 注入)
|
||||
model_obj = getattr(model_apply, "__self__", None)
|
||||
ref_from_options = getattr(model_obj, "cosmos_ref_latents", [])
|
||||
|
||||
all_refs = list(ref_from_cond) + list(ref_from_options)
|
||||
|
||||
if len(all_refs) > 0:
|
||||
orig_x = model_kwargs.get("input")
|
||||
new_x = orig_x
|
||||
|
||||
# 记录原始的时间维度 T,非常重要!
|
||||
# 记录原始的时间维度 T
|
||||
orig_T = orig_x.shape[2]
|
||||
|
||||
refs = ref_latents if isinstance(ref_latents, list) else [ref_latents]
|
||||
|
||||
for ref in refs:
|
||||
for ref in all_refs:
|
||||
if isinstance(ref, torch.Tensor):
|
||||
# Cosmos / Flux2 风格升维
|
||||
if ref.ndim == 4:
|
||||
@@ -62,7 +71,7 @@ class ApplyCosmosReferenceModelPatch:
|
||||
|
||||
ref = ref.to(dtype=new_x.dtype, device=new_x.device)
|
||||
|
||||
# 匹配 CFG 批处理维度,防止 batch size 不匹配崩溃
|
||||
# 匹配 CFG 批处理维度
|
||||
bs_x = new_x.shape[0]
|
||||
bs_ref = ref.shape[0]
|
||||
if bs_ref != bs_x:
|
||||
@@ -76,9 +85,7 @@ class ApplyCosmosReferenceModelPatch:
|
||||
|
||||
model_kwargs['input'] = new_x
|
||||
|
||||
# -------------------------
|
||||
# 执行原模型链条
|
||||
# -------------------------
|
||||
if prev_wrapper is not None:
|
||||
out = prev_wrapper(model_apply, model_kwargs)
|
||||
else:
|
||||
@@ -88,9 +95,9 @@ class ApplyCosmosReferenceModelPatch:
|
||||
cond_dict = mk.pop("c", {})
|
||||
out = model_apply(x_val, t_val, **cond_dict, **mk)
|
||||
|
||||
# 裁剪回原始长度
|
||||
out = out[:, :, :orig_T, :, :]
|
||||
return out
|
||||
|
||||
else:
|
||||
# 如果没有接参考图,走正常流程
|
||||
if prev_wrapper is not None:
|
||||
@@ -106,12 +113,52 @@ class ApplyCosmosReferenceModelPatch:
|
||||
|
||||
return (m,)
|
||||
|
||||
class ApplyCosmosReferenceLatent:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"latent": ("LATENT",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MODEL",)
|
||||
FUNCTION = "apply"
|
||||
CATEGORY = "Cosmos/Reference"
|
||||
|
||||
def apply(self, model, latent):
|
||||
# 1. 确保基础补丁已应用
|
||||
patcher = ApplyCosmosReferenceModelPatch()
|
||||
(m,) = patcher.patch(model)
|
||||
|
||||
# 2. 注入当前 Latent
|
||||
samples = latent["samples"]
|
||||
|
||||
# 处理 Latent 缩放
|
||||
if hasattr(m.model, "process_latent_in"):
|
||||
samples = m.model.process_latent_in(samples)
|
||||
|
||||
# 3. 维护参考图列表
|
||||
# 使用 model_options 存储列表以确保节点链条间的隔离,避免读取到模型对象的全局缓存
|
||||
ref_list = list(m.model_options.get("cosmos_ref_latents_list", []))
|
||||
ref_list.append(samples)
|
||||
|
||||
# 更新 model_options 以便链式调用
|
||||
m.model_options["cosmos_ref_latents_list"] = ref_list
|
||||
|
||||
# 将最终列表通过 Object Patch 同步给模型对象,供采样时的 Wrapper 读取
|
||||
# 注意:这里的 key 必须与 Wrapper 中 getattr 的 key (cosmos_ref_latents) 一致
|
||||
m.add_object_patch("cosmos_ref_latents", ref_list)
|
||||
|
||||
return (m,)
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"ApplyCosmosReferenceModelPatch": ApplyCosmosReferenceModelPatch
|
||||
"ApplyCosmosReferenceModelPatch": ApplyCosmosReferenceModelPatch,
|
||||
"ApplyCosmosReferenceLatent": ApplyCosmosReferenceLatent
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"ApplyCosmosReferenceModelPatch": "Apply Cosmos Reference Model Patch"
|
||||
}
|
||||
"ApplyCosmosReferenceModelPatch": "Apply Cosmos Reference Model Patch",
|
||||
"ApplyCosmosReferenceLatent": "Apply Cosmos Reference Latent"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user