Text Classification
Transformers
Safetensors
Russian
English
multilingual
modernbert
feature-extraction
zero-shot-classification
typed-decision
russian
routing
intent-classification
calibrated
calibration
on-prem
cpu
mmbert
text-embeddings-inference
Instructions to use besktech/ru-jev with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use besktech/ru-jev with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="besktech/ru-jev")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModel tokenizer = AutoTokenizer.from_pretrained("besktech/ru-jev") model = AutoModel.from_pretrained("besktech/ru-jev", device_map="auto") - Notebooks
- Google Colab
- Kaggle
card for v1.3: measured numbers only, jargon row explained
Browse files
README.md
CHANGED
|
@@ -22,7 +22,7 @@ base_model: jhu-clsp/mmBERT-base
|
|
| 22 |
inference: false
|
| 23 |
---
|
| 24 |
|
| 25 |
-
# Ру-Жев (Ru-Jev) v1.
|
| 26 |
|
| 27 |
Open, Russian-first typed-decision model. It does not generate text. Given a
|
| 28 |
context and a set of candidate options, it returns a calibrated probability over
|
|
@@ -33,8 +33,8 @@ runs on CPU and can be deployed inside a closed perimeter.
|
|
| 33 |
Project page: https://ru-jev.besk.tech
|
| 34 |
Training and evaluation code: https://github.com/beskvladimir-create/ru-jev
|
| 35 |
|
| 36 |
-
|
| 37 |
-
`revision="v1"` if you depend on its exact behaviour.
|
| 38 |
|
| 39 |
The inference widget is switched off on purpose. This is a backbone plus a
|
| 40 |
separate scoring head, not a standard sequence-classification checkpoint, so the
|
|
@@ -44,195 +44,281 @@ stock widget cannot load it. Use the snippet below.
|
|
| 44 |
trained from scratch on open, human-labelled datasets. The name is a play on the
|
| 45 |
category, not a claim of compatibility or endorsement.
|
| 46 |
|
| 47 |
-
## What changed since v1
|
| 48 |
|
| 49 |
-
v1
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
| --- | --- | --- |
|
| 55 |
-
|
|
| 56 |
-
|
|
| 57 |
-
|
|
| 58 |
-
|
|
| 59 |
-
|
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
|
|
|
|
|
|
| 70 |
|
| 71 |
## Results
|
| 72 |
|
| 73 |
-
|
| 74 |
-
|
| 75 |
|
| 76 |
| Metric | Value |
|
| 77 |
| --- | --- |
|
| 78 |
-
| Accuracy (micro) | 0.
|
| 79 |
-
| ECE, temperature fitted on a disjoint half | 0.
|
| 80 |
| ECE, temperature fitted on this same data | 0.0159 |
|
| 81 |
-
| Shipped temperature |
|
| 82 |
|
| 83 |
Two ECE figures, because the number depends on where the temperature came from.
|
| 84 |
Fitting and scoring on the same rows is in-sample and optimistic. The first
|
| 85 |
figure is what to expect on new data of the same kind, and it is the one to
|
| 86 |
quote.
|
| 87 |
|
| 88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
|
| 90 |
-
| Task |
|
| 91 |
| --- | --- | --- |
|
| 92 |
-
|
|
| 93 |
-
|
|
| 94 |
-
| massive_scenario
|
| 95 |
-
|
|
| 96 |
-
|
|
| 97 |
-
|
|
| 98 |
-
|
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
|
| 106 |
## Name your options carefully
|
| 107 |
|
| 108 |
-
The model reads the option text
|
| 109 |
-
|
| 110 |
-
eighteen categories every time, only the wording differs:
|
| 111 |
|
| 112 |
-
|
|
| 113 |
-
| --- | --- | --- |
|
| 114 |
-
|
|
| 115 |
-
|
|
| 116 |
-
|
|
| 117 |
-
|
|
| 118 |
-
| Department name
|
| 119 |
-
|
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
must use in-house jargon, measure it on your own data first with
|
| 126 |
-
`scripts/robustness.py` from the code repository.
|
| 127 |
|
| 128 |
## Withholding an answer
|
| 129 |
|
| 130 |
-
A calibrated probability is worth something only if the caller acts on it.
|
| 131 |
-
|
| 132 |
-
|
| 133 |
|
| 134 |
-
| Share answered
|
| 135 |
| --- | --- | --- | --- |
|
| 136 |
-
|
|
| 137 |
-
|
|
| 138 |
-
|
|
| 139 |
-
| 80% | 0.
|
| 140 |
-
|
|
|
|
|
| 141 |
|
| 142 |
-
|
| 143 |
-
the entire stream, while yes/no questions and small choices clear about half.
|
| 144 |
|
| 145 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
| russe | 0.631 | 0.701 | 0.822 |
|
| 154 |
-
| georeview | 0.199 | 0.544 | 0.629 |
|
| 155 |
-
| rureviews | 0.324 | 0.720 | 0.772 |
|
| 156 |
-
| rucola | 0.587 | 0.609 | 0.650 |
|
| 157 |
-
| toxicity | 0.766 | 0.943 | 0.961 |
|
| 158 |
-
| rwsd | 0.554 | 0.554 | 0.564 |
|
| 159 |
-
|
| 160 |
-
The model earns its place on routing, entailment and yes/no questions. On
|
| 161 |
-
toxicity it is 1.8 points over character n-grams and on sentiment 5.2 points,
|
| 162 |
-
so for those tasks alone a linear model is cheaper to run and easier to debug.
|
| 163 |
|
| 164 |
-
|
|
|
|
|
|
|
| 165 |
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
encoder does not chain inferences, and no amount of further training on this
|
| 170 |
-
architecture will change that.
|
| 171 |
-
- **Unfamiliar label wording degrades both the answer and the confidence**, as
|
| 172 |
-
the table above shows.
|
| 173 |
-
- Russian first. The multilingual base handles other languages, but they were
|
| 174 |
-
not measured.
|
| 175 |
|
| 176 |
## Speed on CPU
|
| 177 |
|
| 178 |
-
Apple M4,
|
| 179 |
-
float32.
|
| 180 |
-
|
| 181 |
-
| Request | Tokens | Median | p95 |
|
| 182 |
-
| --- | --- | --- | --- |
|
| 183 |
-
| yes/no, short context | 23 | 24.5 ms | 26.5 ms |
|
| 184 |
-
| choice of three | 17 | 31.2 ms | 32.6 ms |
|
| 185 |
-
| yes/no, full 256-token context | 315, truncated to 256 | 133.2 ms | 141.1 ms |
|
| 186 |
|
| 187 |
-
|
| 188 |
-
|
|
|
|
|
|
|
|
|
|
| 189 |
|
| 190 |
## Usage
|
| 191 |
|
| 192 |
```python
|
| 193 |
-
import torch, torch.nn as nn
|
| 194 |
-
from transformers import AutoTokenizer, AutoModel
|
| 195 |
from huggingface_hub import hf_hub_download
|
|
|
|
| 196 |
|
| 197 |
REPO = "besktech/ru-jev"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
tok = AutoTokenizer.from_pretrained(REPO)
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
decide("Клиента списали дважды", ["да", "нет"])
|
| 213 |
-
decide("Не приходит счёт", ["оплата, счета и возвраты", "техническая проблема"])
|
| 214 |
-
decide("Отличный сервис, всё быстро", ["негативный", "нейтральный", "позитивный"])
|
| 215 |
```
|
| 216 |
|
| 217 |
-
|
|
|
|
| 218 |
|
| 219 |
-
|
| 220 |
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
- RuCoLA (Apache-2.0 labels): acceptability
|
| 228 |
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
|
| 233 |
## License
|
| 234 |
|
| 235 |
-
MIT.
|
| 236 |
|
| 237 |
Vladimir Beskorovainyi, Enterprise AI Architect & CTO, author of the Amazon
|
| 238 |
bestseller "Enterprise AI: The KATA Way", founder of Besk Tech (besk.tech)
|
|
|
|
| 22 |
inference: false
|
| 23 |
---
|
| 24 |
|
| 25 |
+
# Ру-Жев (Ru-Jev) v1.3
|
| 26 |
|
| 27 |
Open, Russian-first typed-decision model. It does not generate text. Given a
|
| 28 |
context and a set of candidate options, it returns a calibrated probability over
|
|
|
|
| 33 |
Project page: https://ru-jev.besk.tech
|
| 34 |
Training and evaluation code: https://github.com/beskvladimir-create/ru-jev
|
| 35 |
|
| 36 |
+
Earlier releases are kept on branches: `v1.1` and `v1`. Load one with
|
| 37 |
+
`revision="v1.1"` if you depend on its exact behaviour.
|
| 38 |
|
| 39 |
The inference widget is switched off on purpose. This is a backbone plus a
|
| 40 |
separate scoring head, not a standard sequence-classification checkpoint, so the
|
|
|
|
| 44 |
trained from scratch on open, human-labelled datasets. The name is a play on the
|
| 45 |
category, not a claim of compatibility or endorsement.
|
| 46 |
|
| 47 |
+
## What changed since v1.1
|
| 48 |
|
| 49 |
+
v1.1 read the option text, which is the point of the design, but it read it
|
| 50 |
+
narrowly. It had learned the exact wordings its training data used. Rename a
|
| 51 |
+
category and accuracy fell off a cliff: 0.956 when a scenario was called
|
| 52 |
+
`погода`, 0.633 when the same scenario was called `вэзер`. Worse, on the
|
| 53 |
+
unfamiliar wording it stayed confident while being wrong, so the probability
|
| 54 |
+
stopped carrying information exactly where a caller needed it most.
|
| 55 |
|
| 56 |
+
v1.3 ships every fixed option set in several wordings and draws one per example,
|
| 57 |
+
so the model has to read an option instead of recognising it. For the routing
|
| 58 |
+
tasks that includes the English key written in Cyrillic and a clipped form of
|
| 59 |
+
it, generated by rule.
|
| 60 |
+
|
| 61 |
+
| Option wording | v1.1 | v1.3 |
|
| 62 |
| --- | --- | --- |
|
| 63 |
+
| Russian word, `погода` | 0.956 | 0.960 |
|
| 64 |
+
| English key, `weather` | 0.957 | 0.962 |
|
| 65 |
+
| Descriptive sentence | 0.939 | 0.958 |
|
| 66 |
+
| Russian phrase, `прогноз погоды` | 0.881 | 0.957 |
|
| 67 |
+
| Department name, `метеослужба` | 0.835 | 0.869 |
|
| 68 |
+
| Jargon, `вэзер` | 0.633 | 0.855 |
|
| 69 |
+
|
| 70 |
+
A thousand routing questions per row, the same eighteen categories every time,
|
| 71 |
+
only the wording differs.
|
| 72 |
+
|
| 73 |
+
One caveat on the jargon row, because it is the headline number. An intent key
|
| 74 |
+
begins with its scenario name, so three of the eighteen jargon labels coincide
|
| 75 |
+
with what the transliteration rule produces and reach training as a first word.
|
| 76 |
+
On the fifteen that do not coincide, which is the honest measure of
|
| 77 |
+
generalisation to wording the model has never seen, v1.3 scores 0.838 against 0.624 for v1.1.
|
| 78 |
+
The rules were not tuned against this test vocabulary; `scripts/robustness.py`
|
| 79 |
+
in the code repository reports both figures.
|
| 80 |
|
| 81 |
## Results
|
| 82 |
|
| 83 |
+
v1.3 on its own validation split, 13,373 decisions, with the temperature
|
| 84 |
+
fitted on the other half:
|
| 85 |
|
| 86 |
| Metric | Value |
|
| 87 |
| --- | --- |
|
| 88 |
+
| Accuracy (micro) | 0.823 |
|
| 89 |
+
| ECE, temperature fitted on a disjoint half | 0.0185 |
|
| 90 |
| ECE, temperature fitted on this same data | 0.0159 |
|
| 91 |
+
| Shipped temperature | 1.8640 |
|
| 92 |
|
| 93 |
Two ECE figures, because the number depends on where the temperature came from.
|
| 94 |
Fitting and scoring on the same rows is in-sample and optimistic. The first
|
| 95 |
figure is what to expect on new data of the same kind, and it is the one to
|
| 96 |
quote.
|
| 97 |
|
| 98 |
+
### Why most of the comparison with v1.1 had to be thrown away
|
| 99 |
+
|
| 100 |
+
Two things stood between the two releases, and both were found by checking
|
| 101 |
+
rather than by reasoning.
|
| 102 |
+
|
| 103 |
+
The data builder carved each task's validation slice by shuffling that task's
|
| 104 |
+
pool with a module-level random generator, seeded once and consumed by every
|
| 105 |
+
other random call in the file. Adding two label styles to one task changed how
|
| 106 |
+
many bits those draws consumed, the stream diverged from that point, and every
|
| 107 |
+
task below it in the build order received a different slice. Measured: of
|
| 108 |
+
v1.3's validation rows, 90.3% of rucola and 89.8% of mera_qa had been in v1.1's
|
| 109 |
+
training set, along with 47.2% of georeview and 21.7% of toxicity.
|
| 110 |
+
|
| 111 |
+
The second is the point of this release working against its own measurement.
|
| 112 |
+
Where v1.3 ships an option set in several wordings, its validation rows carry
|
| 113 |
+
wordings v1.1 never trained on. Scoring v1.1 there measures how well it handles
|
| 114 |
+
renamed options, which is a real question but not the question a per-task
|
| 115 |
+
accuracy table is asking. Comparing by text alone hides this, so the rows were
|
| 116 |
+
compared by text and option wordings together.
|
| 117 |
|
| 118 |
+
| Task | Same rows | Same rows and same option wordings |
|
| 119 |
| --- | --- | --- |
|
| 120 |
+
| terra, danetqa, russe, rwsd, parus, rcb | 100% | 100% |
|
| 121 |
+
| rureviews | 100% | 19.6% |
|
| 122 |
+
| massive_scenario, massive_intent | 63% | 0% |
|
| 123 |
+
| mera_qa | 10.6% | 10.6% |
|
| 124 |
+
| rucola | 9.7% | 9.7% |
|
| 125 |
+
| georeview | 5.3% | 1.5% |
|
| 126 |
+
| toxicity | 2.4% | 0.4% |
|
| 127 |
+
|
| 128 |
+
What this cost in published claims is worth stating plainly. An early draft of
|
| 129 |
+
this card read rucola 0.909 against 0.647 and mera_qa 0.939 against 0.596, both
|
| 130 |
+
of which were v1.1 being scored on its own training data. It also read toxicity
|
| 131 |
+
0.722 against 0.954 as a gain in capability, when v1.1 scores 0.961 on toxicity
|
| 132 |
+
against the wordings it trained on; 0.722 is that same model with the labels
|
| 133 |
+
renamed. None of those three numbers belonged in a per-task accuracy table.
|
| 134 |
+
|
| 135 |
+
The builder now seeds each carve from the task name, so a wording change in one
|
| 136 |
+
task can no longer move the split in another.
|
| 137 |
+
|
| 138 |
+
### Six tasks measured on identical rows with identical option wordings
|
| 139 |
+
|
| 140 |
+
| Metric, six comparable tasks | v1.1 | v1.3 |
|
| 141 |
+
| --- | --- | --- |
|
| 142 |
+
| Accuracy (micro) | 0.7948 | 0.7920 |
|
| 143 |
+
| ECE, temperature fitted on the other half | 0.0172 | 0.0160 |
|
| 144 |
+
|
| 145 |
+
Scored on 5,078 decisions, half of the six comparable tasks, with each model's temperature fitted on the other half. The accuracy difference is -0.0028, which is 0.3 standard errors and therefore nothing.
|
| 146 |
+
|
| 147 |
+
| Task | v1.1 | v1.3 | n |
|
| 148 |
+
| --- | --- | --- | --- |
|
| 149 |
+
| russe (word sense) | 0.822 | 0.824 | 8505 |
|
| 150 |
+
| danetqa (yes/no) | 0.742 | 0.753 | 821 |
|
| 151 |
+
| terra (entailment) | 0.775 | 0.733 | 307 |
|
| 152 |
+
| parus (choice) | 0.680 | 0.590 | 100 |
|
| 153 |
+
| rcb (3-way NLI) | 0.450 | 0.509 | 220 |
|
| 154 |
+
| rwsd (coreference) | 0.564 | 0.480 | 204 |
|
| 155 |
+
|
| 156 |
+
On the only ground where the two releases can be compared directly, they are
|
| 157 |
+
the same model for accuracy. v1.3 is not more accurate than v1.1 and this
|
| 158 |
+
release does not claim to be. What it is, is far less dependent on how the
|
| 159 |
+
options are worded, and slightly better calibrated with a temperature of
|
| 160 |
+
1.8640 against 2.2754, meaning less of the confidence has to be flattened
|
| 161 |
+
away after the fact.
|
| 162 |
+
|
| 163 |
+
### The remaining seven tasks, each model on its own held-out slice
|
| 164 |
+
|
| 165 |
+
No shared rows exist for these, so each column is that model's own validation
|
| 166 |
+
slice scored with its own option wordings. That is an honest measurement of
|
| 167 |
+
each model separately and a weak comparison between them.
|
| 168 |
+
|
| 169 |
+
| Task | v1.1, own slice | v1.3, own slice | n |
|
| 170 |
+
| --- | --- | --- | --- |
|
| 171 |
+
| massive_intent (60 labels) | not measured | 0.960 | 3000 |
|
| 172 |
+
| massive_scenario (18 labels) | not measured | 0.955 | 3000 |
|
| 173 |
+
| toxicity | 0.961 | 0.954 | 3000 |
|
| 174 |
+
| rureviews (sentiment) | not measured | 0.774 | 3000 |
|
| 175 |
+
| rucola (acceptability) | 0.650 | 0.647 | 1344 |
|
| 176 |
+
| georeview (5 levels) | 0.629 | 0.631 | 3000 |
|
| 177 |
+
| mera_qa (reasoning) | 0.522 | 0.596 | 245 |
|
| 178 |
+
|
| 179 |
+
## Four epochs were trained and the third was shipped
|
| 180 |
+
|
| 181 |
+
The run went four epochs and each one was kept. The fourth overfits: training
|
| 182 |
+
loss fell to 0.085 while validation loss rose from 0.483 to 0.820, and a
|
| 183 |
+
temperature fitted on it comes out at 3.92, which is what overconfidence looks
|
| 184 |
+
like as a number.
|
| 185 |
+
|
| 186 |
+
| Epoch | Training loss | Validation loss | Validation accuracy |
|
| 187 |
+
| --- | --- | --- | --- |
|
| 188 |
+
| 1 | 0.6029 | 0.5054 | 0.7536 |
|
| 189 |
+
| 2 | 0.4336 | 0.4576 | 0.7920 |
|
| 190 |
+
| 3 | 0.2714 | 0.4831 | 0.8181 |
|
| 191 |
+
| 4 | 0.0849 | 0.8204 | 0.8139 |
|
| 192 |
+
|
| 193 |
+
The shipped weights are the third epoch. Had only the last checkpoint been kept,
|
| 194 |
+
the released model would have been the worse one and nothing would have shown it.
|
| 195 |
|
| 196 |
## Name your options carefully
|
| 197 |
|
| 198 |
+
The model reads the option text, so wording still matters, just much less than
|
| 199 |
+
it did.
|
|
|
|
| 200 |
|
| 201 |
+
| Option wording | Accuracy | Confident errors |
|
| 202 |
+
| --- | --- | --- |
|
| 203 |
+
| English key, `weather` | 0.962 | 26 |
|
| 204 |
+
| Russian word, `погода` | 0.960 | 19 |
|
| 205 |
+
| Russian phrase, `прогноз погоды` | 0.957 | 14 |
|
| 206 |
+
| Jargon, `вэзер` | 0.855 | 44 |
|
| 207 |
+
| Department name, `метеослужба` | 0.869 | 52 |
|
| 208 |
+
| Descriptive sentence | 0.958 | 16 |
|
| 209 |
+
|
| 210 |
+
The last column counts answers that were wrong while above 0.8 confidence.
|
| 211 |
+
Write options as ordinary words that describe the category. If you use in-house
|
| 212 |
+
jargon, measure it on your own data first with `scripts/robustness.py` from the
|
| 213 |
+
code repository rather than assuming it transfers.
|
|
|
|
|
|
|
| 214 |
|
| 215 |
## Withholding an answer
|
| 216 |
|
| 217 |
+
A calibrated probability is worth something only if the caller acts on it. Set a
|
| 218 |
+
confidence threshold, answer above it and send the rest to a human. The serving
|
| 219 |
+
API takes a `threshold` and returns the withheld decisions in a review list.
|
| 220 |
|
| 221 |
+
| Share answered | Confidence threshold | Accuracy on those | Errors per 1000 |
|
| 222 |
| --- | --- | --- | --- |
|
| 223 |
+
| 50% | 0.85 | 0.967 | 33 |
|
| 224 |
+
| 60% | 0.77 | 0.947 | 53 |
|
| 225 |
+
| 70% | 0.69 | 0.921 | 79 |
|
| 226 |
+
| 80% | 0.61 | 0.892 | 108 |
|
| 227 |
+
| 90% | 0.54 | 0.859 | 141 |
|
| 228 |
+
| 100% | 0.23 | 0.823 | 177 |
|
| 229 |
|
| 230 |
+
## Limitations
|
|
|
|
| 231 |
|
| 232 |
+
Hard reasoning tasks with small training sets remain weak and are not fixed by
|
| 233 |
+
anything in this release: `rwsd` coreference, `rcb` three-way inference and
|
| 234 |
+
`parus` causal choice all train on fewer than a thousand rows each. For a 307M
|
| 235 |
+
encoder that is a size limit, not a data-wording limit. A larger backbone was
|
| 236 |
+
tried once, xlm-roberta-large at 560M, and lost to v1.
|
| 237 |
|
| 238 |
+
Those same tasks are where the two releases differ most in the comparable
|
| 239 |
+
table, and in both directions: v1.3 is 0.059 above v1.1 on `rcb` and 0.084 and
|
| 240 |
+
0.090 below it on `rwsd` and `parus`. Their validation slices hold 220, 204 and
|
| 241 |
+
100 rows, so one standard error is roughly 0.03 to 0.05 and none of those three
|
| 242 |
+
gaps is far outside it. Read them as scatter, not as a trend, and do not plan
|
| 243 |
+
around either direction.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 244 |
|
| 245 |
+
The model answers only within the option set it is given. It cannot say that
|
| 246 |
+
none of the options fit, so include an explicit "none of these" option when that
|
| 247 |
+
outcome is possible.
|
| 248 |
|
| 249 |
+
Probabilities are calibrated in aggregate, not per task. A single temperature
|
| 250 |
+
serves all thirteen tasks, so a task far from the mix average can be
|
| 251 |
+
systematically over or under confident.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 252 |
|
| 253 |
## Speed on CPU
|
| 254 |
|
| 255 |
+
Apple M4, 4 threads, float32, median of 25 runs:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 256 |
|
| 257 |
+
| Decision | Latency |
|
| 258 |
+
| --- | --- |
|
| 259 |
+
| Short yes/no | 25 ms |
|
| 260 |
+
| Choice from three options | 31 ms |
|
| 261 |
+
| Full 256-token context | 131 ms |
|
| 262 |
|
| 263 |
## Usage
|
| 264 |
|
| 265 |
```python
|
| 266 |
+
import json, torch, torch.nn as nn
|
|
|
|
| 267 |
from huggingface_hub import hf_hub_download
|
| 268 |
+
from transformers import AutoModel, AutoTokenizer
|
| 269 |
|
| 270 |
REPO = "besktech/ru-jev"
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
class Scorer(nn.Module):
|
| 274 |
+
def __init__(self, repo):
|
| 275 |
+
super().__init__()
|
| 276 |
+
self.backbone = AutoModel.from_pretrained(repo)
|
| 277 |
+
self.head = nn.Linear(self.backbone.config.hidden_size, 1)
|
| 278 |
+
self.head.load_state_dict(
|
| 279 |
+
torch.load(hf_hub_download(repo, "head.pt"), map_location="cpu"))
|
| 280 |
+
|
| 281 |
+
def forward(self, ids, mask):
|
| 282 |
+
cls = self.backbone(input_ids=ids, attention_mask=mask).last_hidden_state[:, 0]
|
| 283 |
+
return self.head(cls).squeeze(-1)
|
| 284 |
+
|
| 285 |
+
|
| 286 |
+
calib = json.load(open(hf_hub_download(REPO, "calibration.json")))
|
| 287 |
+
T = calib["temperature"]
|
| 288 |
tok = AutoTokenizer.from_pretrained(REPO)
|
| 289 |
+
model = Scorer(REPO).eval()
|
| 290 |
+
|
| 291 |
+
context = "Приложение падает при входе после обновления."
|
| 292 |
+
options = ["техническая проблема", "оплата, счета и возвраты", "продажи"]
|
| 293 |
+
|
| 294 |
+
with torch.no_grad():
|
| 295 |
+
enc = tok([context] * len(options), options, truncation=True,
|
| 296 |
+
max_length=calib["max_len"], padding=True, return_tensors="pt")
|
| 297 |
+
probs = torch.softmax(model(enc["input_ids"], enc["attention_mask"]) / T, dim=0)
|
| 298 |
+
|
| 299 |
+
for option, p in zip(options, probs.tolist()):
|
| 300 |
+
print(f"{p:.3f} {option}")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 301 |
```
|
| 302 |
|
| 303 |
+
Divide by the shipped temperature before the softmax. Without it the
|
| 304 |
+
probabilities are overconfident and the threshold logic above does not hold.
|
| 305 |
|
| 306 |
+
## Training data
|
| 307 |
|
| 308 |
+
Thirteen tasks from open Russian datasets, 143,991 training and 26,746
|
| 309 |
+
validation decisions. Russian SuperGLUE (`terra`, `danetqa`, `russe`, `rwsd`,
|
| 310 |
+
`parus`, `rcb`), RuCoLA, MERA (`ruopenbookqa`, `ruworldtree`), MTEB Russian
|
| 311 |
+
(`RuReviewsClassification`, `GeoreviewClassification`, `amazon_massive_intent`,
|
| 312 |
+
`amazon_massive_scenario`) and `rudetoxifier_data`. Each source keeps its own
|
| 313 |
+
licence; see `DATASETS.md` in the code repository.
|
|
|
|
| 314 |
|
| 315 |
+
Every fixed option set ships in several wordings. The builder verifies that all
|
| 316 |
+
thirteen tasks are present and refuses to write the data if any is short, which
|
| 317 |
+
exists because an earlier run silently trained on eleven.
|
| 318 |
|
| 319 |
## License
|
| 320 |
|
| 321 |
+
MIT, weights and code.
|
| 322 |
|
| 323 |
Vladimir Beskorovainyi, Enterprise AI Architect & CTO, author of the Amazon
|
| 324 |
bestseller "Enterprise AI: The KATA Way", founder of Besk Tech (besk.tech)
|