Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ TeleFuser is a high-performance runtime for world model inference and multimodal
chunk-boundary time slicing, reconnect-friendly browser transport, and server-push/bidirectional contracts.
- ✨ **2026-07-22**: Added [**LingBot-Video**](examples/lingbot_video/README.md) support for Dense and MoE T2I/T2V/TI2V generation, native four-GPU CFG/SP execution, and in-memory MoE refinement.
- ✨ **2026-07-15**: Added [**LingBot-World v2**](https://github.com/Robbyant/lingbot-world-v2) support for offline generation, interactive WebRTC streaming, and multi-GPU inference.
- ✨ **2026-08-06**: Added [**ABot-World 0.5B-LF**](docs/en/abot_world.md) single-GPU browser interaction with persistent causal KV state and bounded RoPE positions.

- ✨ **2026-07-06**: Added external **CacheSeek** latent cache integration for service-mode cross-request reuse. Cache hits can skip the first N denoising steps; the Wan2.2 cache-enabled service example snapshots `[5, 10, 15, 20, 25]` by default. See [docs/en/latent_cache.md](docs/en/latent_cache.md).

Expand Down Expand Up @@ -220,6 +221,7 @@ telefuser/
| Pipeline | Task | Notes |
|----------|------|-------|
| `LingBot-World v2` | Bidirectional world-model streaming | LiveKit control loop via [examples/lingbot/lingbot_world_v2_image_to_video_h100.py](examples/lingbot/lingbot_world_v2_image_to_video_h100.py) |
| `ABot-World 0.5B-LF` | Single-GPU interactive world model | Direct browser controller via [examples/abot_world/README.md](examples/abot_world/README.md); no LiveKit required |
| `LiveAct` | S2V | Speech-driven talking head generation via [examples/liveact/liveact_s2v_h100.py](examples/liveact/liveact_s2v_h100.py) |
| `FlashVSR` | VSR | Streaming video super-resolution via [examples/flashvsr/README.md](examples/flashvsr/README.md) |

Expand Down Expand Up @@ -257,13 +259,14 @@ See [examples/README.md](examples/README.md) for the example runner and baseline
- [docs/en/torch_compile_compatibility.md](docs/en/torch_compile_compatibility.md): compile-related constraints
- [docs/en/adding_new_model.md](docs/en/adding_new_model.md): integrating new models
- [docs/en/adding_new_example.md](docs/en/adding_new_example.md): authoring examples and pipeline contracts
- [docs/en/abot_world.md](docs/en/abot_world.md): ABot-World single-GPU interactive pipeline, controls, and tests

## Known Limitations

- `AdaTaylorCache` is only calibrated for selected model families.
- `torch.compile` support is still experimental in parts of the stack.
- Some optimized paths require specific GPU architectures and CUDA versions.
- World-model examples such as `LingBot-World v2` require external checkpoints and environment setup.
- World-model examples such as `LingBot-World v2` and `ABot-World` require external checkpoints and environment setup.
- Multi-machine deployment exists in the architecture but may require project-specific integration and validation.

## Development
Expand All @@ -274,7 +277,7 @@ pre-commit install
pytest tests/
```

See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution workflow and [AGENTS.md](AGENTS.md) for project-specific agent guidance.
See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution workflow and [CLAUDE.md](CLAUDE.md) for repository guidance.

## License

Expand Down
101 changes: 101 additions & 0 deletions docs/en/abot_world.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# ABot-World 0.5B-LF

TeleFuser provides a single-GPU, direct-browser integration for the public
ABot-World 0.5B-LF long-forcing checkpoint. The supported entry point is the
native HTTP controller:

```bash
python examples/abot_world/abot_world_interactive_web.py \
--model-root /path/to/ABot-World-0-5B-LF \
--host 127.0.0.1 \
--port 7860
```

This integration does not use `telefuser stream-serve`, LiveKit, WebRTC, or a
TURN server. The browser speaks to the local HTTP controller. For an SSH
session, forward the port from the remote host:

```bash
ssh -N -p <ssh-port> -L 7860:127.0.0.1:7860 <user>@<server>
```

## Checkpoint And Image

The loader expects the unmodified checkpoint layout:

```text
ABot-World-0-5B-LF/
diffusion_pytorch_model.safetensors
Wan2.2_VAE.pth
models_t5_umt5-xxl-enc-bf16.pth
```

The browser's default sample image comes from the official ABot-World web
client asset at `../ABot-World/web_client/datasets/images/84b90ad568b693d2.png`.
Pass a different server-side image path from the page when needed.

## Pipeline Structure

`ABotWorldPipeline` is a TeleFuser `BasePipeline`. It uses the existing Wan
VAE and text stages plus the model-specific `ABotWorldDenoisingStage`.
`ABotWorldDiT` uses the public TeleFuser attention operations and the official
four-step x0-prediction causal sampler.

`ABotWorldInteractivePipeline` retains the prompt embedding, initial image
latent, self/cross KV caches, scheduler, RNG, and VAE temporal cache between
control blocks. The initial integration supports one GPU and one retained
causal session.

## Controls And Idle Behavior

WASD and arrow keys control movement. IJKL controls camera rotation. Connect
creates the image-conditioned session and displays the input preview; it does
not advance the DiT with an empty action state. A non-empty control snapshot
starts the next three-latent causal block. Releasing all keys stops new model
execution without discarding frames already queued for playback.

The browser consumes decoded frames in order at 12 FPS. The bounded FIFO
applies producer backpressure when playback is behind, so normal playback does
not drop generated blocks.

## KV And RoPE

The default causal window is 18 latent frames: six sink frames plus a
twelve-frame rolling tail. KV cache entries remain unrotated; RoPE is applied
when keys are read using bounded logical positions. Sink positions are `0..5`
and the rolling tail occupies the remaining local window, so the global session
frame number does not grow the RoPE index past the precomputed table.

This fixed logical position policy is an intentional difference from the
original non-sink ABot baseline and must be evaluated as part of any future
long-horizon quality claim.

## Tests

CPU contract tests cover model conversion, sink KV rolling, RoPE boundaries,
session cleanup, idle behavior, FIFO backpressure, and action layout:

```bash
python -m pytest tests/unit/models/test_wan22_video_vae.py \
tests/unit/pipelines/abot_world -q
```

The opt-in GPU smoke uses the release checkpoint, the public `480x832` shape,
a fixed seed, and 30 control blocks:

```bash
CUDA_VISIBLE_DEVICES=0 \
ABOT_WORLD_MODEL_ROOT=/path/to/ABot-World-0-5B-LF \
ABOT_WORLD_TEST_IMAGE=/path/to/initial.png \
python -m pytest -m "gpu and slow" \
tests/integration/test_abot_world_smoke.py -v -s
```

The smoke is a generation and cache contract test. It does not establish
visual quality, prompt fidelity, or parity over an unbounded session.

## Scope

The first integration is intentionally single-GPU and direct HTTP. LiveKit or
`stream-serve` support requires a separate transport integration and is not
part of this example.
1 change: 1 addition & 0 deletions docs/en/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Reusable stages, model configs, schedulers, and pipeline orchestration.
|-------|-------|-------------|
| LingBot-World v2 | Bidirectional streaming | Camera-controlled interactive world model via LiveKit |
| LingBot-World-Fast | Bidirectional streaming | Legacy/causal-fast model via LiveKit reliable data messages |
| ABot-World 0.5B-LF | Single-GPU interactive generation | Direct browser control with persistent causal KV state; see the [ABot guide](abot_world/) |

### Video Generation

Expand Down
40 changes: 40 additions & 0 deletions examples/abot_world/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# ABot-World 0.5B-LF

This example exposes one local single-GPU entry point:

```bash
python examples/abot_world/abot_world_interactive_web.py \
--model-root /path/to/ABot-World-0-5B-LF \
--host 127.0.0.1 \
--port 7860
```

The browser controls WASD/arrow movement and IJKL camera rotation. Connecting
creates the image-conditioned causal session but does not advance the DiT
until a non-empty control state is received. Generated blocks remain ordered
in a bounded FIFO and the producer waits when the browser is behind.
The six sink latents and rolling tail use fixed logical RoPE positions, so the
global session frame number does not index beyond the trained local window.

## Test tiers

CPU contract tests cover action-channel layout, checkpoint conversion, sink
KV rolling, RoPE boundary validation, session cleanup, and the direct runtime
idle/FIFO behavior:

```bash
pytest tests/unit/pipelines/abot_world
```

The 30-block GPU smoke is opt-in because it loads the release checkpoint:

```bash
ABOT_WORLD_MODEL_ROOT=/path/to/ABot-World-0-5B-LF \
ABOT_WORLD_TEST_IMAGE=/path/to/initial.png \
pytest -m "gpu and slow" tests/integration/test_abot_world_smoke.py -v
```

The smoke uses the public 480x832 shape, a fixed seed, and a fixed control
state. It checks that every block decodes frames and that the session's
emitted-frame counter matches the observed count. It is a generation contract
test, not a visual-quality or long-horizon parity claim.
101 changes: 101 additions & 0 deletions examples/abot_world/_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"""Internal ABot-World checkpoint loader for the interactive example."""

from __future__ import annotations

import os
from pathlib import Path

import torch

from telefuser.core.config import (
AttentionConfig,
AttnImplType,
ModelRuntimeConfig,
OffloadConfig,
WeightOffloadType,
)
from telefuser.core.module_manager import ModuleManager
from telefuser.models.abot_world_dit import ABotWorldDiT
from telefuser.models.wan22_video_vae import Wan22VideoVAE
from telefuser.models.wan_video_text_encoder import WanTextEncoder
from telefuser.ops.attention.backends import FLASH_ATTN_3_AVAILABLE, FLASH_ATTN_4_AVAILABLE
from telefuser.pipelines.abot_world import ABotWorldPipeline, ABotWorldPipelineConfig

_PROJECT_ROOT = Path(__file__).resolve().parents[2]
_DEFAULT_MODEL_ROOT = (
Path(os.environ.get("TF_MODEL_ZOO_PATH", _PROJECT_ROOT.parent / "model_zoo")) / "ABot-World-0-5B-LF"
)
DEFAULT_PROMPT = "A smooth first-person exploration through a vivid natural landscape."


def _attention_backend() -> AttnImplType:
if FLASH_ATTN_4_AVAILABLE:
return AttnImplType.FLASH_ATTN_4
if FLASH_ATTN_3_AVAILABLE:
return AttnImplType.FLASH_ATTN_3
return AttnImplType.TORCH_SDPA


def get_pipeline(
model_root: str | Path = _DEFAULT_MODEL_ROOT,
*,
height: int = 480,
width: int = 832,
latent_frames: int = 31,
pipeline_class: type[ABotWorldPipeline] = ABotWorldPipeline,
) -> ABotWorldPipeline:
"""Load the downloaded ABot checkpoint with VAE/T5 model CPU offload."""
root = Path(model_root).expanduser()
required = ("diffusion_pytorch_model.safetensors", "Wan2.2_VAE.pth", "models_t5_umt5-xxl-enc-bf16.pth")
missing = [name for name in required if not (root / name).is_file()]
if missing:
raise FileNotFoundError(f"ABot model root {root} is missing: {', '.join(missing)}")

model_manager = ModuleManager(device="cpu")
model_manager.load_model(
str(root / "Wan2.2_VAE.pth"),
name="wan_video_vae",
model_class=Wan22VideoVAE,
torch_dtype=torch.float32,
low_cpu_mem_usage=True,
)
model_manager.load_model(
str(root / "models_t5_umt5-xxl-enc-bf16.pth"),
name="wan_video_text_encoder",
model_class=WanTextEncoder,
torch_dtype=torch.bfloat16,
low_cpu_mem_usage=True,
)
model_manager.load_model(
str(root / "diffusion_pytorch_model.safetensors"),
name="abot_world_dit",
model_class=ABotWorldDiT,
torch_dtype=torch.bfloat16,
low_cpu_mem_usage=True,
)

cpu_offload = OffloadConfig(offload_type=WeightOffloadType.MODEL_CPU_OFFLOAD)
pipeline = pipeline_class(device="cuda", torch_dtype=torch.bfloat16)
pipeline.init(
model_manager,
ABotWorldPipelineConfig(
vae_config=ModelRuntimeConfig(
device_type="cuda", device_id=0, torch_dtype=torch.float32, offload_config=cpu_offload
),
text_encoding_config=ModelRuntimeConfig(
device_type="cuda", device_id=0, torch_dtype=torch.bfloat16, offload_config=cpu_offload
),
dit_config=ModelRuntimeConfig(
device_type="cuda",
device_id=0,
torch_dtype=torch.bfloat16,
attention_config=AttentionConfig.dense_attention(_attention_backend()),
),
height=height,
width=width,
latent_frames=latent_frames,
local_attn_size=18,
sink_size=6,
),
)
return pipeline
Loading
Loading