Feature Extraction
sentence-transformers
Safetensors
English
slideon
sparse
custom-code
sparse-autoencoder
sparse-retrieval
custom_code
🇪🇺 Region: EU
Instructions to use lightonai/SlideOn-SAE with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- sentence-transformers
How to use lightonai/SlideOn-SAE with sentence-transformers:
from sentence_transformers import SentenceTransformer model = SentenceTransformer("lightonai/SlideOn-SAE", trust_remote_code=True) sentences = [ "The weather is lovely today.", "It's so sunny outside!", "He drove to the stadium." ] embeddings = model.encode(sentences) similarities = model.similarity(embeddings, embeddings) print(similarities.shape) # [3, 3] - Notebooks
- Google Colab
- Kaggle
Commit ·
9372da2
0
Parent(s):
Initial release
Browse files- .gitattributes +35 -0
- README.md +99 -0
- config.json +120 -0
- config_sentence_transformers.json +14 -0
- model.safetensors +3 -0
- modeling_slideon.py +219 -0
- modules.json +8 -0
- slideon.py +96 -0
- tokenizer.json +0 -0
- tokenizer_config.json +24 -0
.gitattributes
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
library_name: sentence-transformers
|
| 3 |
+
pipeline_tag: feature-extraction
|
| 4 |
+
base_model: lightonai/DenseOn
|
| 5 |
+
language:
|
| 6 |
+
- en
|
| 7 |
+
datasets:
|
| 8 |
+
- lightonai/embeddings-fine-tuning-filtered-en
|
| 9 |
+
tags:
|
| 10 |
+
- sentence-transformers
|
| 11 |
+
- custom-code
|
| 12 |
+
- sparse-autoencoder
|
| 13 |
+
- sparse-retrieval
|
| 14 |
+
---
|
| 15 |
+
<div align="center">
|
| 16 |
+
<img src="https://cdn-uploads.huggingface.co/production/uploads/67e184d667350657a7d68aac/5PySy2cTawrkFWwaqNtDA.png" alt="SlideOn: a puppy sliding through a library with a bag of glowing stars" width="512" style="max-width: 100%; height: auto;">
|
| 17 |
+
|
| 18 |
+
[](https://lighton.ai)
|
| 19 |
+
[](https://www.linkedin.com/company/lighton/)
|
| 20 |
+
[](https://x.com/LightOnIO)
|
| 21 |
+
|
| 22 |
+
[SlideOn](https://huggingface.co/lightonai/SlideOn) | [mSlideOn](https://huggingface.co/lightonai/mSlideOn) | 📚 [Collection](https://huggingface.co/collections/lightonai/slideon-and-mslideon)
|
| 23 |
+
|
| 24 |
+
📝 [Blogpost](https://huggingface.co/blog/lightonai/slideon-mslideon) | 🛠️ [Training and Evaluation](https://github.com/lightonai/slideon-mslideon/)
|
| 25 |
+
|
| 26 |
+
</div>
|
| 27 |
+
|
| 28 |
+
<h1 align="center">SlideOn-SAE</h1>
|
| 29 |
+
<h3 align="center">English Sparse Autoencoder by LightOn</h3>
|
| 30 |
+
|
| 31 |
+
> 🎯 **TL;DR**: The pretrained sparse autoencoder used to initialize **[SlideOn](https://huggingface.co/lightonai/SlideOn)**. It learns **32,768 latent features** from frozen DenseOn token representations and provides a starting point for supervised sparse retrieval fine-tuning. Use the final SlideOn checkpoint for the retrieval results reported in our blog.
|
| 32 |
+
|
| 33 |
+
## Model Details
|
| 34 |
+
|
| 35 |
+
SlideOn-SAE maps L2-normalized DenseOn token representations to their top-32 latent activations, followed by ReLU. Its decoder reconstructs the original token representations during SAE pretraining. For retrieval, the included adapter max-pools token activations into one sparse vector per query or document.
|
| 36 |
+
|
| 37 |
+
| Property | Value |
|
| 38 |
+
| --- | --- |
|
| 39 |
+
| Backbone | [DenseOn](https://huggingface.co/lightonai/DenseOn) / ModernBERT-base |
|
| 40 |
+
| Training stage | SAE pretraining, before supervised retrieval fine-tuning |
|
| 41 |
+
| Token representation | 768 dimensions, L2-normalized before sparse encoding |
|
| 42 |
+
| Latent dimensionality | 32,768 learned features |
|
| 43 |
+
| Token sparsity | Top-32 latent selection followed by ReLU |
|
| 44 |
+
| Sequence pooling | Maximum over token activations |
|
| 45 |
+
| Similarity function | Dot product |
|
| 46 |
+
| Language | English |
|
| 47 |
+
|
| 48 |
+
The checkpoint includes the DenseOn backbone, SAE encoder, and original SAE decoder in a single `model.safetensors` file. The model and tokenizer load directly from this repository.
|
| 49 |
+
|
| 50 |
+
## Training Data and Recipe
|
| 51 |
+
|
| 52 |
+
See our blog post for [training data](https://huggingface.co/blog/lightonai/slideon-mslideon#training-data), [SAE pretraining](https://huggingface.co/blog/lightonai/slideon-mslideon#sparse-autoencoder-pretraining), and [supervised retrieval fine-tuning](https://huggingface.co/blog/lightonai/slideon-mslideon#supervised-fine-tuning-for-sparse-retrieval). Training code and the recorded training configuration are available in the [code repository](https://github.com/lightonai/slideon-mslideon/).
|
| 53 |
+
|
| 54 |
+
## Usage
|
| 55 |
+
|
| 56 |
+
Install the supported library versions:
|
| 57 |
+
|
| 58 |
+
```bash
|
| 59 |
+
pip install -U "sentence-transformers>=6.1,<6.2" "transformers>=5.3,<6"
|
| 60 |
+
```
|
| 61 |
+
|
| 62 |
+
Load the SAE initialization and encode text into sparse vectors:
|
| 63 |
+
|
| 64 |
+
```python
|
| 65 |
+
from sentence_transformers import SparseEncoder
|
| 66 |
+
|
| 67 |
+
model = SparseEncoder("lightonai/SlideOn-SAE", trust_remote_code=True)
|
| 68 |
+
|
| 69 |
+
query_embeddings = model.encode_query(["What is sparse retrieval?"])
|
| 70 |
+
document_embeddings = model.encode_document([
|
| 71 |
+
"Sparse retrieval uses inverted indexes to search sparse vectors."
|
| 72 |
+
])
|
| 73 |
+
|
| 74 |
+
print(query_embeddings.shape, document_embeddings.shape)
|
| 75 |
+
# torch.Size([1, 32768]) torch.Size([1, 32768])
|
| 76 |
+
```
|
| 77 |
+
|
| 78 |
+
The model loaded above can also be fine-tuned with Sentence Transformers' `SparseEncoderTrainer`. Our [code repository](https://github.com/lightonai/slideon-mslideon/) provides the custom retrieval loss and training scripts used for our fine-tuning recipe.
|
| 79 |
+
|
| 80 |
+
## Related Checkpoints
|
| 81 |
+
|
| 82 |
+
| Model | Description |
|
| 83 |
+
| --- | --- |
|
| 84 |
+
| **[SlideOn-SAE](https://huggingface.co/lightonai/SlideOn-SAE)** *(this model)* | DenseOn-based SAE initialization |
|
| 85 |
+
| [SlideOn](https://huggingface.co/lightonai/SlideOn) | English sparse retriever after supervised fine-tuning |
|
| 86 |
+
| [mSlideOn-SAE](https://huggingface.co/lightonai/mSlideOn-SAE) | mLateOn-based multilingual SAE initialization |
|
| 87 |
+
| [mSlideOn](https://huggingface.co/lightonai/mSlideOn) | Multilingual sparse retriever after supervised fine-tuning |
|
| 88 |
+
|
| 89 |
+
## Citation
|
| 90 |
+
|
| 91 |
+
```bibtex
|
| 92 |
+
@misc{moura2026slideon,
|
| 93 |
+
author = {Moura Junior, Paulo Roberto and Sourty, Raphaël},
|
| 94 |
+
title = {{SlideOn} \& {mSlideOn}: Sparsified late-interaction and dense retrievers},
|
| 95 |
+
year = {2026},
|
| 96 |
+
howpublished = {Hugging Face Blog},
|
| 97 |
+
url = {https://huggingface.co/blog/lightonai/slideon-mslideon}
|
| 98 |
+
}
|
| 99 |
+
```
|
config.json
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"SlideOnModel"
|
| 4 |
+
],
|
| 5 |
+
"auto_map": {
|
| 6 |
+
"AutoConfig": "modeling_slideon.SlideOnConfig",
|
| 7 |
+
"AutoModel": "modeling_slideon.SlideOnModel"
|
| 8 |
+
},
|
| 9 |
+
"backbone_config": {
|
| 10 |
+
"architectures": [
|
| 11 |
+
"ModernBertModel"
|
| 12 |
+
],
|
| 13 |
+
"attention_bias": false,
|
| 14 |
+
"attention_dropout": 0.0,
|
| 15 |
+
"bos_token_id": 50281,
|
| 16 |
+
"classifier_activation": "gelu",
|
| 17 |
+
"classifier_bias": false,
|
| 18 |
+
"classifier_dropout": 0.0,
|
| 19 |
+
"classifier_pooling": "mean",
|
| 20 |
+
"cls_token_id": 50281,
|
| 21 |
+
"decoder_bias": true,
|
| 22 |
+
"deterministic_flash_attn": false,
|
| 23 |
+
"dtype": "float32",
|
| 24 |
+
"embedding_dropout": 0.0,
|
| 25 |
+
"eos_token_id": 50282,
|
| 26 |
+
"global_attn_every_n_layers": 3,
|
| 27 |
+
"gradient_checkpointing": false,
|
| 28 |
+
"hidden_activation": "gelu",
|
| 29 |
+
"hidden_size": 768,
|
| 30 |
+
"initializer_cutoff_factor": 2.0,
|
| 31 |
+
"initializer_range": 0.02,
|
| 32 |
+
"intermediate_size": 1152,
|
| 33 |
+
"layer_norm_eps": 1e-05,
|
| 34 |
+
"layer_types": [
|
| 35 |
+
"full_attention",
|
| 36 |
+
"sliding_attention",
|
| 37 |
+
"sliding_attention",
|
| 38 |
+
"full_attention",
|
| 39 |
+
"sliding_attention",
|
| 40 |
+
"sliding_attention",
|
| 41 |
+
"full_attention",
|
| 42 |
+
"sliding_attention",
|
| 43 |
+
"sliding_attention",
|
| 44 |
+
"full_attention",
|
| 45 |
+
"sliding_attention",
|
| 46 |
+
"sliding_attention",
|
| 47 |
+
"full_attention",
|
| 48 |
+
"sliding_attention",
|
| 49 |
+
"sliding_attention",
|
| 50 |
+
"full_attention",
|
| 51 |
+
"sliding_attention",
|
| 52 |
+
"sliding_attention",
|
| 53 |
+
"full_attention",
|
| 54 |
+
"sliding_attention",
|
| 55 |
+
"sliding_attention",
|
| 56 |
+
"full_attention"
|
| 57 |
+
],
|
| 58 |
+
"local_attention": 128,
|
| 59 |
+
"max_position_embeddings": 8192,
|
| 60 |
+
"mlp_bias": false,
|
| 61 |
+
"mlp_dropout": 0.0,
|
| 62 |
+
"model_type": "modernbert",
|
| 63 |
+
"norm_bias": false,
|
| 64 |
+
"norm_eps": 1e-05,
|
| 65 |
+
"num_attention_heads": 12,
|
| 66 |
+
"num_hidden_layers": 22,
|
| 67 |
+
"pad_token_id": 50283,
|
| 68 |
+
"position_embedding_type": "absolute",
|
| 69 |
+
"repad_logits_with_grad": false,
|
| 70 |
+
"rope_parameters": {
|
| 71 |
+
"full_attention": {
|
| 72 |
+
"rope_theta": 160000.0,
|
| 73 |
+
"rope_type": "default"
|
| 74 |
+
},
|
| 75 |
+
"sliding_attention": {
|
| 76 |
+
"rope_theta": 10000.0,
|
| 77 |
+
"rope_type": "default"
|
| 78 |
+
}
|
| 79 |
+
},
|
| 80 |
+
"sep_token_id": 50282,
|
| 81 |
+
"sparse_pred_ignore_index": -100,
|
| 82 |
+
"sparse_prediction": false,
|
| 83 |
+
"tie_word_embeddings": true,
|
| 84 |
+
"vocab_size": 50368
|
| 85 |
+
},
|
| 86 |
+
"base_model": "lightonai/DenseOn",
|
| 87 |
+
"base_model_revision": "cb9947ebccb33862d24e3c7ca2edb25e51acd887",
|
| 88 |
+
"checkpoint_type": "sae",
|
| 89 |
+
"head_config": {
|
| 90 |
+
"d_lift": 0,
|
| 91 |
+
"d_model": 768,
|
| 92 |
+
"has_decoder": true,
|
| 93 |
+
"n_latents": 32768
|
| 94 |
+
},
|
| 95 |
+
"inference": {
|
| 96 |
+
"document_length": 8192,
|
| 97 |
+
"document_top_k": 0,
|
| 98 |
+
"head_chunk_size": 256,
|
| 99 |
+
"pooling": "max_relu",
|
| 100 |
+
"prompts": {
|
| 101 |
+
"document": "document: ",
|
| 102 |
+
"query": "query: "
|
| 103 |
+
},
|
| 104 |
+
"query_length": 8192,
|
| 105 |
+
"query_top_k": 0,
|
| 106 |
+
"score": "dot",
|
| 107 |
+
"token_k": 32
|
| 108 |
+
},
|
| 109 |
+
"model_type": "slideon",
|
| 110 |
+
"projection_configs": [],
|
| 111 |
+
"sae_revision": "669feba609eeb5d4ee59ef791679c7e393092677",
|
| 112 |
+
"sae_source": "lightonai/SlideOn-SAE",
|
| 113 |
+
"skip_token_ids": [],
|
| 114 |
+
"tokenizer_settings": {
|
| 115 |
+
"document_prefix": "",
|
| 116 |
+
"query_prefix": "",
|
| 117 |
+
"skiplist_words": []
|
| 118 |
+
},
|
| 119 |
+
"transformers_version": "5.3.0"
|
| 120 |
+
}
|
config_sentence_transformers.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"__version__": {
|
| 3 |
+
"pytorch": "2.14.1+cu130",
|
| 4 |
+
"sentence_transformers": "6.1.0",
|
| 5 |
+
"transformers": "5.19.0"
|
| 6 |
+
},
|
| 7 |
+
"default_prompt_name": null,
|
| 8 |
+
"model_type": "SparseEncoder",
|
| 9 |
+
"prompts": {
|
| 10 |
+
"document": "",
|
| 11 |
+
"query": ""
|
| 12 |
+
},
|
| 13 |
+
"similarity_fn_name": "dot"
|
| 14 |
+
}
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:81dde50d52aeadad52af09af3bb28905ff3c6c5c7b8a26421ca0e7b4a0ec5d6d
|
| 3 |
+
size 797925808
|
modeling_slideon.py
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Complete SlideOn model: Transformer, token projections, and sparse latent head."""
|
| 2 |
+
from __future__ import annotations
|
| 3 |
+
|
| 4 |
+
import torch
|
| 5 |
+
from torch.utils.checkpoint import checkpoint as activation_checkpoint
|
| 6 |
+
from transformers import AutoConfig, AutoModel, PretrainedConfig, PreTrainedModel
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class SlideOnConfig(PretrainedConfig):
|
| 10 |
+
model_type = "slideon"
|
| 11 |
+
sub_configs = {"backbone_config": AutoConfig}
|
| 12 |
+
|
| 13 |
+
def __init__(self, backbone_config=None, projection_configs=None, head_config=None,
|
| 14 |
+
inference=None, tokenizer_settings=None, skip_token_ids=None,
|
| 15 |
+
checkpoint_type="retrieval", **kwargs):
|
| 16 |
+
super().__init__(**kwargs)
|
| 17 |
+
if isinstance(backbone_config, dict):
|
| 18 |
+
backbone_config = dict(backbone_config)
|
| 19 |
+
model_type = backbone_config.pop("model_type", "modernbert")
|
| 20 |
+
backbone_config = AutoConfig.for_model(model_type, **backbone_config)
|
| 21 |
+
self.backbone_config = backbone_config or AutoConfig.for_model("modernbert")
|
| 22 |
+
self.projection_configs = projection_configs or []
|
| 23 |
+
self.head_config = head_config or dict(d_model=768, n_latents=32768, d_lift=0)
|
| 24 |
+
self.inference = inference or dict(
|
| 25 |
+
token_k=32, query_top_k=0, document_top_k=0,
|
| 26 |
+
query_length=8192, document_length=8192, head_chunk_size=2048,
|
| 27 |
+
prompts={"query": "", "document": ""}, pooling="max_relu", score="dot")
|
| 28 |
+
self.tokenizer_settings = tokenizer_settings or {}
|
| 29 |
+
self.skip_token_ids = skip_token_ids or []
|
| 30 |
+
self.checkpoint_type = checkpoint_type
|
| 31 |
+
if self.inference.get("pooling") != "max_relu" or self.inference.get("score") != "dot":
|
| 32 |
+
raise ValueError("SlideOn supports max_relu pooling and dot scoring")
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
class TokenProjection(torch.nn.Module):
|
| 36 |
+
"""The token-wise residual Dense layers used by mSlideOn."""
|
| 37 |
+
|
| 38 |
+
def __init__(self, config):
|
| 39 |
+
super().__init__()
|
| 40 |
+
self.config = config
|
| 41 |
+
self.linear = torch.nn.Linear(
|
| 42 |
+
config["in_features"], config["out_features"], bias=config["bias"]
|
| 43 |
+
)
|
| 44 |
+
self.use_residual = config.get("use_residual", False)
|
| 45 |
+
self.residual = None
|
| 46 |
+
if self.use_residual and config["in_features"] != config["out_features"]:
|
| 47 |
+
self.residual = torch.nn.Linear(
|
| 48 |
+
config["in_features"], config["out_features"], bias=False
|
| 49 |
+
)
|
| 50 |
+
if config["activation_function"] != "torch.nn.modules.linear.Identity":
|
| 51 |
+
raise ValueError("Unsupported projection activation")
|
| 52 |
+
|
| 53 |
+
def forward(self, tokens):
|
| 54 |
+
projected = self.linear(tokens)
|
| 55 |
+
if self.use_residual:
|
| 56 |
+
projected = projected + (
|
| 57 |
+
self.residual(tokens) if self.residual is not None else tokens
|
| 58 |
+
)
|
| 59 |
+
return projected
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
class LatentHead(torch.nn.Module):
|
| 63 |
+
def __init__(self, config):
|
| 64 |
+
super().__init__()
|
| 65 |
+
d_model, n_latents = config["d_model"], config["n_latents"]
|
| 66 |
+
d_lift = config.get("d_lift") or 0
|
| 67 |
+
self.W_enc = torch.nn.Parameter(torch.empty(d_lift or d_model, n_latents))
|
| 68 |
+
self.b_enc = torch.nn.Parameter(torch.zeros(n_latents))
|
| 69 |
+
self.b_dec = torch.nn.Parameter(torch.zeros(d_model))
|
| 70 |
+
self.gate_relu_phi = torch.nn.Parameter(torch.ones(n_latents))
|
| 71 |
+
self.lift = None
|
| 72 |
+
if d_lift:
|
| 73 |
+
hidden = config["hidden_dim"]
|
| 74 |
+
self.lift = torch.nn.Linear(d_model, d_lift, bias=False)
|
| 75 |
+
self.mlp = torch.nn.Sequential(
|
| 76 |
+
torch.nn.Linear(d_lift, hidden), torch.nn.ReLU(),
|
| 77 |
+
torch.nn.Linear(hidden, d_lift))
|
| 78 |
+
if config.get("has_decoder", False):
|
| 79 |
+
# Preserve the pretrained SAE decoder without optimizing it in retrieval SFT.
|
| 80 |
+
self.W_dec = torch.nn.Parameter(torch.empty(n_latents, d_model), requires_grad=False)
|
| 81 |
+
self.register_buffer("steps_since_fired", torch.zeros(n_latents, dtype=torch.long))
|
| 82 |
+
|
| 83 |
+
def forward(self, tokens):
|
| 84 |
+
centered = tokens - self.b_dec
|
| 85 |
+
if self.lift is not None:
|
| 86 |
+
lifted = self.lift(centered)
|
| 87 |
+
centered = lifted + self.mlp(lifted)
|
| 88 |
+
return centered @ self.W_enc + self.b_enc
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
class SlideOnModel(PreTrainedModel):
|
| 92 |
+
config_class = SlideOnConfig
|
| 93 |
+
base_model_prefix = "backbone"
|
| 94 |
+
_supports_sdpa = True
|
| 95 |
+
_supports_flash_attn = True
|
| 96 |
+
_no_split_modules = ["ModernBertEncoderLayer", "LatentHead", "TokenProjection"]
|
| 97 |
+
_keep_in_fp32_modules_strict = ["head"]
|
| 98 |
+
|
| 99 |
+
def __init__(self, config):
|
| 100 |
+
super().__init__(config)
|
| 101 |
+
config.backbone_config._attn_implementation = config._attn_implementation
|
| 102 |
+
self.backbone = AutoModel.from_config(config.backbone_config)
|
| 103 |
+
self.projections = torch.nn.ModuleList(
|
| 104 |
+
TokenProjection(item) for item in config.projection_configs)
|
| 105 |
+
self.head = LatentHead(config.head_config)
|
| 106 |
+
self.settings = config.inference
|
| 107 |
+
self.post_init()
|
| 108 |
+
|
| 109 |
+
def _init_weights(self, module):
|
| 110 |
+
if isinstance(module, LatentHead):
|
| 111 |
+
torch.nn.init.normal_(module.W_enc, std=0.02)
|
| 112 |
+
if hasattr(module, "W_dec"):
|
| 113 |
+
torch.nn.init.normal_(module.W_dec, std=0.02)
|
| 114 |
+
else:
|
| 115 |
+
super()._init_weights(module)
|
| 116 |
+
|
| 117 |
+
@classmethod
|
| 118 |
+
def from_pretrained(cls, *args, **kwargs):
|
| 119 |
+
result = super().from_pretrained(*args, **kwargs)
|
| 120 |
+
model = result[0] if isinstance(result, tuple) else result
|
| 121 |
+
# Match the original PyLate encoder's RoPE buffer precision.
|
| 122 |
+
model.backbone.to(dtype=model.backbone.dtype)
|
| 123 |
+
# Loading tensors can reset the decoder's requires_grad flag.
|
| 124 |
+
if hasattr(model.head, "W_dec"):
|
| 125 |
+
model.head.W_dec.requires_grad_(False)
|
| 126 |
+
return result
|
| 127 |
+
|
| 128 |
+
def get_embedding_dimension(self):
|
| 129 |
+
return self.config.head_config["n_latents"]
|
| 130 |
+
|
| 131 |
+
@staticmethod
|
| 132 |
+
def _task(task):
|
| 133 |
+
task = task or "document"
|
| 134 |
+
if task not in ("query", "document"):
|
| 135 |
+
raise ValueError("task must be 'query' or 'document'")
|
| 136 |
+
return task
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
def forward(self, input_ids, attention_mask, token_type_ids=None, task=None,
|
| 140 |
+
slideon_task=None, top_k=None, token_k=None, **kwargs):
|
| 141 |
+
features = {"input_ids": input_ids, "attention_mask": attention_mask}
|
| 142 |
+
if slideon_task is not None or task is not None:
|
| 143 |
+
features["slideon_task"] = slideon_task or task
|
| 144 |
+
if token_type_ids is not None:
|
| 145 |
+
features["token_type_ids"] = token_type_ids
|
| 146 |
+
task = self._task(task or features.get("slideon_task"))
|
| 147 |
+
if features.get("slideon_task", task) != task:
|
| 148 |
+
raise ValueError("Preprocessing and forward tasks must match")
|
| 149 |
+
n_latents = self.get_embedding_dimension()
|
| 150 |
+
cap = self.settings[task + "_top_k"] if top_k is None else top_k
|
| 151 |
+
k = self.settings["token_k"] if token_k is None else token_k
|
| 152 |
+
if not isinstance(cap, int) or not 0 <= cap <= n_latents:
|
| 153 |
+
raise ValueError(f"top_k must be an integer between 0 and {n_latents}")
|
| 154 |
+
if not isinstance(k, int) or not 1 <= k <= n_latents:
|
| 155 |
+
raise ValueError(f"token_k must be an integer between 1 and {n_latents}")
|
| 156 |
+
model_inputs = {
|
| 157 |
+
key: features[key]
|
| 158 |
+
for key in ("input_ids", "attention_mask", "token_type_ids")
|
| 159 |
+
if key in features
|
| 160 |
+
}
|
| 161 |
+
tokens = self.backbone(**model_inputs).last_hidden_state
|
| 162 |
+
for projection in self.projections:
|
| 163 |
+
tokens = projection(tokens)
|
| 164 |
+
mask = features["attention_mask"].bool()
|
| 165 |
+
if task == "document" and self.config.skip_token_ids:
|
| 166 |
+
skip_ids = torch.tensor(self.config.skip_token_ids, device=input_ids.device)
|
| 167 |
+
mask = mask & ~torch.isin(input_ids, skip_ids)
|
| 168 |
+
owners = torch.arange(tokens.shape[0], device=tokens.device)[:, None].expand_as(
|
| 169 |
+
mask
|
| 170 |
+
)[mask]
|
| 171 |
+
tokens = torch.nn.functional.normalize(tokens[mask], p=2, dim=-1)
|
| 172 |
+
# Match the evaluation loader's FP16 token transfer before head pooling.
|
| 173 |
+
if not self.training:
|
| 174 |
+
tokens = tokens.half().float()
|
| 175 |
+
probability_sum = tokens.new_zeros(n_latents, dtype=torch.float32)
|
| 176 |
+
usage_sum = tokens.new_zeros(n_latents, dtype=torch.float32)
|
| 177 |
+
pooled = torch.zeros(
|
| 178 |
+
mask.shape[0] * n_latents, dtype=torch.float32, device=tokens.device
|
| 179 |
+
)
|
| 180 |
+
for start in range(0, tokens.shape[0], self.settings["head_chunk_size"]):
|
| 181 |
+
end = start + self.settings["head_chunk_size"]
|
| 182 |
+
# The reference evaluates the head under BF16 autocast on CUDA.
|
| 183 |
+
def head_chunk(chunk):
|
| 184 |
+
with torch.autocast(chunk.device.type, dtype=torch.bfloat16, enabled=chunk.is_cuda):
|
| 185 |
+
activations = self.head(chunk)
|
| 186 |
+
values, indices = activations.topk(k, dim=-1)
|
| 187 |
+
probabilities = activations.float().softmax(-1).sum(0) if self.training else chunk.new_zeros(n_latents)
|
| 188 |
+
return values, indices, probabilities
|
| 189 |
+
if self.training and torch.is_grad_enabled():
|
| 190 |
+
values, indices, probabilities = activation_checkpoint(head_chunk, tokens[start:end], use_reentrant=False)
|
| 191 |
+
else:
|
| 192 |
+
values, indices, probabilities = head_chunk(tokens[start:end])
|
| 193 |
+
if self.training:
|
| 194 |
+
probability_sum = probability_sum + probabilities
|
| 195 |
+
usage_sum = usage_sum + torch.bincount(indices.flatten(), minlength=n_latents)
|
| 196 |
+
values = values.float().relu()
|
| 197 |
+
indices = owners[start:end, None] * n_latents + indices
|
| 198 |
+
pooled = pooled.scatter_reduce(
|
| 199 |
+
0, indices.flatten(), values.flatten(), reduce="amax", include_self=True
|
| 200 |
+
)
|
| 201 |
+
pooled = (
|
| 202 |
+
pooled.view(mask.shape[0], n_latents)
|
| 203 |
+
* self.head.gate_relu_phi.float().relu()
|
| 204 |
+
)
|
| 205 |
+
if cap:
|
| 206 |
+
values, indices = pooled.topk(cap, dim=-1)
|
| 207 |
+
pooled = torch.zeros_like(pooled).scatter(1, indices, values)
|
| 208 |
+
# The reference stores retrieval weights in FP16; retain that rounding.
|
| 209 |
+
features["sentence_embedding"] = pooled if self.training else pooled.half().float()
|
| 210 |
+
if self.training:
|
| 211 |
+
count = max(tokens.shape[0], 1)
|
| 212 |
+
features["load_balance"] = n_latents * (
|
| 213 |
+
probability_sum / count * usage_sum.detach() / (count * k)
|
| 214 |
+
).sum()
|
| 215 |
+
return {key: features[key] for key in ("sentence_embedding", "load_balance") if key in features}
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
SlideOnConfig.register_for_auto_class()
|
| 219 |
+
SlideOnModel.register_for_auto_class("AutoModel")
|
modules.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"idx": 0,
|
| 4 |
+
"name": "0",
|
| 5 |
+
"path": "",
|
| 6 |
+
"type": "slideon.SlideOn"
|
| 7 |
+
}
|
| 8 |
+
]
|
slideon.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Sentence Transformers adapter for the complete, flat SlideOn checkpoint."""
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
|
| 4 |
+
import torch
|
| 5 |
+
from sentence_transformers.base.modules import InputModule
|
| 6 |
+
from transformers import AutoConfig, AutoModel, AutoTokenizer
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class SlideOn(InputModule):
|
| 10 |
+
config_file_name = "config.json"
|
| 11 |
+
forward_kwargs = {"task", "top_k", "token_k"}
|
| 12 |
+
save_in_root = True
|
| 13 |
+
|
| 14 |
+
def __init__(self, checkpoint, model_kwargs=None, processor_kwargs=None,
|
| 15 |
+
config_kwargs=None, **hub_kwargs):
|
| 16 |
+
super().__init__()
|
| 17 |
+
config = AutoConfig.from_pretrained(
|
| 18 |
+
checkpoint, trust_remote_code=True, **hub_kwargs, **(config_kwargs or {}))
|
| 19 |
+
if config.model_type != "slideon":
|
| 20 |
+
raise ValueError("Expected a flat SlideOn checkpoint; use slideon.export for legacy checkpoints")
|
| 21 |
+
self.model = AutoModel.from_pretrained(
|
| 22 |
+
checkpoint, config=config, trust_remote_code=True,
|
| 23 |
+
**hub_kwargs, **(model_kwargs or {}))
|
| 24 |
+
self.tokenizer = AutoTokenizer.from_pretrained(
|
| 25 |
+
checkpoint, trust_remote_code=True, **hub_kwargs, **(processor_kwargs or {}))
|
| 26 |
+
if self.tokenizer.mask_token_id is not None:
|
| 27 |
+
self.tokenizer.pad_token_id = self.tokenizer.mask_token_id
|
| 28 |
+
elif self.tokenizer.eos_token_id is not None:
|
| 29 |
+
self.tokenizer.pad_token_id = self.tokenizer.eos_token_id
|
| 30 |
+
self.settings = self.model.config.inference
|
| 31 |
+
self.encoder_config = self.model.config.tokenizer_settings
|
| 32 |
+
self.max_seq_length = max(self.settings["query_length"], self.settings["document_length"])
|
| 33 |
+
|
| 34 |
+
def get_embedding_dimension(self):
|
| 35 |
+
return self.model.get_embedding_dimension()
|
| 36 |
+
|
| 37 |
+
@staticmethod
|
| 38 |
+
def _task(task):
|
| 39 |
+
task = task or "document"
|
| 40 |
+
if task not in ("query", "document"):
|
| 41 |
+
raise ValueError("task must be 'query' or 'document'")
|
| 42 |
+
return task
|
| 43 |
+
|
| 44 |
+
def preprocess(
|
| 45 |
+
self, inputs, prompt=None, task=None, processing_kwargs=None, **kwargs
|
| 46 |
+
):
|
| 47 |
+
task = self._task(task)
|
| 48 |
+
if not all(isinstance(text, str) for text in inputs):
|
| 49 |
+
raise TypeError("SlideOn accepts text strings only")
|
| 50 |
+
if prompt is None:
|
| 51 |
+
prompt = self.settings["prompts"][task]
|
| 52 |
+
texts = [(prompt + text).strip() for text in inputs]
|
| 53 |
+
prefix = self.encoder_config.get(task + "_prefix", "")
|
| 54 |
+
length = min(self.max_seq_length, self.settings[task + "_length"])
|
| 55 |
+
options = dict(
|
| 56 |
+
padding=True,
|
| 57 |
+
truncation=True,
|
| 58 |
+
max_length=length - bool(prefix),
|
| 59 |
+
return_tensors="pt",
|
| 60 |
+
)
|
| 61 |
+
options.update(processing_kwargs or {})
|
| 62 |
+
features = dict(self.tokenizer(texts, **options))
|
| 63 |
+
if prefix:
|
| 64 |
+
prefix_id = self.tokenizer.convert_tokens_to_ids(prefix)
|
| 65 |
+
for name, value in list(features.items()):
|
| 66 |
+
fill = (
|
| 67 |
+
prefix_id
|
| 68 |
+
if name == "input_ids"
|
| 69 |
+
else (1 if name == "attention_mask" else 0)
|
| 70 |
+
)
|
| 71 |
+
marker = torch.full(
|
| 72 |
+
(value.shape[0], 1), fill, dtype=value.dtype, device=value.device
|
| 73 |
+
)
|
| 74 |
+
features[name] = torch.cat((value[:, :1], marker, value[:, 1:]), dim=1)
|
| 75 |
+
features["slideon_task"] = task
|
| 76 |
+
return features
|
| 77 |
+
|
| 78 |
+
def forward(self, features, task=None, top_k=None, token_k=None, **kwargs):
|
| 79 |
+
inputs = {key: features[key] for key in
|
| 80 |
+
("input_ids", "attention_mask", "token_type_ids", "slideon_task") if key in features}
|
| 81 |
+
features.update(self.model(**inputs, task=task, top_k=top_k, token_k=token_k))
|
| 82 |
+
return features
|
| 83 |
+
|
| 84 |
+
def save(self, output_path, safe_serialization=True, **kwargs):
|
| 85 |
+
self.model.save_pretrained(output_path, safe_serialization=safe_serialization)
|
| 86 |
+
self.tokenizer.save_pretrained(output_path)
|
| 87 |
+
|
| 88 |
+
@classmethod
|
| 89 |
+
def load(cls, model_name_or_path, subfolder="", token=None, cache_folder=None,
|
| 90 |
+
revision=None, local_files_only=False, model_kwargs=None,
|
| 91 |
+
processor_kwargs=None, config_kwargs=None, backend="torch", **kwargs):
|
| 92 |
+
if backend != "torch":
|
| 93 |
+
raise ValueError("SlideOn currently supports the torch backend only")
|
| 94 |
+
return cls(model_name_or_path, model_kwargs, processor_kwargs, config_kwargs,
|
| 95 |
+
subfolder=subfolder, token=token, cache_dir=cache_folder,
|
| 96 |
+
revision=revision, local_files_only=local_files_only)
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"backend": "tokenizers",
|
| 3 |
+
"clean_up_tokenization_spaces": true,
|
| 4 |
+
"cls_token": "[CLS]",
|
| 5 |
+
"is_local": true,
|
| 6 |
+
"local_files_only": false,
|
| 7 |
+
"mask_token": "[MASK]",
|
| 8 |
+
"max_length": 512,
|
| 9 |
+
"model_input_names": [
|
| 10 |
+
"input_ids",
|
| 11 |
+
"attention_mask"
|
| 12 |
+
],
|
| 13 |
+
"model_max_length": 512,
|
| 14 |
+
"pad_to_multiple_of": null,
|
| 15 |
+
"pad_token": "[MASK]",
|
| 16 |
+
"pad_token_type_id": 0,
|
| 17 |
+
"padding_side": "right",
|
| 18 |
+
"sep_token": "[SEP]",
|
| 19 |
+
"stride": 0,
|
| 20 |
+
"tokenizer_class": "TokenizersBackend",
|
| 21 |
+
"truncation_side": "right",
|
| 22 |
+
"truncation_strategy": "longest_first",
|
| 23 |
+
"unk_token": "[UNK]"
|
| 24 |
+
}
|