YiYiXu HF Staff commited on
Commit
5207650
·
verified ·
1 Parent(s): 31cbb28

Barebone interactive ABot-World on Modular Diffusers: one pipe.stream(action_source=...) loop

Browse files
.gitattributes CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ examples/desert_valley.png filter=lfs diff=lfs merge=lfs -text
37
+ examples/example.png filter=lfs diff=lfs merge=lfs -text
38
+ examples/forest_stream.png filter=lfs diff=lfs merge=lfs -text
39
+ examples/mountain_meadow.png filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,13 +1,18 @@
1
  ---
2
- title: Abot World Interactive
3
- emoji: 🌍
4
- colorFrom: red
5
- colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 6.25.0
8
- python_version: '3.13'
9
  app_file: app.py
10
  pinned: false
 
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
1
  ---
2
+ title: ABot World Interactive
3
+ emoji: 🕹️
4
+ colorFrom: yellow
5
+ colorTo: green
6
  sdk: gradio
7
+ sdk_version: 6.5.1
8
+ python_version: '3.12'
9
  app_file: app.py
10
  pinned: false
11
+ short_description: Drive a live world model with Modular Diffusers
12
  ---
13
 
14
+ Interactive [ABot-World](https://huggingface.co/YiYiXu/ABot-World-0-5B-LF-Diffusers) (a real-time,
15
+ action-conditioned world model, Wan2.2-TI2V-5B) running natively on Modular Diffusers: the whole app is a
16
+ `pipe.stream(action_source=...)` consumer — the pipeline polls the held control once per generated block.
17
+
18
+ Needs a persistent GPU (the rollout keeps a K/V cache alive across blocks); ~20 GB VRAM in bf16.
app.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import threading
2
+
3
+ import gradio as gr
4
+ import numpy as np
5
+ import torch
6
+
7
+ from diffusers.modular_pipelines import ABotWorldStreamingBlocks
8
+ from diffusers.utils import load_image
9
+
10
+
11
+ REPO = "YiYiXu/ABot-World-0-5B-LF-Diffusers"
12
+
13
+ pipe = ABotWorldStreamingBlocks().init_pipeline(REPO)
14
+ pipe.load_components(dtype=torch.bfloat16)
15
+ pipe.to("cuda")
16
+
17
+ DEFAULT_PROMPT = (
18
+ "A realistic outdoor world scene with a navigable path, natural lighting, "
19
+ "detailed ground texture, and stable forward motion."
20
+ )
21
+
22
+ CONTROLS = {
23
+ "▲ forward (W)": [1, 0, 0, 0, 0, 0, 0, 0],
24
+ "◀ left (A)": [0, 1, 0, 0, 0, 0, 0, 0],
25
+ "▼ back (S)": [0, 0, 1, 0, 0, 0, 0, 0],
26
+ "▶ right (D)": [0, 0, 0, 1, 0, 0, 0, 0],
27
+ "cam ↑ (I)": [0, 0, 0, 0, 1, 0, 0, 0],
28
+ "cam ◀ (J)": [0, 0, 0, 0, 0, 1, 0, 0],
29
+ "cam ↓ (K)": [0, 0, 0, 0, 0, 0, 1, 0],
30
+ "cam ▶ (L)": [0, 0, 0, 0, 0, 0, 0, 1],
31
+ "· idle": [0] * 8,
32
+ }
33
+
34
+ # one live world at a time: buttons write the held control here, the rollout polls it per block
35
+ session = {"action": [0] * 8, "stop": False}
36
+ run_lock = threading.Lock()
37
+
38
+
39
+ def hold(control):
40
+ session["action"] = CONTROLS[control]
41
+ return f"holding: {control}"
42
+
43
+
44
+ def stop():
45
+ session["stop"] = True
46
+ return "stopping after this block…"
47
+
48
+
49
+ def play(image, prompt, max_blocks):
50
+ if not run_lock.acquire(blocking=False):
51
+ raise gr.Error("A session is already running — stop it first.")
52
+ try:
53
+ if image is None:
54
+ image = load_image("examples/desert_valley.png")
55
+ session["stop"] = False
56
+ session["action"] = CONTROLS["▲ forward (W)"]
57
+
58
+ def action_source(block_index):
59
+ if session["stop"] or block_index >= max_blocks:
60
+ return None
61
+ return session["action"]
62
+
63
+ for event in pipe.stream(
64
+ prompt=(prompt or DEFAULT_PROMPT).strip() or DEFAULT_PROMPT,
65
+ image=image,
66
+ action_source=action_source,
67
+ generator=torch.Generator("cpu").manual_seed(42),
68
+ ):
69
+ if event.path != "denoise.rollout":
70
+ continue
71
+ frames = event.state.get("frames")
72
+ yield (frames[-1] * 255).clip(0, 255).astype(np.uint8)
73
+ finally:
74
+ run_lock.release()
75
+
76
+
77
+ with gr.Blocks(title="ABot-World Interactive") as demo:
78
+ gr.Markdown(
79
+ """# ABot-World — interactive world, Modular Diffusers
80
+ Upload a scene, press Start, then hold a control: each ~1 s block is generated live by
81
+ [ABot-World](https://huggingface.co/YiYiXu/ABot-World-0-5B-LF-Diffusers) conditioned on the held action.
82
+ The whole app is one `pipe.stream(action_source=...)` loop — the pipeline polls your current input once
83
+ per block ([huggingface/diffusers#14159](https://github.com/huggingface/diffusers/pull/14159))."""
84
+ )
85
+ with gr.Row():
86
+ with gr.Column(scale=1):
87
+ image = gr.Image(label="starting scene", type="pil", height=220)
88
+ prompt = gr.Textbox(label="scene prompt", value=DEFAULT_PROMPT, lines=2)
89
+ max_blocks = gr.Slider(label="max blocks (~seconds)", minimum=4, maximum=120, step=1, value=60)
90
+ with gr.Row():
91
+ start_button = gr.Button("Start", variant="primary")
92
+ stop_button = gr.Button("Stop")
93
+ gr.Examples(
94
+ examples=[["examples/desert_valley.png"], ["examples/forest_stream.png"],
95
+ ["examples/mountain_meadow.png"], ["examples/example.png"]],
96
+ inputs=[image],
97
+ )
98
+ with gr.Column(scale=2):
99
+ view = gr.Image(label="world", show_label=False, interactive=False)
100
+ status = gr.Textbox(value="holding: ▲ forward (W)", show_label=False, container=False)
101
+ with gr.Row():
102
+ buttons = [gr.Button(name, size="sm") for name in CONTROLS]
103
+
104
+ for button in buttons:
105
+ button.click(hold, inputs=gr.State(button.value), outputs=status, api_name="hold")
106
+ start_button.click(play, inputs=[image, prompt, max_blocks], outputs=view, api_name="play")
107
+ stop_button.click(stop, outputs=status, api_name="stop")
108
+
109
+ demo.launch(show_error=True)
examples/desert_valley.png ADDED

Git LFS Details

  • SHA256: 7200407b480dfa198809c4e512c4d801da3642629495fa93a5626f8fd8bdf2ba
  • Pointer size: 132 Bytes
  • Size of remote file: 1.83 MB
examples/example.png ADDED

Git LFS Details

  • SHA256: 10aeeea2938b89959bccd3b91c7a4ad7b078d7c07b1a9c86cff18681c0bd8630
  • Pointer size: 132 Bytes
  • Size of remote file: 2.77 MB
examples/forest_stream.png ADDED

Git LFS Details

  • SHA256: fada1d2eb3b559bd157bc9b3c063071260fb24de50082450694e1a951b6ee99c
  • Pointer size: 132 Bytes
  • Size of remote file: 1.61 MB
examples/mountain_meadow.png ADDED

Git LFS Details

  • SHA256: 1c877c3b685c2a07484d753d17a69c05e8eb8a636cc08035af8837673d22752b
  • Pointer size: 132 Bytes
  • Size of remote file: 1.87 MB
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ accelerate
2
+ git+https://github.com/huggingface/diffusers.git@abot-world-modular
3
+ torch
4
+ transformers
5
+ ftfy