Implement VibeVoice #40546
Conversation
ebezzam
left a comment
There was a problem hiding this comment.
@pengzhiliang thanks for the PR! This is an exciting model to add 🔥
My first comments are mainly on rearranging content to be consistent with the other models in Transformers, and creating a modular file to better optimize copying components from other models in Transformers.
There are also some other files to modify:
- in
src/transformers/models/auto - in
docs - and eventually some tests (for which a lot of code can be copied from other models)
As an example of typical files to create/modify, you can check out the Qwen2.5-Omni PR, which is also multimodal.
|
Hopefully this PR can get merged, since the deletion of the VibeVoice repo not sure the original authors can continue contributing to this PR |
|
Glad to see that someone has picked this PR up, thanks 🤗 |
CI recapDashboard: View test results in Grafana |
|
run-slow: vibevoice |
|
This comment contains models: ["models/vibevoice"] |
vasqu
left a comment
There was a problem hiding this comment.
Some initial comments from my side 🤗 mainly took a look at generation/modeling for now
| - [bezzam/VibeVoice-1.5B-hf](https://huggingface.co/bezzam/VibeVoice-1.5B-hf) | ||
| - [bezzam/VibeVoice-7B-hf](https://huggingface.co/bezzam/VibeVoice-7B-hf) |
There was a problem hiding this comment.
Rebump before it gets lost, ig a community org or we have contact to transfer?
| noise_scheduler = diffusers.DPMSolverMultistepScheduler( | ||
| beta_schedule="squaredcos_cap_v2", | ||
| prediction_type="v_prediction", | ||
| ) | ||
| model.generation_config.noise_scheduler = noise_scheduler | ||
| audio = model.generate(**inputs) |
There was a problem hiding this comment.
My main idea would be to add a custom dict like entry that we resolve for vibevoice only as custom entries are passed along and saved so we can make use of that and integrate it into our own generate pipeline in the end --> create the scheduler at runtime then
| Padding mask to remove padded parts of audio. | ||
| """ | ||
|
|
||
| with torch.no_grad(): |
There was a problem hiding this comment.
taken from original and because the acoustic tokenizer (audio tower) is only meant for inference within this architecture, even during training ("During VIBEVOICE training, the pre-trained acoustic and semantic tokenizers remained frozen, with only the LLM and diffusion head parameters being learnable", bottom of p.3 of paper).
is there better way to do this?
There was a problem hiding this comment.
Let's add a small comment but should be fine. Was just surprised
| inputs_embeds: torch.FloatTensor | None = None, | ||
| input_values: torch.FloatTensor | None = None, | ||
| padding_mask: torch.BoolTensor | None = None, | ||
| **kwargs, |
| num_diffusion_steps (`int`, *optional*, defaults to config.num_diffusion_steps): | ||
| For training, the number of diffusion steps to use. |
There was a problem hiding this comment.
hmm ok here it is, let's avoid the double trouble and only have it as config value?
There was a problem hiding this comment.
how about only as a forward parameter? like ddpm_batch_multiplier and noise_scheduler so all training-related parameters are passed this way
There was a problem hiding this comment.
Yep glad with either version just dont want both 😬
Co-authored-by: Anton Vlasjuk <73884904+vasqu@users.noreply.github.com>
|
Thank you for your contribution 🤗! CI Security Gate — automatic approval blockedThis PR was not automatically approved for CI because the security gate failed. Possible reasons:
See the workflow run for the exact violations. A maintainer can review and manually approve CI if a finding is a false positive. |
|
[For maintainers] Suggested jobs to run (before merge) run-slow: auto, csm, vibevoice, vibevoice_acoustic_tokenizer |
Co-authored-by: Anton Vlasjuk <73884904+vasqu@users.noreply.github.com>
|
Thank you for your contribution 🤗! CI Security Gate — automatic approval blockedThis PR was not automatically approved for CI because the security gate failed. Possible reasons:
See the workflow run for the exact violations. A maintainer can review and manually approve CI if a finding is a false positive. |
|
[For maintainers] Suggested jobs to run (before merge) run-slow: auto, csm, vibevoice, vibevoice_acoustic_tokenizer |
|
Thank you for your contribution 🤗! CI Security Gate — automatic approval blockedThis PR was not automatically approved for CI because the security gate failed. Possible reasons:
See the workflow run for the exact violations. A maintainer can review and manually approve CI if a finding is a false positive. |
|
[For maintainers] Suggested jobs to run (before merge) run-slow: auto, csm, vibevoice, vibevoice_acoustic_tokenizer |
|
Thank you for your contribution 🤗! CI Security Gate — automatic approval blockedThis PR was not automatically approved for CI because the security gate failed. Possible reasons:
See the workflow run for the exact violations. A maintainer can review and manually approve CI if a finding is a false positive. |
|
[For maintainers] Suggested jobs to run (before merge) run-slow: auto, csm, vibevoice, vibevoice_acoustic_tokenizer |
Co-authored-by: Anton Vlasjuk <73884904+vasqu@users.noreply.github.com>
|
Thank you for your contribution 🤗! CI Security Gate — automatic approval blockedThis PR was not automatically approved for CI because the security gate failed. Possible reasons:
See the workflow run for the exact violations. A maintainer can review and manually approve CI if a finding is a false positive. |
|
[For maintainers] Suggested jobs to run (before merge) run-slow: auto, csm, vibevoice, vibevoice_acoustic_tokenizer |
|
Thank you for your contribution 🤗! CI Security Gate — automatic approval blockedThis PR was not automatically approved for CI because the security gate failed. Possible reasons:
See the workflow run for the exact violations. A maintainer can review and manually approve CI if a finding is a false positive. |
vasqu
left a comment
There was a problem hiding this comment.
Some more comments in the meantime, did not go full deep dive but still a few details here and there
| print(f"Saved output to {fn}") | ||
| ``` | ||
|
|
||
| ### Batched inference |
| # Compute losses | ||
| lm_loss = outputs.loss | ||
| diffusion_loss = outputs.diffusion_loss | ||
| total_loss = lm_loss + diffusion_loss |
There was a problem hiding this comment.
this is weird why are we outputting both separately and not directly the final one? Otherwise the trainer will also not work OOB
There was a problem hiding this comment.
I think it's better to output separately, because some training schemes may weight them differently as training progresses.
There was a problem hiding this comment.
I'll put a comment that this is a sum just for demo purposes
| _ = model(**inputs) | ||
| torch.cuda.synchronize() | ||
| print(f"Warmup complete in {time.time() - warmup_start:.2f}s.") | ||
| # Warmup complete in 46.39s |
There was a problem hiding this comment.
feels like we should add a final forward after the warmup?
| device = kwargs.get("device") | ||
| processors.append(VibeVoiceTokenConstraintProcessor(valid_tokens, device=device)) |
There was a problem hiding this comment.
Hmm self.device maybe? Or is this the better way, havent seen this in kwargs tbh
| if noise_scheduler is None: | ||
| raise ValueError( | ||
| "VibeVoice generation requires a `noise_scheduler` to be provided, e.g., " | ||
| "`diffusers.DPMSolverMultistepScheduler(beta_schedule='squaredcos_cap_v2', prediction_type='v_prediction')`." | ||
| ) | ||
| if not ( | ||
| hasattr(noise_scheduler, "set_timesteps") | ||
| and hasattr(noise_scheduler, "step") | ||
| and hasattr(noise_scheduler, "timesteps") | ||
| ): | ||
| raise ValueError( | ||
| f"The provided noise_scheduler ({type(noise_scheduler).__name__}) is not compatible with VibeVoice " | ||
| "generation. It must implement `set_timesteps` and `step` methods, and have a `timesteps` attribute." | ||
| ) |
There was a problem hiding this comment.
Yup, it looked very awkward in the docs tbh
| base_model_tp_plan = { | ||
| "language_model.layers.*.self_attn.q_proj": "colwise", | ||
| "language_model.layers.*.self_attn.k_proj": "colwise", | ||
| "language_model.layers.*.self_attn.v_proj": "colwise", | ||
| "language_model.layers.*.self_attn.o_proj": "rowwise", | ||
| "language_model.layers.*.mlp.gate_proj": "colwise", | ||
| "language_model.layers.*.mlp.up_proj": "colwise", | ||
| "language_model.layers.*.mlp.down_proj": "rowwise", | ||
| } |
There was a problem hiding this comment.
Hmm does it not automatically be applied on submodels with the correct config? Can you double check?
|
|
||
| # NOTE (ebezzam) for modular usage of `LlamaMLP` | ||
| @property | ||
| def hidden_size(self) -> int: |
There was a problem hiding this comment.
or actually can avoid this altogether by doing
class VibeVoiceMLP(LlamaMLP):
def __init__(self, config):
super().__init__(config)
self.hidden_size = config.text_config.hidden_size
| num_head_layers: int = 4 | ||
| intermediate_size: int = 4608 | ||
| rms_norm_eps: float = 1e-5 | ||
| hidden_act: str = "silu" | ||
| frequency_embedding_size: int = 256 | ||
| diffusion_max_period: int = 10000 | ||
| mlp_bias: bool = False |
There was a problem hiding this comment.
Might be a big nit but maybe also a subconfig?
|
|
||
| @auto_docstring | ||
| class VibeVoicePreTrainedModel(VoxtralPreTrainedModel): | ||
| _supports_cache_class = False |
There was a problem hiding this comment.
Hmm so we have no cache or more like we have a super custom cache?
What does this PR do?
Merge the model from https://github.com/microsoft/VibeVoice/tree/main
HF:
https://huggingface.co/microsoft/VibeVoice-1.5B