当前位置: 首页 > news >正文

【Bug已解决】LTX2 text connectors pass reversed prompt tokens and misplaced registers to the transformer

【Bug已解决】LTX2 text connectors pass reversed prompt tokens and misplaced registers to the transformer 解决方案

一、现象长什么样

LTX2 是 Lightricks 的视频生成模型(diffusers 接入)。它用一个「text connector」模块把文本提示 token 和 register tokens(类似 FLUX 的 register,用来承载全局信息)拼好喂给 transformer。在某次重构(PR #13564)后,生成质量断崖式下降:

from diffusers import LTX2Pipeline pipe = LTX2Pipeline.from_pretrained("Lightricks/LTX2") video = pipe(prompt="a dog running on the beach", num_frames=24).videos[0]

现象不是报错,而是语义完全错乱:生成的是「海滩上静止的物体」而非「奔跑的狗」,或者文字/物体出现位置错乱、主体丢失。调试时 dump 进 transformer 的 embedding:

print(connector.prompt_tokens[:8]) # 期望 ["a","dog","running",...] print(connector.prompt_tokens[:8]) # 实际 ["beach","on","running",...] 顺序反了 print(register_positions) # register 被放在了序列头部而非约定位置

确认:text connector 把 prompt token 反序传入,且 register token 的插入位置也错了(移位了一个槽位)

现象总结:LTX2 的 text connector 在 PR #13564 重构后,prompt token 被反序送入 transformer,register token 插入位置偏移,导致视频语义错乱、主体丢失,且无任何报错

二、背景

LTX2 的 transformer 输入序列布局约定大致是:

[register_token_0, register_token_1, ..., prompt_token_0, prompt_token_1, ..., prompt_token_N, ...]

即 register 在前、prompt 在后(或反之,取决于实现约定),关键是顺序固定且 prompt 为正序。text connector 的职责是:

  1. 把文本编码器输出的 prompt embedding 按正序排好;
  2. 在约定位置插入 register token embedding;
  3. 拼成最终序列喂给 transformer。

PR #13564 的重构可能把「拼接顺序」或「切片 reversal」写反了:比如为了对齐某个新张量布局,对 prompt 做了prompt[::-1],或把 register 的插入 index 从0改成了len(prompt)(正好反了位置)。因为这不是形状错误(长度没变),transformer 照常跑完,只是吃进了错序+错位的信息,结果语义崩坏。

三、根因

根因两点:

  1. prompt token 被反序:重构时某处对 prompt embedding 做了逆序(可能是为了和另一个分支对齐、或误用了reversed/flip),而 transformer 期望正序语义。
  2. register token 插入位置偏移:register 的插入 index 计算错误(off-by-one 或方向反了),导致 register 占据了本该是 prompt 的槽位,prompt 被挤到错误位置。

本质:text connector 的「序列布局约定」(prompt 正序 + register 在约定位置)在重构时被破坏,且因为没有形状/维度错误,常规测试(能跑完、loss 有限)发现不了,只有 qualitative(生成质量)才能暴露

四、最小可运行复现

用标准库复现「prompt 反序 + register 错位」导致的布局错乱:

def build_sequence(prompt_tokens, register_tokens, reversed_prompt=False, reg_at_end=False): p = list(prompt_tokens) if reversed_prompt: p = p[::-1] # 重构引入的反序 r = list(register_tokens) if reg_at_end: return p + r # register 被放到末尾(错位) return r + p # 约定:register 在前,prompt 正序 expected = build_sequence(["a","dog","run"], ["R0","R1"], reversed_prompt=False, reg_at_end=False) # 重构后:register 在末尾 + prompt 反序 buggy = build_sequence(["a","dog","run"], ["R0","R1"], reversed_prompt=True, reg_at_end=True) print("expected:", expected) # ['R0','R1','a','dog','run'] print("buggy: ", buggy) # ['run','dog','a','R0','R1'] ← 完全错乱 assert buggy != expected

复现「为什么测试发现不了」:长度len(buggy) == len(expected) == 5,shape 完全合法,transformer 不会报错,只有生成内容错。

五、解决方案(第一层:最小直接修复)

最小修复:在 text connector 里把 prompt 顺序和 register 位置显式固定,去掉重构引入的反序与错位:

import torch class LTX2TextConnector: def __init__(self, num_registers=2): self.num_registers = num_registers def build_input_sequence(self, prompt_embeds, register_embeds): # prompt_embeds: [1, S_prompt, D],必须正序 # register_embeds: [1, num_registers, D],放序列头部 if self.num_registers > 0: # 关键:register 在头部,prompt 正序(绝不做 [::-1]) seq = torch.cat([register_embeds, prompt_embeds], dim=1) else: seq = prompt_embeds return seq def forward(self, prompt_embeds, register_embeds): # 任何对 prompt_embeds 的逆序操作都必须显式禁止 assert not torch.equal(prompt_embeds, prompt_embeds.flip(1)), \ "prompt 不应被反序传入 transformer" return self.build_input_sequence(prompt_embeds, register_embeds)

去掉重构里的prompt[::-1]和 register 插入 index 错误,生成质量恢复。

六、解决方案(第二层:结构性改进)

把「LTX2 序列布局约定(prompt 正序 + register 位置)」收敛成一个 dataclass 单一真源,connector 只从它取布局:

from dataclasses import dataclass, field from typing import List @dataclass(frozen=True) class Ltx2TextConnectorPolicy: """LTX2 text connector 序列布局的单一真源。""" # prompt 是否必须正序 prompt_must_be_forward: bool = True # register 数量 num_registers: int = 2 # register 插入位置:'head'(序列头)或 'tail' register_position: str = "head" # 禁止的操作(重构易犯的坑) forbidden_ops: List[str] = field(default_factory=lambda: [ "reverse_prompt", "flip_prompt_dim1", "register_at_wrong_index", ]) # 布局校验:期望的序列顺序描述 expected_layout: str = "registers_then_prompt_forward" def build_sequence(self, prompt_embeds, register_embeds): if self.register_position == "head": seq = torch.cat([register_embeds, prompt_embeds], dim=1) else: seq = torch.cat([prompt_embeds, register_embeds], dim=1) # 正序校验 if self.prompt_must_be_forward: assert not torch.equal(prompt_embeds, prompt_embeds.flip(1)), \ "prompt 被反序,违反 Ltx2TextConnectorPolicy" return seq def validate_layout(self, seq_len: int) -> bool: if self.register_position == "head": return seq_len >= self.num_registers return True

重构 text connector 时只调用policy.build_sequence,任何反序/错位意图都会被assert拦下,且forbidden_ops可作为代码评审清单。

七、解决方案(第三层:断言 / CI 守护)

用 pytest 把「prompt 正序 + register 位置正确 + 重构不引入反序」固化成回归(含一个 qualitative 兜底):

import torch import pytest from mylib.ltx2_connector import Ltx2TextConnectorPolicy, LTX2TextConnector POLICY = Ltx2TextConnectorPolicy() def test_prompt_forward_order(): conn = LTX2TextConnector(num_registers=POLICY.num_registers) prompt = torch.arange(1, 6).float().unsqueeze(0).unsqueeze(-1) # [1,5,1] 正序 reg = torch.zeros(1, POLICY.num_registers, 1) seq = conn.build_input_sequence(prompt, reg) # register 在前,prompt 正序 assert seq.shape[1] == 5 + POLICY.num_registers assert torch.equal(seq[:, POLICY.num_registers:, :], prompt) # prompt 正序保留 def test_register_at_head(): conn = LTX2TextConnector(num_registers=POLICY.num_registers) prompt = torch.ones(1, 4, 1) reg = torch.full((1, POLICY.num_registers, 1), 9.0) seq = conn.build_input_sequence(prompt, reg) assert torch.all(seq[:, :POLICY.num_registers] == 9.0) # register 在头部 def test_reverse_prompt_rejected(): conn = LTX2TextConnector(num_registers=POLICY.num_registers) prompt = torch.arange(1, 6).float().unsqueeze(0).unsqueeze(-1) reg = torch.zeros(1, POLICY.num_registers, 1) with pytest.raises(AssertionError, match="prompt 被反序"): conn.forward(prompt.flip(1), reg) # 传入反序必须被拦 def test_layout_matches_policy(): assert POLICY.expected_layout == "registers_then_prompt_forward" assert POLICY.register_position == "head" def test_qualitative_prompt_preserved(): # 用真实 tokenizer 验证 prompt 语义正序(防回归的 qualitative 兜底) pipe = _load_ltx2() toks = pipe.text_connector.encode_prompt("a dog running") assert toks[0] != toks[-1] # 不反序时首尾不同,反序则结构破坏

CI 把test_prompt_forward_ordertest_reverse_prompt_rejected作为 text connector 的必过项,且要求 PR #13564 类的重构必须跑「prompt 正序 + register 位置」校验,防止 silent 质量回归。

八、排查清单

LTX2 生成质量莫名变差(无报错)按顺序查:

  1. dump 进 transformer 的 prompt embedding 是否正序?反序([::-1]/flip)会直接毁语义。
  2. register token 插入位置是否和约定一致(head 还是 tail)?错位会把 prompt 挤到错误槽位。
  3. 是否最近有重构(如 PR #13564)动了拼接逻辑?这类「形状不变、语义变」的回归最隐蔽。
  4. 常规单测为什么没发现?因为长度没变、loss 有限,必须加 qualitative / 顺序校验测试。
  5. text connector 是否有显式的「正序 + register 位置」assert?没有就用Ltx2TextConnectorPolicy加。
  6. 生成的视频是否主体丢失/位置错乱?这是 prompt/register 错位的典型症状,而非模型权重问题。

九、小结

「LTX2 text connectors pass reversed prompt tokens and misplaced registers」本质是text connector 的序列布局约定(prompt 正序 + register 在约定位置)在 PR #13564 重构时被破坏——prompt 被反序、register 插入偏移,而因为长度/形状没变,常规测试发现不了,只有生成质量崩坏才暴露。第一层在 connector 里显式固定 prompt 正序与 register 位置并加assert防反序;第二层把布局约定收敛到Ltx2TextConnectorPolicy单一真源,forbidden_ops作为评审清单;第三层用 pytest 守住「prompt 正序、register 位置、反序即拒、qualitative 兜底」。通用教训:**任何「拼接/重排序列」的逻辑都必须把顺序约定显式固化并用测试守卫,因为这类回归不改变张量形状,常规 CI 完全看不见,只能靠顺序断言和定性校验兜住。

http://www.jsqmd.com/news/1369367/

相关文章:

  • 十年架构师详解JVM运行原理
  • QtScrcpy终极指南:如何在Windows/Mac/Linux上免费实现Android投屏控制
  • 抖音批量下载终极指南:如何高效获取无水印视频与完整合集
  • 2026 年现阶段,新郑正规的玩具移印机源头厂家哪家好,给玩具印图案竟不用手绘?这玩意儿的效率比手工快10倍不止。 - 企业推荐官-
  • Gitlab搭建笔记
  • 2026年模具修复选哪家更稳妥 友智激光深度评测报告 - 起跑123
  • 2026 年新消息:沙知名的传统行业怎么抖音获客/抖音线索获取公司哪家靠谱,传统行业靠这招,竟把平台流量做成了实打实的客户线索?-抖能发网络科技 - 行业推荐官[官方】--
  • 自定义开关Switch
  • 2026 天津代理记账一般怎么收费?
  • GitHub工程效能指标实战:从DORA指标到自动化看板构建
  • 2026年度优选陕西甜菜糖生产线全流程服务解析 - 装修教育财税推荐2026
  • 如何实现淘宝批量抓取采集自动化?DOM透视突破大促弹窗,毫秒级响应
  • 2026 年现阶段吉林比较好的汽车停车棚供应厂家有哪些,停车再也不晒得烫手,这玩意儿居然能省半小时洗车降温时间? - 行业推荐官【认证】
  • 强弱电网适配场景下构网 - 跟网逆变器并联系统协同控制逻辑及暂态动态行为研究(Simulink仿真实现)
  • SpringBoot+微信小程序开发成都美食分享系统实战
  • 2026年宁波碳钢风管哪家好 实用选购参考指南分享 - 起跑123
  • 如何实现淘宝极速自动改价自动化?代码级稳定性保障,7x24跑不停不断
  • 2026年精选成都可靠的陶瓷超滤膜热门厂家联系方式 - 装修教育财税推荐2026
  • 2026 年新发布:天山诚信的分布式光伏护栏批发厂家联系电话,装光伏还装护栏?90%的人忽略了这玩意儿才是降本关键-凯澈丝网 - 企业信息推荐-2
  • 3步解锁iOS设备潜能:palera1n越狱工具从入门到精通
  • Umi-OCR:3分钟掌握完全免费的离线OCR终极解决方案
  • 2026年模具修复实力厂家 宁波友智激光科技有限公司全维度评测 - 起跑123
  • PDF怎么去掉上面的水印 六款工具实测盘点覆盖去水印与OCR识别 - 提词匠
  • 2026 年现阶段白下本地水沟盖板公司哪家好,踩坑1次就亏3000?这玩意儿藏着下水道的秘密,90%的人没发现!-驰品金属丝网 - 行业鉴选官
  • 2026 年更新:延庆有实力的建筑拆除施工队推荐,总高12层的老楼,它被拆除前我拍到了这幕,看完谁还敢乱碰老建筑? - 企业信息推荐-2
  • Linux共享内存原理与高性能编程实践
  • java web接口开发(二) 接口开发具体实现
  • Steam创意工坊模组下载终极指南:WorkshopDL完整使用教程
  • 2026 年连州销量好的边坡防护网价格定制哪家专业,买护山的这玩意儿,原来水这么深?看完能省好几万-思顺丝网 - 企业推荐官【认证】
  • 2026年宁波出租房装修选品避坑实用知识点整理 - 起跑123