Improve modular converter
Author: Cyrilvallez
Pull request: yes

# What does this PR do?

This improves the modular file converter.  

- support for top-level functions newly defined in the `modular_xxx.py` code and used in a class inheriting from another model class without the function dependency (and recursively adding all other top-level functions that may be needed for that function)
e.g. 
```py
def foo():
    pass
 
class RobertaEmbeddings(BertEmbeddings):
   
    def forward(...)
        foo()
        pass
```
would currently not import `foo()` in the modeling if `foo` is not in the `modeling_bert.py` file.

- support to remove functions that are not needed anywhere but are a dependency of a class somewhere (and thus are wrongly imported at this time)
e.g.
```py
class RobertaPreTrainedModel(PreTrainedModel):
    """
    An abstract class to handle weights initialization and a simple interface for downloading and loading pretrained
    models.
    """

    config_class = RobertaConfig
    base_model_prefix = "roberta"
    supports_gradient_checkpointing = True
    _no_split_modules = ["RobertaEmbeddings", "RobertaSelfAttention", "RobertaSdpaSelfAttention"]
    _supports_sdpa = True

    def _init_weights(self, module):
        """Initialize the weights"""
        if isinstance(module, nn.Linear):
            # Slightly different from the TF version which uses truncated_normal for initialization
            # cf https://github.com/pytorch/pytorch/pull/5617
            module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
            if module.bias is not None:
                module.bias.data.zero_()
        elif isinstance(module, nn.Embedding):
            module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
            if module.padding_idx is not None:
                module.weight.data[module.padding_idx].zero_()
        elif isinstance(module, nn.LayerNorm):
            module.bias.data.zero_()
            module.weight.data.fill_(1.0)


class RobertaModel(RobertaPreTrainedModel, BertModel):
    def __init__(self, config, add_pooling_layer=True):
        super().__init__(config)
        self.embeddings = RobertaEmbeddings(config)
        self.encoder = RobertaEncoder(config)
        self.pooler = RobertaPooler(config) if add_pooling_layer else None
        # Initialize weights and apply final processing
        self.post_init()
```
would currently import the function `load_tf_weights_in_bert` because `BertModel` has dependency `BertPreTrainedModel` in which the function is used, but here we did not redefine `RobertaPreTrainedModel` based on `BertPreTrainedModel` mostly because this given class attribute (the function) was not needed.

- support to avoid rewriting some top-level variables such as `_CHECKPOINT_FOR_DOC` which should not be changed as part of the graph dependency
- add the correct file-name in the header warning

cc @ArthurZucker 

Comments:
The docs for this PR live [here](https://moon-ci-docs.huggingface.co/docs/transformers/pr_33991). All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

- added support to automatically remove classes that are wrongly added as part of the dependencies (in addition to functions). This case appear if e.g. inheriting from a `LlamaModel` having dependency `LlamaRMSNorm`, but we redefined the `.norm` attribute as a `nn.LayerNorm`, thus not using the RMSNorm

smart use of deque - need that functionality, looking forward to it :D