H3-World 的动作控制,为什么不能只靠一句提示词?

H3-World 的动作控制,为什么不能只靠一句提示词?

作者静态机制/未执行记录;不代表模型生成成功或实时测量。

给视频模型写"镜头先向左转,再向右转",听起来已经把动作和顺序交代清楚了。但模型读懂左右,不等于这两个方向分别进入了指定的视频时间段。H3-World 要解决的就是这个差别:动作仍用语言表达,时间归属却不能只留在一句全局描述里。

本文以 2026 年 10 月 12 日核对的论文 v1 与官方固定代码为准。讨论对象是按动作生成固定长度视频片段的接口,不是实时游戏控制器。没有运行模型、下载权重或测量设备延迟。逐帧动作如何压入时间槽,是进入模型前需要核对的另一处边界。这里假定槽级动作已正确准备,继续追问它们如何进入主干,以及读代码时怎样证明"左句属于左段、右句属于右段"。

1. 模型会向左转,为什么还不能先左后右?

官方原页面原像素聚焦与中文作者解释;论文v1/固定commit,2026-10-12核对,非我们复测。

最直接的证据不是架构名词,而是论文第 4.2 节的一组对照:前 15 个视频 latent 要求镜头向左转,后 22 个要求向右转,切换点放在 latent 边界。作者比较了全局运动提示、逐 latent 接口但 LoRA 更新置零,以及训练后的 H3-World。同一"懂得镜头方向"的基础能力,在三种接入方式下并没有产生相同的时序响应。

论文展示条件 切换前累计水平光流 切换后累计水平光流
冻结 H3,全局运动提示 0.0 -17.3
逐 latent 接口,LoRA 置零 -0.1 0.0
训练后的 H3-World +52.7 -106.0

这组值来自厂商论文的公开样例;论文在此约定正值对应镜头左向运动、负值对应右向运动。它们不是我们复测的轨迹,也不是所有场景、所有随机种子的成功率。对当前问题,它们提供的反常点已经足够明确:把一条句子拆成多条,并不能自动得到动作时序;但只把失败归因于模型"不会转镜头",同样过早。论文 §4.2

全局提示在整个生成范围内作为共享条件。"先左后右"含有顺序语义,却没有在计算图中单独标出哪些视频 token 直接读取"左"、哪些直接读取"右"。模型可以根据语言与训练先验自行组织一段运动,但接口没有给应用一个逐时间段的读取约束。需求若只是整段保持一个方向,这种简单接入可能已够用;若要检查某个切换点前后的方向,就需要把时间归属变成可核对的输入与可见关系。

H3-World 因而为每个视频 latent 区间准备独立动作句。这里的 latent 是视频在模型内部的时间表示,一个区间可能解码为多帧,不等于一条按键对应一张输出画面。角色动作与镜头动作拼成该区间的短句,经共享的 H3 编码器进入同一个表示空间。本文的"左句""右句"指镜头动作;不能把镜头左转、人物向左移动和画面光流方向当成同一个控制变量。

把左段和右段分开,首先解决的是身份问题:这条文本是谁的动作条件。随后还要避免在进入主干之前把身份混掉。官方补丁中,Token Refiner(文本 token 细化层)把静态头部与每条动作句划成独立序列。句内 token 可以互相读取,不同动作句在这一层不互相混合。这一步很容易在只看主干路由图时被漏掉。

例如,假设 A左 在细化层已经读入 A右 的内容,后面即使只让左段视频读取 A左,它读到的也不再是单独的左动作表征。后端掩码能够禁止一条读取边,却不能把已经混入向量的右动作内容剥离出来。源码对 Refiner 分段的说明正是在处理这个上游问题。因此核对"动作直达匹配视频"之前,要先核对动作表征有没有通过其他动作句获得旁路信息。

这不意味着动作句从此没有场景信息。Refiner 的句间分隔,与主干中动作读取静态场景、首帧条件,是两处不同的关系。把它们都画成"动作完全孤立",会误读模型;反过来,因为动作需要场景信息就允许所有动作句先混合,也会丢掉逐段绑定的意义。

2. 位置告诉模型去哪里找,路由规定谁能读

官方原页面原像素聚焦与中文作者解释;论文v1/固定commit,2026-10-12核对,非我们复测。

H3-World 没有另设一层专用的文本到视频交叉注意力。动作文本、静态语义、初始画面条件和视频表示进入同一条打包序列,由单流自注意力处理。论文为了突出视觉控制省略部分音频记号;当前代码的实际布局是 text、condition、audio、video、padding。静态语义与各动作句都属于文本区域,首帧细节条件与生成目标也不能因同属视觉 token 就混为一段。

打包在一起,只说明它们共享计算路径,并没有替应用规定动作属于哪个视频区间。补丁为动作文本 span(连续 token 范围)记录起止位置,再给该 span 写入与匹配视频区间有固定偏移的时间坐标。镜像位置不是把动作 token 移到视频 token 的内存位置:文本仍处于文本侧,只是用于位置编码的时间坐标按匹配视频的顺序排列,并保持在视频之前。

这一做法让各匹配对有统一的相对位置线索,也保留预训练中的文本在视频之前的排列关系。但位置线索本身不会把非匹配读取权重强制归零。如果一条动作具有正确时间坐标,另一段视频仍然被允许直接读取它,那么"它应该属于哪里"与"谁实际上可以读到它"仍是两件事。前者由位置与 span 标识表达,后者由路由掩码决定。

固定补丁把位置与读取关系分成两处边界。 _build_packed_fl2va 要求动作 span 数量等于视频 latent 数量,范围合法且有序、互不重叠;它按视频时间网格设置动作坐标,并检查动作位置不会侵入前面的头部范围。_build_action_block_masks 则根据动作编号与视频编号决定查询和键是否可见。不能用"span 数量正确"替代"可见关系正确",也不能因为掩码存在就省略前面的对应关系检查。固定补丁

作者静态机制/未执行记录;不代表模型生成成功或实时测量。

读掩码时最容易看反的是方向。表中行是 query,即正在读取信息的位置;列是 key,即被读取的位置。若 V左 读取 A左,信息从 A左 进入 V左,而不是动作句从视频读到了什么。下面按固定补丁表达直接可见性,不表示生成结果已达到要求。

Query 读取者 / Key 被读取者 静态语义或首帧、音频 A左 A右 V左 V右
静态语义或首帧、音频 保留原关系 禁止 禁止 保留原关系 保留原关系
A左 允许 句内允许 禁止 允许 禁止
A右 允许 禁止 句内允许 禁止 允许
V左 保留原关系 允许 禁止 保留原关系 保留原关系
V右 保留原关系 禁止 允许 保留原关系 保留原关系

A左 与 A右 各自代表一个匹配区间的动作 span;如果一段方向连续占多个区间,应逐区间建立对应,不能把上表的一个符号当成随意跨越多个区间的实际 token 块。"保留原关系"指该动作路由没有新增阻断,不是取消基础模型原有的序列边界、padding 或其他规则。

Single-Egress(单出口)约束的是动作进入视频流的直接入口。A左 作为 key 时,只有本句内部及匹配 V左 可以读它;静态条件、音频和其他动作句不能先读走 A左,再把内容绕进不匹配的视频。A左 作为 query 时,仍能读取静态上下文及匹配 V左,但不能读取 A右 或 V右。两种方向都检查,才不会把"右视频不能读左动作"误写成"左动作可以从右动作得到内容也无妨"。

这也是为什么该机制不是把视频切成彼此隔绝的小模型。V左 与 V右 之间仍保留基础模型的双向关系。A左 的信息先通过 V左 进入视频流后,可以沿视频间通信影响 V右。上表把这条间接路径与动作句之间的上游混合、静态条件旁路分别列开,方便读者检查是哪一种边被阻断。这里没有承诺后半段绝不受到前半段影响,也没有把生成未来改成只能读取过去的因果模型。

FlexAttention 在实现中承担按这些规则计算注意力的工作。补丁通过 create_block_mask 构造分段掩码,再在存在掩码的分支传入 attn_mask 并启用 use_flex。分段索引是局部的,所以应核当前 packed segment 的映射,而不是把整个序列的绝对坐标未经换算塞进每个分段。当前实现还处理真实长度与 padding:真实 token 不应读到补齐行,补齐行保留自读。本文只从分支和索引规则核对接入条件,没有测量编译耗时、显存或速度提升。

因此,看到项目里用了 FlexAttention,并不足以断定当前输入已经启用了动作路由。还要沿实际传参确认 action_text_rows 到达主干、动作与视频起点匹配,以及对应分支确实获得 block mask。工具名称说明可以怎样计算,不替代这次输入实际上用了什么规则。

3. 一条先左后右记录,要分别核输入、路由与输出

位置与路由不包含可学习参数,LoRA(低秩适配)则更新注意力投影,学习如何沿允许路径把动作语义变成视觉变化。论文把基础主干与编码器等参数冻结,低秩更新作用于主干自注意力及两层 Refiner 的 QKV 与输出投影。由此不能把 LoRA 文件理解成已经包含路由实现的独立控制器:低秩权重负责学习,span 分段与掩码负责访问关系,两者需要在同一接入路径中配合。

论文的零 LoRA 对照说明,完整逐 latent 接口即使已经存在,仍不能直接继承为可用时序控制。这是该样例支持的判断。它没有给出一组训练后 LoRA 保留、仅移除 routing 的严格对照,所以不能据此把收益百分比分配给位置、Refiner 分段、路由或 LoRA,也不能说所有增益只由某一处产生。"理论上阻断了直接读取"与"训练后每次都能按时执行"应分开验收。

对接入者来说,可带走的产物不必是一套评测大全,而是一条可以留空、可以失败的方向切换记录。

作者静态机制/未执行记录;不代表模型生成成功或实时测量。

下面是作者设计的未执行记录,字段属于检查记录,不是 H3-World 的新 API 或可直接运行的配置。

记录项 本例预期 / 实际待填
固定版本 论文 v1;代码 f0c7be2acbbde8256b2473f6e7b088f58272acae;实际运行版本待填
动作对象 镜头先左转、后右转;角色动作保持一致;实际句子待填
槽级输入 切换点前后使用各自方向的动作句;区间对应与实际 span 待填
Refiner 静态头部与各动作句分段;实际分段边界待填
位置 各动作 span 与匹配视频有统一时间偏移;实际坐标与合法范围待填
主干可见性 匹配视频可读本动作,非匹配视频与其他动作不可直接读;实际 mask 与激活分支待填
保留关系 视频之间仍双向读取;不能将其写成未来不可见
适配权重 预期使用相应训练后 LoRA;实际加载与作用层待填
输出观察 切换前后镜头方向、切换附近偏差及连续性均待观察,不因前面检查通过自动填成功

填写时先保留槽级动作文本和对应区间,再记录 Refiner 与主干各自的分段。这样某段运动错误时,能够区分"动作内容或所属区间已经不对"和"输入正确但生成没有遵从"。原始帧聚合检查适用于前一种情况;表格继续检查正确的动作是否经过了正确的入口。两者不是相互替代的诊断。

如果实际记录里没有 action_text_rows,不要先修改动作句的形容词来试运气:应确认当前走的是逐 latent 文本路径还是普通全局提示路径。如果对应关系正确但 Refiner 仍把多句当成一个序列,也不能只在主干补一个"左右分开"的图就声称修好。反之,输入与可见性均核对无误、输出仍未按要求切换,记录应保留这一失败,而不是把结构检查升级成模型行为证明。

观察输出时应固定需要比较的初始条件与生成设置,并把实际使用的权重、动作顺序和切换区间记录下来。这是作者建议的核对方法,不是本次已经完成的实验。若另做反向顺序对照,也要保留两条各自的记录,不能把"左后右"和"右后左"的输出拼成一次成功过程。没有输出轨迹,就只填写输入与静态代码核对;没有实际延迟测量,就不填写实时可用。

不加载模型,先运行一个读取关系检查

读取矩阵不一定要等到 GPU 推理失败之后才核对。下面的最小示例将固定补丁中 mask_mod 的布尔关系转写成 Python 标量运算,并添加文本 span 的数量、范围与顺序检查。保存为 mask_check.py 后,用 Python 3 标准库即可执行;不安装 PyTorch,不构造 FlexAttention block mask,也不加载任何视频权重。

本例只取一个 packed segment,用六个位置代表静态条件 S、左右动作 Aleft/Aright、左右视频 Vleft/Vright 和一个 padding。每个动作 span 和视频区间各用一个 token,目的是让矩阵的每一格可以直接读懂;真实句子多 token、单个视频区间多空间 token 的情况,必须先由应用建立正确行编号,不能照搬这六个索引。real_len=5 表示前五个位置有效,第六个只是补齐。

annotations 给动作位置标出所属区间,frames 给视频位置标出所属区间,其余位置标 -1。判断动作作为 key 时,只有同一句动作内部与匹配的视频可以读取;动作作为 query 时,不能读取其他区间的视频。最后单独加上真实长度限制和自读例外,保留原补丁"padding 只读自己"的条件。这里的列方向依旧是被读取的 key,信息从列流向行。

代码中的五行预期值来自前文已经逐格解释的读取矩阵,不是运行后把程序结果再填回预期值。新增反例则故意把两个动作的区间编号交换:即使 span 数量与范围都合法,Vleft 也会读到被错误绑定的 Aright。这能说明数量检查为什么不能代替语义对应检查。

python 复制代码
"""Scalar transcription of pinned mask_mod, one segment; no torch/model run."""


def validate_spans(spans, text_len, latent_t):
    if len(spans) != latent_t:
        raise ValueError("count")
    previous = 0
    for lo, hi in spans:
        if not 0 <= lo < hi <= text_len:
            raise ValueError("range")
        if lo < previous:
            raise ValueError("overlap_or_order")
        previous = hi


def visible(q, key, annotations, frames, real_len):
    aq, ak = annotations[q], annotations[key]
    fq, fk = frames[q], frames[key]
    same_action = aq >= 0 and ak >= 0 and aq == ak
    own_video = fq >= 0 and ak >= 0 and fq == ak
    leak_out = ak >= 0 and not same_action and not own_video
    leak_in = aq >= 0 and fk >= 0 and aq != fk
    real = q < real_len and key < real_len
    return q == key or (real and not (leak_out or leak_in))


def run_examples():
    # S, Aleft, Aright, Vleft, Vright, padding; one token per role.
    annotations = [-1, 0, 1, -1, -1, -1]
    frames = [-1, -1, -1, 0, 1, -1]
    names = ["S", "Aleft", "Aright", "Vleft", "Vright"]
    expected = ["10011", "11010", "10101", "11011", "10111"]
    print("columns: " + " ".join(names))
    for q, name in enumerate(names):
        row = "".join(str(int(visible(q, k, annotations, frames, 5))) for k in range(5))
        if row != expected[q]:
            raise AssertionError((name, row, expected[q]))
        print(f"{name}: {row}")
    for i in range(5):
        if visible(i, 5, annotations, frames, 5) or visible(5, i, annotations, frames, 5):
            raise AssertionError("padding leaked")
    if not visible(5, 5, annotations, frames, 5):
        raise AssertionError("padding lost self-read")
    # Swapped role-to-latent mapping produces an observable wrong direct edge.
    swapped = [-1, 1, 0, -1, -1, -1]
    if visible(3, 1, swapped, frames, 5) or not visible(3, 2, swapped, frames, 5):
        raise AssertionError("wrong-map counterexample missing")
    print("matrix: 25/25; padding: 11/11; swapped_map: detected")
    cases = [
        ("valid", [(1, 2), (2, 3)], None),
        ("count", [(1, 2)], "count"),
        ("range", [(1, 2), (2, 4)], "range"),
        ("overlap", [(1, 3), (2, 3)], "overlap_or_order"),
        ("reversed", [(2, 3), (1, 2)], "overlap_or_order"),
    ]
    for name, spans, expected_error in cases:
        error = None
        try:
            validate_spans(spans, text_len=3, latent_t=2)
        except ValueError as exc:
            error = str(exc)
        if error != expected_error:
            raise AssertionError((name, error, expected_error))
        print(f"span_{name}: " + ("accepted" if error is None else "rejected:" + error))
    print("scope=one_segment_scalar_boolean_and_span_checks")


if __name__ == "__main__":
    run_examples()

在文件所在目录运行:

bash 复制代码
python3 mask_check.py

2026 年 10 月 13 日,本地 Python 3 实际运行该文件,退出码为 0,标准错误为空。当次标准输出如下:

text 复制代码
columns: S Aleft Aright Vleft Vright
S: 10011
Aleft: 11010
Aright: 10101
Vleft: 11011
Vright: 10111
matrix: 25/25; padding: 11/11; swapped_map: detected
span_valid: accepted
span_count: rejected:count
span_range: rejected:range
span_overlap: rejected:overlap_or_order
span_reversed: rejected:overlap_or_order
scope=one_segment_scalar_boolean_and_span_checks

五位字符串从左到右对应 S、Aleft、Aright、Vleft、Vright;1 表示允许直接读取,0 表示禁止。Vleft 的 11011 因而允许读取 S 与 Aleft,禁止读取 Aright,同时保留左右视频之间的关系。Aright 的 10101 则可以读取 S、本句及 Vright,不能读取另一句和 Vleft。这里报告的 25/25 是五乘五布尔单元与预先写定矩阵相等,不是 25 次视频生成通过。

padding 的 11 个条件分别是五个真实位置不能读 padding、padding 不能读五个真实位置,以及 padding 自读必须保留。即使它对应零向量,放进注意力归一化也可能改变结果;反过来,若 padding 行连自己都不能读,就可能出现没有可见 key 的情况。示例只验证可见关系,没有计算 softmax、数值稳定性或编译行为。

swapped_map: detected 不是程序替读者自动识别"左"的语义,而是已知左右预期下构造的反例。我们交换动作编号后,Vleft 不能再读位置 1,却能读位置 2;断言确认这种错误对应会改变直接入口。真实集成中,需要从输入动作计划取得预期绑定,再核实际行编号,不能只给动作随意编号后让代码自证正确。否则一个错误映射也可以拥有整齐、可运行的矩阵。

span 的五条记录检验另一类问题:两个合法连续区间被接受;数量不等于视频区间数、超过文本边界、重叠和倒序分别被拒绝。半开区间 [lo, hi) 中,起点包含、终点不包含,因此 [1,2) 与 [2,3) 相邻但不重叠。把终点误当包含会在接口转换时多算一行,这不是增加一个 mask 就能修好的问题。实际句子长度改变时,也应重新核对 span,而不是沿用上次的范围。

这段 validate_spans 只转写固定补丁的前三类入口条件,不包含镜像时间坐标不得侵入头部范围的检查,也不实现 Refiner 的完整分段与连续铺满约束。合法 span 只证明这三个条件成立,不能自动宣告位置编码和上游句段均正确。正文把这些职责分开,是为了在失败时知道接下来应该检查哪一处,而不是让一个短脚本冒充完整模型接入验收。

如果改动代码,可以先做三个破坏性对照:去掉非匹配动作限制,读取矩阵应报错;取消真实长度判断,padding 条件应报错;取消重叠判断,重叠 span 应被错误接受并触发断言。程序退出码与"某条非法输入被拒绝"也要分开理解:非法输入是预设案例,正确拒绝它才是本地检查成功。任何预期不符都会以异常退出,让后续命令能发现回归。

以上结果仍需要与真实接入的边界分开。该布尔转写没有覆盖多 segment 的绝对坐标换算、位置网格、权重加载、分支实际激活和 GPU 内核;它也没有测量光流、切换偏差或实时延迟。图中那些项目继续等待真实执行记录。读者现在可以带走的是一段能跑、能被错误输入推翻的静态检查,用来先排除左右读取方向、padding 和基本 span 约束上的误读。

论文自身也限定了范围:当前生成固定长度片段,尚不提供持久世界状态、实时交互、规划或策略学习。把论文中的 interactive 一词直接搬成"按键后实时更新世界"的产品能力,会跳过尚未提供的部分。视频能按一个预先给定的动作计划变化,与用户随时改变输入、系统维持长期状态,是不同的验证对象。

所以,这条记录最后回答的不是"H3-World 是否已经是完整游戏引擎",而是一个更具体的问题:这次先左后右的动作计划,是否以独立表征、匹配位置和实际启用的路由进入模型;进入之后,输出是否真的遵从。全局提示仍是简单需求的合理入口,但当应用需要核对动作何时生效时,语言语义之外的这些对应关系不能省略。

来源与范围

  • 作者论文 H3-World v1,2026-09-01:§3.3/§3.4 的时序绑定与路由,§4.2 的单组方向切换对照,§5 的局限;检查日 2026-10-12。
  • 官方固定代码补丁:packing、Refiner 分段、查询/键掩码及 FlexAttention 调用。原文全文、行号摘录与 SHA 随研究包保留。
  • 官方固定仓库说明:接入与研究范围交叉核对。原 ZIP 仅为选题种子,未把其中推论升级为新实测结果;视频素材仅 reference_only,本文没有据未审看媒体评价生成质量。
相关推荐
虾..1 小时前
计算机图形学:理解光照模型
人工智能
一木 之林1 小时前
LangChain 第3章 消息与提示词模板:四类消息、历史管理与 ChatPromptTemplate
人工智能·计算机视觉·langchain
熊出没1 小时前
AI Agent 生产级架构设计:工具调用与MCP、RAG、安全护栏与评估体系
人工智能·安全·架构设计·rag·ai agent
EEET智选1 小时前
科技晨间速报 | AI 安全警钟、开源新模型与苹果智能家居
人工智能·科技·算法·机器学习·ai
Georgewu1 小时前
Selected model is at capacity. Please try a different model. 绕过去不使用Codex, OpenCo
agent
CCblandy1 小时前
Airllm 大模型本地化部署与高效推理应用指南
大数据·网络·人工智能
workflower1 小时前
手术机器人市场发展阶段
大数据·人工智能·机器人·云计算·无人机
Markus实验室1 小时前
多Agent协作的“审查幻觉”:当两个AI互相点赞,谁来兜底?
agent
ai_xiaogui2 小时前
PanelAI 私有化 AI 助理实战:打通 API 聚合、Token 监控与多用户算力变现
人工智能·panelai 私有化部署·api 聚合网关·大模型 token 监控·企业级算力调度系统·go 语言后端架构·vue 3 管理后台