Kostya165 commited on
Commit
3d68cb6
·
verified ·
1 Parent(s): 70bd5f6

Upload folder using huggingface_hub

Browse files
.gitattributes CHANGED
@@ -33,3 +33,6 @@ saved_model/**/* 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
 
 
 
 
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
+ assets/leaderboard_gradient.png filter=lfs diff=lfs merge=lfs -text
37
+ assets/mrl_degradation.png filter=lfs diff=lfs merge=lfs -text
38
+ assets/ours_by_split.png filter=lfs diff=lfs merge=lfs -text
1_Pooling/config.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ {
2
+ "embedding_dimension": 768,
3
+ "pooling_mode": "mean",
4
+ "include_prompt": true
5
+ }
README.md ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ language:
4
+ - ru
5
+ library_name: sentence-transformers
6
+ pipeline_tag: sentence-similarity
7
+ base_model: deepvk/USER2-base
8
+ tags:
9
+ - sentence-transformers
10
+ - feature-extraction
11
+ - sentence-similarity
12
+ - code-retrieval
13
+ - 1c
14
+ - bsl
15
+ - matryoshka
16
+ - ru
17
+ model-index:
18
+ - name: USER2-1C-code
19
+ results:
20
+ - task:
21
+ type: retrieval
22
+ name: Code Retrieval
23
+ dataset:
24
+ type: PruhaNLP/1C-Ebench
25
+ name: 1C-Ebench (forum)
26
+ config: forum
27
+ split: test
28
+ metrics:
29
+ - type: ndcg_at_10
30
+ value: 0.4617
31
+ - type: recall_at_10
32
+ value: 0.6008
33
+ - type: mrr_at_10
34
+ value: 0.4178
35
+ - task:
36
+ type: retrieval
37
+ name: Code Retrieval
38
+ dataset:
39
+ type: PruhaNLP/1C-Ebench
40
+ name: 1C-Ebench (fastcode)
41
+ config: fastcode
42
+ split: test
43
+ metrics:
44
+ - type: ndcg_at_10
45
+ value: 0.7366
46
+ - type: recall_at_10
47
+ value: 0.9208
48
+ - type: mrr_at_10
49
+ value: 0.6774
50
+ ---
51
+
52
+ # USER2-1C-code
53
+
54
+ **Первая открытая эмбеддинг-модель, заточенная под код и язык 1С (1С:Предприятие / BSL).**
55
+
56
+ `USER2-1C-code` — это би-энкодер для семантического поиска по коду 1С: на вход подаётся вопрос на естественном языке, на выходе — релевантные фрагменты кода/решений. Модель — fine-tune [`deepvk/USER2-base`](https://huggingface.co/deepvk/USER2-base) (ModernBERT, контекст до 8192 токенов) на парах «вопрос → код 1С».
57
+
58
+
59
+ - **Тип:** bi-encoder (sentence-transformers), mean pooling, cosine similarity
60
+ - **База:** `deepvk/USER2-base` (ModernBERT, 768d, до 8192 токенов)
61
+ - **Языки:** русский + код 1С (BSL)
62
+ - **Matryoshka (MRL):** полноценные эмбеддинги на `768 / 512 / 384 / 256 / 128 / 64 / 32`
63
+ - **Префиксы:** `search_query` для запросов, `search_document` для кода
64
+
65
+ ## Результаты на 1C-Ebench
66
+
67
+ Бенчмарк [`PruhaNLP/1C-Ebench`](https://huggingface.co/datasets/PruhaNLP/1C-Ebench): retrieval по двум источникам — `forum` (живые вопросы с тематических площадок) и `fastcode` (готовые сниппеты/шаблоны). Метрика — nDCG@10.
68
+
69
+ ![Leaderboard](assets/leaderboard_gradient.png)
70
+
71
+ | Модель | avg nDCG@10 |
72
+ |---|---|
73
+ | **USER2-1C-code (наша)** | **0.599** |
74
+ | google/embeddinggemma-300m | 0.540 |
75
+ | deepvk/USER2-base | 0.493 |
76
+ | deepvk/USER-bge-m3 | 0.491 |
77
+ | ibm-granite/granite-embedding-311m-multilingual-r2 | 0.485 |
78
+ | microsoft/harrier-oss-v1-270m | 0.480 |
79
+ | intfloat/multilingual-e5-base | 0.429 |
80
+ | ai-forever/sbert_large_nlu_ru | 0.086 |
81
+
82
+ Прирост относительно базовой `deepvk/USER2-base` — **+0.106 avg nDCG@10** (0.493 → 0.599).
83
+
84
+ ### Детально по сплитам
85
+
86
+ ![Метрики по сплитам](assets/ours_by_split.png)
87
+
88
+ | Сплит | nDCG@10 | Recall@10 | MRR@10 |
89
+ |---|---|---|---|
90
+ | forum | 0.4617 | 0.6008 | 0.4178 |
91
+ | fastcode | 0.7366 | 0.9208 | 0.6774 |
92
+
93
+ ## Matryoshka (MRL): обрезаемые эмбеддинги
94
+
95
+ Модель обучена с `MatryoshkaLoss`, поэтому эмбеддинг можно усекать до меньшей размерности (взять первые `d` компонент и перенормировать) почти без потери качества. Это позволяет экономить память индекса и ускорять поиск.
96
+
97
+ ![MRL degradation](assets/mrl_degradation.png)
98
+
99
+ | dim | avg nDCG@10 | от полной 768d |
100
+ |---|---|---|
101
+ | 768 | 0.599 | 100.0% |
102
+ | 512 | 0.600 | 100.1% |
103
+ | 384 | 0.600 | 100.2% |
104
+ | 256 | 0.598 | 99.9% |
105
+ | 128 | 0.584 | 97.5% |
106
+ | 64 | 0.560 | 93.5% |
107
+ | 32 | 0.503 | 83.9% |
108
+
109
+ До **256d качество практически не падает** — можно смело уменьшать индекс втрое.
110
+
111
+ ## Использование
112
+
113
+ ```python
114
+ from sentence_transformers import SentenceTransformer
115
+
116
+ model = SentenceTransformer("PruhaNLP/USER2-1C-code")
117
+
118
+ query = "Как программно провести документ в 1С?"
119
+ docs = [
120
+ "Документы.РеализацияТоваровУслуг.СоздатьДокумент();",
121
+ "Процедура ПровестиДокумент(Ссылка) Экспорт ... КонецПроцедуры",
122
+ ]
123
+
124
+ q_emb = model.encode(query, prompt_name="search_query", normalize_embeddings=True)
125
+ d_emb = model.encode(docs, prompt_name="search_document", normalize_embeddings=True)
126
+
127
+ scores = model.similarity(q_emb, d_emb)
128
+ print(scores)
129
+ ```
130
+
131
+ Для MRL укажите целевую размерность:
132
+
133
+ ```python
134
+ model = SentenceTransformer("PruhaNLP/USER2-1C-code", truncate_dim=256)
135
+ ```
136
+
137
+ ## Кастомный токенайзер для при��атности
138
+
139
+ При подготовке данных персональные данные в коде/текстах не вырезаются грубо, а заменяются на отдельные **служебные токены**, которые модель видит как единый элемент (а не как ломаную последовательность сабтокенов):
140
+
141
+ | Сущность | Токен | Токенов после кодирования |
142
+ |---|---|---|
143
+ | Пути | `[PATH]` | 1 |
144
+ | Имена | `[PERSON]` | 1 |
145
+ | E-mail | `\|\|\|EMAIL_ADDRESS\|\|\|` | 1 |
146
+ | Телефон | `\|\|\|PHONE_NUMBER\|\|\|` | 1 |
147
+ | IP | `\|\|\|IP_ADDRESS\|\|\|` | 1 |
148
+
149
+ Свободные слоты словаря (`[unused0]`/`[unused1]`) переиспользованы под `[PATH]`/`[PERSON]`, а их эмбеддинги инициализированы средним по сабтокенам исходных строк. В результате анонимизация не ломает токенизацию и не плодит шум в последовательности — это аккуратно закрывает персональные данные и держит распределение входа стабильным.
150
+
151
+ ## Детали обучения
152
+
153
+ - **База:** `deepvk/USER2-base` (ModernBERT)
154
+ - **Лосс:** `CachedMultipleNegativesRankingLoss` (scale 20, hard-negatives) внутри `MatryoshkaLoss` по размерностям `[768, 512, 384, 256, 128, 64, 32]`
155
+ - **Хард-негативы:** майнинг по FAISS
156
+ - **LR-расписание:** трапеция (warmup → stable → cosine decay), peak LR 2e-5
157
+ - **Контекст:** до 8192 токенов, fp16
158
+ - **Префиксы:** `search_query` / `search_document`
159
+
160
+ ## Код валидации
161
+
162
+ Eval-харнесс и протокол воспроизведения метрик опубликованы отдельно:
163
+ [`github.com/PruhaNLP/1C-Ebench`](https://github.com/PruhaNLP/1C-Ebench).
164
+
165
+ ## Правовая информация
166
+
167
+ «1С», «1С:Предприятие» и связанные обозначения — товарные знаки ООО «1С». Проект является независимым, **не аффилирован с фирмой «1С»** и не одобрен ею. Названия используются исключительно для указания предметной области (номинативное использование). Модель и датасеты предоставляются «как есть», без гарантий. Если вы правообладатель и считаете, что какой-либо материал нарушает ваши права — напишите на контакт ниже, и он будет удалён.
168
+
169
+ ## Контакт для связи
170
+
171
+ `konstphx@gmail.com`
172
+
173
+ ## Цитирование
174
+
175
+ ```bibtex
176
+ @misc{user2_1c_code,
177
+ title = {USER2-1C-code: эмбеддинг-модель для поиска по коду 1С},
178
+ author = {PruhaNLP},
179
+ year = {2026},
180
+ url = {https://huggingface.co/PruhaNLP/USER2-1C-code}
181
+ }
182
+ ```
assets/leaderboard_gradient.png ADDED

Git LFS Details

  • SHA256: 390cc454b08f74eb36dc67746f8037426a2b211d908d3c575e8fac602314c64f
  • Pointer size: 131 Bytes
  • Size of remote file: 105 kB
assets/mrl_degradation.png ADDED

Git LFS Details

  • SHA256: fa6fe1d7c77f86825a8f3367eb176d439ff6cd74a928d6802961450edb58047f
  • Pointer size: 131 Bytes
  • Size of remote file: 139 kB
assets/ours_by_split.png ADDED

Git LFS Details

  • SHA256: 9150fcb4349ad476493407949cbc110ae19491fcdc75a46fc2a1cde409f11280
  • Pointer size: 131 Bytes
  • Size of remote file: 134 kB
config.json ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "activation_function": "gelu",
3
+ "allow_embedding_resizing": true,
4
+ "architectures": [
5
+ "ModernBertModel"
6
+ ],
7
+ "attention_bias": false,
8
+ "attention_dropout": 0.0,
9
+ "attention_layer": "rope",
10
+ "attention_probs_dropout_prob": 0.0,
11
+ "attn_out_bias": false,
12
+ "attn_out_dropout_prob": 0.1,
13
+ "attn_qkv_bias": false,
14
+ "bert_layer": "prenorm",
15
+ "bos_token_id": null,
16
+ "classifier_activation": "gelu",
17
+ "classifier_bias": false,
18
+ "classifier_dropout": 0.0,
19
+ "classifier_pooling": "cls",
20
+ "cls_token_id": 50281,
21
+ "compile_model": true,
22
+ "decoder_bias": true,
23
+ "deterministic_flash_attn": false,
24
+ "dtype": "float32",
25
+ "embed_dropout_prob": 0.0,
26
+ "embed_norm": true,
27
+ "embedding_dropout": 0.0,
28
+ "embedding_layer": "sans_pos",
29
+ "eos_token_id": null,
30
+ "final_norm": true,
31
+ "global_attn_every_n_layers": 3,
32
+ "head_pred_act": "gelu",
33
+ "hidden_act": "gelu",
34
+ "hidden_activation": "gelu",
35
+ "hidden_dropout_prob": 0.0,
36
+ "hidden_size": 768,
37
+ "init_method": "full_megatron",
38
+ "initializer_cutoff_factor": 2.0,
39
+ "initializer_range": 0.02,
40
+ "intermediate_size": 1152,
41
+ "layer_norm_eps": 1e-05,
42
+ "layer_types": [
43
+ "full_attention",
44
+ "sliding_attention",
45
+ "sliding_attention",
46
+ "full_attention",
47
+ "sliding_attention",
48
+ "sliding_attention",
49
+ "full_attention",
50
+ "sliding_attention",
51
+ "sliding_attention",
52
+ "full_attention",
53
+ "sliding_attention",
54
+ "sliding_attention",
55
+ "full_attention",
56
+ "sliding_attention",
57
+ "sliding_attention",
58
+ "full_attention",
59
+ "sliding_attention",
60
+ "sliding_attention",
61
+ "full_attention",
62
+ "sliding_attention",
63
+ "sliding_attention",
64
+ "full_attention"
65
+ ],
66
+ "local_attention": 256,
67
+ "local_attn_rotary_emb_base": 10000.0,
68
+ "loss_function": "fa_cross_entropy",
69
+ "loss_kwargs": {
70
+ "reduction": "mean"
71
+ },
72
+ "masked_prediction": true,
73
+ "max_position_embeddings": 8192,
74
+ "mlp_bias": false,
75
+ "mlp_dropout": 0.0,
76
+ "mlp_dropout_prob": 0.0,
77
+ "mlp_in_bias": false,
78
+ "mlp_layer": "glu",
79
+ "mlp_out_bias": false,
80
+ "model_type": "modernbert",
81
+ "norm_bias": false,
82
+ "norm_eps": 1e-05,
83
+ "norm_kwargs": {
84
+ "bias": false,
85
+ "eps": 1e-05
86
+ },
87
+ "normalization": "layernorm",
88
+ "num_attention_heads": 12,
89
+ "num_hidden_layers": 22,
90
+ "pad_token_id": 50283,
91
+ "padding": "unpadded",
92
+ "repad_logits_with_grad": false,
93
+ "rope_parameters": {
94
+ "full_attention": {
95
+ "rope_theta": 160000.0,
96
+ "rope_type": "default"
97
+ },
98
+ "sliding_attention": {
99
+ "rope_theta": 10000.0,
100
+ "rope_type": "default"
101
+ }
102
+ },
103
+ "rotary_emb_base": 160000.0,
104
+ "rotary_emb_dim": null,
105
+ "rotary_emb_interleaved": false,
106
+ "rotary_emb_scale_base": null,
107
+ "sep_token_id": 50282,
108
+ "skip_first_prenorm": true,
109
+ "sparse_pred_ignore_index": -100,
110
+ "sparse_prediction": false,
111
+ "tie_word_embeddings": true,
112
+ "transformers_version": "5.1.0",
113
+ "unpad_embeddings": true,
114
+ "use_cache": false,
115
+ "vocab_size": 50368
116
+ }
config_sentence_transformers.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "__version__": {
3
+ "pytorch": "2.8.0+cu128",
4
+ "sentence_transformers": "5.5.1",
5
+ "transformers": "5.1.0"
6
+ },
7
+ "default_prompt_name": null,
8
+ "model_type": "SentenceTransformer",
9
+ "prompts": {
10
+ "classification": "classification: ",
11
+ "clustering": "clustering: ",
12
+ "document": "",
13
+ "query": "",
14
+ "search_document": "search_document: ",
15
+ "search_query": "search_query: "
16
+ },
17
+ "similarity_fn_name": "cosine"
18
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bd09b757bf568b446b88789b4fa57e4487a8d119d9f755691affaa01d34bf13b
3
+ size 596070136
modules.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "idx": 0,
4
+ "name": "0",
5
+ "path": "",
6
+ "type": "sentence_transformers.base.modules.transformer.Transformer"
7
+ },
8
+ {
9
+ "idx": 1,
10
+ "name": "1",
11
+ "path": "1_Pooling",
12
+ "type": "sentence_transformers.sentence_transformer.modules.pooling.Pooling"
13
+ }
14
+ ]
sentence_bert_config.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "transformer_task": "feature-extraction",
3
+ "modality_config": {
4
+ "text": {
5
+ "method": "forward",
6
+ "method_output_name": "last_hidden_state"
7
+ }
8
+ },
9
+ "module_output_name": "token_embeddings"
10
+ }
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "clean_up_tokenization_spaces": true,
4
+ "cls_token": "[CLS]",
5
+ "is_local": true,
6
+ "mask_token": "[MASK]",
7
+ "max_length": 2048,
8
+ "model_input_names": [
9
+ "input_ids",
10
+ "attention_mask"
11
+ ],
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": "[SEP]",
18
+ "stride": 0,
19
+ "tokenizer_class": "TokenizersBackend",
20
+ "truncation_side": "right",
21
+ "truncation_strategy": "longest_first",
22
+ "unk_token": "[UNK]"
23
+ }