Spaces:
Running on Zero
Running on Zero
Download aoti.py from OpenMOSS-Team/MOSS-Image: direct link, hf CLI and curl.
- Browser
- Download file 3.18 kB
-
https://huggingface.co/spaces/OpenMOSS-Team/MOSS-Image/resolve/main/aoti.py
- Command line
-
hf download hf://spaces/OpenMOSS-Team/MOSS-Image/aoti.py
-
curl -L -o aoti.py https://huggingface.co/spaces/OpenMOSS-Team/MOSS-Image/resolve/main/aoti.py
3.18 kB
| """Compile repeated transformer blocks once on the Space's actual ZeroGPU device.""" | |
| import logging | |
| from pathlib import Path | |
| import time | |
| import spaces | |
| import torch | |
| from spaces.zero.torch.aoti import LazyAOTIModel | |
| logger = logging.getLogger(__name__) | |
| BLOCK_GROUPS = ("text_embedder.blocks", "layers") | |
| def export_block(block, args): | |
| # The transformer evaluates each sample separately at its true sequence length. | |
| sequence = torch.export.Dim("sequence", min=1) | |
| shapes = ({1: sequence}, {1: sequence}) + ({},) * (len(args) - 2) | |
| return torch.export.export(block, args=args, dynamic_shapes=shapes) | |
| def prepare_aoti(pipelines, package_dir=".cache/aoti"): | |
| pipelines = tuple(pipelines) | |
| transformer = pipelines[0].transformer | |
| package_dir = Path(package_dir) | |
| def compile_blocks(): | |
| started = time.monotonic() | |
| logger.info("AOT compilation starting on %s", torch.cuda.get_device_name()) | |
| cfg = transformer.config | |
| dtype = next(transformer.parameters()).dtype | |
| # Capture real input layouts/dtypes, without encoding a prompt or decoding an image. | |
| inputs = dict( | |
| hidden_states=torch.zeros(1, cfg.latent_channels, 64, 64, device="cuda"), | |
| timestep=torch.tensor([500.0], device="cuda"), | |
| encoder_hidden_states=torch.zeros(1, 32, cfg.text_dim, device="cuda", dtype=dtype), | |
| ) | |
| for name in BLOCK_GROUPS: | |
| block = transformer.get_submodule(name)[0] | |
| with spaces.aoti_capture(block) as call: | |
| transformer(**inputs) | |
| exported = export_block(block, call.args) | |
| spaces.aoti_compile_and_save( | |
| package_dir, exported, submodule=name, | |
| inductor_configs={"dynamic_scale_rblock": False}, | |
| ) | |
| # Verify that the shared graph uses each model's own weights. | |
| compiled = LazyAOTIModel(package_dir / "submodules" / name / "package.pt2") | |
| for pipe in pipelines: | |
| candidate = pipe.transformer.get_submodule(name)[-1] | |
| expected = candidate(*call.args).float() | |
| actual = compiled.with_weights(candidate.state_dict())(*call.args).float() | |
| relative_error = ((actual - expected).square().mean().sqrt() | |
| / expected.square().mean().sqrt().clamp_min(1e-6)).item() | |
| if not torch.isfinite(actual).all() or relative_error > 0.02: | |
| raise RuntimeError(f"AOT validation failed for {name}: relative RMS error {relative_error}") | |
| logger.info("AOT validated %s revision=%s relative_rms_error=%.6f", | |
| name, pipe._moss_revision, relative_error) | |
| logger.info("AOT compiled %s in %.1fs", name, time.monotonic() - started) | |
| return round(time.monotonic() - started, 3) | |
| elapsed = compile_blocks() | |
| for pipe in pipelines: | |
| spaces.aoti_load_from_package_dir(pipe.transformer, package_dir) | |
| pipe._execution_backend = "regional-aoti" | |
| logger.info("AOT ready for both models; startup compilation took %.1fs", elapsed) | |