Add Seamless M4T model#25693
Conversation
ylacombe
left a comment
There was a problem hiding this comment.
Hey @ArthurZucker, I've made some refactoring on the tokenizer, which I believe will content you 🤗
I still have to add copied from statements in the tests, but I think you can already finish your review here, if that's ok with you!
Thanks!
| <!--This tip is automatically generated by `make fix-copies`, do not fill manually!--> | ||
|
|
||
| [BART](../model_doc/bart), [BigBird-Pegasus](../model_doc/bigbird_pegasus), [Blenderbot](../model_doc/blenderbot), [BlenderbotSmall](../model_doc/blenderbot-small), [Encoder decoder](../model_doc/encoder-decoder), [FairSeq Machine-Translation](../model_doc/fsmt), [GPTSAN-japanese](../model_doc/gptsan-japanese), [LED](../model_doc/led), [LongT5](../model_doc/longt5), [M2M100](../model_doc/m2m_100), [Marian](../model_doc/marian), [mBART](../model_doc/mbart), [MT5](../model_doc/mt5), [MVP](../model_doc/mvp), [NLLB](../model_doc/nllb), [NLLB-MOE](../model_doc/nllb-moe), [Pegasus](../model_doc/pegasus), [PEGASUS-X](../model_doc/pegasus_x), [PLBart](../model_doc/plbart), [ProphetNet](../model_doc/prophetnet), [SwitchTransformers](../model_doc/switch_transformers), [T5](../model_doc/t5), [UMT5](../model_doc/umt5), [XLM-ProphetNet](../model_doc/xlm-prophetnet) | ||
| [BART](../model_doc/bart), [BigBird-Pegasus](../model_doc/bigbird_pegasus), [Blenderbot](../model_doc/blenderbot), [BlenderbotSmall](../model_doc/blenderbot-small), [Encoder decoder](../model_doc/encoder-decoder), [FairSeq Machine-Translation](../model_doc/fsmt), [GPTSAN-japanese](../model_doc/gptsan-japanese), [LED](../model_doc/led), [LongT5](../model_doc/longt5), [M2M100](../model_doc/m2m_100), [Marian](../model_doc/marian), [mBART](../model_doc/mbart), [MT5](../model_doc/mt5), [MVP](../model_doc/mvp), [NLLB](../model_doc/nllb), [NLLB-MOE](../model_doc/nllb-moe), [Pegasus](../model_doc/pegasus), [PEGASUS-X](../model_doc/pegasus_x), [PLBart](../model_doc/plbart), [ProphetNet](../model_doc/prophetnet), [SeamlessM4T](../model_doc/seamless_m4t), [SwitchTransformers](../model_doc/switch_transformers), [T5](../model_doc/t5), [UMT5](../model_doc/umt5), [XLM-ProphetNet](../model_doc/xlm-prophetnet) |
There was a problem hiding this comment.
I actually don't know why it happens, do you have any ideas?
| represented by the `inputs_ids` passed when calling the Text-To-Units sub-model of [`~SeamlessM4TModel`], | ||
| [`~SeamlessM4TForSpeechToSpeech`] or [`~SeamlessM4TForTextToSpeech`]. | ||
|
|
||
| > Parameters shared across sub-models |
There was a problem hiding this comment.
This seems to break check_repository_consistency, any ideas why @ydshieh ? I think PretrainedConfig uses something similar
There was a problem hiding this comment.
Sorry for being late. I will check this afternoon!
There was a problem hiding this comment.
It's conv_depthwise_kernel_size (int, defaults to 31, *optional*, defaults to 31): causing problem
There was a problem hiding this comment.
change it to conv_depthwise_kernel_size (int, *optional*, defaults to 31):
then run
python utils/check_docstrings.py --fix_and_overwriteThere was a problem hiding this comment.
For lines like > Text-To-Unit (t2u) model specific parameters, I think utils/check_docstrings.py could not handle it. Is this a standard way to add comment while we are in an Args block? Could this be rendered correctly?
There was a problem hiding this comment.
For lines like
> Text-To-Unit (t2u) model specific parameters, I thinkutils/check_docstrings.pycould not handle it. Is this a standard way to add comment while we are in anArgsblock? Could this be rendered correctly?
Hi @ydshieh , thanks for your feedback! this is something that I've mimicked from PretrainedConfig
How should I handle this ? I'd like to keep these lines!
There was a problem hiding this comment.
Added to OBJECT_TO_IGNORE in utils/check_docstrings.py after having check it passes our requirements without the weird > markdown.
Thanks for your offline support on this @ydshieh
There was a problem hiding this comment.
As requested, I've made a big cleaning, I believe it's much better now, thanks for your guidance @ArthurZucker !
| if src_lang is not None: | ||
| self.src_lang = src_lang | ||
| if tgt_lang is not None: | ||
| self.tgt_lang = tgt_lang |
There was a problem hiding this comment.
I actually think they should be in the docstrings, WDYT?
| @classmethod | ||
| def _from_pretrained( | ||
| cls, | ||
| resolved_vocab_files, | ||
| pretrained_model_name_or_path, | ||
| init_configuration, | ||
| *init_inputs, | ||
| token=None, | ||
| cache_dir=None, | ||
| local_files_only=False, | ||
| _commit_hash=None, | ||
| _is_local=False, | ||
| **kwargs, | ||
| ): | ||
| tokenizer = super()._from_pretrained( | ||
| resolved_vocab_files, | ||
| pretrained_model_name_or_path, | ||
| init_configuration, | ||
| *init_inputs, | ||
| token=token, | ||
| cache_dir=cache_dir, | ||
| local_files_only=local_files_only, | ||
| _commit_hash=_commit_hash, | ||
| _is_local=_is_local, | ||
| **kwargs, | ||
| ) | ||
|
|
||
| # ensure also set after from pretrained | ||
| tokenizer.set_src_lang_special_tokens(tokenizer._src_lang) | ||
| tokenizer.set_tgt_lang_special_tokens(tokenizer._tgt_lang) | ||
|
|
||
| return tokenizer |
There was a problem hiding this comment.
I unfortunately had to add this to pass test, otherwise, it won't use set_src_lang_special_tokens and set_tgt_lang_special_tokens
There was a problem hiding this comment.
but it should be enough in the init no ?
There was a problem hiding this comment.
Well, it should but from_pretrained first call __init__, and then add special tokens, so the lang tokens are set to unk_token_id
There was a problem hiding this comment.
If the tokenizer fast is properly saved this should not happen (meaning the additional special tokens are added after only if you don't have a fast tokenizer file save. Otherwise it's directly passed. This is something I gotta take care in the intiialization (meaning yes you should be able to set the target language normally without having to call this
There was a problem hiding this comment.
I'm quite sure this happens during the regular test suite and not the integration tests though!
| pass | ||
|
|
||
| @unittest.skip( | ||
| reason="Expected missing keys serve when using SeamlessM4TForXXX.from_pretrained from a checkpoint saved by SeamlessM4TModel.save_pretrained." |
There was a problem hiding this comment.
Well, for example, I've set SeamlessM4TForSpeechToSpeech keys to ignore like this:
_keys_to_ignore_on_load_missing = ["text_encoder"]
But the model doesn't have a text_encoder, it is used to make it compatible with loading weights from a SeamlessM4TModel checkpoint without warnings.
| pass | ||
|
|
||
| @unittest.skip( | ||
| reason="SeamlessM4TModel has actually a bigger architecture than seamlessM4T models for specific tasks." |
There was a problem hiding this comment.
The base model is SeamlessM4TModel, but it has actually more components than the non-base models, a.k.a the task-specific models
| docs/source/en/model_doc/roformer.md | ||
| docs/source/en/model_doc/rwkv.md | ||
| docs/source/en/model_doc/sam.md | ||
| docs/source/en/model_doc/seamless_m4t.md |
There was a problem hiding this comment.
Just slow I believe, I'll move it to the right file than
ArthurZucker
left a comment
There was a problem hiding this comment.
Looks a lot better indeed! Left a few small nits
| # fairseq | '<pad>' | '<unk>' | '<s>' | '</s>' | 'an' | 'en' | '▁d' | 'er' | 'in' | '▁s' | ||
|
|
||
| # Mimic fairseq token-to-id alignment for the first 4 token | ||
| self.fairseq_tokens_to_ids = {pad_token: 0, unk_token: 1, bos_token: 2, eos_token: 3} |
There was a problem hiding this comment.
| self.fairseq_tokens_to_ids = {pad_token: 0, unk_token: 1, bos_token: 2, eos_token: 3} | |
| self._added_tokens_decoder = {AddedToken(pad_token): 0, AddedToken(unk_token): 1, AddedToken(bos_token): 2, AddedToken(eos_token): 3} |
| if token in self.fairseq_tokens_to_ids: | ||
| return self.fairseq_tokens_to_ids[token] | ||
| spm_id = self.sp_model.PieceToId(token) |
There was a problem hiding this comment.
this should not be needed. The tokens that are part of the added tokens decoder do not reach this part
| inputs = self(raw_inputs, add_special_tokens=True, return_tensors=return_tensors, **extra_kwargs) | ||
| if "__" not in tgt_lang: | ||
| tgt_lang = f"__{tgt_lang}__" | ||
| tgt_lang_id = self.convert_tokens_to_ids(tgt_lang) |
There was a problem hiding this comment.
convert_tokens_to_ids calls super. convert_tokens_to_ids_with_added_voc so no worries if you don't have the fairseq token id
| self._convert_id_to_token(i): i for i in range(self.fairseq_offset, self.vocab_size + self.fairseq_offset) | ||
| } | ||
| # need to ensure that fairseq_tokens_to_id are placed at the beginning of the vocabulary | ||
| vocab.update(self.fairseq_tokens_to_ids) |
There was a problem hiding this comment.
| vocab.update(self.fairseq_tokens_to_ids) |
|
|
||
| def get_vocab(self): | ||
| vocab = { | ||
| self._convert_id_to_token(i): i for i in range(self.fairseq_offset, self.vocab_size + self.fairseq_offset) |
There was a problem hiding this comment.
| self._convert_id_to_token(i): i for i in range(self.fairseq_offset, self.vocab_size + self.fairseq_offset) | |
| self.convert_ids_to_tokens(i): i for i in range(self.fairseq_offset, self.vocab_size + self.fairseq_offset) |
| def _tokenize(self, text: str) -> List[str]: | ||
| return self.sp_model.encode(text, out_type=str) |
There was a problem hiding this comment.
(by that I mean if the sentencepiece model allways adds an extra space after the special tokens!
| @classmethod | ||
| def _from_pretrained( | ||
| cls, | ||
| resolved_vocab_files, | ||
| pretrained_model_name_or_path, | ||
| init_configuration, | ||
| *init_inputs, | ||
| token=None, | ||
| cache_dir=None, | ||
| local_files_only=False, | ||
| _commit_hash=None, | ||
| _is_local=False, | ||
| **kwargs, | ||
| ): | ||
| tokenizer = super()._from_pretrained( | ||
| resolved_vocab_files, | ||
| pretrained_model_name_or_path, | ||
| init_configuration, | ||
| *init_inputs, | ||
| token=token, | ||
| cache_dir=cache_dir, | ||
| local_files_only=local_files_only, | ||
| _commit_hash=_commit_hash, | ||
| _is_local=_is_local, | ||
| **kwargs, | ||
| ) | ||
|
|
||
| # ensure also set after from pretrained | ||
| tokenizer.set_src_lang_special_tokens(tokenizer._src_lang) | ||
| tokenizer.set_tgt_lang_special_tokens(tokenizer._tgt_lang) | ||
|
|
||
| return tokenizer |
There was a problem hiding this comment.
but it should be enough in the init no ?
|
Thanks for the quick review, I'll address most your comments this morning. I still have this pending questions if you have time: |
|
Hey @ArthurZucker, your suggestions made it even cleaner! I've also added some copied from statements! Thanks for that! Do you think you can review a bit more thoroughly the modeling code soon ? |
|
on it tomorrow! |
ArthurZucker
left a comment
There was a problem hiding this comment.
Overall looks good to me. THanks for the huge effort!
| } | ||
|
|
||
|
|
||
| class SeamlessM4TConfig(PretrainedConfig): |
There was a problem hiding this comment.
No problem thanks for explaining! 🤗
|
|
||
|
|
||
| def _load_hf_config(model_type="medium"): | ||
| if model_type == "medium": |
There was a problem hiding this comment.
ok, wondering for potential futur models but we'll see then!
| Meta SeamlessM4T is made of 8 main components: | ||
| - speech_encoder (#1) and speech_encoder_frontend (#2) | ||
| - t2u_model (#3) | ||
| - text_encoder (#4) and text_encoder_frontend (#5) | ||
| - text_decoder (#6) [and text_decoder_frontend (#5) = equals to text_encoder_frontend] | ||
| - final_proj (#7) | ||
| - vocoder (#8) |
| frame_length=400, | ||
| hop_length=160, | ||
| fft_length=512, | ||
| power=2.0, | ||
| center=False, | ||
| preemphasis=0.97, | ||
| mel_filters=self.mel_filters, | ||
| log_mel="log", | ||
| mel_floor=1.192092955078125e-07, | ||
| remove_dc_offset=True, |
| raise ValueError( | ||
| "`input_ids`,`input_features`, `inputs_embeds` and `encoder_outputs` are all empty. Make sure at least one of them is not." | ||
| ) | ||
| elif input_features is not None: |
|
Thanks for the last review @ArthurZucker! |
What does this PR do?
Meta recently introduced Seamless M4T, a collection of models designed to provide high quality translation, allowing people from different linguistic communities to communicate effortlessly through speech and text.
SeamlessM4T supports multiple audio and/or translation tasks, namely S2TT, S2ST, T2TT, T2ST, where the last T stands for translation.
In other words, this model seamlessly supports audio|text to translated audio|text.
SeamlessM4T weights are already available on the hub (large and medium) and the code is available on the seamless_communication git repo.
In terms of architecture, and after having discussed with @sanchit-gandhi, I've came up with 4 differents models for the 4 tasks and one model that can do each task.
I've been working on the integration for a couple of days already. At the moment, the converting script is more or less ready and the different models can generate.
Here is a TODO of what's left to be done:
cc @sanchit-gandhi and @ArthurZucker !