NeelContractor commited on
Commit
74b70da
·
verified ·
1 Parent(s): 5d59e2a

Upload folder using huggingface_hub

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ 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
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: cc-by-nc-4.0
3
+ base_model: Qwen/Qwen3-0.6B
4
+ library_name: bev-decider
5
+ base_model_relation: finetune
6
+ datasets:
7
+ - avbiswas/bev-decision-150K
8
+ pipeline_tag: text-classification
9
+ tags:
10
+ - system-one
11
+ - decision-model
12
+ - jev-compatible
13
+ language:
14
+ - en
15
+ ---
16
+
17
+ # jev-decider-0.4B
18
+
19
+ A **0.4B-parameter System One decision model** in the bev-decider / Jev format. It reads a state (text or JSON) and typed questions about it and returns probabilities in a single forward pass, with no text generation:
20
+
21
+ - **`choice`**: pick one of several named options.
22
+ - **`noul`**: yes/no, returned as P(yes).
23
+ - **`score`**: an ordinal level, returned as the expected value over the levels.
24
+
25
+ ## Architecture
26
+
27
+ This is a single self-contained model. `model.safetensors` holds the whole network in one file.
28
+
29
+ | | |
30
+ |---|---|
31
+ | Backbone | The first **20 of 28 layers** of [`Qwen/Qwen3-0.6B`](https://huggingface.co/Qwen/Qwen3-0.6B), with the fine-tuned LoRA (r=8, alpha=16 on `q/k/v/o_proj` of layers 8–19) **merged** into the weights |
32
+ | Decision head | 2-layer attention head, 512-dim, with a task-type embedding |
33
+ | Parameters | ≈ 0.4B (0.31B in the transformer layers, 0.16B token embeddings, 7.4M head) |
34
+ | Weights | `model.safetensors` (bf16 backbone + fp32 head), plus `backbone_config.json`, `config.json` and Qwen's tokenizer files |
35
+ | Context | Trained with states up to **512** tokens; options are limited to 64 tokens each |
36
+
37
+ The head is a custom module, so the model is loaded with the [`bev-decider`](https://github.com/avbiswas/bev-decider) package.
38
+
39
+ ## Usage
40
+
41
+ Install the `bev-decider` package, which downloads this model on first use:
42
+
43
+ ```bash
44
+ pip install bev-decider
45
+ from bev_decider import load
46
+
47
+ decider = load("NeelContractor/jev-decider-0.4B")
48
+
49
+ state = {
50
+ "message": (
51
+ "URGENT: you charged my card twice this month. "
52
+ "Refund the duplicate within 24 hours or I'm disputing it with my bank."
53
+ )
54
+ }
55
+
56
+ questions = {
57
+ "intent": {
58
+ "type": "choice",
59
+ "instructions": "What does the customer want?",
60
+ "criteria": {
61
+ "refund": "money returned or a duplicate charge reversed",
62
+ "technical_help": "a bug, outage or integration problem",
63
+ "cancellation": "wants to cancel or downgrade",
64
+ },
65
+ },
66
+ "urgent": {
67
+ "type": "noul",
68
+ "instructions": "Does the message communicate time pressure or a deadline?",
69
+ },
70
+ "anger": {
71
+ "type": "score",
72
+ "instructions": "How angry is the customer?",
73
+ "criteria": ["calm", "mildly annoyed", "frustrated", "furious"],
74
+ },
75
+ }
76
+
77
+ print(decider.decide(state, questions))
78
+ Evaluation
79
+ Held-out test split of avbiswas/bev-decision-150K (https://huggingface.co/datasets/avbiswas/bev-decision-150K),
80
+ 2,000 questions, single forward pass:
81
+ Metric Value
82
+ Accuracy (all) 0.7300
83
+ Yes/no (noul) 0.8178
84
+ Choice 0.7192
85
+ Score 0.5964
86
+ AUC (noul) 0.8859
87
+ These numbers come from the best checkpoint (step 1000 of the final run) selected by test accuracy.
88
+ Training
89
+ - Base: first 20 layers of Qwen/Qwen3-0.6B (weights frozen except LoRA).
90
+ - LoRA: r=8, alpha=16, dropout 0, on q/k/v/o_proj of layers 8–19.
91
+ - Head: 2 attention blocks, 512-dim, num_task_types=3 (choice, noul, score).
92
+ - Data: avbiswas/bev-decision-150K (250,262 exploded training questions).
93
+ - Objective: cross-entropy over the options.
94
+ - Precision: bf16 autocast, fp32 head. Optimizer: AdamW (head lr 1e-3, LoRA lr 1e-4).
95
+ The exported weights are the LoRA-merged backbone plus the trained head.
96
+ License
97
+ The model is CC-BY-NC-4.0 (non-commercial), because the training data includes sources with non-commercial terms. It contains weights derived from
98
+ Qwen3-0.6B (https://huggingface.co/Qwen/Qwen3-0.6B), which is Apache-2.0; Qwen's license is included as LICENSE-Qwen.
backbone_config.json ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Qwen3ForCausalLM"
4
+ ],
5
+ "attention_bias": false,
6
+ "attention_dropout": 0.0,
7
+ "bos_token_id": 151643,
8
+ "dtype": "float32",
9
+ "eos_token_id": 151645,
10
+ "head_dim": 128,
11
+ "hidden_act": "silu",
12
+ "hidden_size": 1024,
13
+ "initializer_range": 0.02,
14
+ "intermediate_size": 3072,
15
+ "layer_types": [
16
+ "full_attention",
17
+ "full_attention",
18
+ "full_attention",
19
+ "full_attention",
20
+ "full_attention",
21
+ "full_attention",
22
+ "full_attention",
23
+ "full_attention",
24
+ "full_attention",
25
+ "full_attention",
26
+ "full_attention",
27
+ "full_attention",
28
+ "full_attention",
29
+ "full_attention",
30
+ "full_attention",
31
+ "full_attention",
32
+ "full_attention",
33
+ "full_attention",
34
+ "full_attention",
35
+ "full_attention",
36
+ "full_attention",
37
+ "full_attention",
38
+ "full_attention",
39
+ "full_attention",
40
+ "full_attention",
41
+ "full_attention",
42
+ "full_attention",
43
+ "full_attention"
44
+ ],
45
+ "max_position_embeddings": 40960,
46
+ "max_window_layers": 28,
47
+ "model_type": "qwen3",
48
+ "num_attention_heads": 16,
49
+ "num_hidden_layers": 20,
50
+ "num_key_value_heads": 8,
51
+ "pad_token_id": null,
52
+ "rms_norm_eps": 1e-06,
53
+ "rope_parameters": {
54
+ "rope_theta": 1000000,
55
+ "rope_type": "default"
56
+ },
57
+ "sliding_window": null,
58
+ "tie_word_embeddings": true,
59
+ "transformers_version": "5.19.0",
60
+ "use_cache": true,
61
+ "use_sliding_window": false,
62
+ "vocab_size": 151936
63
+ }
chat_template.jinja ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0].role == 'system' %}
4
+ {{- messages[0].content + '\n\n' }}
5
+ {%- endif %}
6
+ {{- "# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
7
+ {%- for tool in tools %}
8
+ {{- "\n" }}
9
+ {{- tool | tojson }}
10
+ {%- endfor %}
11
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
12
+ {%- else %}
13
+ {%- if messages[0].role == 'system' %}
14
+ {{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }}
15
+ {%- endif %}
16
+ {%- endif %}
17
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
18
+ {%- for message in messages[::-1] %}
19
+ {%- set index = (messages|length - 1) - loop.index0 %}
20
+ {%- if ns.multi_step_tool and message.role == "user" and message.content is string and not(message.content.startswith('<tool_response>') and message.content.endswith('</tool_response>')) %}
21
+ {%- set ns.multi_step_tool = false %}
22
+ {%- set ns.last_query_index = index %}
23
+ {%- endif %}
24
+ {%- endfor %}
25
+ {%- for message in messages %}
26
+ {%- if message.content is string %}
27
+ {%- set content = message.content %}
28
+ {%- else %}
29
+ {%- set content = '' %}
30
+ {%- endif %}
31
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
32
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
33
+ {%- elif message.role == "assistant" %}
34
+ {%- set reasoning_content = '' %}
35
+ {%- if message.reasoning_content is string %}
36
+ {%- set reasoning_content = message.reasoning_content %}
37
+ {%- else %}
38
+ {%- if '</think>' in content %}
39
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
40
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
41
+ {%- endif %}
42
+ {%- endif %}
43
+ {%- if loop.index0 > ns.last_query_index %}
44
+ {%- if loop.last or (not loop.last and reasoning_content) %}
45
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content.strip('\n') + '\n</think>\n\n' + content.lstrip('\n') }}
46
+ {%- else %}
47
+ {{- '<|im_start|>' + message.role + '\n' + content }}
48
+ {%- endif %}
49
+ {%- else %}
50
+ {{- '<|im_start|>' + message.role + '\n' + content }}
51
+ {%- endif %}
52
+ {%- if message.tool_calls %}
53
+ {%- for tool_call in message.tool_calls %}
54
+ {%- if (loop.first and content) or (not loop.first) %}
55
+ {{- '\n' }}
56
+ {%- endif %}
57
+ {%- if tool_call.function %}
58
+ {%- set tool_call = tool_call.function %}
59
+ {%- endif %}
60
+ {{- '<tool_call>\n{"name": "' }}
61
+ {{- tool_call.name }}
62
+ {{- '", "arguments": ' }}
63
+ {%- if tool_call.arguments is string %}
64
+ {{- tool_call.arguments }}
65
+ {%- else %}
66
+ {{- tool_call.arguments | tojson }}
67
+ {%- endif %}
68
+ {{- '}\n</tool_call>' }}
69
+ {%- endfor %}
70
+ {%- endif %}
71
+ {{- '<|im_end|>\n' }}
72
+ {%- elif message.role == "tool" %}
73
+ {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
74
+ {{- '<|im_start|>user' }}
75
+ {%- endif %}
76
+ {{- '\n<tool_response>\n' }}
77
+ {{- content }}
78
+ {{- '\n</tool_response>' }}
79
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
80
+ {{- '<|im_end|>\n' }}
81
+ {%- endif %}
82
+ {%- endif %}
83
+ {%- endfor %}
84
+ {%- if add_generation_prompt %}
85
+ {{- '<|im_start|>assistant\n' }}
86
+ {%- if enable_thinking is defined and enable_thinking is false %}
87
+ {{- '<think>\n\n</think>\n\n' }}
88
+ {%- endif %}
89
+ {%- endif %}
config.json ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "bev-decider",
3
+ "version": "0.4.0",
4
+ "format": "merged",
5
+ "backbone_config": "backbone_config.json",
6
+ "backbone_dtype": "bf16",
7
+ "num_layers": 20,
8
+ "head": {
9
+ "new_dim": 512,
10
+ "num_layers": 2,
11
+ "num_task_types": 3
12
+ },
13
+ "task_types": {
14
+ "choice": 0,
15
+ "noul": 1,
16
+ "score": 2
17
+ },
18
+ "max_state_tokens_train": 512,
19
+ "max_state_tokens": 512,
20
+ "max_choice_tokens": 64,
21
+ "source_checkpoint": "best",
22
+ "derived_from": {
23
+ "base_model": "Qwen/Qwen3-0.6B",
24
+ "lora": {
25
+ "r": 8,
26
+ "alpha": 16,
27
+ "layers": [
28
+ 8,
29
+ 9,
30
+ 10,
31
+ 11,
32
+ 12,
33
+ 13,
34
+ 14,
35
+ 15,
36
+ 16,
37
+ 17,
38
+ 18,
39
+ 19
40
+ ]
41
+ }
42
+ }
43
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bc59c856f60714b3985749d24b8017b8ca89636cdda44dd0c91142db342d3645
3
+ size 969892784
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:be75606093db2094d7cd20f3c2f385c212750648bd6ea4fb2bf507a6a4c55506
3
+ size 11422650
tokenizer_config.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "backend": "tokenizers",
4
+ "bos_token": null,
5
+ "clean_up_tokenization_spaces": false,
6
+ "eos_token": "<|im_end|>",
7
+ "errors": "replace",
8
+ "extra_special_tokens": [
9
+ "<|im_start|>",
10
+ "<|im_end|>",
11
+ "<|object_ref_start|>",
12
+ "<|object_ref_end|>",
13
+ "<|box_start|>",
14
+ "<|box_end|>",
15
+ "<|quad_start|>",
16
+ "<|quad_end|>",
17
+ "<|vision_start|>",
18
+ "<|vision_end|>",
19
+ "<|vision_pad|>",
20
+ "<|image_pad|>",
21
+ "<|video_pad|>"
22
+ ],
23
+ "is_local": false,
24
+ "local_files_only": false,
25
+ "model_max_length": 131072,
26
+ "pad_token": "<|endoftext|>",
27
+ "split_special_tokens": false,
28
+ "tokenizer_class": "Qwen2Tokenizer",
29
+ "unk_token": null
30
+ }