yjoonjang commited on
Commit
63bb3d9
·
0 Parent(s):

KURE-Sparse-base

Browse files
.gitattributes ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
36
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
37
+ assets/ndcg_flops.png filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ tags:
3
+ - sentence-transformers
4
+ - sparse-encoder
5
+ - sparse
6
+ - splade
7
+ - learned-sparse-retrieval
8
+ - feature-extraction
9
+ language:
10
+ - ko
11
+ - en
12
+ base_model: omai-research/milco-650m
13
+ pipeline_tag: feature-extraction
14
+ library_name: sentence-transformers
15
+ license: apache-2.0
16
+ ---
17
+
18
+ <a href="https://github.com/nlpai-lab/KURE">
19
+ <img src="https://huggingface.co/nlpai-lab/KURE-v2/resolve/main/kure_logo.png" width="50%"/>
20
+ </a>
21
+
22
+
23
+ # 🔎 KURE-Sparse-base
24
+
25
+ **KURE-Sparse-base** is a Korean-English bilingual learned sparse retrieval model. It shows state-of-the-art performance among sparse models supporting Korean, averging **0.7984** nDCG@10 on MTEB(kor, v2) Retrieval. It also outperforms 8B dense models, such as Qwen3-Embedding-8B and comsat-embed-ko-8b-preview.
26
+
27
+ ## Key Characteristics
28
+
29
+ - **Learned Sparse Retrieval (LSR)**: every vector lives in a fixed vocabulary, so documents can be indexed in an inverted
30
+ index and matched terms are inspectable.
31
+ - **Dual view**: represented with 30,522 English pivot terms (projected from the multilingual encoder) +
32
+ 250,002 source-language tokens.
33
+ - **Long documents**: up to 8,192 tokens.
34
+ - **Sparse at both ends**: on average 100 active dimensions per query and 1,897 per document.
35
+
36
+ ## Usage
37
+
38
+ ```bash
39
+ pip install -U sentence-transformers
40
+ ```
41
+
42
+ ```python
43
+ from sentence_transformers import SparseEncoder
44
+
45
+ model = SparseEncoder("nlpai-lab/KURE-Sparse-base", trust_remote_code=True)
46
+
47
+ query = "훈민정음은 언제 만들어졌나요?"
48
+ documents = [
49
+ "세종대왕은 1443년에 훈민정음을 창제하고 1446년에 이를 반포하였다.",
50
+ "김치는 배추나 무를 소금에 절인 뒤 고춧가루와 젓갈을 넣어 발효시킨 음식이다.",
51
+ "한라산은 해발 1,947m로 남한에서 가장 높은 산이며 제주도 중앙에 자리한다.",
52
+ ]
53
+
54
+ query_embeddings = model.encode_query(query)
55
+ document_embeddings = model.encode_document(documents)
56
+ print(query_embeddings.shape, document_embeddings.shape)
57
+ # torch.Size([280524]) torch.Size([3, 280524])
58
+
59
+ # Dot-product scores (higher is more relevant)
60
+ scores = model.similarity(query_embeddings, document_embeddings)
61
+ print(scores)
62
+ # tensor([[23.9621, 2.0522, 1.0599]])
63
+ ```
64
+
65
+ ## Evaluation
66
+
67
+ KURE-Sparse-base is evaluated on the nine **MTEB(kor, v2) Retrieval** tasks. We report nDCG@10.
68
+
69
+ | Model | Params | Avg | AutoRAG | PubHealthQA | Ko-StrategyQA | LawIRKo | SQuADKorV1 | Belebele (ko-ko) | MrTidy | MLDR | MIRACL |
70
+ | :--- | :--- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
71
+ | **Our Models** | | | | | | | | | | | |
72
+ | **[nlpai-lab/KURE-Sparse-base](https://huggingface.co/nlpai-lab/KURE-Sparse-base)** | 0.6B | **0.7984** | 0.9445 | 0.8099 | 0.8188 | 0.7244 | 0.9815 | 0.9703 | 0.6255 | 0.5716 | 0.7395 |
73
+ | **[nlpai-lab/KURE-Sparse-nano](https://huggingface.co/nlpai-lab/KURE-Sparse-nano)** | 0.1B | 0.7716 | 0.9360 | 0.7711 | 0.7924 | 0.7226 | 0.9774 | 0.9608 | 0.5618 | 0.5133 | 0.7091 |
74
+ | **Sparse Models** | | | | | | | | | | | |
75
+ | omai-research/milco-650m | 0.6B | 0.7824 | 0.9483 | 0.8219 | 0.8143 | 0.6724 | 0.9700 | 0.9623 | 0.6997 | 0.4318 | 0.7209 |
76
+ | telepix/PIXIE-Splade-v1.5 | 0.1B | 0.7608 | 0.9412 | 0.7910 | 0.7993 | 0.7667 | 0.9687 | 0.9651 | 0.5132 | 0.4938 | 0.6085 |
77
+ | yjoonjang/splade-ko-v1 | 0.1B | 0.7526 | 0.9423 | 0.7977 | 0.7583 | 0.6509 | 0.9754 | 0.9576 | 0.5299 | 0.5162 | 0.6451 |
78
+ | telepix/PIXIE-Splade-v1.0 | 0.1B | 0.6636 | 0.9597 | 0.7860 | 0.7352 | 0.5330 | 0.9417 | 0.9413 | 0.2909 | 0.3991 | 0.3858 |
79
+ | opensearch-project/opensearch-neural-sparse-encoding-multilingual-v1 | 0.2B | 0.5444 | 0.6482 | 0.5506 | 0.5553 | 0.3554 | 0.7770 | 0.7321 | 0.5526 | 0.1219 | 0.6064 |
80
+ | **Dense (Single-Vector) Models** | | | | | | | | | | | |
81
+ | nvidia/Nemotron-3-Embed-8B-BF16 | 8.0B | 0.8127 | 0.9311 | 0.8898 | 0.8405 | 0.8481 | 0.9650 | 0.9714 | 0.6540 | 0.4785 | 0.7363 |
82
+ | sionic-ai/comsat-embed-ko-8b-preview | 7.6B | 0.7927 | 0.8518 | 0.8871 | 0.8394 | 0.8164 | 0.9168 | 0.9853 | 0.6253 | 0.5157 | 0.6964 |
83
+ | Qwen/Qwen3-Embedding-8B | 7.6B | 0.7826 | 0.8276 | 0.8721 | 0.8363 | 0.8171 | 0.9063 | 0.9824 | 0.6187 | 0.5046 | 0.6783 |
84
+ | nvidia/Nemotron-3-Embed-1B-BF16 | 1.1B | 0.7817 | 0.9074 | 0.8642 | 0.8136 | 0.7758 | 0.9505 | 0.9629 | 0.6084 | 0.4202 | 0.7325 |
85
+ | Qwen/Qwen3-Embedding-4B | 4.0B | 0.7737 | 0.8431 | 0.8693 | 0.8270 | 0.7769 | 0.9044 | 0.9522 | 0.6076 | 0.5022 | 0.6803 |
86
+ | perplexity-ai/pplx-embed-v1-4b | 4.0B | 0.7705 | 0.8321 | 0.9042 | 0.8326 | 0.7736 | 0.9402 | 0.9624 | 0.5778 | 0.4343 | 0.6775 |
87
+ | microsoft/harrier-oss-v1-27b | 27.0B | 0.7667 | 0.8176 | 0.8971 | 0.8361 | 0.8737 | 0.9204 | 0.9546 | 0.5306 | 0.4046 | 0.6653 |
88
+ | dragonkue/snowflake-arctic-embed-l-v2.0-ko | 0.6B | 0.7653 | 0.9093 | 0.8337 | 0.8050 | 0.7735 | 0.9447 | 0.9518 | 0.5712 | 0.4304 | 0.6685 |
89
+ | codefuse-ai/F2LLM-v2-8B | 7.6B | 0.7638 | 0.7678 | 0.9380 | 0.8371 | 0.8405 | 0.8874 | 0.9513 | 0.6162 | 0.4047 | 0.6313 |
90
+ | telepix/PIXIE-Rune-v1.5 | 0.6B | 0.7618 | 0.8927 | 0.8426 | 0.8064 | 0.7705 | 0.9457 | 0.9617 | 0.5492 | 0.4482 | 0.6393 |
91
+ | [nlpai-lab/KURE-v1](https://huggingface.co/nlpai-lab/KURE-v1) | 0.6B | 0.7616 | 0.8708 | 0.8193 | 0.7999 | 0.7426 | 0.9357 | 0.9502 | 0.5909 | 0.4637 | 0.6816 |
92
+ | nvidia/llama-nemotron-embed-1b-v2 | 1.2B | 0.7564 | 0.8708 | 0.8177 | 0.8055 | 0.7329 | 0.9345 | 0.9519 | 0.5988 | 0.3952 | 0.7004 |
93
+ | dragonkue/BGE-m3-ko | 0.6B | 0.7547 | 0.8738 | 0.8155 | 0.7959 | 0.7322 | 0.9414 | 0.9503 | 0.6099 | 0.3899 | 0.6833 |
94
+ | BAAI/bge-m3 | 0.6B | 0.7509 | 0.8301 | 0.8041 | 0.7941 | 0.7174 | 0.9038 | 0.9315 | 0.6471 | 0.4287 | 0.7015 |
95
+ | perplexity-ai/pplx-embed-v1-0.6b | 0.6B | 0.7390 | 0.8414 | 0.8255 | 0.8100 | 0.7444 | 0.9174 | 0.9393 | 0.5524 | 0.3179 | 0.7026 |
96
+ | [nlpai-lab/KoE5](https://huggingface.co/nlpai-lab/KoE5) | 0.6B | 0.7337 | 0.8434 | 0.8351 | 0.8001 | 0.7756 | 0.8980 | 0.9425 | 0.5841 | 0.3015 | 0.6235 |
97
+ | Qwen/Qwen3-Embedding-0.6B | 0.6B | 0.7140 | 0.8338 | 0.8107 | 0.7586 | 0.7526 | 0.8490 | 0.9124 | 0.4870 | 0.4199 | 0.6023 |
98
+
99
+ ### Performance-Sparsity
100
+
101
+ <p align="center">
102
+ <img src="assets/ndcg_flops.png" width="80%" alt="Average nDCG@10 vs. average FLOPs of sparse retrievers on MTEB(kor, v2) Retrieval">
103
+ </p>
104
+
105
+ Average active dimensions per vector and FLOPs, averaged over the nine tasks.
106
+
107
+ | Model | Params | Query dims | Document dims | FLOPs |
108
+ | :--- | :--- | ---: | ---: | ---: |
109
+ | **KURE-Sparse-base** | 0.6B | 100 | 1,897 | 36.5 |
110
+ | **KURE-Sparse-nano** | 0.1B | 147 | 843 | 23.0 |
111
+ | omai-research/milco-650m | 0.6B | 105 | 1,167 | 32.3 |
112
+ | telepix/PIXIE-Splade-v1.5 | 0.1B | 117 | 1,541 | 37.3 |
113
+ | yjoonjang/splade-ko-v1 | 0.1B | 109 | 742 | 29.1 |
114
+ | telepix/PIXIE-Splade-v1.0 | 0.1B | 121 | 625 | 22.4 |
115
+ | opensearch-project/opensearch-neural-sparse-encoding-multilingual-v1 | 0.2B | 29 | 176 | 6.8 |
116
+
117
+ ### English Retrieval (BEIR)
118
+
119
+ KURE-Sparse-base is also evaluated on the 13 English BEIR tasks (BEIR-13) with nDCG@10. SparseUp runs at its own length limits (128 query and 512 document tokens), and the other models at up to 8,192 tokens.
120
+
121
+ | Model | Params | BEIR-13 | FLOPs |
122
+ | :--- | :--- | ---: | ---: |
123
+ | **Our Models** | | | |
124
+ | **KURE-Sparse-base** | 0.6B | **0.5864** | 55.8 |
125
+ | **KURE-Sparse-nano** | 0.1B | 0.5317 | 37.0 |
126
+ | **Sparse Models** | | | |
127
+ | Linkup-Platform/linkup-sparseup-embed-v1 | 0.2B | 0.5645 | 8.5 |
128
+ | omai-research/milco-650m | 0.6B | 0.5545 | 20.6 |
129
+ | telepix/PIXIE-Splade-v1.5 | 0.1B | 0.4149 | 125.6 |
130
+
131
+ <details>
132
+ <summary>Per-task nDCG@10</summary>
133
+
134
+ | Model | Avg | ArguAna | ClimateFEVER | DBPedia | FEVER | FiQA | HotpotQA | NFCorpus | NQ | Quora | SCIDOCS | SciFact | TREC-COVID | Touche-2020 |
135
+ | :--- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
136
+ | **Our Models** | | | | | | | | | | | | | | |
137
+ | **KURE-Sparse-base** | **0.5864** | 0.5896 | 0.3959 | 0.4837 | 0.9325 | 0.4720 | 0.8084 | 0.3678 | 0.6758 | 0.8252 | 0.1741 | 0.7183 | 0.8260 | 0.3535 |
138
+ | **KURE-Sparse-nano** | 0.5317 | 0.5075 | 0.2865 | 0.4214 | 0.9079 | 0.4080 | 0.7476 | 0.3340 | 0.5647 | 0.7825 | 0.1581 | 0.7120 | 0.7637 | 0.3183 |
139
+ | **Sparse Models** | | | | | | | | | | | | | | |
140
+ | Linkup-Platform/linkup-sparseup-embed-v1 | 0.5645 | 0.5648 | 0.3747 | 0.4150 | 0.8969 | 0.4687 | 0.7761 | 0.3523 | 0.5717 | 0.8656 | 0.1852 | 0.7376 | 0.7823 | 0.3478 |
141
+ | omai-research/milco-650m | 0.5545 | 0.6157 | 0.3079 | 0.4501 | 0.8353 | 0.4262 | 0.7780 | 0.3629 | 0.6495 | 0.8818 | 0.1704 | 0.7020 | 0.7476 | 0.2813 |
142
+ | telepix/PIXIE-Splade-v1.5 | 0.4149 | 0.2185 | 0.1302 | 0.3519 | 0.6475 | 0.2753 | 0.5756 | 0.3325 | 0.3858 | 0.6878 | 0.1468 | 0.6694 | 0.7068 | 0.2650 |
143
+
144
+ </details>
145
+
146
+ ## Citation
147
+
148
+ ```bibtex
149
+ @misc{kure-sparse,
150
+ title = {KURE-Sparse: a Korean-English bilingual learned sparse retriever},
151
+ author = {Jang, Youngjoon and Son, Junyoung and Lee, Taemin and Hong, Seongtae and Lim, Heuiseok},
152
+ year = {2026},
153
+ url = {https://huggingface.co/nlpai-lab/KURE-Sparse-base},
154
+ }
155
+ ```
156
+
157
+ ```bibtex
158
+ @inproceedings{jang2025kure,
159
+ title={KURE: Embedding Model for Korean-Specific Retrieval},
160
+ author={Jang, Youngjoon and Son, Junyoung and Lee, Taemin and Hong, Seongtae and Park, JeongBae and Lim, Heuiseok},
161
+ booktitle={Annual Conference on Human and Language Technology},
162
+ pages={129--134},
163
+ year={2025},
164
+ organization={Human and Language Technology}
165
+ }
166
+ ```
167
+
168
+ ```bibtex
169
+ @inproceedings{nguyen2026milco,
170
+ title={MILCO: Learned Sparse Retrieval Across Languages via a Multilingual Connector},
171
+ author={Nguyen, Thong and Lei, Yibin and Ju, Jia-Huei and Yang, Eugene and Yates, Andrew},
172
+ booktitle={International Conference on Learning Representations},
173
+ year={2026}
174
+ }
175
+ ```
assets/ndcg_flops.png ADDED

Git LFS Details

  • SHA256: 0dbafef614ce610b4674c7cf43c8a7b847414eeca92d40aa79a5f2c4e50b00db
  • Pointer size: 131 Bytes
  • Size of remote file: 110 kB
config.json ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "MILCOModel"
4
+ ],
5
+ "auto_map": {
6
+ "AutoConfig": "milco.MILCOConfig",
7
+ "AutoModel": "milco.MILCOModel"
8
+ },
9
+ "dtype": "bfloat16",
10
+ "en_hidden_size": 768,
11
+ "en_sub_config": {
12
+ "_name_or_path": "naver/splade-v3",
13
+ "add_cross_attention": false,
14
+ "architectures": [
15
+ "BertForMaskedLM"
16
+ ],
17
+ "attention_probs_dropout_prob": 0.1,
18
+ "bad_words_ids": null,
19
+ "begin_suppress_tokens": null,
20
+ "bos_token_id": null,
21
+ "chunk_size_feed_forward": 0,
22
+ "classifier_dropout": null,
23
+ "cross_attention_hidden_size": null,
24
+ "decoder_start_token_id": null,
25
+ "diversity_penalty": 0.0,
26
+ "do_sample": false,
27
+ "dtype": "float32",
28
+ "early_stopping": false,
29
+ "encoder_no_repeat_ngram_size": 0,
30
+ "eos_token_id": null,
31
+ "exponential_decay_length_penalty": null,
32
+ "finetuning_task": null,
33
+ "forced_bos_token_id": null,
34
+ "forced_eos_token_id": null,
35
+ "gradient_checkpointing": false,
36
+ "hidden_act": "gelu",
37
+ "hidden_dropout_prob": 0.1,
38
+ "hidden_size": 768,
39
+ "id2label": {
40
+ "0": "LABEL_0",
41
+ "1": "LABEL_1"
42
+ },
43
+ "initializer_range": 0.02,
44
+ "intermediate_size": 3072,
45
+ "is_decoder": false,
46
+ "is_encoder_decoder": false,
47
+ "label2id": {
48
+ "LABEL_0": 0,
49
+ "LABEL_1": 1
50
+ },
51
+ "layer_norm_eps": 1e-12,
52
+ "length_penalty": 1.0,
53
+ "max_length": 20,
54
+ "max_position_embeddings": 512,
55
+ "min_length": 0,
56
+ "model_type": "bert",
57
+ "no_repeat_ngram_size": 0,
58
+ "num_attention_heads": 12,
59
+ "num_beam_groups": 1,
60
+ "num_beams": 1,
61
+ "num_hidden_layers": 12,
62
+ "num_return_sequences": 1,
63
+ "output_attentions": false,
64
+ "output_hidden_states": false,
65
+ "output_scores": false,
66
+ "pad_token_id": 0,
67
+ "position_embedding_type": "absolute",
68
+ "prefix": null,
69
+ "problem_type": null,
70
+ "pruned_heads": {},
71
+ "remove_invalid_values": false,
72
+ "repetition_penalty": 1.0,
73
+ "return_dict": true,
74
+ "return_dict_in_generate": false,
75
+ "sep_token_id": null,
76
+ "suppress_tokens": null,
77
+ "task_specific_params": null,
78
+ "temperature": 1.0,
79
+ "tf_legacy_loss": false,
80
+ "tie_encoder_decoder": false,
81
+ "tie_word_embeddings": true,
82
+ "tokenizer_class": null,
83
+ "top_k": 50,
84
+ "top_p": 1.0,
85
+ "torchscript": false,
86
+ "transformers_version": "4.57.3",
87
+ "type_vocab_size": 2,
88
+ "typical_p": 1.0,
89
+ "use_bfloat16": false,
90
+ "use_cache": true,
91
+ "vocab_size": 30522
92
+ },
93
+ "en_vocab_size": 30522,
94
+ "freeze_embeddings": false,
95
+ "lambda_commitment": 0.0,
96
+ "lambda_d": 1e-05,
97
+ "lambda_q": 0.001,
98
+ "lambda_sparsity": 0.0,
99
+ "lsr_encoder_checkpoint": "naver/splade-v3",
100
+ "m_hidden_size": 1024,
101
+ "m_sub_config": {
102
+ "_name_or_path": "BAAI/bge-m3-unsupervised",
103
+ "add_cross_attention": false,
104
+ "architectures": [
105
+ "XLMRobertaModel"
106
+ ],
107
+ "attention_probs_dropout_prob": 0.1,
108
+ "bad_words_ids": null,
109
+ "begin_suppress_tokens": null,
110
+ "bos_token_id": 0,
111
+ "chunk_size_feed_forward": 0,
112
+ "classifier_dropout": null,
113
+ "cross_attention_hidden_size": null,
114
+ "decoder_start_token_id": null,
115
+ "diversity_penalty": 0.0,
116
+ "do_sample": false,
117
+ "dtype": "float32",
118
+ "early_stopping": false,
119
+ "encoder_no_repeat_ngram_size": 0,
120
+ "eos_token_id": 2,
121
+ "exponential_decay_length_penalty": null,
122
+ "finetuning_task": null,
123
+ "forced_bos_token_id": null,
124
+ "forced_eos_token_id": null,
125
+ "hidden_act": "gelu",
126
+ "hidden_dropout_prob": 0.1,
127
+ "hidden_size": 1024,
128
+ "id2label": {
129
+ "0": "LABEL_0",
130
+ "1": "LABEL_1"
131
+ },
132
+ "initializer_range": 0.02,
133
+ "intermediate_size": 4096,
134
+ "is_decoder": false,
135
+ "is_encoder_decoder": false,
136
+ "label2id": {
137
+ "LABEL_0": 0,
138
+ "LABEL_1": 1
139
+ },
140
+ "layer_norm_eps": 1e-05,
141
+ "length_penalty": 1.0,
142
+ "max_length": 20,
143
+ "max_position_embeddings": 8194,
144
+ "min_length": 0,
145
+ "model_type": "xlm-roberta",
146
+ "no_repeat_ngram_size": 0,
147
+ "num_attention_heads": 16,
148
+ "num_beam_groups": 1,
149
+ "num_beams": 1,
150
+ "num_hidden_layers": 24,
151
+ "num_return_sequences": 1,
152
+ "output_attentions": false,
153
+ "output_hidden_states": false,
154
+ "output_past": true,
155
+ "output_scores": false,
156
+ "pad_token_id": 1,
157
+ "position_embedding_type": "absolute",
158
+ "prefix": null,
159
+ "problem_type": null,
160
+ "pruned_heads": {},
161
+ "remove_invalid_values": false,
162
+ "repetition_penalty": 1.0,
163
+ "return_dict": true,
164
+ "return_dict_in_generate": false,
165
+ "sep_token_id": null,
166
+ "suppress_tokens": null,
167
+ "task_specific_params": null,
168
+ "temperature": 1.0,
169
+ "tf_legacy_loss": false,
170
+ "tie_encoder_decoder": false,
171
+ "tie_word_embeddings": true,
172
+ "tokenizer_class": null,
173
+ "top_k": 50,
174
+ "top_p": 1.0,
175
+ "torchscript": false,
176
+ "transformers_version": "4.57.3",
177
+ "type_vocab_size": 1,
178
+ "typical_p": 1.0,
179
+ "use_bfloat16": false,
180
+ "use_cache": true,
181
+ "vocab_size": 250002
182
+ },
183
+ "m_vocab_size": 250002,
184
+ "model_type": "milco",
185
+ "model_variant": "bert",
186
+ "multilingual_encoder_checkpoint": "BAAI/bge-m3-unsupervised",
187
+ "only_distillation": true,
188
+ "pooling": "2d",
189
+ "projector_pretraining": false,
190
+ "prompt_length": 0,
191
+ "separate_mlp": true,
192
+ "softmax_temperature": 1.0,
193
+ "sparse_reg": "l1",
194
+ "transformers_version": "5.14.1",
195
+ "use_2d_mlp": true,
196
+ "use_cross_device_negatives": false
197
+ }
config_sentence_transformers.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "__version__": {
3
+ "pytorch": "2.8.0+cu128",
4
+ "sentence_transformers": "5.6.1",
5
+ "transformers": "5.14.1"
6
+ },
7
+ "default_prompt_name": null,
8
+ "model_type": "SparseEncoder",
9
+ "prompts": {
10
+ "document": "",
11
+ "query": ""
12
+ },
13
+ "similarity_fn_name": "dot"
14
+ }
milco.py ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ from transformers import (
4
+ AutoConfig,
5
+ AutoModel,
6
+ AutoModelForMaskedLM,
7
+ AutoTokenizer,
8
+ PretrainedConfig,
9
+ PreTrainedModel,
10
+ )
11
+ from transformers.activations import GELUActivation
12
+ from transformers.utils import logging
13
+
14
+ logger = logging.get_logger(__name__)
15
+
16
+
17
+ class MILCOConfig(PretrainedConfig):
18
+ model_type = "milco"
19
+
20
+ def __init__(self, **kwargs):
21
+ super().__init__(**kwargs)
22
+ self.lsr_encoder_checkpoint = kwargs.get("lsr_encoder_checkpoint", "bert-base-uncased")
23
+ self.multilingual_encoder_checkpoint = kwargs.get("multilingual_encoder_checkpoint", "bert-base-uncased")
24
+ self.model_variant = kwargs.get("model_variant", "bert")
25
+ # Sub-model dimensions — cached in config.json after first save.
26
+ self.en_vocab_size = kwargs.get("en_vocab_size", None)
27
+ self.en_hidden_size = kwargs.get("en_hidden_size", None)
28
+ self.m_vocab_size = kwargs.get("m_vocab_size", None)
29
+ self.m_hidden_size = kwargs.get("m_hidden_size", None)
30
+ # Sub-model config dicts — stored so __init__ can rebuild architecture offline.
31
+ self.en_sub_config = kwargs.get("en_sub_config", None)
32
+ self.m_sub_config = kwargs.get("m_sub_config", None)
33
+
34
+ def _resolve_sub_configs(self):
35
+ """Fetch sub-model configs from HF hub if not already cached."""
36
+ if self.en_sub_config is None:
37
+ en_config = AutoConfig.from_pretrained(self.lsr_encoder_checkpoint, trust_remote_code=True)
38
+ self.en_vocab_size = en_config.vocab_size
39
+ self.en_hidden_size = en_config.hidden_size
40
+ self.en_sub_config = en_config.to_dict()
41
+ if self.m_sub_config is None:
42
+ m_config = AutoConfig.from_pretrained(self.multilingual_encoder_checkpoint, trust_remote_code=True)
43
+ self.m_vocab_size = m_config.vocab_size
44
+ self.m_hidden_size = m_config.hidden_size
45
+ self.m_sub_config = m_config.to_dict()
46
+
47
+
48
+ class MILCOModel(PreTrainedModel):
49
+ config_class = MILCOConfig
50
+ base_model_prefix = "milco"
51
+
52
+ def __init__(self, config: MILCOConfig):
53
+ super().__init__(config)
54
+ config._resolve_sub_configs()
55
+ # Build architecture from cached configs — no pretrained weight downloads.
56
+ m_sub_config = AutoConfig.for_model(**config.m_sub_config)
57
+ self.m_model = AutoModel.from_config(m_sub_config)
58
+ en_sub_config = AutoConfig.for_model(**config.en_sub_config)
59
+ en_lsr = AutoModelForMaskedLM.from_config(en_sub_config)
60
+ if hasattr(en_lsr, "cls"):
61
+ self.mlm_head = en_lsr.cls
62
+ else:
63
+ self.mlm_head = en_lsr.lm_head
64
+ self.projector = nn.Linear(config.m_hidden_size, config.en_hidden_size)
65
+ self.activation = GELUActivation()
66
+ self.echo = nn.Linear(config.m_hidden_size, 1)
67
+ self.scale = nn.Parameter(torch.tensor([1.0]))
68
+ self.post_init()
69
+
70
+ @property
71
+ def en_tokenizer(self):
72
+ if not hasattr(self, "_en_tokenizer"):
73
+ self._en_tokenizer = AutoTokenizer.from_pretrained(
74
+ self.config.lsr_encoder_checkpoint, trust_remote_code=True,
75
+ )
76
+ return self._en_tokenizer
77
+
78
+ @property
79
+ def m_tokenizer(self):
80
+ if not hasattr(self, "_m_tokenizer"):
81
+ self._m_tokenizer = AutoTokenizer.from_pretrained(
82
+ self.config.multilingual_encoder_checkpoint, trust_remote_code=True,
83
+ )
84
+ return self._m_tokenizer
85
+
86
+ def get_vocab(self):
87
+ en_term2id = self.en_tokenizer.vocab
88
+ en_id2term = {idx: f"e_{term}" for term, idx in en_term2id.items()}
89
+ m_term2id = self.m_tokenizer.vocab
90
+ m_id2term = {idx + self.config.en_vocab_size: f"m_{term}" for term, idx in m_term2id.items()}
91
+ return en_id2term | m_id2term
92
+
93
+ def encode_query(self, *args, **kwargs):
94
+ return self.encode_text(*args, **kwargs)
95
+
96
+ def encode_document(self, *args, **kwargs):
97
+ return self.encode_text(*args, **kwargs)
98
+
99
+ def encode_text(self, texts, batch_size: int = 32, max_length: int = None, source_view=False, return_dict=False, **kwargs):
100
+ if isinstance(texts, str):
101
+ texts = [texts]
102
+ if max_length is None:
103
+ max_length = self.m_tokenizer.model_max_length
104
+ device = "cuda" if torch.cuda.is_available() else "cpu"
105
+ self.to(device)
106
+ reps = []
107
+ for idx in range(0, len(texts), batch_size):
108
+ batch_texts = texts[idx:idx + batch_size]
109
+ inputs = self.m_tokenizer(
110
+ batch_texts, padding=True, truncation=True,
111
+ pad_to_multiple_of=32, max_length=max_length, return_tensors="pt",
112
+ )
113
+ inputs = {k: v.to(device) for k, v in inputs.items()}
114
+ with torch.no_grad(), torch.autocast(device_type=device, dtype=torch.bfloat16):
115
+ output = self._encode(
116
+ input_ids=inputs["input_ids"],
117
+ attention_mask=inputs["attention_mask"],
118
+ source_view=source_view,
119
+ )
120
+ if isinstance(output, tuple):
121
+ sparse_rep = self._build_dual_view_sparse(output)
122
+ else:
123
+ sparse_rep = output.to_sparse()
124
+ reps.append(sparse_rep.cpu())
125
+ combined = sparse_row_cat_2d(reps)
126
+ assert len(texts) == combined.size(0)
127
+ if return_dict:
128
+ return self._sparse_to_dicts(combined)
129
+ return combined
130
+
131
+ def _sparse_to_dicts(self, sparse_tensor):
132
+ """Convert a sparse [N, vocab] tensor to a list of {token: weight} dicts."""
133
+ id2term = self.get_vocab()
134
+ sparse_tensor = sparse_tensor.coalesce()
135
+ indices = sparse_tensor.indices()
136
+ values = sparse_tensor.values()
137
+ rows, cols = indices[0], indices[1]
138
+ result = [[] for _ in range(sparse_tensor.size(0))]
139
+ for i in range(len(values)):
140
+ row = rows[i].item()
141
+ col = cols[i].item()
142
+ weight = values[i].item()
143
+ token = id2term.get(col, f"unk_{col}")
144
+ result[row].append((token, weight))
145
+ return [
146
+ dict(sorted(pairs, key=lambda x: x[1], reverse=True))
147
+ for pairs in result
148
+ ]
149
+
150
+ def _build_dual_view_sparse(self, output):
151
+ pivot_view, (source_ids, source_weights) = output
152
+ batch_size = source_ids.size(0)
153
+ vocab_size = self.config.en_vocab_size + self.config.m_vocab_size
154
+
155
+ pivot_rows, pivot_cols = pivot_view.nonzero(as_tuple=True)
156
+ pivot_vals = pivot_view[pivot_rows, pivot_cols].contiguous()
157
+
158
+ source_rows = torch.arange(batch_size, device=source_ids.device).repeat_interleave(source_ids.size(1))
159
+ source_cols = source_ids.view(-1)
160
+ source_vals = source_weights.view(-1)
161
+ nonzero_mask = source_vals > 0
162
+ source_rows = source_rows[nonzero_mask]
163
+ source_cols = source_cols[nonzero_mask] + self.config.en_vocab_size
164
+ source_vals = source_vals[nonzero_mask]
165
+
166
+ rows = torch.cat([pivot_rows, source_rows])
167
+ cols = torch.cat([pivot_cols, source_cols])
168
+ indices = torch.stack([rows, cols], dim=0)
169
+ values = torch.cat([pivot_vals, source_vals])
170
+ return torch.sparse_coo_tensor(indices, values, (batch_size, vocab_size))
171
+
172
+ def _encode(self, input_ids, attention_mask, source_view=False):
173
+ hidden_states_m = self.m_model(input_ids=input_ids, attention_mask=attention_mask).last_hidden_state
174
+ hidden_states_e = self.activation(self.projector(hidden_states_m))
175
+ logits = self.mlm_head(hidden_states_e) * attention_mask.unsqueeze(-1)
176
+ pivot_view = torch.log1p(torch.relu(logits.max(dim=1).values))
177
+ if source_view:
178
+ token_scores = torch.relu(self.echo(hidden_states_m).squeeze(-1))
179
+ source_weights = token_scores * attention_mask
180
+ return pivot_view, (input_ids, source_weights)
181
+ return pivot_view
182
+
183
+ def forward(self, *args, **kwargs):
184
+ return self._encode(*args, **kwargs)
185
+
186
+ def save_pretrained(self, save_directory: str, **kwargs):
187
+ kwargs["safe_serialization"] = False
188
+ super().save_pretrained(save_directory, **kwargs)
189
+
190
+
191
+ def sparse_row_cat_2d(tensors):
192
+ """Concatenate a list of 2-D COO sparse tensors along rows (dim=0)."""
193
+ assert len(tensors) > 0, "empty list"
194
+ if len(tensors) == 1:
195
+ return tensors[0]
196
+ tensors = [t.coalesce() for t in tensors]
197
+ assert all(t.layout == torch.sparse_coo for t in tensors), "COO only"
198
+
199
+ ncols = tensors[0].size(1)
200
+ assert all(t.dim() == 2 and t.size(1) == ncols for t in tensors), "size(1) mismatch"
201
+
202
+ total_rows = sum(t.size(0) for t in tensors)
203
+ device = tensors[0].device
204
+
205
+ ind_parts, val_parts = [], []
206
+ row_offset = 0
207
+ for t in tensors:
208
+ idx = t._indices()
209
+ if row_offset:
210
+ idx = idx.clone()
211
+ idx[0] += row_offset
212
+ ind_parts.append(idx)
213
+ val_parts.append(t._values())
214
+ row_offset += t.size(0)
215
+
216
+ indices = torch.cat(ind_parts, dim=1)
217
+ values = torch.cat(val_parts, dim=0)
218
+ return torch.sparse_coo_tensor(indices, values, (total_rows, ncols), device=device).coalesce()
milco_encoder.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """MILCO (arXiv:2510.00671) as a sentence-transformers input module, so the SPARSE pipeline trains,
2
+ saves and evaluates it like any SparseEncoder.
3
+
4
+ MILCO is a bge-m3 body (XLM-R large) -> projector -> splade-v3's MLM head over the English BERT
5
+ vocabulary (the pivot view, 30522 dims), plus LexEcho: one relu score per input token, placed on that
6
+ token's XLM-R id (the source view, 250002 dims). Its native API returns the two as one sparse
7
+ [N, 30522 + 250002] tensor scored by a dot product; this module emits the same vector dense, as
8
+ ``sentence_embedding``, so every loss and regularizer here applies to both views unchanged.
9
+
10
+ The source view adds up the scores of a repeated token: MILCO builds its COO tensor with one entry per
11
+ position and coalescing sums duplicates, so this uses scatter_add. Special tokens (<s>, </s>) are
12
+ attended and scored exactly as MILCO does.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import inspect
18
+ import shutil
19
+ from pathlib import Path
20
+
21
+ import torch
22
+ from sentence_transformers.base.modules.input_module import InputModule
23
+ from transformers import AutoModel, AutoTokenizer
24
+
25
+
26
+ def is_milco(model_name_or_path: str) -> bool:
27
+ config = Path(model_name_or_path) / "config.json"
28
+ return config.is_file() and '"model_type": "milco"' in config.read_text()
29
+
30
+
31
+ class MilcoDualView(InputModule):
32
+ config_file_name = "milco_encoder_config.json" # config.json is MILCO's own
33
+ config_keys = ["max_seq_length", "source_view", "chunk_size"]
34
+
35
+ def __init__(
36
+ self,
37
+ model_name_or_path: str,
38
+ max_seq_length: int = 8192,
39
+ source_view: bool = True,
40
+ chunk_size: int = 512,
41
+ model_kwargs: dict | None = None,
42
+ ) -> None:
43
+ super().__init__()
44
+ model_kwargs = dict(model_kwargs or {})
45
+ # MILCOModel itself declares no attention backends; only its XLM-R body has them.
46
+ attn = model_kwargs.pop("attn_implementation", None)
47
+ # A dtype would reach only MILCOModel's own layers: its sub-models are built with from_config and keep
48
+ # their config's float32, so bf16 projector/echo would sit next to an fp32 body -- and at lr 1e-5 a bf16
49
+ # weight of typical size rounds every AdamW step away. Keep fp32 master weights; training runs under
50
+ # --bf16 autocast, and eval.py casts the whole model to bf16 itself.
51
+ model_kwargs.pop("torch_dtype", None)
52
+ model_kwargs.pop("dtype", None)
53
+ self.milco = AutoModel.from_pretrained(model_name_or_path, trust_remote_code=True, **model_kwargs).float()
54
+ if attn:
55
+ self.milco.m_model.set_attn_implementation(attn)
56
+ # BertLMPredictionHead.bias is never read in the forward (the decoder carries its own bias), but
57
+ # MILCO's checkpoint stores the two on one storage, which save_pretrained refuses as untied
58
+ # shared tensors. Give the unused one its own copy.
59
+ head = self.milco.mlm_head.predictions
60
+ head.bias = torch.nn.Parameter(head.decoder.bias.detach().clone())
61
+ # Never used in the forward: frozen, so they neither take optimizer state nor stall a DDP built
62
+ # with find_unused_parameters=False.
63
+ for param in [*self.milco.m_model.pooler.parameters(), self.milco.scale, head.bias]:
64
+ param.requires_grad_(False)
65
+ # The XLM-R body supports checkpointing; the wrapper class just does not say so.
66
+ self.milco.supports_gradient_checkpointing = True
67
+ has_tokenizer = (Path(model_name_or_path) / "tokenizer_config.json").is_file()
68
+ # trust_remote_code: a saved checkpoint's config.json maps to MILCO's code, and AutoTokenizer reads it.
69
+ self.tokenizer = AutoTokenizer.from_pretrained(
70
+ model_name_or_path if has_tokenizer else self.milco.config.multilingual_encoder_checkpoint,
71
+ trust_remote_code=True,
72
+ )
73
+ self.max_seq_length = max_seq_length
74
+ self.source_view = source_view
75
+ self.chunk_size = chunk_size
76
+
77
+ def preprocess(self, inputs, prompt: str | None = None, **kwargs) -> dict[str, torch.Tensor]:
78
+ texts = self._prepend_prompt(list(inputs), prompt) if prompt else list(inputs)
79
+ return self.tokenizer(
80
+ texts, padding=True, truncation=True, max_length=self.max_seq_length, return_tensors="pt"
81
+ )
82
+
83
+ def forward(self, features: dict[str, torch.Tensor], **kwargs) -> dict[str, torch.Tensor]:
84
+ # MILCOModel._encode, with the MLM head run over position chunks: it materializes
85
+ # [batch, seq, 30522] logits at once, ~16 GB for an evaluation batch of 32 at 8192 tokens.
86
+ # Max over chunks of the max is the same max, and log1p(relu(.)) is monotone, so the
87
+ # result is unchanged.
88
+ milco = self.milco
89
+ input_ids, attention_mask = features["input_ids"], features["attention_mask"]
90
+ hidden = milco.m_model(input_ids=input_ids, attention_mask=attention_mask).last_hidden_state
91
+ mask = attention_mask.unsqueeze(-1)
92
+ pivot = None
93
+ for i in range(0, hidden.shape[1], self.chunk_size):
94
+ logits = milco.mlm_head(milco.activation(milco.projector(hidden[:, i : i + self.chunk_size])))
95
+ chunk_max = (logits * mask[:, i : i + self.chunk_size]).max(dim=1).values
96
+ pivot = chunk_max if pivot is None else torch.maximum(pivot, chunk_max)
97
+ pivot = torch.log1p(torch.relu(pivot)).float()
98
+ if not self.source_view:
99
+ features["sentence_embedding"] = pivot
100
+ return features
101
+ weights = torch.relu(milco.echo(hidden).squeeze(-1)) * attention_mask
102
+ source = pivot.new_zeros((input_ids.shape[0], self.milco.config.m_vocab_size), dtype=torch.float32)
103
+ source = source.scatter_add(1, input_ids, weights.float())
104
+ features["sentence_embedding"] = torch.cat([pivot, source], dim=1)
105
+ return features
106
+
107
+ def get_sentence_embedding_dimension(self) -> int:
108
+ config = self.milco.config
109
+ return config.en_vocab_size + (config.m_vocab_size if self.source_view else 0)
110
+
111
+ def save(self, output_path: str, *args, safe_serialization: bool = True, **kwargs) -> None:
112
+ # Keep the unused bias equal to the trained one, in case a later transformers re-ties the two on load.
113
+ head = self.milco.mlm_head.predictions
114
+ head.bias.data.copy_(head.decoder.bias.data)
115
+ self.milco.save_pretrained(output_path)
116
+ # MILCO's remote code, for AutoModel(trust_remote_code=True) on the saved directory.
117
+ shutil.copyfile(inspect.getfile(type(self.milco)), Path(output_path) / "milco.py")
118
+ self.tokenizer.save_pretrained(output_path)
119
+ self.save_config(output_path)
120
+ # modules.json names this class as milco_encoder.MilcoDualView; ship the source so the
121
+ # checkpoint loads where SPARSE/src is not on sys.path (as pooling.py does).
122
+ shutil.copyfile(Path(__file__), Path(output_path) / Path(__file__).name)
123
+
124
+ @classmethod
125
+ def load(cls, model_name_or_path: str, subfolder: str = "", model_kwargs: dict | None = None, **kwargs):
126
+ config = cls.load_config(model_name_or_path, subfolder=subfolder)
127
+ path = str(Path(model_name_or_path) / subfolder) if subfolder else model_name_or_path
128
+ return cls(path, model_kwargs=model_kwargs, **config)
milco_encoder_config.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ {
2
+ "max_seq_length": 8192,
3
+ "source_view": true,
4
+ "chunk_size": 512
5
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:57c97e07b025c4a0b4a61ec2e2c12bfbbabd25e2e7cad9d854dc31e64dd852cc
3
+ size 1185323644
modules.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "idx": 0,
4
+ "name": "0",
5
+ "path": "",
6
+ "type": "milco_encoder.MilcoDualView"
7
+ }
8
+ ]
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:326c392f5799a1a73fb5118bac1e78bfc02ad3ca7f04c002cda9915721218c7d
3
+ size 17098339
tokenizer_config.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": true,
3
+ "backend": "tokenizers",
4
+ "bos_token": "<s>",
5
+ "clean_up_tokenization_spaces": true,
6
+ "cls_token": "<s>",
7
+ "eos_token": "</s>",
8
+ "is_local": true,
9
+ "local_files_only": false,
10
+ "mask_token": "<mask>",
11
+ "max_length": 8192,
12
+ "model_max_length": 8192,
13
+ "pad_to_multiple_of": null,
14
+ "pad_token": "<pad>",
15
+ "pad_token_type_id": 0,
16
+ "padding_side": "right",
17
+ "sep_token": "</s>",
18
+ "sp_model_kwargs": {},
19
+ "stride": 0,
20
+ "tokenizer_class": "XLMRobertaTokenizer",
21
+ "truncation_side": "right",
22
+ "truncation_strategy": "longest_first",
23
+ "unk_token": "<unk>"
24
+ }