BERT, XLM-RoBERTa and ModernBERT
The text encoders of transformers: BertModel (MiniLM, the BGE and GTE embedding models, ...), XLMRobertaModel (the multilingual E5 models, BGE-M3 and the BGE rerankers' backbone, ...) and ModernBertModel (ModernBERT and the models built on it). They map the token indices of their processor, the TextProcessor of the repository, to the hidden states of the tokens; a head on top gives the logits of a classifier, such as a cross-encoder that ranks passages, or of a masked language model.
using Metalhead, HuggingFaceTokenizers
model = create_model("answerdotai/ModernBERT-base") # a ModernBertForMaskedLM
proc = create_processor("answerdotai/ModernBERT-base")
inputs = proc(["The capital of France is [MASK].", "Dogs bark."])
hidden = forward_features(model, inputs) # 768 × seq_len × 2: its ModernBertModel's output
logits = model(inputs) # 50368 × seq_len × 2
reranker = create_model("BAAI/bge-reranker-base")
proc = create_processor("BAAI/bge-reranker-base")
inputs = proc(["what is a panda?", "what is a panda?"];
text_pair = ["The giant panda is a bear native to China.", "Paris is the capital of France."])
reranker(inputs) # 1 × 2 scores, the first higherThe models take input_ids and the attention_mask that excludes the padding of a batch (and BERT's token_type_ids), or the output of the processor as it is. The processors of these repositories return the keys of transformers' tokenizers: token_type_ids too for BERT's, and with text_pair the two texts of a cross-encoder joined by the tokenizer's template. Pooling the hidden states into one embedding per text, as sentence-transformers does, is not part of these models. The repositories of embedding models (all-MiniLM-L6-v2, bge-small-en-v1.5, multilingual-e5-base, gte-modernbert-base, ...) have a modules.json: create_model builds the sentence-transformers model over them (see Sentence transformers), and create_processor has no processor for it. Their BertModel, XLMRobertaModel or ModernBertModel is the one that the config.json names, which the references of these repositories validate.
Models
Metalhead.Transformers.TextEncoder — Type
TextEncoderThe base models of the text encoders BERT, XLM-RoBERTa and ModernBERT, which map token indices input_ids (seq_len, batch), 1-based, to the hidden states of each token: BertModel, XLMRobertaModel and ModernBertModel.
(model::TextEncoder)(input_ids; attention_mask = nothing, token_type_ids = nothing)
(model::TextEncoder)(inputs::NamedTuple)The last_hidden_state of transformers' model, of size (hidden_size, seq_len, batch), the hidden states of each token after the last layer (and the final norm of ModernBERT), as the decoder models return theirs. Every token attends to every other, in both directions. A batch of sequences of different lengths, padded on the right, takes the tokenizer's attention_mask (seqlen, batch), which keeps the padding out of the keys; the outputs at the positions of the padding are not meaningful. `tokentypeids` (seqlen, batch) are the segment ids of transformers, 0 or 1, and default to 0 (ModernBERT takes none). A vector input_ids is a single sequence, whose output has no batch dimension. The output of the processor of a repository, a TextProcessor, can replace all of them: model(proc(texts)).
forward_features is the same call, and forward_intermediates returns the output of each layer (transformers' hidden_states without the embeddings; ModernBERT's last one is normed only with norm = true), with the keyword arguments of the vision models' (indices, stop_early, intermediates_only) and those of the model. feature_info gives the module of each layer. The BERT and XLM-RoBERTa models also have transformers' pooler_output (hiddensize, batch), the first token through the dense layer and tanh of the pooler: `forwardhead(model, hiddenstates), which errors for a model built without a pooler (addpooling_layer = false`).
Metalhead.Transformers.BertModel — Type
BertModeltransformers' BertModel, the encoder of BERT (Devlin et al., 2018) and of the many models that share its architecture (MiniLM, the BGE and GTE embedding models, ELECTRA's and cross-encoders' backbones, ...), which bert_model builds. It is a TextEncoder: see it for the inputs and outputs.
The tokens are embedded by the sum of their word, absolute position and token type embeddings, normalised, and go through num_hidden_layers post-norm layers of bidirectional self-attention and a feed-forward network.
using Metalhead, HuggingFaceTokenizers
model = create_model("cross-encoder/ms-marco-MiniLM-L6-v2") # a BertForSequenceClassification
proc = create_processor("cross-encoder/ms-marco-MiniLM-L6-v2")
inputs = proc("how many people live in Berlin?"; text_pair = "Berlin has 3.5 million inhabitants.")
hidden = model.bert(inputs) # 384 × seq_len: the hidden states of its BertModel
pooled = forward_head(model.bert, hidden) # 384: the pooler output```
Metalhead.Transformers.BertForSequenceClassification — Type
BertForSequenceClassificationtransformers' BertForSequenceClassification, a BertModel with a linear layer on its pooled output, as the cross-encoders for ranking and the classification models of BERT are, which bert_for_sequence_classification builds.
(model::BertForSequenceClassification)(input_ids; attention_mask = nothing,
token_type_ids = nothing)
(model::BertForSequenceClassification)(inputs::NamedTuple)The logits (numlabels, batch) of the token indices `inputids(seq_len, batch), or of the output of the processor of the repository. A vector is one sequence, with logits(numlabels,). [forwardfeatures`](@ref) returns the hidden states of the base model.
Metalhead.Transformers.XLMRobertaModel — Type
XLMRobertaModeltransformers' XLMRobertaModel, the multilingual encoder of XLM-RoBERTa (Conneau et al., 2019) and of the models built on it (BGE-M3 and the BGE rerankers, ...), which xlm_roberta_model builds. It is a TextEncoder: see it for the inputs and outputs.
It has the layers of BertModel and differs in its position embeddings: the positions count the tokens that are not the padding token (pad_token_id, 1), from pad_token_id + 1, and the padding has the position pad_token_id. They follow the token indices, not the attention_mask. A sequence holds at most max_position_embeddings - pad_token_id - 1 tokens (512 of the 514 of XLM-RoBERTa).
Metalhead.Transformers.XLMRobertaForSequenceClassification — Type
XLMRobertaForSequenceClassificationtransformers' XLMRobertaForSequenceClassification, an XLMRobertaModel without a pooler, with a classification head on the hidden states of its first token (<s>): a dense layer, tanh and a linear layer. The BGE rerankers are such models, with one label, the relevance of the second text of a pair to the first. xlm_roberta_for_sequence_classification builds it.
(model::XLMRobertaForSequenceClassification)(input_ids; attention_mask = nothing,
token_type_ids = nothing)
(model::XLMRobertaForSequenceClassification)(inputs::NamedTuple)The logits (numlabels, batch) of the token indices `inputids(seq_len, batch), or of the output of the processor of the repository. A vector is one sequence, with logits(numlabels,). [forwardfeatures`](@ref) returns the hidden states of the base model.
Metalhead.Transformers.ModernBertModel — Type
ModernBertModeltransformers' ModernBertModel, the encoder of ModernBERT (Warner et al., 2024) and of the models built on it (GTE-ModernBERT, ModernColBERT, ...), which modernbert_model builds. It is a TextEncoder: see it for the inputs and outputs. It takes no token_type_ids and has no pooler.
The tokens are embedded and normalised, and go through pre-norm layers with rotary position embeddings, bias-free linear layers, a gated feed-forward network (GeGLU) and no norm before the first attention. One layer in global_attn_every_n_layers (3) attends to all tokens, with a rotary base of 160 000, and the others only to the tokens within local_attention ÷ 2 (64) of the query, with a base of 10 000.
Metalhead.Transformers.ModernBertForMaskedLM — Type
ModernBertForMaskedLMtransformers' ModernBertForMaskedLM, a ModernBertModel with the head of its masked language modeling, which modernbert_for_masked_lm builds, and the architecture of answerdotai/ModernBERT-base and -large. Its decoder is tied to the token embeddings.
(model::ModernBertForMaskedLM)(input_ids; attention_mask = nothing)
(model::ModernBertForMaskedLM)(inputs::NamedTuple)The logits (vocabsize, seqlen, batch) of the token indices input_ids, of the tokens that were masked or not. A vector is one sequence. forward_features returns the hidden states of the base model.
Metalhead.Transformers.ModernBertForSequenceClassification — Type
ModernBertForSequenceClassificationtransformers' ModernBertForSequenceClassification, a ModernBertModel whose pooled hidden states (those of the first token, or their mean over the tokens that attention_mask keeps, as classifier_pooling says) go through a prediction head and a linear layer, as the rerankers built on ModernBERT do. modernbert_for_sequence_classification builds it.
(model::ModernBertForSequenceClassification)(input_ids; attention_mask = nothing)
(model::ModernBertForSequenceClassification)(inputs::NamedTuple)The logits (numlabels, batch) of the token indices `inputids(seq_len, batch), or of the output of the processor of the repository. A vector is one sequence, with logits(numlabels,). [forwardfeatures`](@ref) returns the hidden states of the base model.
Builders
create_model calls these with the fields of the repository's config.json.
Metalhead.Transformers.bert_model — Function
bert_model(; vocab_size = 30522, hidden_size = 768, num_hidden_layers = 12,
num_attention_heads = 12, intermediate_size = 3072, hidden_act = "gelu",
hidden_dropout_prob = 0.1, attention_probs_dropout_prob = 0.1,
max_position_embeddings = 512, type_vocab_size = 2, initializer_range = 0.02,
layer_norm_eps = 1e-12, add_pooling_layer = true)Port of transformers' BertModel (see BertModel for its inputs and outputs), built from the fields of its BertConfig with the same names and defaults. The decoder (is_decoder, add_cross_attention) is not supported. The activations are "gelu" (the exact one), "gelu_new" and "gelu_pytorch_tanh" (the tanh approximation), "relu", "silu", "swish" and "quick_gelu". add_pooling_layer = false builds a model without a pooler, for checkpoints that don't have one (transformers initialises it at random for those).
Metalhead.Transformers.bert_for_sequence_classification — Function
bert_for_sequence_classification(; vocab_size = 30522, hidden_size = 768, ...,
classifier_dropout = nothing, id2label = nothing, num_labels = nothing)Port of transformers' BertForSequenceClassification (see BertForSequenceClassification), built from the fields of its BertConfig (see bert_model) with the same names and defaults. The number of labels is the length of id2label, else num_labels, else 2; classifier_dropout defaults to hidden_dropout_prob.
Metalhead.Transformers.xlm_roberta_model — Function
xlm_roberta_model(; vocab_size = 30522, hidden_size = 768, num_hidden_layers = 12,
num_attention_heads = 12, intermediate_size = 3072, hidden_act = "gelu",
hidden_dropout_prob = 0.1, attention_probs_dropout_prob = 0.1,
max_position_embeddings = 512, type_vocab_size = 2, initializer_range = 0.02,
layer_norm_eps = 1e-12, pad_token_id = 1, add_pooling_layer = true)Port of transformers' XLMRobertaModel (see XLMRobertaModel for its inputs and outputs), built from the fields of its XLMRobertaConfig with the same names and defaults (the checkpoints set max_position_embeddings = 514 and type_vocab_size = 1). See bert_model for the activations and the options. The decoder is not supported.
Metalhead.Transformers.xlm_roberta_for_sequence_classification — Function
xlm_roberta_for_sequence_classification(; vocab_size = 30522, hidden_size = 768, ...,
classifier_dropout = nothing, id2label = nothing, num_labels = nothing)Port of transformers' XLMRobertaForSequenceClassification (see XLMRobertaForSequenceClassification), built from the fields of its XLMRobertaConfig (see xlm_roberta_model) with the same names and defaults. The number of labels is the length of id2label, else num_labels, else 2; classifier_dropout defaults to hidden_dropout_prob.
Metalhead.Transformers.modernbert_model — Function
modernbert_model(; vocab_size = 50368, hidden_size = 768, intermediate_size = 1152,
num_hidden_layers = 22, num_attention_heads = 12, hidden_activation = "gelu",
max_position_embeddings = 8192, initializer_range = 0.02, norm_eps = 1e-5,
norm_bias = false, attention_bias = false, attention_dropout = 0.0,
layer_types = nothing, rope_parameters = nothing, local_attention = 128,
embedding_dropout = 0.0, mlp_bias = false, mlp_dropout = 0.0, ...)Port of transformers' ModernBertModel (see ModernBertModel for its inputs and outputs), built from the fields of its ModernBertConfig with the same names and defaults, and the keys of the older configurations that it still reads: global_attn_every_n_layers (3), which sets the layer_types, global_rope_theta (160 000) and local_rope_theta (10 000), which set the rope_theta of the rope_parameters of the two layer types, and rope_scaling, which updates both. The rotary embeddings are the default one, or "linear" or "llama3".
Metalhead.Transformers.modernbert_for_masked_lm — Function
modernbert_for_masked_lm(; ..., decoder_bias = true, classifier_bias = false,
classifier_activation = "gelu", tie_word_embeddings = true)Port of transformers' ModernBertForMaskedLM (see ModernBertForMaskedLM), built from the fields of its ModernBertConfig (see modernbert_model) with the same names and defaults. sparse_prediction only matters when training.
Metalhead.Transformers.modernbert_for_sequence_classification — Function
modernbert_for_sequence_classification(; ..., classifier_pooling = "cls",
classifier_dropout = 0.0, classifier_bias = false, classifier_activation = "gelu",
id2label = nothing, num_labels = nothing)Port of transformers' ModernBertForSequenceClassification (see ModernBertForSequenceClassification), built from the fields of its ModernBertConfig (see modernbert_model) with the same names and defaults. The number of labels is the length of id2label, else num_labels, else 2.