Skip to content

Commit e7fdfdb

Browse files
yiyixuxuclaude
andcommitted
Add ABot-World: real-time action-conditioned world model (Wan2.2-TI2V-5B)
Integrates https://github.com/amap-cvlab/ABot-World (acvlab/ABot-World-0-5B-LF, Apache-2.0) as a modular pipeline. - ABotWorldTransformer3DModel: block-causal rollout over a rolling K/V cache (window eviction, pinned reference-token prefix, relative RoPE with periodic rebase), per-frame timesteps, keyboard-action adapter added onto the patch tokens, per-stream cross-attention cache. Bit-exact vs the reference (CPU/fp32) incl. eviction, rebase, and the real 5B weights. - scripts/convert_abot_world_to_diffusers.py: pure key renames, no surgery. VAE and umt5 are byte-identical to Wan-AI/Wan2.2-TI2V-5B and are reused from Wan-AI/Wan2.2-TI2V-5B-Diffusers; FlowMatchEulerDiscreteScheduler(shift=5.0) covers the warped DMD grid (scale_noise == the reference re-noise). - modular_pipelines/abot_world: text/image/reference encoders -> core denoise (prepare + rollout IterativePipelineBlocks over blocks k, with a nested distilled denoise loop over (i, t) and a KV-cache context update) -> decode. Streams via pipe.stream() (events per denoise step and per ~1s block) and drives interactively via loop_step, writing new actions into the state between calls. - Converted checkpoint + runnable example: YiYiXu/ABot-World-0-5B-LF-Diffusers Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 3282034 commit e7fdfdb

16 files changed

Lines changed: 2007 additions & 0 deletions
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Convert the ABot-World checkpoint (https://huggingface.co/acvlab/ABot-World-0-5B-LF) to diffusers format.
2+
#
3+
# python scripts/convert_abot_world_to_diffusers.py \
4+
# --checkpoint_path <repo>/diffusion_pytorch_model.safetensors --output_path <out_dir> [--dtype bf16]
5+
import argparse
6+
7+
import torch
8+
from safetensors.torch import load_file
9+
10+
from diffusers import ABotWorldTransformer3DModel
11+
12+
13+
def convert_abot_world_transformer(state_dict):
14+
"""Map the reference CausalWanModel state dict to ABotWorldTransformer3DModel naming."""
15+
converted = {}
16+
for key, value in state_dict.items():
17+
new_key = key
18+
new_key = new_key.replace("text_embedding.0.", "condition_embedder.text_embedder.0.")
19+
new_key = new_key.replace("text_embedding.2.", "condition_embedder.text_embedder.2.")
20+
new_key = new_key.replace("time_embedding.0.", "condition_embedder.time_embedder.0.")
21+
new_key = new_key.replace("time_embedding.2.", "condition_embedder.time_embedder.2.")
22+
new_key = new_key.replace("time_projection.1.", "condition_embedder.time_proj.1.")
23+
if ".self_attn." in new_key or ".cross_attn." in new_key:
24+
new_key = new_key.replace(".self_attn.", ".attn1.").replace(".cross_attn.", ".attn2.")
25+
new_key = new_key.replace(".q.", ".to_q.").replace(".k.", ".to_k.").replace(".v.", ".to_v.")
26+
new_key = new_key.replace(".o.", ".to_out.0.")
27+
new_key = new_key.replace(".norm3.", ".norm2.") # the cross-attn LayerNorm
28+
if new_key.endswith(".modulation"):
29+
new_key = new_key.replace("head.modulation", "scale_shift_table")
30+
new_key = new_key.replace(".modulation", ".scale_shift_table")
31+
new_key = new_key.replace("head.head.", "proj_out.")
32+
converted[new_key] = value
33+
return converted
34+
35+
36+
def main():
37+
parser = argparse.ArgumentParser()
38+
parser.add_argument("--checkpoint_path", type=str, required=True)
39+
parser.add_argument("--output_path", type=str, required=True)
40+
parser.add_argument("--dtype", type=str, default="bf16", choices=["bf16", "fp32"])
41+
args = parser.parse_args()
42+
43+
state_dict = convert_abot_world_transformer(load_file(args.checkpoint_path))
44+
45+
transformer = ABotWorldTransformer3DModel()
46+
transformer.load_state_dict(state_dict, strict=True)
47+
if args.dtype == "bf16":
48+
transformer = transformer.to(torch.bfloat16)
49+
transformer.save_pretrained(args.output_path)
50+
51+
# round-trip check
52+
ABotWorldTransformer3DModel.from_pretrained(args.output_path)
53+
print(f"saved and round-trip loaded: {args.output_path}")
54+
55+
56+
if __name__ == "__main__":
57+
main()

src/diffusers/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@
224224
]
225225
_import_structure["models"].extend(
226226
[
227+
"ABotWorldTransformer3DModel",
227228
"AceStepTransformer1DModel",
228229
"AllegroTransformer3DModel",
229230
"AnimaTextConditioner",
@@ -513,6 +514,8 @@
513514
else:
514515
_import_structure["modular_pipelines"].extend(
515516
[
517+
"ABotWorldBlocks",
518+
"ABotWorldModularPipeline",
516519
"AnimaAutoBlocks",
517520
"AnimaModularPipeline",
518521
"Cosmos3DistilledBlocks",
@@ -1098,6 +1101,7 @@
10981101
VaeImageProcessorLDM3D,
10991102
)
11001103
from .models import (
1104+
ABotWorldTransformer3DModel,
11011105
AceStepTransformer1DModel,
11021106
AllegroTransformer3DModel,
11031107
AnimaTextConditioner,
@@ -1366,6 +1370,8 @@
13661370
from .utils.dummy_torch_and_transformers_objects import * # noqa F403
13671371
else:
13681372
from .modular_pipelines import (
1373+
ABotWorldBlocks,
1374+
ABotWorldModularPipeline,
13691375
AnimaAutoBlocks,
13701376
AnimaModularPipeline,
13711377
Cosmos3DistilledBlocks,

src/diffusers/models/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
_import_structure["transformers.t5_film_transformer"] = ["T5FilmDecoder"]
104104
_import_structure["transformers.transformer_2d"] = ["Transformer2DModel"]
105105
_import_structure["transformers.transformer_2d_dreamlite"] = ["DreamLiteTransformer2DModel"]
106+
_import_structure["transformers.transformer_abot_world"] = ["ABotWorldTransformer3DModel"]
106107
_import_structure["transformers.transformer_allegro"] = ["AllegroTransformer3DModel"]
107108
_import_structure["transformers.transformer_anyflow"] = ["AnyFlowTransformer3DModel"]
108109
_import_structure["transformers.transformer_anyflow_far"] = ["AnyFlowFARTransformer3DModel"]
@@ -234,6 +235,7 @@
234235
from .embeddings import ImageProjection
235236
from .modeling_utils import ModelMixin
236237
from .transformers import (
238+
ABotWorldTransformer3DModel,
237239
AceStepTransformer1DModel,
238240
AllegroTransformer3DModel,
239241
AnyFlowFARTransformer3DModel,

src/diffusers/models/transformers/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from .t5_film_transformer import T5FilmDecoder
2020
from .transformer_2d import Transformer2DModel
2121
from .transformer_2d_dreamlite import DreamLiteTransformer2DModel
22+
from .transformer_abot_world import ABotWorldTransformer3DModel
2223
from .transformer_allegro import AllegroTransformer3DModel
2324
from .transformer_anyflow import AnyFlowTransformer3DModel
2425
from .transformer_anyflow_far import AnyFlowFARTransformer3DModel

0 commit comments

Comments
 (0)