Skip to content

add Bernini-R notebook#3482

Open
openvino-dev-samples wants to merge 20 commits into
openvinotoolkit:latestfrom
openvino-dev-samples:bernini-r-1.3b
Open

add Bernini-R notebook#3482
openvino-dev-samples wants to merge 20 commits into
openvinotoolkit:latestfrom
openvino-dev-samples:bernini-r-1.3b

Conversation

@openvino-dev-samples

Copy link
Copy Markdown
Collaborator

No description provided.

openvino-dev-samples and others added 6 commits June 10, 2026 17:39
ByteDance/Bernini-R-1.3B-Diffusers is a unified multi-task diffusion renderer
(t2i / i2i / t2v / v2v / r2v / rv2v) fine-tuned from Wan2.1-1.3B. Its generation
logic (per-step loop, 7 guidance modes, source-id rotary embeddings, per-step
token assembly) is data-dependent python that a static OpenVINO graph cannot
express, so only the leaf compute is exported to OpenVINO while the original
bernini sampler/pipeline code drives it unchanged:

- text encoder (UMT5)  -> single static graph
- transformer          -> BlocksCore (condition embedder + blocks + proj) with
                          patch-embedding and rotary construction kept in torch;
                          packed-token axis is dynamic so one graph serves every
                          guidance combo. varlen attention -> SDPA, complex RoPE
                          -> real cos/sin to stay OpenVINO-friendly.
- VAE encoder/decoder  -> one graph per temporal latent length (the Wan VAE
                          walks frames with a causal feature-cache loop), built
                          eagerly for images and lazily for video lengths.

Verified against the reference: transformer split is bit-exact, VAE ~1e-6;
full t2i/t2v/r2v run end to end; INT8 matches FP16. On GPU/NPU the UMT5 text
encoder and VAE run in fp32 (fp16-overflow -> black image for some prompts)
while the heavy transformer stays in fast fp16, keeping GPU output aligned with
CPU at ~2x the speed of all-fp32.

Files: ov_bernini_helper.py (conversion + OpenVINO wrappers + load_ov_pipeline),
gradio_helper.py (task-routed demo), bernini-r-image-video.ipynb, README.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Align the task -> guidance_mode mapping with the reference bytedance/Bernini
testcases (t2i/t2v use t2v_apg, i2i uses v2v, v2v uses v2v_apg) and add the
per-task system prompts and required-input table (TASK_SYSTEM_PROMPT /
TASK_INPUTS). The system prompt is prefixed to the user prompt as in the
reference pipeline.

The original model supports image editing (i2i) and video editing (v2v); both
now run end to end on the real checkpoint (i2i std ~64; v2v produces a valid
mp4). The notebook gains dedicated i2i and v2v cells (downloading the reference
source image/video) and the gradio demo routes inputs per TASK_INPUTS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…E device)

- Default video to 20 frames and 4 steps in the notebook and gradio demo, as in
  the wan2.1 / wan2.2 notebooks.
- Add num_frames_to_latent() helper (Bernini rounds num_frames to n//4*4+1, the
  VAE then uses (n-1)//4+1 latent frames; 20 -> 6) and pre-convert that VAE graph
  so the default video length needs no on-demand conversion. Other lengths are
  still converted and cached on first use.
- Place the VAE on CPU by default: decoding a multi-frame video allocates a large
  USM buffer that can exhaust GPU memory (observed "Can not allocate ... USM
  Device"); the VAE is one forward per generation, so CPU costs little while the
  transformer / text encoder keep running on GPU. Documented in the README and
  the device-selection cell.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ter startup

Addresses three issues:

1. load_ov_pipeline no longer takes the original model path. convert_pipeline now
   copies the bernini/vae configs (plus tokenizer/scheduler) into the OpenVINO
   output dir, so the converted model is self-contained.

2. load_ov_pipeline reads everything from the OV dir and loads NO PyTorch model
   weights -- only OpenVINO IR is compiled. The original dir is needed only via
   the optional source_model_dir, and only to convert a VAE graph for a video
   length that was not pre-built. (The lone torch tensor kept at run time is the
   few-KB patch-embedding Conv3d that drives the data-dependent patchify/rotary.)

3. The long pause before the denoise progress bar was the GPU compiling the
   ~5 GB fp32 UMT5 text encoder (~80 s) and thrashing GPU memory. The text
   encoder and VAE now default to CPU (TE must be fp32 anyway; it compiles in
   ~2 s on CPU and runs twice per generation), while the transformer keeps using
   the GPU. If TE/VAE are placed on GPU, an fp32 hint is applied automatically.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The VAE decode is ~6.7x faster on GPU for a single image frame (~1 GB) but a
multi-frame video decode unrolls the Wan causal-conv loop into a tens-of-GB USM
buffer (~24 GB at 13 frames, ~34 GB at 21) that exhausts the integrated GPU once
the transformer is also resident -- confirmed on both stable 2026.2 and nightly
2026.3 OpenVINO (the isolated decode can spill to host, but the full pipeline
still OOMs).

OVVAEWrapper now chooses the device per call by latent temporal length: lengths
<= vae_gpu_max_latent_frames (default 1, i.e. images) run on the requested GPU
device, longer video lengths transparently use a CPU-compiled copy of the graph.
The per-length graph cache is keyed by (length, device) and the chosen device is
logged once. The notebook's VAE device widget now defaults to AUTO since the
wrapper self-selects.

Verified: image t2i with VAE on GPU (std 46.77), 20-frame t2v auto-routes the
VAE to CPU and produces a valid mp4 with no OOM.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per request, the VAE simply runs on whatever device it is assigned (default
AUTO) -- the size-based GPU->CPU routing for video is removed. Correctness is
preserved by the existing fp32 precision hint applied on GPU/NPU; verified the
VAE on GPU is not black (matches CPU, maxdiff ~2e-3) for images. Memory/OOM for
large video decodes is out of scope.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@review-notebook-app

Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@openvino-dev-samples openvino-dev-samples marked this pull request as draft June 15, 2026 00:47
openvino-dev-samples and others added 6 commits June 15, 2026 09:42
Debugged the VAE-on-GPU black-image concern: with a real pipeline latent the VAE
decodes correctly on GPU in fp16 for images on stable OpenVINO, and for video too
on the 2026.3 nightly (its GPU plugin spills the large multi-frame activation
buffer to host instead of failing). fp16 vs fp32 max diff is ~0.013, no NaN, not
black. So the VAE now runs in fp16 on GPU (was fp32) and the notebook installs the
OpenVINO nightly. The UMT5 text encoder remains fp32 -- it is the genuine fp16
overflow source and stays on CPU by default.

Verified end to end with the shipped default config on nightly: t2i (VAE GPU fp16)
std 34.06 not black; 20-frame t2v (VAE GPU fp16) produces a valid mp4.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixes the CI spellcheck failure for notebooks/bernini-r-image-video: ByteDance,
renderer, VTI, uncond, patchify, UMT, bernini, rv, testcases.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The truststore line was a workaround for a TLS-intercepting corporate proxy on
the dev machine, not something a general user needs. Remove it from the shipped
notebook.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
openvino-dev-samples and others added 7 commits June 16, 2026 13:51
Validated the notebook from a fresh venv on a tiny model and hit two install
breakages:
- the upstream Bernini HEAD now hard-imports `veomni` (heavy multi-GPU dep) and
  fails to import for OpenVINO inference -> pin commit 94a52f78.
- modelscope pulls huggingface-hub>=1.0, which breaks transformers 4.57.3
  (ImportError) -> pin huggingface-hub<1.0 after it.

Only the install cell changed; convert + t2i + t2v verified end to end in the
clean env on the tiny model.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
pip skips reinstalling git packages when the version (0.1.0) already matches, so
an environment that previously installed Bernini HEAD keeps the veomni-dependent
build and still fails with ModuleNotFoundError: veomni. Add --force-reinstall so
the pinned commit replaces it. Verified HEAD -> pinned switch in a clean venv.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The device-selection cell uses device_widget but the prerequisites cell only
imported collect_telemetry, raising NameError. Add device_widget to the import.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@openvino-dev-samples openvino-dev-samples changed the title Bernini r 1.3b add Bernini-R notebook Jun 17, 2026
@openvino-dev-samples openvino-dev-samples marked this pull request as ready for review June 17, 2026 02:20
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

This PR will be closed in a week because of 2 weeks of no activity.

@github-actions github-actions Bot added the Stale label Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant