* DeepSeek V4 Flash declares tokenizer.ggml.pre = "joyai-llm". The split * below mirrors the JoyAI BPE pre-tokenizer for the cases this model * uses in normal text and source-code prompts: * * \p{N}{1,3} * [CJK/Hiragana/Katakana]+ * [P/S][A-Za-z]+ * [^\r\n\p{L}\p{P}\p{S}]?[\p{L}\p{M}]+ * ?[\p{P}\p{S}]+[\r\n]* * \s*[\r\n]+ * \s+(?!\S) * \s+ * * The punctuation rule in
| 22151 | } |
| 22152 | } else if (ok) { |
| 22153 | ok = metal_graph_decode_hc_pre(metal_graph_attn_cur(g), |
| 22154 | metal_graph_hc_split(g), |
| 22155 | metal_graph_hc_mix(g), |
| 22156 | metal_graph_cur_hc(g), |
| 22157 | model, |
| 22158 | layer->hc_attn_scale->abs_offset, |
| 22159 | layer->hc_attn_base->abs_offset); |
| 22160 | } |
| 22161 | DS4_METAL_PROFILE_DECODE_STAGE("attn_hc_pre"); |
| 22162 | if (ok) { |
| 22163 | metal_graph_debug_dump_tensor("hc_attn_pre_mixes", metal_graph_hc_mix(g), mix_hc, il, pos); |
| 22164 | metal_graph_debug_dump_tensor("hc_attn_pre_weights", metal_graph_hc_pre(g), DS4_N_HC, il, pos); |
| 22165 | metal_graph_debug_dump_tensor("hc_attn_pre_post_weights", metal_graph_hc_post(g), DS4_N_HC, il, pos); |
| 22166 | metal_graph_debug_dump_tensor("hc_attn_pre_comb", metal_graph_hc_comb(g), (uint64_t)DS4_N_HC * DS4_N_HC, il, pos); |
| 22167 | } |
| 22168 | if (ok) { |
| 22169 | metal_graph_debug_dump_tensor("hc_attn_pre", metal_graph_attn_cur(g), DS4_N_EMBD, il, pos); |
| 22170 | } |
| 22171 | if (ok && !fuse_hc_norm) ok = ds4_gpu_rms_norm_weight_tensor(metal_graph_attn_norm(g), metal_graph_attn_cur(g), |
| 22172 | model->map, model->size, |
| 22173 | layer->attn_norm->abs_offset, |
| 22174 | DS4_N_EMBD, DS4_RMS_EPS) != 0; |
| 22175 | DS4_METAL_PROFILE_DECODE_STAGE("attn_norm"); |
| 22176 | if (ok) { |
| 22177 | metal_graph_debug_dump_tensor("attn_norm", metal_graph_attn_norm(g), DS4_N_EMBD, il, pos); |
| 22178 | } |
| 22179 | if (phase == METAL_DECODE_LAYER_TO_QKV) return ok; |
| 22180 | } |
| 22181 | bool kv_norm_store_fused = false; |
| 22182 | if (!resume_after_attn) { |
| 22183 | /* Fuse the KV RoPE tail into the FP8/raw finalizer: both were single |
| 22184 | * 64-thread threadgroups on the same 2 KB row, so the pair paid two full |
| 22185 | * dispatch launches. Deferring the RoPE and running it inside the |
| 22186 | * finalizer removes one dispatch per layer. */ |
| 22187 | bool fuse_kv_rope_store = false; |
| 22188 | bool qkv_pair_quad_fused = false; |
| 22189 | if (!resume_after_qkv) { |
| 22190 | bool qkv_pair_projected = resume_after_qa_kv_raw; |
| 22191 | /* M1-M5 decode fusion: the q_a/kv Q8 pair and the four F16 compressor |
| 22192 | * projections all read the same normalized attention input and write |
| 22193 | * disjoint outputs, so one dispatch covers both stages with unchanged |
| 22194 | * per-row reduction trees (see the kernel comment). Restricted to the |
| 22195 | * resident FULL phase so split-phase / CUDA / SSD flows keep their |
| 22196 | * original ordering. */ |
| 22197 | if (!resume_after_qa_kv_raw && ok && qkv_rms_fused && compressed && |
| 22198 | phase == METAL_DECODE_LAYER_FULL && |
| 22199 | !g->ssd_streaming && !g->ssd_streaming_cold && |
| 22200 | ds4_layer_compress_ratio(il) == 4u && |
| 22201 | layer->attn_q_a->type == DS4_TENSOR_Q8_0 && |
| 22202 | layer->attn_kv->type == DS4_TENSOR_Q8_0 && |
| 22203 | g->cuda_qkv_pair && !metal_graph_use_reference_qkv_pair_proj() && |
| 22204 | !metal_graph_use_reference_compressor_pair_proj() && |
| 22205 | layer->attn_compressor_kv && layer->attn_compressor_gate && |
| 22206 | layer->attn_compressor_ape && |
| 22207 | layer->attn_compressor_kv->type == DS4_TENSOR_F16 && |
| 22208 | layer->attn_compressor_gate->type == DS4_TENSOR_F16 && |
| 22209 | layer->attn_compressor_kv->dim[0] == DS4_N_EMBD && |
| 22210 | layer->attn_compressor_gate->dim[0] == DS4_N_EMBD && |
no test coverage detected