ai-forever commited on
Commit
13534af
·
0 Parent(s):

FRIDA-Decisions: bf16 weights, head, int8 ONNX, model card

Browse files
.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,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ language:
4
+ - ru
5
+ - en
6
+ base_model: ai-forever/FRIDA
7
+ base_model_relation: finetune
8
+ pipeline_tag: text-classification
9
+ library_name: frida-decisions
10
+ tags:
11
+ - decisions
12
+ - routing
13
+ - intent-classification
14
+ - guardrails
15
+ - zero-shot-classification
16
+ - reranking
17
+ - encoder
18
+ - russian
19
+ ---
20
+
21
+ # FRIDA-Decisions
22
+
23
+ **FRIDA-Decisions** makes structured decisions over Russian text in a single encoder pass: pick one of K options, place a text on an ordinal scale, answer yes / no, or rank candidates. The options are written as text inside the request, so a new label set is a new JSON, not a new training run. No generation, no output tokens, no parsing: every answer is one of the declared options, with its confidence.
24
+
25
+ It is built on [ai-forever/FRIDA](https://huggingface.co/ai-forever/FRIDA) (T5 encoder, 823M parameters) and runs on a consumer GPU.
26
+
27
+ * **razvilka.** 0.890 on [razvilka](https://huggingface.co/datasets/artemsnegirev/razvilka) (735 items); TypeSafe Jev, a commercial API, scores 0.897 on the same items (paired McNemar p = 0.68). The highest among the open models we ran on razvilka.
28
+ * **Fast.** About 30–45 ms per request on an RTX 5060 Ti, in process; exact conditions in the latency table below.
29
+ * **Cheap to run.** 4.3 GiB of GPU memory at peak; an int8 ONNX build runs on CPU.
30
+ * **Packing.** All options of all questions share one sequence and the text is encoded once; with the state cache a follow-up question about the same text costs only its own tokens. A catalog of 243 intents is answered in 0.44 s, against 4.65 s for one sequence per option.
31
+
32
+ ## Quickstart
33
+
34
+ ```bash
35
+ pip install "frida-decisions[torch] @ git+https://github.com/ai-forever/frida-decisions"
36
+ ```
37
+
38
+ ```python
39
+ from frida_decisions import Judge
40
+
41
+ judge = Judge.from_pretrained("ai-forever/FRIDA-Decisions", device="cuda")
42
+
43
+ request = {
44
+ "state": "Здравствуйте, у меня не приходит код подтверждения уже час.",
45
+ "questions": {
46
+ "topic": {
47
+ "type": "choice",
48
+ "instructions": "К какой теме относится обращение?",
49
+ "criteria": {
50
+ "login": "вход в аккаунт, коды подтверждения, пароли",
51
+ "payment": "оплата, списания, возвраты",
52
+ "delivery": "доставка заказа",
53
+ },
54
+ },
55
+ "urgency": {
56
+ "type": "score",
57
+ "instructions": "Оцени срочность обращения.",
58
+ "criteria": ["низкая", "средняя", "высокая"],
59
+ },
60
+ "spam": {
61
+ "type": "noul",
62
+ "instructions": "Является ли сообщение спамом?",
63
+ "criteria": {"true": "реклама, чужие ссылки, просьба перевести деньги",
64
+ "false": "вопрос или жалоба по нашему сервису"},
65
+ },
66
+ },
67
+ }
68
+ print(judge.judge(request)["answers"])
69
+ ```
70
+
71
+ CPU without PyTorch: `pip install "frida-decisions[onnx] @ git+..."` and `OnnxJudge.from_pretrained("ai-forever/FRIDA-Decisions")` — int8 weights and per-token int8 activations; its decisions agree with the fp32 model on 120 of 122 test decisions, and a 384-token request with 3 questions takes 0.88 s on 6 CPU threads (2.6x faster than fp32).
72
+
73
+ ## Question types
74
+
75
+ | type | asks | returns |
76
+ |---|---|---|
77
+ | `choice` | which of K options is right | the option key and a distribution over all options |
78
+ | `score` | where the text sits on an ordinal scale | a level 0..K−1 and its distribution |
79
+ | `noul` | is a statement true | `p(true)` |
80
+ | `ranking` | order candidates for a query | the order and a margin per candidate |
81
+
82
+ Texts up to 512 tokens are the recommended range.
83
+
84
+ ## Benchmarks
85
+
86
+ **razvilka** — 735 Russian items, 15 tasks (routing, intents, topic and sentiment classification, moderation, relevance ranking), all four question types, gold from published datasets. All models are run on the same requests and scored with the same script ([razvilka_eval.py](https://github.com/ai-forever/frida-decisions/tree/main/benchmarks/razvilka)).
87
+
88
+ | model | parameters | accuracy |
89
+ |---|--:|--:|
90
+ | TypeSafe Jev (commercial API) | — | 0.897 |
91
+ | **FRIDA-Decisions** | 823M | **0.890** |
92
+ | smolnikov/migom-2b | 1.9B | 0.853 |
93
+ | Mapika/decider-2b | 1.9B | 0.833 |
94
+ | smolnikov/kivok-0.3b | 0.3B | 0.619 |
95
+ | fastino/GLiNER2.5-multi-Decide | 287M | 0.576 |
96
+ | convaiinnovations/laya (multilingual) | — | 0.559 |
97
+ | KaLM-Reranker-V1-Nano-R2 | 786M | 0.521 |
98
+ | open-jev (DeBERTa-v3-large) | 437M | 0.490¹ |
99
+ | lexical baseline | — | 0.333 |
100
+ | chance | — | 0.257 |
101
+
102
+ ¹ 140 of 735 texts exceed open-jev's input window and count as random answers; on the other 595 it scores 0.565.
103
+
104
+ **Latency**, one request, single stream, in process:
105
+
106
+ | hardware | request | time |
107
+ |---|---|--:|
108
+ | RTX 5060 Ti, bf16 | 384-token state, 1 question | 31.9 ms² |
109
+ | RTX 5060 Ti, bf16 | 384-token state, 3 questions | 44.5 ms² |
110
+ | RTX 5060 Ti, bf16 | 317-token state, 3 questions (8 options) | 28.3 ms |
111
+ | CPU, 6 threads, PyTorch fp32 | 384-token state, 3 questions (8 options) | 2.28 s |
112
+ | CPU, 6 threads, ONNX int8 | 384-token state, 3 questions (8 options) | 0.88 s (x2.6) |
113
+
114
+ ² An earlier measurement on the same architecture; the other rows were measured on the released weights.
115
+
116
+ **Packing**, RTX 5060 Ti, bf16, same model, one sequence per option vs packed with the state cache:
117
+
118
+ | scenario | candidates | tokens, naive / packed | time, naive / packed |
119
+ |---|--:|--:|--:|
120
+ | intent from a 243-intent support-bot catalog | 243 | 97,685 / 4,871 | 4.65 s / 0.44 s |
121
+ | full triage of a support email | 16 questions, 65 options | 23,487 / 1,853 | 1.10 s / 0.18 s |
122
+ | follow-up question about a cached document | 13 | 5,081 / 277 | 0.24 s / 25 ms |
123
+
124
+ ## Training
125
+
126
+ * 1.42M examples (1.5M questions) over 151 question types in eight domains: relevance and RAG grounding, NLI and fact checking, moderation and safety, agents and tool choice, topic classification, sentiment and emotion, LLM request routing, intents and customer support.
127
+ * 71% Russian, 29% English; mostly human or naturally labelled data, about a quarter with LLM-generated text or model labels; instruction wordings augmented with paraphrases.
128
+ * LoRA rank 16 on the attention projections (q, k, v, o) of all 24 layers plus a scalar head, 4.7M trainable parameters; merged into the weights in this release. Listwise softmax for `choice` / `ranking`, pairwise BCE for `noul`.
129
+ * One epoch, with a compute budget comparable to about 50 hours of a single consumer GPU (RTX 5060 Ti class).
130
+
131
+ ## Files
132
+
133
+ * `model.safetensors` — encoder weights, bf16
134
+ * `head.safetensors` — readout head, fp32
135
+ * `decisions_config.json` — packing limits and instruction suffixes
136
+ * `onnx/model_int8_pertoken.onnx` — CPU build
137
+
138
+ ## License
139
+
140
+ MIT. Based on [ai-forever/FRIDA](https://huggingface.co/ai-forever/FRIDA) (MIT).
141
+
142
+ ## Citation
143
+
144
+ TODO
config.json ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "T5EncoderModel"
4
+ ],
5
+ "bos_token_id": 1,
6
+ "classifier_dropout": 0.0,
7
+ "d_ff": 4096,
8
+ "d_kv": 64,
9
+ "d_model": 1536,
10
+ "decoder_start_token_id": 0,
11
+ "dense_act_fn": "gelu_new",
12
+ "dropout_rate": 0.0,
13
+ "dtype": "bfloat16",
14
+ "eos_token_id": 2,
15
+ "feed_forward_proj": "gated-gelu",
16
+ "gradient_checkpointing": false,
17
+ "initializer_factor": 1.0,
18
+ "is_decoder": false,
19
+ "is_encoder_decoder": false,
20
+ "is_gated_act": true,
21
+ "layer_norm_epsilon": 1e-06,
22
+ "model_type": "t5",
23
+ "num_decoder_layers": 24,
24
+ "num_heads": 24,
25
+ "num_layers": 24,
26
+ "output_past": true,
27
+ "pad_token_id": 0,
28
+ "relative_attention_max_distance": 128,
29
+ "relative_attention_num_buckets": 32,
30
+ "scale_decoder_outputs": false,
31
+ "tie_word_embeddings": true,
32
+ "transformers_version": "5.17.0",
33
+ "use_cache": false,
34
+ "vocab_size": 93651
35
+ }
decisions_config.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "state_max_tokens": 512,
3
+ "instruction_max_tokens": 96,
4
+ "option_max_tokens": 256,
5
+ "max_options_per_row": 16,
6
+ "max_row_tokens": 1024,
7
+ "align": 8,
8
+ "eos_token_id": 2,
9
+ "pad_token_id": 0,
10
+ "tokenizer_max_length": 1024,
11
+ "num_buckets": 32,
12
+ "max_distance": 128,
13
+ "instruction_suffixes": {
14
+ "choice": "Оцени, является ли вариант, описанный в кандидате, подходящим ответом на вопрос выше, с учётом сведений в запросе. Суди о варианте по его описанию, а не по одной лишь тематической близости.",
15
+ "score": "Оцени, точно ли уровень, описанный в кандидате, характеризует запрос в рамках оценки выше. Суди об уровне по его описанию, а не по одной лишь тематической близости.",
16
+ "noul": "Оцени, верно ли кандидат описывает ответ на вопрос выше, с учётом сведений в запросе. Отвечай утвердительно, если этот вариант выполняется, иначе отрицательно.",
17
+ "ranking": "Оцени, насколько кандидат подходит под вопрос выше с учётом сведений в запросе. Кандидат — это сам материал, а не описание варианта: суди по его содержанию, а не по одной лишь тематической близости."
18
+ },
19
+ "yes_no_default_criteria": {
20
+ "true": "The answer to the question is yes.",
21
+ "false": "The answer to the question is no."
22
+ },
23
+ "format_version": 1
24
+ }
head.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e822115e760c243d9b36010573efadc2e29c315323cccdbd5597a4f6dbd74f91
3
+ size 6284
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:70a8cb915323c072f549f46b0f89c57a83b54128458e3cc7178a7bc3c013de5f
3
+ size 1646829336
onnx/model_int8_pertoken.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:09e17f504d100551108d2af96f20d0e8a5b4ee656bf39e18dd092d0115694124
3
+ size 1257200228
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "backend": "tokenizers",
4
+ "bos_token": "<s>",
5
+ "clean_up_tokenization_spaces": true,
6
+ "cls_token": "<s>",
7
+ "eos_token": "</s>",
8
+ "errors": "replace",
9
+ "mask_token": "<mask>",
10
+ "model_max_length": 1024,
11
+ "pad_token": "<pad>",
12
+ "sep_token": "</s>",
13
+ "tokenizer_class": "RobertaTokenizer",
14
+ "trim_offsets": true,
15
+ "unk_token": "<unk>"
16
+ }