mlboydaisuke commited on
Commit
5ec6faf
·
verified ·
1 Parent(s): a70718a

Shieldstral-1.0-3B -> Core AI: policy-conditioned safety classifier, one forward = one verdict; 9/9 vs fp32 at int4lin

Browse files
Files changed (17) hide show
  1. .gitattributes +4 -0
  2. README.md +124 -0
  3. config.json +65 -0
  4. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/reference.json +16 -0
  5. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/shieldstral_1_0_3b_classify_int4lin_s256.aimodel/main.hash +0 -0
  6. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/shieldstral_1_0_3b_classify_int4lin_s256.aimodel/main.mlirb +3 -0
  7. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/shieldstral_1_0_3b_classify_int4lin_s256.aimodel/metadata.json +8 -0
  8. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/tokenizer/chat_template.jinja +143 -0
  9. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/tokenizer/tokenizer.json +3 -0
  10. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/tokenizer/tokenizer_config.json +10 -0
  11. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/reference.json +16 -0
  12. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/shieldstral_1_0_3b_classify_int4lin_s512.aimodel/main.hash +1 -0
  13. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/shieldstral_1_0_3b_classify_int4lin_s512.aimodel/main.mlirb +3 -0
  14. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/shieldstral_1_0_3b_classify_int4lin_s512.aimodel/metadata.json +8 -0
  15. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/tokenizer/chat_template.jinja +143 -0
  16. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/tokenizer/tokenizer.json +3 -0
  17. gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/tokenizer/tokenizer_config.json +10 -0
.gitattributes CHANGED
@@ -33,3 +33,7 @@ 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
+ gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/shieldstral_1_0_3b_classify_int4lin_s256.aimodel/main.mlirb filter=lfs diff=lfs merge=lfs -text
37
+ gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/tokenizer/tokenizer.json filter=lfs diff=lfs merge=lfs -text
38
+ gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/shieldstral_1_0_3b_classify_int4lin_s512.aimodel/main.mlirb filter=lfs diff=lfs merge=lfs -text
39
+ gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/tokenizer/tokenizer.json filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ base_model: mistralai/Shieldstral-1.0-3B
4
+ tags:
5
+ - coreai
6
+ - aimodel
7
+ - apple-silicon
8
+ - on-device
9
+ - safety
10
+ - moderation
11
+ - classifier
12
+ - mistral
13
+ pipeline_tag: text-classification
14
+ ---
15
+
16
+ # Shieldstral-1.0-3B — Apple Core AI (`.aimodel`)
17
+
18
+ **Mistral's 3B safety model converted to Apple's Core AI** (the Core ML successor announced at
19
+ WWDC26), for macOS 27 and iOS 27. Twelve languages, Apache-2.0.
20
+
21
+ The policy is a string in your code, not a fixed taxonomy: the host writes an Instruction ("Flag
22
+ self-harm promotion; do not flag help-seeking or support resources") and a Query, hands over the
23
+ content, and gets back a probability.
24
+
25
+ **It ships as a classifier, not a decoder.** Shieldstral answers by putting mass on `yes` or `no`
26
+ at the last prompt token, so the whole tail is baked into the graph:
27
+
28
+ ```
29
+ (input_ids [1,S] int32, attention_mask [1,S] int32) -> probs [1,2] = softmax([no, yes])
30
+ ```
31
+
32
+ One `.aimodel` forward is one verdict. No KV cache, no decode loop, no sampling, and no
33
+ 131 072-way head — two rows of the tied embedding are the head, which is 805 MB of fp16 a
34
+ classifier never reads.
35
+
36
+ > Requires macOS 27 / iOS 27 (Core AI ships with the OS). Conversion code, gates and knowledge base:
37
+ > **[coreai-model-zoo](https://github.com/john-rocky/coreai-model-zoo)**.
38
+
39
+ ## Bundles
40
+
41
+ | path | size | verdict latency (M4 Max) | numerics |
42
+ |---|---:|---:|---|
43
+ | `gpu-classify/…_int4lin_s512` | 2.53 GB | **232.5 ms** | **9/9** verdicts vs fp32, worst \|ΔP\| 0.030 |
44
+ | `gpu-classify/…_int4lin_s256` | 2.53 GB | **123.6 ms** | 9/9, numerics identical to S=512 |
45
+
46
+ macOS 27.0 (26A5378n), Xcode 27.0 (27A5218g), `coreai-torch 0.4.1`, median of 10 warm forwards,
47
+ engine ready in ~2 s.
48
+
49
+ **No iPhone bundle yet.** The AOT build for `h18p` is 2.336 GiB — under the 2.39 GiB that another
50
+ model in this zoo loads on an iPhone 17 Pro — so it is expected to fit, and *expected to fit* is
51
+ not a measurement. It ships when a phone has run it.
52
+
53
+ **Two measurements worth knowing before you pick a bundle.**
54
+
55
+ **Quantization buys size, not speed.** At the same grid, fp16 runs 230.5 ms and int8lin 253.8 ms
56
+ against int4lin's 232.5 — one forward over a padded grid is compute-bound, so shrinking weights
57
+ moves 6.88 GB to 2.53 GB and leaves the clock alone. That is the inverse of the decode loop,
58
+ where int4 is the main speed lever. Only int4lin is published because the larger bundles are not
59
+ better at anything.
60
+
61
+ **The cost of a verdict is the grid, not the text.** Both bundles hold the same weights and
62
+ produce the same probabilities; S=256 is 1.9× faster because it computes half as much padding.
63
+ Pick the grid from the longest document you will actually moderate — the scaffolding alone is
64
+ ~60 tokens, so S=256 leaves ~196 for the document and S=512 leaves ~450.
65
+
66
+ ## Verdicts
67
+
68
+ Nine cases, four policies, EN + JA — four of them near-misses that share a topic with a flagged
69
+ case, because a model that only separates the easy pairs is a keyword filter with extra steps.
70
+
71
+ | flagged | fp32 | int4 | | not flagged | fp32 | int4 |
72
+ |---|---:|---:|---|---|---:|---:|
73
+ | violence (EN) | 0.9972 | 0.9988 | | sourdough recipe | 0.0000 | 0.0000 |
74
+ | violence (**JA**) | 0.9011 | 0.9315 | | park recommendation (**JA**) | 0.0001 | 0.0001 |
75
+ | weapon-making | 0.9919 | 0.9967 | | chemical **safety** question | 0.0001 | 0.0001 |
76
+ | doxxing request | 1.0000 | 1.0000 | | refusal to dox | 0.0003 | 0.0004 |
77
+ | | | | | help-seeking | 0.0001 | 0.0002 |
78
+
79
+ Every verdict survives int4. What moves is the probability, and only on the case fp32 did not
80
+ already saturate (JA violence). The fp16 bundle's own noise floor is 0.00056, which is what makes
81
+ int4's 0.030 readable as real. **Tune any threshold against the bundle you ship, not against
82
+ fp32.**
83
+
84
+ ## Host contract
85
+
86
+ Everything outside the forward is yours, and all of it is in `reference.json` next to the bundle:
87
+
88
+ ```
89
+ PREFIX = "<s>[SYSTEM_PROMPT]" + SYSTEM + "[/SYSTEM_PROMPT][INST]"
90
+ BODY = "<Instruct>: {instruction}\n\n<Query>: {query}\n\n<Document>: {document}"
91
+ SUFFIX = "[/INST]"
92
+ ```
93
+
94
+ - encode with **`add_special_tokens=False`** — `<s>` is in the template text and this tokenizer's
95
+ post-processor does not add one, so letting it add specials gives you two;
96
+ - **right-pad** to the grid with `pad_token_id` 11, mask `1 × real + 0 × pad`. Under the causal
97
+ mask the last real token never sees the padding, which is why S=128 and S=512 agree exactly;
98
+ - read `probs[1]` = P(violation).
99
+
100
+ `SYSTEM` is fixed (it ships in `reference.json`); `Instruct`, `Query` and `Document` are yours.
101
+
102
+ **Not included:** the checkpoint's Pixtral vision tower (`image_size` 1540). Text only.
103
+
104
+ ## Converting it yourself
105
+
106
+ The conversion venv here is transformers 4.57.6, which cannot load this checkpoint at all — the
107
+ tokenizer declares `TokenizersBackend`, `AutoModelForCausalLM` rejects `Mistral3Config`. The
108
+ oracle therefore runs on transformers **git main**, which knows `ministral3` natively, and the
109
+ export is built on the claim that `ministral3` is Mistral + YARN (4.57.6's `MistralModel` handed
110
+ this config's `rope_parameters` as `rope_scaling`).
111
+
112
+ That claim is **measured, not assumed** — cos 1.000000 on last-position logits and |ΔP| = 0.00000
113
+ across all nine cases — because a mis-scaled rope still emits fluent logits and plausible
114
+ probabilities. See
115
+ [`_smoke/test_shieldstral_torch_ladder.py`](https://github.com/john-rocky/coreai-model-zoo/blob/main/_smoke/test_shieldstral_torch_ladder.py),
116
+ [`conversion/export_shieldstral.py`](https://github.com/john-rocky/coreai-model-zoo/blob/main/conversion/export_shieldstral.py)
117
+ and
118
+ [`knowledge/shieldstral-port.md`](https://github.com/john-rocky/coreai-model-zoo/blob/main/knowledge/shieldstral-port.md).
119
+
120
+ ## License
121
+
122
+ Apache-2.0, carried from
123
+ [`mistralai/Shieldstral-1.0-3B`](https://huggingface.co/mistralai/Shieldstral-1.0-3B) (revision
124
+ `003ec7e2b0bab5f0e6307edbaf186fa5822b76f5`). Not affiliated with Apple or Mistral AI.
config.json ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Mistral3ForConditionalGeneration"
4
+ ],
5
+ "dtype": "bfloat16",
6
+ "image_token_index": 10,
7
+ "model_type": "mistral3",
8
+ "multimodal_projector_bias": false,
9
+ "projector_hidden_act": "gelu",
10
+ "spatial_merge_size": 2,
11
+ "text_config": {
12
+ "attention_dropout": 0.0,
13
+ "bos_token_id": 1,
14
+ "eos_token_id": 2,
15
+ "head_dim": 128,
16
+ "hidden_act": "silu",
17
+ "hidden_size": 3072,
18
+ "initializer_range": 0.02,
19
+ "intermediate_size": 9216,
20
+ "max_position_embeddings": 262144,
21
+ "model_type": "ministral3",
22
+ "num_attention_heads": 32,
23
+ "num_hidden_layers": 26,
24
+ "num_key_value_heads": 8,
25
+ "pad_token_id": 11,
26
+ "rms_norm_eps": 1e-05,
27
+ "rope_parameters": {
28
+ "beta_fast": 32.0,
29
+ "beta_slow": 1.0,
30
+ "factor": 16.0,
31
+ "llama_4_scaling_beta": 0.1,
32
+ "mscale": 1.0,
33
+ "mscale_all_dim": 1.0,
34
+ "original_max_position_embeddings": 16384,
35
+ "rope_theta": 1000000.0,
36
+ "rope_type": "yarn",
37
+ "type": "yarn"
38
+ },
39
+ "sliding_window": null,
40
+ "tie_word_embeddings": true,
41
+ "use_cache": true,
42
+ "vocab_size": 131072
43
+ },
44
+ "tie_word_embeddings": true,
45
+ "transformers_version": "5.13.0.dev0",
46
+ "vision_config": {
47
+ "attention_dropout": 0.0,
48
+ "head_dim": 64,
49
+ "hidden_act": "silu",
50
+ "hidden_size": 1024,
51
+ "image_size": 1540,
52
+ "initializer_range": 0.02,
53
+ "intermediate_size": 4096,
54
+ "model_type": "pixtral",
55
+ "num_attention_heads": 16,
56
+ "num_channels": 3,
57
+ "num_hidden_layers": 24,
58
+ "patch_size": 14,
59
+ "rope_parameters": {
60
+ "rope_theta": 10000.0,
61
+ "rope_type": "default"
62
+ }
63
+ },
64
+ "vision_feature_layer": -1
65
+ }
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/reference.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "mistralai/Shieldstral-1.0-3B",
3
+ "seq_len": 256,
4
+ "mode": "int4lin",
5
+ "yes_id": 13059,
6
+ "no_id": 2649,
7
+ "pad_token_id": 11,
8
+ "padding_side": "right",
9
+ "prefix": "<s>[SYSTEM_PROMPT]Judge whether the Document meets the requirements based on the Query and the Instruction provided. Note that the answer can only be \"yes\" or \"no\".[/SYSTEM_PROMPT][INST]",
10
+ "suffix": "[/INST]",
11
+ "body_format": "<Instruct>: {instruction}\n\n<Query>: {query}\n\n<Document>: {document}",
12
+ "default_instruction": "You are a strict safety moderator reviewing potentially harmful content. Apply a low tolerance threshold.",
13
+ "default_query": "Does this content promote physical violence?",
14
+ "output": "probs [1,2] = softmax([no, yes]); violation = probs[1] = P(yes)",
15
+ "add_special_tokens": false
16
+ }
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/shieldstral_1_0_3b_classify_int4lin_s256.aimodel/main.hash ADDED
Binary file (32 Bytes). View file
 
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/shieldstral_1_0_3b_classify_int4lin_s256.aimodel/main.mlirb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:97173bc6b80047cdf1c56d5cd77a6cc0338fb41fd1fbc05c2e0ab9bd6faa9992
3
+ size 2508612665
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/shieldstral_1_0_3b_classify_int4lin_s256.aimodel/metadata.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "creationDate" : "20260814T110050Z",
3
+ "author" : "Mistral AI",
4
+ "assetVersion" : "2.0",
5
+ "license" : "Apache-2.0",
6
+ "producer" : "coreai-core 1.0.0b2",
7
+ "description" : "Shieldstral-1.0-3B policy-conditioned safety classifier. probs[1] = P(the Document violates the policy stated in Instruct\/Query). Source: https:\/\/huggingface.co\/mistralai\/Shieldstral-1.0-3B"
8
+ }
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/tokenizer/chat_template.jinja ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {#- Default system message if no system prompt is passed. #}
2
+ {%- set default_system_message = '' %}
3
+
4
+ {#- Begin of sequence token. #}
5
+ {{- bos_token }}
6
+
7
+
8
+ {#- Handle system prompt if it exists. #}
9
+ {%- set loop_messages = messages %}
10
+ {%- if messages[0]['role'] != 'system' and default_system_message != '' %}
11
+ {{- '[SYSTEM_PROMPT]' + default_system_message + '[/SYSTEM_PROMPT]' }}
12
+ {%- endif %}
13
+
14
+
15
+ {#- Macros #}
16
+ {%- macro render_content(content, context_name, supported_types_desc, support_images) -%}
17
+ {%- if content is string -%}
18
+ {{- content -}}
19
+ {%- elif content -%}
20
+ {%- for block in content -%}
21
+ {%- if block['type'] == 'text' -%}
22
+ {{- block['text'] -}}
23
+ {%- elif support_images and block['type'] in ['image', 'image_url'] -%}
24
+ {{- '[IMG]' -}}
25
+ {%- else -%}
26
+ {{- raise_exception('Only ' + supported_types_desc + ' chunks are supported in ' + context_name + '.') -}}
27
+ {%- endif -%}
28
+ {%- endfor -%}
29
+ {%- else -%}
30
+ {{- raise_exception(context_name + ' must have non-empty content.') -}}
31
+ {%- endif -%}
32
+ {%- endmacro -%}
33
+
34
+ {#- Aggregate consecutive messages with the same role except system. #}
35
+ {#- A sentinel message is appended so the last group gets flushed inside the loop. #}
36
+ {%- set ns_agg = namespace(messages=[], current_group=[], current_role=none) %}
37
+ {%- for message in loop_messages + [{'role': '__sentinel__'}] %}
38
+ {%- if message['role'] != ns_agg.current_role or message['role'] == 'system' %}
39
+ {%- if ns_agg.current_role is not none %}
40
+ {%- set ns_c = namespace(text_parts=[], chunks=[], has_non_text=false) %}
41
+ {%- for msg in ns_agg.current_group %}
42
+ {%- if msg['content'] is string %}
43
+ {%- set ns_c.text_parts = ns_c.text_parts + [msg['content']] %}
44
+ {%- elif msg['content'] is not none %}
45
+ {%- for block in msg['content'] %}
46
+ {%- if block['type'] == 'text' %}
47
+ {%- set ns_c.text_parts = ns_c.text_parts + [block['text']] %}
48
+ {%- else %}
49
+ {%- if ns_c.text_parts | length > 0 %}
50
+ {%- set ns_c.chunks = ns_c.chunks + [{'type': 'text', 'text': ns_c.text_parts | join('\n\n')}] %}
51
+ {%- set ns_c.text_parts = [] %}
52
+ {%- endif %}
53
+ {%- set ns_c.chunks = ns_c.chunks + [block] %}
54
+ {%- set ns_c.has_non_text = true %}
55
+ {%- endif %}
56
+ {%- endfor %}
57
+ {%- endif %}
58
+ {%- endfor %}
59
+ {%- if ns_c.has_non_text %}
60
+ {%- if ns_c.text_parts | length > 0 %}
61
+ {%- set ns_c.chunks = ns_c.chunks + [{'type': 'text', 'text': ns_c.text_parts | join('\n\n')}] %}
62
+ {%- endif %}
63
+ {%- set merged_content = ns_c.chunks %}
64
+ {%- else %}
65
+ {%- set merged_content = ns_c.text_parts | join('\n\n') %}
66
+ {%- endif %}
67
+ {%- set ns_agg.messages = ns_agg.messages + [{'role': ns_agg.current_role, 'content': merged_content}] %}
68
+ {%- endif %}
69
+ {%- if message['role'] != '__sentinel__' %}
70
+ {%- set ns_agg.current_group = [message] %}
71
+ {%- set ns_agg.current_role = message['role'] %}
72
+ {%- endif %}
73
+ {%- else %}
74
+ {%- set ns_agg.current_group = ns_agg.current_group + [message] %}
75
+ {%- endif %}
76
+ {%- endfor %}
77
+ {%- set loop_messages = ns_agg.messages %}
78
+
79
+ {#- Validates message ordering. #}
80
+ {%- if loop_messages | length > 0 and loop_messages[0]['role'] not in ['user', 'system'] %}
81
+ {{- raise_exception('Conversation must start with a user or system message, got ' + loop_messages[0]['role'] + '.') }}
82
+ {%- endif %}
83
+ {%- set ns_order = namespace(previous_role=none) %}
84
+ {%- for message in loop_messages %}
85
+ {%- set current_role = message['role'] %}
86
+ {%- if ns_order.previous_role is not none %}
87
+ {%- if ns_order.previous_role == 'system' %}
88
+ {%- if current_role not in ['user', 'assistant', 'system'] %}
89
+ {{- raise_exception('Unexpected role \'' + current_role + '\' after role \'' + ns_order.previous_role + '\'') }}
90
+ {%- endif %}
91
+ {%- elif ns_order.previous_role == 'user' %}
92
+ {%- if current_role not in ['assistant', 'system', 'user'] %}
93
+ {{- raise_exception('Unexpected role \'' + current_role + '\' after role \'' + ns_order.previous_role + '\'') }}
94
+ {%- endif %}
95
+ {%- elif ns_order.previous_role == 'assistant' %}
96
+ {%- if current_role not in ['assistant', 'user'] %}
97
+ {{- raise_exception('Unexpected role \'' + current_role + '\' after role \'' + ns_order.previous_role + '\'') }}
98
+ {%- endif %}
99
+ {%- endif %}
100
+ {%- endif %}
101
+ {%- set ns_order.previous_role = current_role %}
102
+ {%- endfor %}
103
+
104
+ {#- Handle conversation messages. #}
105
+ {%- for message in loop_messages %}
106
+ {#- User messages supports text, image and image_url content. #}
107
+ {%- if message['role'] == 'user' %}
108
+ {%- if message['content'] is not string and message['content'] %}
109
+ {#- When content has exactly one image and one text block, put image first. #}
110
+ {%- if message['content'] | length == 2 and message['content'][0]['type'] == 'text' and message['content'][1]['type'] in ['image', 'image_url'] %}
111
+ {%- set blocks = [message['content'][1], message['content'][0]] %}
112
+ {%- else %}
113
+ {%- set blocks = message['content'] %}
114
+ {%- endif %}
115
+ {%- set user_content = blocks %}
116
+ {%- else %}
117
+ {%- set user_content = message['content'] %}
118
+ {%- endif %}
119
+ {{- '[INST]' -}}
120
+ {{- render_content(content=user_content, context_name='user message content', supported_types_desc='text, image and image_url', support_images=true) -}}
121
+ {{- '[/INST]' }}
122
+
123
+ {#- Assistant messages supports text content. #}
124
+ {%- elif message['role'] == 'assistant' %}
125
+ {%- if message['content'] is none or message['content'] == '' or message['content']|length == 0 %}
126
+ {{- raise_exception('Assistant message must have a string or a list of chunks in content.') }}
127
+ {%- endif %}
128
+
129
+ {{- render_content(content=message['content'], context_name='assistant message contents', supported_types_desc='text', support_images=false) -}}
130
+
131
+ {{- eos_token }}
132
+
133
+ {#- System messages. #}
134
+ {%- elif message['role'] == 'system' %}
135
+ {{- '[SYSTEM_PROMPT]' -}}
136
+ {{- render_content(content=message['content'], context_name='system message contents', supported_types_desc='text', support_images=false) -}}
137
+ {{- '[/SYSTEM_PROMPT]' -}}
138
+
139
+ {#- Raise exception for unsupported roles. #}
140
+ {%- else %}
141
+ {{- raise_exception('Only user, assistant and system roles are supported, got ' + message['role'] + '.') }}
142
+ {%- endif %}
143
+ {%- endfor %}
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/tokenizer/tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9172cf28b79a17502736f971b560faeced38ee527540cea6882a1f40cce320c0
3
+ size 17077322
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s256/tokenizer/tokenizer_config.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "bos_token": "<s>",
4
+ "eos_token": "</s>",
5
+ "model_max_length": 1000000000000000019884624838656,
6
+ "pad_token": "<pad>",
7
+ "processor_class": "PixtralProcessor",
8
+ "tokenizer_class": "TokenizersBackend",
9
+ "unk_token": "<unk>"
10
+ }
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/reference.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "mistralai/Shieldstral-1.0-3B",
3
+ "seq_len": 512,
4
+ "mode": "int4lin",
5
+ "yes_id": 13059,
6
+ "no_id": 2649,
7
+ "pad_token_id": 11,
8
+ "padding_side": "right",
9
+ "prefix": "<s>[SYSTEM_PROMPT]Judge whether the Document meets the requirements based on the Query and the Instruction provided. Note that the answer can only be \"yes\" or \"no\".[/SYSTEM_PROMPT][INST]",
10
+ "suffix": "[/INST]",
11
+ "body_format": "<Instruct>: {instruction}\n\n<Query>: {query}\n\n<Document>: {document}",
12
+ "default_instruction": "You are a strict safety moderator reviewing potentially harmful content. Apply a low tolerance threshold.",
13
+ "default_query": "Does this content promote physical violence?",
14
+ "output": "probs [1,2] = softmax([no, yes]); violation = probs[1] = P(yes)",
15
+ "add_special_tokens": false
16
+ }
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/shieldstral_1_0_3b_classify_int4lin_s512.aimodel/main.hash ADDED
@@ -0,0 +1 @@
 
 
1
+ {�L�;� �1��z_/�/�<ʙ\4:b���H
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/shieldstral_1_0_3b_classify_int4lin_s512.aimodel/main.mlirb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7b994ca73b840b15fc319a847a5f2f06aa2f08dd3c1eca995c343a62b599c248
3
+ size 2508943782
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/shieldstral_1_0_3b_classify_int4lin_s512.aimodel/metadata.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "license" : "Apache-2.0",
3
+ "assetVersion" : "2.0",
4
+ "producer" : "coreai-core 1.0.0b2",
5
+ "creationDate" : "20260814T104704Z",
6
+ "description" : "Shieldstral-1.0-3B policy-conditioned safety classifier. probs[1] = P(the Document violates the policy stated in Instruct\/Query). Source: https:\/\/huggingface.co\/mistralai\/Shieldstral-1.0-3B",
7
+ "author" : "Mistral AI"
8
+ }
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/tokenizer/chat_template.jinja ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {#- Default system message if no system prompt is passed. #}
2
+ {%- set default_system_message = '' %}
3
+
4
+ {#- Begin of sequence token. #}
5
+ {{- bos_token }}
6
+
7
+
8
+ {#- Handle system prompt if it exists. #}
9
+ {%- set loop_messages = messages %}
10
+ {%- if messages[0]['role'] != 'system' and default_system_message != '' %}
11
+ {{- '[SYSTEM_PROMPT]' + default_system_message + '[/SYSTEM_PROMPT]' }}
12
+ {%- endif %}
13
+
14
+
15
+ {#- Macros #}
16
+ {%- macro render_content(content, context_name, supported_types_desc, support_images) -%}
17
+ {%- if content is string -%}
18
+ {{- content -}}
19
+ {%- elif content -%}
20
+ {%- for block in content -%}
21
+ {%- if block['type'] == 'text' -%}
22
+ {{- block['text'] -}}
23
+ {%- elif support_images and block['type'] in ['image', 'image_url'] -%}
24
+ {{- '[IMG]' -}}
25
+ {%- else -%}
26
+ {{- raise_exception('Only ' + supported_types_desc + ' chunks are supported in ' + context_name + '.') -}}
27
+ {%- endif -%}
28
+ {%- endfor -%}
29
+ {%- else -%}
30
+ {{- raise_exception(context_name + ' must have non-empty content.') -}}
31
+ {%- endif -%}
32
+ {%- endmacro -%}
33
+
34
+ {#- Aggregate consecutive messages with the same role except system. #}
35
+ {#- A sentinel message is appended so the last group gets flushed inside the loop. #}
36
+ {%- set ns_agg = namespace(messages=[], current_group=[], current_role=none) %}
37
+ {%- for message in loop_messages + [{'role': '__sentinel__'}] %}
38
+ {%- if message['role'] != ns_agg.current_role or message['role'] == 'system' %}
39
+ {%- if ns_agg.current_role is not none %}
40
+ {%- set ns_c = namespace(text_parts=[], chunks=[], has_non_text=false) %}
41
+ {%- for msg in ns_agg.current_group %}
42
+ {%- if msg['content'] is string %}
43
+ {%- set ns_c.text_parts = ns_c.text_parts + [msg['content']] %}
44
+ {%- elif msg['content'] is not none %}
45
+ {%- for block in msg['content'] %}
46
+ {%- if block['type'] == 'text' %}
47
+ {%- set ns_c.text_parts = ns_c.text_parts + [block['text']] %}
48
+ {%- else %}
49
+ {%- if ns_c.text_parts | length > 0 %}
50
+ {%- set ns_c.chunks = ns_c.chunks + [{'type': 'text', 'text': ns_c.text_parts | join('\n\n')}] %}
51
+ {%- set ns_c.text_parts = [] %}
52
+ {%- endif %}
53
+ {%- set ns_c.chunks = ns_c.chunks + [block] %}
54
+ {%- set ns_c.has_non_text = true %}
55
+ {%- endif %}
56
+ {%- endfor %}
57
+ {%- endif %}
58
+ {%- endfor %}
59
+ {%- if ns_c.has_non_text %}
60
+ {%- if ns_c.text_parts | length > 0 %}
61
+ {%- set ns_c.chunks = ns_c.chunks + [{'type': 'text', 'text': ns_c.text_parts | join('\n\n')}] %}
62
+ {%- endif %}
63
+ {%- set merged_content = ns_c.chunks %}
64
+ {%- else %}
65
+ {%- set merged_content = ns_c.text_parts | join('\n\n') %}
66
+ {%- endif %}
67
+ {%- set ns_agg.messages = ns_agg.messages + [{'role': ns_agg.current_role, 'content': merged_content}] %}
68
+ {%- endif %}
69
+ {%- if message['role'] != '__sentinel__' %}
70
+ {%- set ns_agg.current_group = [message] %}
71
+ {%- set ns_agg.current_role = message['role'] %}
72
+ {%- endif %}
73
+ {%- else %}
74
+ {%- set ns_agg.current_group = ns_agg.current_group + [message] %}
75
+ {%- endif %}
76
+ {%- endfor %}
77
+ {%- set loop_messages = ns_agg.messages %}
78
+
79
+ {#- Validates message ordering. #}
80
+ {%- if loop_messages | length > 0 and loop_messages[0]['role'] not in ['user', 'system'] %}
81
+ {{- raise_exception('Conversation must start with a user or system message, got ' + loop_messages[0]['role'] + '.') }}
82
+ {%- endif %}
83
+ {%- set ns_order = namespace(previous_role=none) %}
84
+ {%- for message in loop_messages %}
85
+ {%- set current_role = message['role'] %}
86
+ {%- if ns_order.previous_role is not none %}
87
+ {%- if ns_order.previous_role == 'system' %}
88
+ {%- if current_role not in ['user', 'assistant', 'system'] %}
89
+ {{- raise_exception('Unexpected role \'' + current_role + '\' after role \'' + ns_order.previous_role + '\'') }}
90
+ {%- endif %}
91
+ {%- elif ns_order.previous_role == 'user' %}
92
+ {%- if current_role not in ['assistant', 'system', 'user'] %}
93
+ {{- raise_exception('Unexpected role \'' + current_role + '\' after role \'' + ns_order.previous_role + '\'') }}
94
+ {%- endif %}
95
+ {%- elif ns_order.previous_role == 'assistant' %}
96
+ {%- if current_role not in ['assistant', 'user'] %}
97
+ {{- raise_exception('Unexpected role \'' + current_role + '\' after role \'' + ns_order.previous_role + '\'') }}
98
+ {%- endif %}
99
+ {%- endif %}
100
+ {%- endif %}
101
+ {%- set ns_order.previous_role = current_role %}
102
+ {%- endfor %}
103
+
104
+ {#- Handle conversation messages. #}
105
+ {%- for message in loop_messages %}
106
+ {#- User messages supports text, image and image_url content. #}
107
+ {%- if message['role'] == 'user' %}
108
+ {%- if message['content'] is not string and message['content'] %}
109
+ {#- When content has exactly one image and one text block, put image first. #}
110
+ {%- if message['content'] | length == 2 and message['content'][0]['type'] == 'text' and message['content'][1]['type'] in ['image', 'image_url'] %}
111
+ {%- set blocks = [message['content'][1], message['content'][0]] %}
112
+ {%- else %}
113
+ {%- set blocks = message['content'] %}
114
+ {%- endif %}
115
+ {%- set user_content = blocks %}
116
+ {%- else %}
117
+ {%- set user_content = message['content'] %}
118
+ {%- endif %}
119
+ {{- '[INST]' -}}
120
+ {{- render_content(content=user_content, context_name='user message content', supported_types_desc='text, image and image_url', support_images=true) -}}
121
+ {{- '[/INST]' }}
122
+
123
+ {#- Assistant messages supports text content. #}
124
+ {%- elif message['role'] == 'assistant' %}
125
+ {%- if message['content'] is none or message['content'] == '' or message['content']|length == 0 %}
126
+ {{- raise_exception('Assistant message must have a string or a list of chunks in content.') }}
127
+ {%- endif %}
128
+
129
+ {{- render_content(content=message['content'], context_name='assistant message contents', supported_types_desc='text', support_images=false) -}}
130
+
131
+ {{- eos_token }}
132
+
133
+ {#- System messages. #}
134
+ {%- elif message['role'] == 'system' %}
135
+ {{- '[SYSTEM_PROMPT]' -}}
136
+ {{- render_content(content=message['content'], context_name='system message contents', supported_types_desc='text', support_images=false) -}}
137
+ {{- '[/SYSTEM_PROMPT]' -}}
138
+
139
+ {#- Raise exception for unsupported roles. #}
140
+ {%- else %}
141
+ {{- raise_exception('Only user, assistant and system roles are supported, got ' + message['role'] + '.') }}
142
+ {%- endif %}
143
+ {%- endfor %}
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/tokenizer/tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9172cf28b79a17502736f971b560faeced38ee527540cea6882a1f40cce320c0
3
+ size 17077322
gpu-classify/shieldstral_1_0_3b_classify_int4lin_s512/tokenizer/tokenizer_config.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "bos_token": "<s>",
4
+ "eos_token": "</s>",
5
+ "model_max_length": 1000000000000000019884624838656,
6
+ "pad_token": "<pad>",
7
+ "processor_class": "PixtralProcessor",
8
+ "tokenizer_class": "TokenizersBackend",
9
+ "unk_token": "<unk>"
10
+ }