kingjones777 commited on
Commit
7f30bda
·
verified ·
1 Parent(s): d52ceb6

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +1 -0
  2. Nex-N2.5-mini-imatrix-Q4_0-ROCmFP4-STRIX_LEAN.gguf +3 -0
  3. SHA256SUMS +6 -0
  4. chat_template_enable_thinking.jinja +155 -0
  5. recipe/logs/N4_kld_q102.log +92 -0
  6. recipe/logs/N4_kld_q103.log +92 -0
  7. recipe/logs/N4v_kld_q102.log +93 -0
  8. recipe/logs/N6_bench.log +46 -0
  9. recipe/logs/N6t_tools_roff.log +63 -0
  10. recipe/logs/N8b_seats.log +8 -0
  11. recipe/logs/N8c_seats.log +8 -0
  12. recipe/logs/Q1_q106.log +0 -0
  13. recipe/logs/b_n-tools-q106-roff-probe.log +285 -0
  14. recipe/logs/b_n-tools-q106-roff-r2.log +301 -0
  15. recipe/logs/b_n-tools-q106-tpl-probe.log +136 -0
  16. recipe/logs/b_n-tools-q106-tpl.log +299 -0
  17. recipe/logs/b_n-vision-q106-c1-faon.log +71 -0
  18. recipe/logs/probe_reasoning.log +16 -0
  19. recipe/logs/probe_seat_default.log +19 -0
  20. recipe/logs/probe_seat_default_C2.log +185 -0
  21. recipe/pipeline/diag_bf16.sh +20 -0
  22. recipe/pipeline/diag_tools_run.sh +8 -0
  23. recipe/pipeline/nex_aggregate.py +408 -0
  24. recipe/pipeline/nex_bench.py +53 -0
  25. recipe/pipeline/nex_cachegate.py +121 -0
  26. recipe/pipeline/nex_cards.sh +41 -0
  27. recipe/pipeline/nex_download.sh +24 -0
  28. recipe/pipeline/nex_harness.py +326 -0
  29. recipe/pipeline/nex_judge.py +584 -0
  30. recipe/pipeline/nex_phase1.sh +37 -0
  31. recipe/pipeline/nex_phase2.sh +74 -0
  32. recipe/pipeline/nex_phase2b.sh +87 -0
  33. recipe/pipeline/nex_publish.py +171 -0
  34. recipe/pipeline/nex_publish_finish.sh +61 -0
  35. recipe/pipeline/nex_reasoning_probe.py +90 -0
  36. recipe/pipeline/nex_refresh_cards.sh +33 -0
  37. recipe/pipeline/nex_render.py +752 -0
  38. recipe/pipeline/nex_seat_default_probe.py +71 -0
  39. recipe/pipeline/nex_seats.sh +177 -0
  40. recipe/pipeline/nex_sizing.sh +33 -0
  41. recipe/pipeline/nex_tools_diag.py +119 -0
  42. recipe/pipeline/nex_tools_tpl.py +104 -0
  43. recipe/pipeline/readback.py +21 -0
  44. recipe/pipeline/run_tools_c1.sh +7 -0
  45. recipe/pipeline/run_tools_roff.sh +8 -0
  46. recipe/pipeline/upload_watchdog.sh +33 -0
  47. recipe/pipeline/verify_download.py +30 -0
  48. recipe/results_summary.json +1721 -0
  49. recipe/templates/chat_template_enable_thinking_medium.jinja +155 -0
  50. recipe/templates/chat_template_enable_thinking_v2.jinja +155 -0
.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
+ Nex-N2.5-mini-imatrix-Q4_0-ROCmFP4-STRIX_LEAN.gguf filter=lfs diff=lfs merge=lfs -text
Nex-N2.5-mini-imatrix-Q4_0-ROCmFP4-STRIX_LEAN.gguf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:56a1eca8639ad1161a236f852063844f09d0c53dc49920291040f02f2e9e805e
3
+ size 18744342464
SHA256SUMS ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ 51ad9aa42908c0a765b10ed9fdebe99663fffe3bc0e1a15cbc4e2954effe266a Nex-N2.5-mini-imatrix-Q4_0-ROCmFP4-COHERENT.gguf
2
+ 122e62e39ed7141970ca913af5438db86fcae2bfbfd1ad93455f6a149861a4ce Nex-N2.5-mini-imatrix-Q4_0-ROCmFP4-FAST.gguf
3
+ 56a1eca8639ad1161a236f852063844f09d0c53dc49920291040f02f2e9e805e Nex-N2.5-mini-imatrix-Q4_0-ROCmFP4-STRIX_LEAN.gguf
4
+ 7e5afffc822c64a7b43a1223d0094fb60895a521f6c89b912409d25091bd17f8 Nex-N2.5-mini.imatrix
5
+ 9183c7ba8510fb9628edd2265a4cad8c02b3aecec3cbdf65620f47494e75836d chat_template_enable_thinking.jinja
6
+ a80a82977e4787a838a612316c79a6533c1b098fcac19372cc78929120162a4e mmproj-Nex-N2.5-mini-BF16.gguf
chat_template_enable_thinking.jinja ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if reasoning_effort is not defined and enable_thinking is defined %}{%- set reasoning_effort = 'high' if enable_thinking else 'none' %}{%- endif %}
2
+ {%- set image_count = namespace(value=0) %}
3
+ {%- set video_count = namespace(value=0) %}
4
+ {%- macro render_content(content, do_vision_count, is_system_content=false) %}
5
+ {%- if content is string %}
6
+ {{- content }}
7
+ {%- elif content is iterable and content is not mapping %}
8
+ {%- for item in content %}
9
+ {%- if 'image' in item or 'image_url' in item or item.type == 'image' %}
10
+ {%- if is_system_content %}
11
+ {{- raise_exception('System message cannot contain images.') }}
12
+ {%- endif %}
13
+ {%- if do_vision_count %}
14
+ {%- set image_count.value = image_count.value + 1 %}
15
+ {%- endif %}
16
+ {%- if add_vision_id %}
17
+ {{- 'Picture ' ~ image_count.value ~ ': ' }}
18
+ {%- endif %}
19
+ {{- '<|vision_start|><|image_pad|><|vision_end|>' }}
20
+ {%- elif 'video' in item or item.type == 'video' %}
21
+ {%- if is_system_content %}
22
+ {{- raise_exception('System message cannot contain videos.') }}
23
+ {%- endif %}
24
+ {%- if do_vision_count %}
25
+ {%- set video_count.value = video_count.value + 1 %}
26
+ {%- endif %}
27
+ {%- if add_vision_id %}
28
+ {{- 'Video ' ~ video_count.value ~ ': ' }}
29
+ {%- endif %}
30
+ {{- '<|vision_start|><|video_pad|><|vision_end|>' }}
31
+ {%- elif 'text' in item %}
32
+ {{- item.text }}
33
+ {%- else %}
34
+ {{- raise_exception('Unexpected item type in content.') }}
35
+ {%- endif %}
36
+ {%- endfor %}
37
+ {%- elif content is none or content is undefined %}
38
+ {{- '' }}
39
+ {%- else %}
40
+ {{- raise_exception('Unexpected content type.') }}
41
+ {%- endif %}
42
+ {%- endmacro %}
43
+ {%- if not messages %}
44
+ {{- raise_exception('No messages provided.') }}
45
+ {%- endif %}
46
+ {%- if tools and tools is iterable and tools is not mapping %}
47
+ {{- '<|im_start|>system\n' }}
48
+ {{- "# Tools\n\nYou have access to the following functions:\n\n<tools>" }}
49
+ {%- for tool in tools %}
50
+ {{- "\n" }}
51
+ {{- tool | tojson }}
52
+ {%- endfor %}
53
+ {{- "\n</tools>" }}
54
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
55
+ {%- if messages[0].role == 'system' %}
56
+ {%- set content = render_content(messages[0].content, false, true)|trim %}
57
+ {%- if content %}
58
+ {{- '\n\n' + content }}
59
+ {%- endif %}
60
+ {%- endif %}
61
+ {{- '<|im_end|>\n' }}
62
+ {%- else %}
63
+ {%- if messages[0].role == 'system' %}
64
+ {%- set content = render_content(messages[0].content, false, true)|trim %}
65
+ {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
66
+ {%- endif %}
67
+ {%- endif %}
68
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
69
+ {%- for message in messages[::-1] %}
70
+ {%- set index = (messages|length - 1) - loop.index0 %}
71
+ {%- if ns.multi_step_tool and message.role == "user" %}
72
+ {%- set content = render_content(message.content, false)|trim %}
73
+ {%- if not(content.startswith('<tool_response>') and content.endswith('</tool_response>')) %}
74
+ {%- set ns.multi_step_tool = false %}
75
+ {%- set ns.last_query_index = index %}
76
+ {%- endif %}
77
+ {%- endif %}
78
+ {%- endfor %}
79
+ {%- if ns.multi_step_tool %}
80
+ {{- raise_exception('No user query found in messages.') }}
81
+ {%- endif %}
82
+ {%- for message in messages %}
83
+ {%- set content = render_content(message.content, true)|trim %}
84
+ {%- if message.role == "system" %}
85
+ {%- if not loop.first %}
86
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
87
+ {%- endif %}
88
+ {%- elif message.role == "user" %}
89
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
90
+ {%- elif message.role == "assistant" %}
91
+ {%- set reasoning_content = '' %}
92
+ {%- if message.reasoning_content is string %}
93
+ {%- set reasoning_content = message.reasoning_content %}
94
+ {%- else %}
95
+ {%- if '</think>' in content %}
96
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
97
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
98
+ {%- endif %}
99
+ {%- endif %}
100
+ {%- set reasoning_content = reasoning_content|trim %}
101
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}
102
+ {%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}
103
+ {%- for tool_call in message.tool_calls %}
104
+ {%- if tool_call.function is defined %}
105
+ {%- set tool_call = tool_call.function %}
106
+ {%- endif %}
107
+ {%- if loop.first %}
108
+ {%- if content|trim %}
109
+ {{- '\n\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
110
+ {%- else %}
111
+ {{- '<tool_call>\n<function=' + tool_call.name + '>\n' }}
112
+ {%- endif %}
113
+ {%- else %}
114
+ {{- '\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
115
+ {%- endif %}
116
+ {%- if tool_call.arguments is defined %}
117
+ {%- for args_name, args_value in tool_call.arguments|items %}
118
+ {{- '<parameter=' + args_name + '>\n' }}
119
+ {%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}
120
+ {{- args_value }}
121
+ {{- '\n</parameter>\n' }}
122
+ {%- endfor %}
123
+ {%- endif %}
124
+ {{- '</function>\n</tool_call>' }}
125
+ {%- endfor %}
126
+ {%- endif %}
127
+ {{- '<|im_end|>\n' }}
128
+ {%- elif message.role == "tool" %}
129
+ {%- if loop.previtem and loop.previtem.role != "tool" %}
130
+ {{- '<|im_start|>user' }}
131
+ {%- endif %}
132
+ {{- '\n<tool_response>\n' }}
133
+ {{- content }}
134
+ {{- '\n</tool_response>' }}
135
+ {%- if not loop.last and loop.nextitem.role != "tool" %}
136
+ {{- '<|im_end|>\n' }}
137
+ {%- elif loop.last %}
138
+ {{- '<|im_end|>\n' }}
139
+ {%- endif %}
140
+ {%- else %}
141
+ {{- raise_exception('Unexpected message role.') }}
142
+ {%- endif %}
143
+ {%- endfor %}
144
+ {%- if add_generation_prompt %}
145
+ {{- '<|im_start|>assistant\n' }}
146
+ {%- if reasoning_effort is not defined or reasoning_effort is none %}
147
+ {{- '<think>' }}
148
+ {%- elif reasoning_effort == 'none' %}
149
+ {{- '<think>\n\n</think>\n\n' }}
150
+ {%- elif reasoning_effort == 'high' %}
151
+ {{- '<think>\n' }}
152
+ {%- else %}
153
+ {{- '<think>' }}
154
+ {%- endif %}
155
+ {%- endif %}
recipe/logs/N4_kld_q102.log ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 0.00.046.192 I common_init_result: fitting params to device memory ...
2
+ 0.00.046.197 I common_init_result: (for bugs during this step try to reproduce them with -fit off, or provide --verbose logs if the bug only occurs with -fit on)
3
+ 0.00.468.601 W llama_model_loader: direct I/O is enabled, disabling mmap
4
+ 0.26.097.875 W llama_context: n_ctx_seq (2048) < n_ctx_train (262144) -- the full capacity of the model will not be utilized
5
+ 0.26.161.936 W common_init_from_params: warming up the model with an empty run - please wait ... (--no-warmup to disable)
6
+ 0.26.456.383 I
7
+ 0.26.456.524 I system_info: n_threads = 16 (n_threads_batch = 16) / 32 | ROCm : NO_VMM = 1 | PEER_MAX_BATCH_SIZE = 128 | FA_ALL_QUANTS = 1 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX_VNNI = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | AVX512 = 1 | AVX512_VBMI = 1 | AVX512_VNNI = 1 | AVX512_BF16 = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 |
8
+ 0.26.593.623 I kl_divergence: computing over 40 chunks, n_ctx=2048, batch_size=2048, n_seq=1
9
+ 0.29.575.306 I kl_divergence: 2.98 seconds per pass - ETA 1.98 minutes
10
+
11
+ chunk PPL ln(PPL(Q)/PPL(base)) KL Divergence Δp RMS Same top p
12
+ 1 5.9944 ± 0.4685 0.05151 ± 0.01742 0.11333 ± 0.00681 10.320 ± 0.638 % 87.390 ± 1.038 %
13
+ 2 6.9832 ± 0.3895 0.04665 ± 0.01189 0.09838 ± 0.00400 8.897 ± 0.415 % 87.048 ± 0.743 %
14
+ 3 7.5417 ± 0.3512 0.07003 ± 0.00990 0.10487 ± 0.00406 9.267 ± 0.393 % 87.195 ± 0.603 %
15
+ 4 7.8954 ± 0.3289 0.08016 ± 0.00897 0.11061 ± 0.00503 9.327 ± 0.343 % 86.901 ± 0.527 %
16
+ 5 7.6999 ± 0.2880 0.07519 ± 0.00798 0.10848 ± 0.00428 9.187 ± 0.313 % 87.097 ± 0.469 %
17
+ 6 6.6265 ± 0.2194 0.07502 ± 0.00740 0.11000 ± 0.00421 9.941 ± 0.317 % 87.455 ± 0.423 %
18
+ 7 6.1509 ± 0.1859 0.06918 ± 0.00711 0.11837 ± 0.00459 10.426 ± 0.309 % 87.530 ± 0.390 %
19
+ 8 6.0395 ± 0.1692 0.06322 ± 0.00648 0.11517 ± 0.00408 10.254 ± 0.281 % 87.476 ± 0.366 %
20
+ 9 6.3422 ± 0.1682 0.05959 ± 0.00609 0.11478 ± 0.00370 10.054 ± 0.261 % 87.216 ± 0.348 %
21
+ 10 6.4559 ± 0.1635 0.05892 ± 0.00570 0.11065 ± 0.00337 9.793 ± 0.242 % 87.243 ± 0.330 %
22
+ 11 6.5040 ± 0.1565 0.05755 ± 0.00536 0.10715 ± 0.00309 9.593 ± 0.227 % 87.283 ± 0.314 %
23
+ 12 6.7574 ± 0.1569 0.05744 ± 0.00504 0.10450 ± 0.00284 9.400 ± 0.214 % 87.211 ± 0.301 %
24
+ 13 6.8020 ± 0.1514 0.05713 ± 0.00478 0.10247 ± 0.00264 9.285 ± 0.203 % 87.232 ± 0.289 %
25
+ 14 6.8553 ± 0.1467 0.05617 ± 0.00457 0.10045 ± 0.00247 9.123 ± 0.192 % 87.236 ± 0.279 %
26
+ 15 6.8957 ± 0.1427 0.05582 ± 0.00438 0.09956 ± 0.00232 9.076 ± 0.184 % 87.247 ± 0.269 %
27
+ 16 7.0571 ± 0.1415 0.05224 ± 0.00422 0.09847 ± 0.00219 8.961 ± 0.175 % 87.243 ± 0.261 %
28
+ 17 7.0917 ± 0.1375 0.05016 ± 0.00405 0.09704 ± 0.00208 8.871 ± 0.169 % 87.281 ± 0.253 %
29
+ 18 7.1772 ± 0.1353 0.04896 ± 0.00392 0.09635 ± 0.00198 8.799 ± 0.162 % 87.243 ± 0.246 %
30
+ 19 7.1236 ± 0.1311 0.04836 ± 0.00378 0.09524 ± 0.00190 8.763 ± 0.159 % 87.303 ± 0.239 %
31
+ 20 6.8769 ± 0.1227 0.05245 ± 0.00378 0.10018 ± 0.00190 9.053 ± 0.155 % 87.175 ± 0.234 %
32
+ 21 6.8931 ± 0.1198 0.05231 ± 0.00368 0.10066 ± 0.00184 9.029 ± 0.150 % 87.120 ± 0.229 %
33
+ 22 6.9236 ± 0.1178 0.05472 ± 0.00363 0.10218 ± 0.00181 9.063 ± 0.147 % 87.168 ± 0.223 %
34
+ 23 6.9807 ± 0.1162 0.05553 ± 0.00354 0.10187 ± 0.00175 9.045 ± 0.143 % 87.131 ± 0.218 %
35
+ 24 6.9769 ± 0.1134 0.05494 ± 0.00347 0.10222 ± 0.00175 9.051 ± 0.143 % 87.093 ± 0.214 %
36
+ 25 7.0111 ± 0.1117 0.05513 ± 0.00339 0.10169 ± 0.00169 8.997 ± 0.139 % 87.015 ± 0.210 %
37
+ 26 6.9763 ± 0.1088 0.05463 ± 0.00332 0.10165 ± 0.00165 9.014 ± 0.137 % 87.055 ± 0.206 %
38
+ 27 7.1528 ± 0.1102 0.05528 ± 0.00326 0.10141 ± 0.00162 8.950 ± 0.134 % 87.079 ± 0.202 %
39
+ 28 7.2365 ± 0.1098 0.05405 ± 0.00318 0.10027 ± 0.00157 8.866 ± 0.131 % 87.118 ± 0.198 %
40
+ 29 7.2391 ± 0.1079 0.05527 ± 0.00313 0.10044 ± 0.00154 8.907 ± 0.129 % 87.077 ± 0.195 %
41
+ 30 7.1873 ± 0.1051 0.05609 ± 0.00307 0.10003 ± 0.00150 8.887 ± 0.126 % 87.061 ± 0.192 %
42
+ 31 7.0778 ± 0.1015 0.05524 ± 0.00300 0.09893 ± 0.00145 8.840 ± 0.123 % 87.154 ± 0.188 %
43
+ 32 6.9728 ± 0.0983 0.05456 ± 0.00300 0.10164 ± 0.00161 8.995 ± 0.124 % 87.121 ± 0.185 %
44
+ 33 6.9098 ± 0.0957 0.05537 ± 0.00295 0.10136 ± 0.00157 8.987 ± 0.122 % 87.153 ± 0.182 %
45
+ 34 6.8891 ± 0.0938 0.05453 ± 0.00288 0.10042 ± 0.00153 8.943 ± 0.120 % 87.154 ± 0.179 %
46
+ 35 6.9008 ± 0.0926 0.05442 ± 0.00283 0.09974 ± 0.00149 8.883 ± 0.118 % 87.214 ± 0.176 %
47
+ 36 6.9190 ± 0.0917 0.05458 ± 0.00279 0.09958 ± 0.00146 8.857 ± 0.116 % 87.197 ± 0.174 %
48
+ 37 6.8168 ± 0.0888 0.05349 ± 0.00273 0.09856 ± 0.00142 8.817 ± 0.113 % 87.242 ± 0.171 %
49
+ 38 6.7442 ± 0.0864 0.05330 ± 0.00269 0.09804 ± 0.00139 8.824 ± 0.112 % 87.277 ± 0.169 %
50
+ 39 6.6583 ± 0.0839 0.05282 ± 0.00265 0.09776 ± 0.00137 8.827 ± 0.110 % 87.247 ± 0.167 %
51
+ 40 6.5617 ± 0.0812 0.05204 ± 0.00261 0.09707 ± 0.00134 8.800 ± 0.108 % 87.287 ± 0.165 %
52
+
53
+ ====== Perplexity statistics ======
54
+ Mean PPL(Q) : 6.561727 ± 0.081240
55
+ Mean PPL(base) : 6.228979 ± 0.075322
56
+ Cor(ln(PPL(Q)), ln(PPL(base))): 97.76%
57
+ Mean ln(PPL(Q)/PPL(base)) : 0.052041 ± 0.002607
58
+ Mean PPL(Q)/PPL(base) : 1.053419 ± 0.002746
59
+ Mean PPL(Q)-PPL(base) : 0.332749 ± 0.017588
60
+
61
+ ====== KL divergence statistics ======
62
+ Mean KLD: 0.097071 ± 0.001342
63
+ Maximum KLD: 12.257548
64
+ 99.9% KLD: 3.289070
65
+ 99.0% KLD: 0.874485
66
+ 95.0% KLD: 0.332573
67
+ 90.0% KLD: 0.209309
68
+ Median KLD: 0.043524
69
+ 10.0% KLD: 0.000605
70
+ 5.0% KLD: 0.000161
71
+ 1.0% KLD: -0.000023
72
+ 0.1% KLD: -0.000269
73
+ Minimum KLD: -0.000603
74
+
75
+ ====== Token probability statistics ======
76
+ Mean Δp: -0.366 ± 0.043 %
77
+ Maximum Δp: 99.335%
78
+ 99.9% Δp: 53.261%
79
+ 99.0% Δp: 23.761%
80
+ 95.0% Δp: 10.784%
81
+ 90.0% Δp: 6.407%
82
+ 75.0% Δp: 1.292%
83
+ Median Δp: -0.004%
84
+ 25.0% Δp: -1.463%
85
+ 10.0% Δp: -6.895%
86
+ 5.0% Δp: -12.449%
87
+ 1.0% Δp: -30.951%
88
+ 0.1% Δp: -71.092%
89
+ Minimum Δp: -99.867%
90
+ RMS Δp : 8.800 ± 0.108 %
91
+ Same top p: 87.287 ± 0.165 %
92
+
recipe/logs/N4_kld_q103.log ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 0.00.043.507 I common_init_result: fitting params to device memory ...
2
+ 0.00.043.512 I common_init_result: (for bugs during this step try to reproduce them with -fit off, or provide --verbose logs if the bug only occurs with -fit on)
3
+ 0.00.547.415 W llama_model_loader: direct I/O is enabled, disabling mmap
4
+ 0.28.910.009 W llama_context: n_ctx_seq (2048) < n_ctx_train (262144) -- the full capacity of the model will not be utilized
5
+ 0.28.974.230 W common_init_from_params: warming up the model with an empty run - please wait ... (--no-warmup to disable)
6
+ 0.29.190.163 I
7
+ 0.29.190.272 I system_info: n_threads = 16 (n_threads_batch = 16) / 32 | ROCm : NO_VMM = 1 | PEER_MAX_BATCH_SIZE = 128 | FA_ALL_QUANTS = 1 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX_VNNI = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | AVX512 = 1 | AVX512_VBMI = 1 | AVX512_VNNI = 1 | AVX512_BF16 = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 |
8
+ 0.29.311.893 I kl_divergence: computing over 40 chunks, n_ctx=2048, batch_size=2048, n_seq=1
9
+ 0.31.982.391 I kl_divergence: 2.67 seconds per pass - ETA 1.77 minutes
10
+
11
+ chunk PPL ln(PPL(Q)/PPL(base)) KL Divergence Δp RMS Same top p
12
+ 1 6.3324 ± 0.5080 0.10635 ± 0.02072 0.14199 ± 0.00911 10.822 ± 0.626 % 85.728 ± 1.094 %
13
+ 2 7.2445 ± 0.4085 0.08338 ± 0.01320 0.11857 ± 0.00596 9.324 ± 0.416 % 86.510 ± 0.755 %
14
+ 3 7.6437 ± 0.3567 0.08347 ± 0.01046 0.11993 ± 0.00567 9.224 ± 0.356 % 85.956 ± 0.627 %
15
+ 4 7.8662 ± 0.3254 0.07645 ± 0.00919 0.12254 ± 0.00560 9.291 ± 0.320 % 85.997 ± 0.543 %
16
+ 5 7.6438 ± 0.2844 0.06788 ± 0.00816 0.11930 ± 0.00461 9.150 ± 0.277 % 86.041 ± 0.485 %
17
+ 6 6.5928 ± 0.2169 0.06992 ± 0.00760 0.12081 ± 0.00444 9.877 ± 0.294 % 86.298 ± 0.439 %
18
+ 7 6.0938 ± 0.1829 0.05985 ± 0.00717 0.12740 ± 0.00482 10.188 ± 0.281 % 86.468 ± 0.404 %
19
+ 8 6.0037 ± 0.1675 0.05727 ± 0.00661 0.12543 ± 0.00429 10.065 ± 0.258 % 86.522 ± 0.377 %
20
+ 9 6.3212 ± 0.1671 0.05627 ± 0.00620 0.12516 ± 0.00387 9.872 ± 0.238 % 86.282 ± 0.359 %
21
+ 10 6.4505 ± 0.1629 0.05808 ± 0.00580 0.12152 ± 0.00352 9.739 ± 0.221 % 86.354 ± 0.339 %
22
+ 11 6.5075 ± 0.1561 0.05809 ± 0.00543 0.11797 ± 0.00323 9.554 ± 0.208 % 86.404 ± 0.323 %
23
+ 12 6.7603 ± 0.1566 0.05787 ± 0.00509 0.11420 ± 0.00297 9.348 ± 0.196 % 86.355 ± 0.310 %
24
+ 13 6.7920 ± 0.1508 0.05567 ± 0.00486 0.11244 ± 0.00278 9.245 ± 0.186 % 86.397 ± 0.297 %
25
+ 14 6.8545 ± 0.1464 0.05605 ± 0.00465 0.11100 ± 0.00260 9.142 ± 0.177 % 86.385 ± 0.287 %
26
+ 15 6.8911 ± 0.1423 0.05516 ± 0.00446 0.11053 ± 0.00247 9.124 ± 0.169 % 86.354 ± 0.277 %
27
+ 16 7.0572 ± 0.1413 0.05225 ± 0.00431 0.10982 ± 0.00235 9.046 ± 0.163 % 86.254 ± 0.269 %
28
+ 17 7.0949 ± 0.1372 0.05061 ± 0.00415 0.10844 ± 0.00223 8.972 ± 0.157 % 86.263 ± 0.261 %
29
+ 18 7.1844 ± 0.1351 0.04995 ± 0.00401 0.10792 ± 0.00213 8.944 ± 0.152 % 86.168 ± 0.254 %
30
+ 19 7.1415 ± 0.1312 0.05088 ± 0.00389 0.10652 ± 0.00203 8.872 ± 0.147 % 86.191 ± 0.247 %
31
+ 20 6.8778 ± 0.1223 0.05258 ± 0.00387 0.11191 ± 0.00202 9.238 ± 0.145 % 86.144 ± 0.242 %
32
+ 21 6.8965 ± 0.1195 0.05280 ± 0.00379 0.11255 ± 0.00196 9.249 ± 0.143 % 86.110 ± 0.236 %
33
+ 22 6.9128 ± 0.1172 0.05316 ± 0.00370 0.11332 ± 0.00190 9.279 ± 0.140 % 86.150 ± 0.230 %
34
+ 23 6.9751 ± 0.1157 0.05473 ± 0.00362 0.11327 ± 0.00185 9.276 ± 0.138 % 86.124 ± 0.225 %
35
+ 24 6.9742 ± 0.1131 0.05456 ± 0.00353 0.11363 ± 0.00182 9.287 ± 0.137 % 86.091 ± 0.221 %
36
+ 25 7.0117 ± 0.1115 0.05521 ± 0.00346 0.11333 ± 0.00176 9.261 ± 0.133 % 86.088 ± 0.216 %
37
+ 26 6.9819 ± 0.1087 0.05543 ± 0.00339 0.11378 ± 0.00175 9.294 ± 0.131 % 86.127 ± 0.212 %
38
+ 27 7.1532 ± 0.1100 0.05533 ± 0.00332 0.11307 ± 0.00170 9.223 ± 0.128 % 86.148 ± 0.208 %
39
+ 28 7.2405 ± 0.1097 0.05461 ± 0.00324 0.11201 ± 0.00165 9.147 ± 0.126 % 86.193 ± 0.204 %
40
+ 29 7.2447 ± 0.1078 0.05604 ± 0.00319 0.11216 ± 0.00161 9.196 ± 0.125 % 86.133 ± 0.201 %
41
+ 30 7.1827 ± 0.1049 0.05545 ± 0.00314 0.11174 ± 0.00157 9.180 ± 0.122 % 86.103 ± 0.197 %
42
+ 31 7.0787 ± 0.1014 0.05537 ± 0.00308 0.11105 ± 0.00153 9.164 ± 0.119 % 86.201 ± 0.194 %
43
+ 32 6.9666 ± 0.0980 0.05367 ± 0.00307 0.11404 ± 0.00170 9.317 ± 0.121 % 86.150 ± 0.191 %
44
+ 33 6.9006 ± 0.0953 0.05404 ± 0.00303 0.11358 ± 0.00167 9.303 ± 0.119 % 86.167 ± 0.188 %
45
+ 34 6.8792 ± 0.0934 0.05310 ± 0.00297 0.11250 ± 0.00162 9.246 ± 0.117 % 86.180 ± 0.185 %
46
+ 35 6.8869 ± 0.0922 0.05240 ± 0.00291 0.11158 ± 0.00158 9.198 ± 0.116 % 86.242 ± 0.182 %
47
+ 36 6.9043 ± 0.0912 0.05245 ± 0.00287 0.11125 ± 0.00154 9.156 ± 0.113 % 86.239 ± 0.180 %
48
+ 37 6.8080 ± 0.0885 0.05220 ± 0.00282 0.11015 ± 0.00151 9.118 ± 0.111 % 86.304 ± 0.177 %
49
+ 38 6.7280 ± 0.0860 0.05090 ± 0.00278 0.10979 ± 0.00147 9.111 ± 0.109 % 86.343 ± 0.174 %
50
+ 39 6.6466 ± 0.0835 0.05105 ± 0.00274 0.10941 ± 0.00145 9.111 ± 0.107 % 86.370 ± 0.172 %
51
+ 40 6.5498 ± 0.0809 0.05023 ± 0.00270 0.10878 ± 0.00142 9.108 ± 0.106 % 86.405 ± 0.169 %
52
+
53
+ ====== Perplexity statistics ======
54
+ Mean PPL(Q) : 6.549829 ± 0.080919
55
+ Mean PPL(base) : 6.228979 ± 0.075322
56
+ Cor(ln(PPL(Q)), ln(PPL(base))): 97.58%
57
+ Mean ln(PPL(Q)/PPL(base)) : 0.050227 ± 0.002704
58
+ Mean PPL(Q)/PPL(base) : 1.051509 ± 0.002843
59
+ Mean PPL(Q)-PPL(base) : 0.320850 ± 0.018076
60
+
61
+ ====== KL divergence statistics ======
62
+ Mean KLD: 0.108779 ± 0.001420
63
+ Maximum KLD: 12.086925
64
+ 99.9% KLD: 3.352409
65
+ 99.0% KLD: 0.956811
66
+ 95.0% KLD: 0.370801
67
+ 90.0% KLD: 0.235309
68
+ Median KLD: 0.049730
69
+ 10.0% KLD: 0.000721
70
+ 5.0% KLD: 0.000197
71
+ 1.0% KLD: -0.000038
72
+ 0.1% KLD: -0.000343
73
+ Minimum KLD: -0.000800
74
+
75
+ ====== Token probability statistics ======
76
+ Mean Δp: -0.515 ± 0.045 %
77
+ Maximum Δp: 98.721%
78
+ 99.9% Δp: 52.916%
79
+ 99.0% Δp: 24.226%
80
+ 95.0% Δp: 11.222%
81
+ 90.0% Δp: 6.613%
82
+ 75.0% Δp: 1.299%
83
+ Median Δp: -0.007%
84
+ 25.0% Δp: -1.668%
85
+ 10.0% Δp: -7.814%
86
+ 5.0% Δp: -13.545%
87
+ 1.0% Δp: -32.559%
88
+ 0.1% Δp: -70.472%
89
+ Minimum Δp: -99.855%
90
+ RMS Δp : 9.108 ± 0.106 %
91
+ Same top p: 86.405 ± 0.169 %
92
+
recipe/logs/N4v_kld_q102.log ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 0.00.044.057 I common_init_result: fitting params to device memory ...
2
+ 0.00.044.061 I common_init_result: (for bugs during this step try to reproduce them with -fit off, or provide --verbose logs if the bug only occurs with -fit on)
3
+ 0.00.458.402 W llama_model_loader: direct I/O is enabled, disabling mmap
4
+ 0.01.547.350 W read_raw_unsafe: Falling back to buffered IO due to Bad address
5
+ 0.29.871.824 W llama_context: n_ctx_seq (2048) < n_ctx_train (262144) -- the full capacity of the model will not be utilized
6
+ 0.29.921.987 W common_init_from_params: warming up the model with an empty run - please wait ... (--no-warmup to disable)
7
+ 0.30.136.871 I
8
+ 0.30.137.012 I system_info: n_threads = 16 (n_threads_batch = 16) / 32 | ROCm : NO_VMM = 1 | PEER_MAX_BATCH_SIZE = 128 | FA_ALL_QUANTS = 1 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX_VNNI = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | AVX512 = 1 | AVX512_VBMI = 1 | AVX512_VNNI = 1 | AVX512_BF16 = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 |
9
+ 0.30.272.958 I kl_divergence: computing over 40 chunks, n_ctx=2048, batch_size=2048, n_seq=1
10
+ 0.33.203.394 I kl_divergence: 2.93 seconds per pass - ETA 1.95 minutes
11
+
12
+ chunk PPL ln(PPL(Q)/PPL(base)) KL Divergence Δp RMS Same top p
13
+ 1 5.9966 ± 0.4697 0.05187 ± 0.01811 0.11459 ± 0.00733 10.192 ± 0.639 % 86.217 ± 1.078 %
14
+ 2 6.9326 ± 0.3865 0.03938 ± 0.01202 0.09983 ± 0.00427 8.906 ± 0.415 % 86.364 ± 0.759 %
15
+ 3 7.4953 ± 0.3486 0.06386 ± 0.01034 0.10617 ± 0.00431 9.400 ± 0.398 % 86.771 ± 0.612 %
16
+ 4 7.8932 ± 0.3295 0.07988 ± 0.00943 0.11534 ± 0.00606 9.599 ± 0.356 % 86.779 ± 0.530 %
17
+ 5 7.6968 ± 0.2885 0.07479 ± 0.00839 0.11294 ± 0.00512 9.430 ± 0.323 % 86.979 ± 0.471 %
18
+ 6 6.6156 ± 0.2191 0.07337 ± 0.00761 0.11303 ± 0.00469 10.110 ± 0.316 % 87.341 ± 0.424 %
19
+ 7 6.1496 ± 0.1860 0.06895 ± 0.00729 0.12010 ± 0.00470 10.509 ± 0.310 % 87.544 ± 0.390 %
20
+ 8 6.0524 ± 0.1698 0.06536 ± 0.00664 0.11729 ± 0.00419 10.338 ± 0.282 % 87.414 ± 0.367 %
21
+ 9 6.3606 ± 0.1689 0.06248 ± 0.00621 0.11624 ± 0.00378 10.074 ± 0.260 % 87.053 ± 0.350 %
22
+ 10 6.4785 ± 0.1643 0.06242 ± 0.00577 0.11173 ± 0.00343 9.809 ± 0.243 % 87.185 ± 0.330 %
23
+ 11 6.5332 ± 0.1574 0.06204 ± 0.00542 0.10800 ± 0.00313 9.617 ± 0.228 % 87.203 ± 0.315 %
24
+ 12 6.7836 ± 0.1577 0.06132 ± 0.00509 0.10489 ± 0.00288 9.401 ± 0.215 % 87.154 ± 0.302 %
25
+ 13 6.8332 ± 0.1523 0.06171 ± 0.00483 0.10310 ± 0.00268 9.272 ± 0.203 % 87.112 ± 0.291 %
26
+ 14 6.8837 ± 0.1476 0.06029 ± 0.00462 0.10108 ± 0.00251 9.107 ± 0.193 % 87.222 ± 0.279 %
27
+ 15 6.9222 ± 0.1435 0.05966 ± 0.00443 0.10045 ± 0.00236 9.064 ± 0.184 % 87.129 ± 0.270 %
28
+ 16 7.0981 ± 0.1428 0.05802 ± 0.00427 0.09952 ± 0.00223 8.947 ± 0.176 % 87.170 ± 0.261 %
29
+ 17 7.1355 ± 0.1388 0.05632 ± 0.00410 0.09812 ± 0.00211 8.873 ± 0.170 % 87.229 ± 0.253 %
30
+ 18 7.2233 ± 0.1366 0.05535 ± 0.00396 0.09744 ± 0.00201 8.809 ± 0.164 % 87.151 ± 0.247 %
31
+ 19 7.1804 ± 0.1327 0.05631 ± 0.00385 0.09656 ± 0.00193 8.767 ± 0.160 % 87.138 ± 0.240 %
32
+ 20 6.9267 ± 0.1241 0.05967 ± 0.00383 0.10094 ± 0.00190 9.066 ± 0.156 % 87.043 ± 0.235 %
33
+ 21 6.9448 ± 0.1213 0.05978 ± 0.00374 0.10135 ± 0.00184 9.031 ± 0.151 % 87.032 ± 0.229 %
34
+ 22 6.9675 ± 0.1190 0.06104 ± 0.00367 0.10256 ± 0.00183 9.077 ± 0.149 % 87.035 ± 0.224 %
35
+ 23 7.0270 ± 0.1174 0.06214 ± 0.00359 0.10236 ± 0.00177 9.057 ± 0.146 % 86.986 ± 0.219 %
36
+ 24 7.0192 ± 0.1145 0.06099 ± 0.00349 0.10191 ± 0.00171 9.016 ± 0.143 % 86.983 ± 0.215 %
37
+ 25 7.0530 ± 0.1127 0.06108 ± 0.00342 0.10141 ± 0.00166 8.977 ± 0.139 % 86.952 ± 0.211 %
38
+ 26 7.0192 ± 0.1099 0.06075 ± 0.00334 0.10143 ± 0.00162 8.999 ± 0.137 % 86.973 ± 0.206 %
39
+ 27 7.1950 ± 0.1112 0.06116 ± 0.00329 0.10126 ± 0.00160 8.943 ± 0.134 % 86.988 ± 0.202 %
40
+ 28 7.2801 ± 0.1108 0.06006 ± 0.00321 0.10017 ± 0.00155 8.860 ± 0.131 % 86.975 ± 0.199 %
41
+ 29 7.2833 ± 0.1089 0.06136 ± 0.00316 0.10033 ± 0.00152 8.904 ± 0.130 % 86.925 ± 0.196 %
42
+ 30 7.2262 ± 0.1061 0.06148 ± 0.00310 0.09994 ± 0.00148 8.892 ± 0.127 % 86.937 ± 0.192 %
43
+ 31 7.1166 ± 0.1024 0.06072 ± 0.00302 0.09878 ± 0.00144 8.837 ± 0.124 % 87.043 ± 0.189 %
44
+ 32 7.0141 ± 0.0992 0.06047 ± 0.00303 0.10174 ± 0.00161 9.036 ± 0.126 % 87.014 ± 0.186 %
45
+ 33 6.9480 ± 0.0965 0.06088 ± 0.00298 0.10139 ± 0.00157 9.021 ± 0.124 % 87.046 ± 0.183 %
46
+ 34 6.9248 ± 0.0946 0.05971 ± 0.00291 0.10041 ± 0.00152 8.964 ± 0.121 % 87.091 ± 0.180 %
47
+ 35 6.9370 ± 0.0934 0.05965 ± 0.00285 0.09981 ± 0.00149 8.914 ± 0.119 % 87.139 ± 0.177 %
48
+ 36 6.9569 ± 0.0925 0.06004 ± 0.00282 0.09978 ± 0.00146 8.900 ± 0.118 % 87.159 ± 0.174 %
49
+ 37 6.8518 ± 0.0895 0.05860 ± 0.00276 0.09882 ± 0.00142 8.866 ± 0.115 % 87.192 ± 0.172 %
50
+ 38 6.7745 ± 0.0870 0.05779 ± 0.00272 0.09818 ± 0.00139 8.852 ± 0.114 % 87.256 ± 0.169 %
51
+ 39 6.6883 ± 0.0845 0.05732 ± 0.00267 0.09776 ± 0.00137 8.864 ± 0.112 % 87.232 ± 0.167 %
52
+ 40 6.5921 ± 0.0819 0.05666 ± 0.00263 0.09716 ± 0.00134 8.853 ± 0.111 % 87.265 ± 0.165 %
53
+
54
+ ====== Perplexity statistics ======
55
+ Mean PPL(Q) : 6.592123 ± 0.081874
56
+ Mean PPL(base) : 6.228979 ± 0.075322
57
+ Cor(ln(PPL(Q)), ln(PPL(base))): 97.73%
58
+ Mean ln(PPL(Q)/PPL(base)) : 0.056663 ± 0.002630
59
+ Mean PPL(Q)/PPL(base) : 1.058299 ± 0.002783
60
+ Mean PPL(Q)-PPL(base) : 0.363144 ± 0.017958
61
+
62
+ ====== KL divergence statistics ======
63
+ Mean KLD: 0.097165 ± 0.001337
64
+ Maximum KLD: 15.969161
65
+ 99.9% KLD: 3.145117
66
+ 99.0% KLD: 0.858566
67
+ 95.0% KLD: 0.329361
68
+ 90.0% KLD: 0.207554
69
+ Median KLD: 0.043968
70
+ 10.0% KLD: 0.000631
71
+ 5.0% KLD: 0.000159
72
+ 1.0% KLD: -0.000029
73
+ 0.1% KLD: -0.000286
74
+ Minimum KLD: -0.000564
75
+
76
+ ====== Token probability statistics ======
77
+ Mean Δp: -0.372 ± 0.044 %
78
+ Maximum Δp: 98.904%
79
+ 99.9% Δp: 55.573%
80
+ 99.0% Δp: 23.490%
81
+ 95.0% Δp: 10.880%
82
+ 90.0% Δp: 6.394%
83
+ 75.0% Δp: 1.299%
84
+ Median Δp: -0.005%
85
+ 25.0% Δp: -1.458%
86
+ 10.0% Δp: -7.029%
87
+ 5.0% Δp: -12.485%
88
+ 1.0% Δp: -31.169%
89
+ 0.1% Δp: -73.630%
90
+ Minimum Δp: -99.736%
91
+ RMS Δp : 8.853 ± 0.111 %
92
+ Same top p: 87.265 ± 0.165 %
93
+
recipe/logs/N6_bench.log ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [2026-09-16T23:22:44Z] waiting for the quiet-box lock (no HF upload during speed runs)
2
+ [2026-09-17T00:32:03Z] quiet-box lock held
3
+ [2026-09-17T00:32:03Z] bench n-q106-rocm
4
+ {"label": "n-q106-rocm", "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "ROCm0", "ctx": 65536, "workload": "code", "load_s": 22.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 63.94, "tg_min": 63.56, "tg_max": 63.96, "pp_median": 1158.2, "prompt_n": 7098, "accept": null}
5
+ [2026-09-17T00:33:06Z] bench n-q106-vk
6
+ {"label": "n-q106-vk", "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "Vulkan0", "ctx": 65536, "workload": "code", "load_s": 4.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 68.16, "tg_min": 68.1, "tg_max": 68.21, "pp_median": 1006.0, "prompt_n": 7096, "accept": null}
7
+ [2026-09-17T00:33:54Z] bench n-q102-rocm
8
+ {"label": "n-q102-rocm", "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_COHERENT.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "ROCm0", "ctx": 65536, "workload": "code", "load_s": 24.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_COHERENT.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 61.74, "tg_min": 61.74, "tg_max": 61.8, "pp_median": 1186.7, "prompt_n": 7100, "accept": null}
9
+ [2026-09-17T00:34:58Z] bench n-q102-vk
10
+ {"label": "n-q102-vk", "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_COHERENT.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "Vulkan0", "ctx": 65536, "workload": "code", "load_s": 22.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_COHERENT.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 68.0, "tg_min": 67.88, "tg_max": 68.09, "pp_median": 1001.4, "prompt_n": 7098, "accept": null}
11
+ [2026-09-17T00:36:05Z] bench n-q103-rocm
12
+ {"label": "n-q103-rocm", "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_FAST.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "ROCm0", "ctx": 65536, "workload": "code", "load_s": 22.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_FAST.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 63.31, "tg_min": 63.14, "tg_max": 63.38, "pp_median": 1156.6, "prompt_n": 7100, "accept": null}
13
+ [2026-09-17T00:37:08Z] bench n-q103-vk
14
+ {"label": "n-q103-vk", "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_FAST.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "Vulkan0", "ctx": 65536, "workload": "code", "load_s": 20.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_FAST.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 68.62, "tg_min": 68.6, "tg_max": 68.67, "pp_median": 998.9, "prompt_n": 7098, "accept": null}
15
+ [2026-09-17T00:38:12Z] bench n-q106i-rocm
16
+ {"label": "n-q106i-rocm", "model": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "ROCm0", "ctx": 65536, "workload": "code", "load_s": 22.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out-imat/Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 63.29, "tg_min": 63.19, "tg_max": 63.41, "pp_median": 1145.3, "prompt_n": 7100, "accept": null}
17
+ [2026-09-17T00:39:16Z] bench n-q106i-vk
18
+ {"label": "n-q106i-vk", "model": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "Vulkan0", "ctx": 65536, "workload": "code", "load_s": 20.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out-imat/Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 67.77, "tg_min": 67.74, "tg_max": 67.86, "pp_median": 995.0, "prompt_n": 7098, "accept": null}
19
+ [2026-09-17T00:40:20Z] bench n-q102i-rocm
20
+ {"label": "n-q102i-rocm", "model": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_COHERENT.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "ROCm0", "ctx": 65536, "workload": "code", "load_s": 24.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out-imat/Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_COHERENT.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 61.56, "tg_min": 61.53, "tg_max": 61.63, "pp_median": 1183.6, "prompt_n": 7098, "accept": null}
21
+ [2026-09-17T00:41:25Z] bench n-q102i-vk
22
+ {"label": "n-q102i-vk", "model": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_COHERENT.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "Vulkan0", "ctx": 65536, "workload": "code", "load_s": 22.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out-imat/Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_COHERENT.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 67.81, "tg_min": 67.77, "tg_max": 67.85, "pp_median": 998.7, "prompt_n": 7097, "accept": null}
23
+ [2026-09-17T00:42:32Z] bench n-q103i-rocm
24
+ {"label": "n-q103i-rocm", "model": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_FAST.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "ROCm0", "ctx": 65536, "workload": "code", "load_s": 22.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out-imat/Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_FAST.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 63.03, "tg_min": 62.55, "tg_max": 63.11, "pp_median": 1154.4, "prompt_n": 7101, "accept": null}
25
+ [2026-09-17T00:43:35Z] bench n-q103i-vk
26
+ {"label": "n-q103i-vk", "model": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_FAST.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "Vulkan0", "ctx": 65536, "workload": "code", "load_s": 20.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out-imat/Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_FAST.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 68.44, "tg_min": 68.42, "tg_max": 68.56, "pp_median": 993.9, "prompt_n": 7098, "accept": null}
27
+ [2026-09-17T00:44:39Z] bench n-q106-rocm-prose
28
+ {"label": "n-q106-rocm-prose", "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "ROCm0", "ctx": 65536, "workload": "prose", "load_s": 22.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 63.06, "tg_min": 62.94, "tg_max": 63.09, "pp_median": 1139.1, "prompt_n": 7454, "accept": null}
29
+ [2026-09-17T00:45:44Z] bench n-q106-vk-prose
30
+ {"label": "n-q106-vk-prose", "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf", "draft": null, "nmax": null, "strict": false, "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin", "dev": "Vulkan0", "ctx": 65536, "workload": "prose", "load_s": 22.0, "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui", "tg_median": 67.34, "tg_min": 67.31, "tg_max": 67.35, "pp_median": 977.7, "prompt_n": 7454, "accept": null}
31
+ [2026-09-17T00:46:53Z] cachegate n-c3-q106
32
+ 788d", "cold_sha": "a8545d39788d", "instr": "Write a function that returns every regular expression used in this file. ok ok ok", "warm_instr": "Summarise this file. (warm-up 3) ok ok ok ok"}
33
+ {"variant": 4, "L": 7039, "warm_prompt_n": 1028, "warm_cache_n": 6011, "cold_prompt_n": 7039, "cold_cache_n": 0, "aligned": true, "warm_draft": [null, null], "cold_draft": [null, null], "identical": true, "first_diff_char": null, "warm_sha": "af97b2dde4e2", "cold_sha": "af97b2dde4e2", "instr": "Write a function that maps each class in this file to its base classes. ok", "warm_instr": "Summarise this file. (warm-up 4) ok ok ok ok"}
34
+ {"label": "n-c3-q106", "gate": "cachegate3-aligned", "n": 5, "L": 7039, "expect_cache_n": 6011, "all_reused": true, "all_aligned": true, "identical": 5, "result": "PASS"}
35
+ [2026-09-17T00:48:34Z] tools n-tools-q106
36
+ alse enum: unit=fahrenheit
37
+ PASS think=False correct-decline: content='391'
38
+ PASS think=False multi-turn: final='Tokyo is currently **21°C** with clear skies.'
39
+ PASS think=False streaming: stream args={'city': 'Rome', 'unit': 'celsius'}
40
+ PASS think=False parallel: calls=['lima', 'oslo']
41
+ {"label": "n-tools-q106", "passed": 6, "total": 14, "detail": {"multi-arg|think=True": false, "nested-object|think=True": false, "enum|think=True": false, "correct-decline|think=True": false, "multi-turn|think=True": false, "streaming|think=True": false, "parallel|think=True": false, "multi-arg|think=False": true, "nested-object|think=False": false, "enum|think=False": true, "correct-decline|think=False": true, "multi-turn|think=False": true, "streaming|think=False": true, "parallel|think=False": true}}
42
+ [2026-09-17T00:49:16Z] vision n-vision-q106-faon
43
+ {"label": "n-vision-q106-faon", "fa": "on", "mtp": false, "expected": "red,blue,circle,square", "answer": "The image shows two shapes: a red circle on the left and a blue square on the right.", "hits": ["red", "blue", "circle", "square"], "error": null, "server_died": false, "server_log_errors": [], "result": "PASS"}
44
+ [2026-09-17T00:49:42Z] vision n-vision-q106-faoff
45
+ {"label": "n-vision-q106-faoff", "fa": "off", "mtp": false, "expected": "red,blue,circle,square", "answer": "The image shows two simple shapes:\n\n- A **red circle** on the left.\n- A **blue square** on the right.", "hits": ["red", "blue", "circle", "square"], "error": null, "server_died": false, "server_log_errors": [], "result": "PASS"}
46
+ [2026-09-17T00:50:08Z] NEX_BENCH_DONE
recipe/logs/N6t_tools_roff.log ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ PASS think=True multi-arg: args={'city': 'Paris', 'unit': 'celsius'}
2
+ FAIL think=True nested-object: exception KeyError('tool_calls')
3
+ PASS think=True enum: unit=fahrenheit
4
+ PASS think=True correct-decline: content='391'
5
+ PASS think=True multi-turn: final='Tokyo is **21°C** and **clear** right now.'
6
+ PASS think=True streaming: stream args={'city': 'Rome', 'unit': 'celsius'}
7
+ PASS think=True parallel: calls=['lima', 'oslo']
8
+ PASS think=False multi-arg: args={'city': 'Paris', 'unit': 'celsius'}
9
+ PASS think=False nested-object: args={'title': 'Design review', 'when': {'date': '2026-10-02', 'time': '14:00'}, 'attendees': ['ana@x.io', 'bo@x.io']}
10
+ PASS think=False enum: unit=fahrenheit
11
+ PASS think=False correct-decline: content='391'
12
+ PASS think=False multi-turn: final='Tokyo is **21°C** and **clear**.'
13
+ PASS think=False streaming: stream args={'city': 'Rome', 'unit': 'celsius'}
14
+ PASS think=False parallel: calls=['lima', 'oslo']
15
+ {"label": "n-tools-q106-roff", "passed": 13, "total": 14, "detail": {"multi-arg|think=True": true, "nested-object|think=True": false, "enum|think=True": true, "correct-decline|think=True": true, "multi-turn|think=True": true, "streaming|think=True": true, "parallel|think=True": true, "multi-arg|think=False": true, "nested-object|think=False": true, "enum|think=False": true, "correct-decline|think=False": true, "multi-turn|think=False": true, "streaming|think=False": true, "parallel|think=False": true}}
16
+ PASS think=True multi-arg: args={'city': 'Paris', 'unit': 'celsius'}
17
+ PASS think=True nested-object: args={'title': 'Design review', 'when': {'date': '2026-10-02', 'time': '14:00'}, 'attendees': ['ana@x.io', 'bo@x.io']}
18
+ PASS think=True enum: unit=fahrenheit
19
+ PASS think=True correct-decline: content='391'
20
+ PASS think=True multi-turn: final='Tokyo is **21°C** and **clear**.'
21
+ PASS think=True streaming: stream args={'city': 'Rome', 'unit': 'celsius'}
22
+ FAIL think=True parallel: calls=['oslo']
23
+ PASS think=False multi-arg: args={'city': 'Paris', 'unit': 'celsius'}
24
+ PASS think=False nested-object: args={'title': 'Design review', 'when': {'date': '2026-10-02', 'time': '14:00'}, 'attendees': ['ana@x.io', 'bo@x.io']}
25
+ PASS think=False enum: unit=fahrenheit
26
+ PASS think=False correct-decline: content='391'
27
+ PASS think=False multi-turn: final='Tokyo’s current weather is **21°C and clear**.'
28
+ PASS think=False streaming: stream args={'city': 'Rome', 'unit': 'celsius'}
29
+ PASS think=False parallel: calls=['lima', 'oslo']
30
+ {"label": "n-tools-q106-roff-r2", "passed": 13, "total": 14, "detail": {"multi-arg|think=True": true, "nested-object|think=True": true, "enum|think=True": true, "correct-decline|think=True": true, "multi-turn|think=True": true, "streaming|think=True": true, "parallel|think=True": false, "multi-arg|think=False": true, "nested-object|think=False": true, "enum|think=False": true, "correct-decline|think=False": true, "multi-turn|think=False": true, "streaming|think=False": true, "parallel|think=False": true}}
31
+ PASS think=True multi-arg: args={'city': 'Paris', 'unit': 'celsius'}
32
+ PASS think=True nested-object: args={'title': 'Design review', 'when': {'date': '2026-10-02', 'time': '14:00'}, 'attendees': ['ana@x.io', 'bo@x.io']}
33
+ PASS think=True enum: unit=fahrenheit
34
+ PASS think=True correct-decline: content='391'
35
+ PASS think=True multi-turn: final='Tokyo is currently **21°C** with **clear skies**.'
36
+ PASS think=True streaming: stream args={'city': 'Rome', 'unit': 'celsius'}
37
+ PASS think=True parallel: calls=['lima', 'oslo']
38
+ PASS think=False multi-arg: args={'city': 'Paris', 'unit': 'celsius'}
39
+ PASS think=False nested-object: args={'title': 'Design review', 'when': {'date': '2026-10-02', 'time': '14:00'}, 'attendees': ['ana@x.io', 'bo@x.io']}
40
+ PASS think=False enum: unit=fahrenheit
41
+ PASS think=False correct-decline: content='391'
42
+ PASS think=False multi-turn: final='Tokyo’s weather is **21°C and clear**.'
43
+ PASS think=False streaming: stream args={'city': 'Rome', 'unit': 'celsius'}
44
+ PASS think=False parallel: calls=['lima', 'oslo']
45
+ {"label": "n-tools-q106-roff-r3", "passed": 14, "total": 14, "detail": {"multi-arg|think=True": true, "nested-object|think=True": true, "enum|think=True": true, "correct-decline|think=True": true, "multi-turn|think=True": true, "streaming|think=True": true, "parallel|think=True": true, "multi-arg|think=False": true, "nested-object|think=False": true, "enum|think=False": true, "correct-decline|think=False": true, "multi-turn|think=False": true, "streaming|think=False": true, "parallel|think=False": true}}
46
+ {"label": "n-vision-q106-roff-faon", "fa": "on", "mtp": false, "expected": "red,blue,circle,square", "answer": "The image shows two shapes: a red circle on the left and a blue square on the right.", "hits": ["red", "blue", "circle", "square"], "error": null, "server_died": false, "server_log_errors": [], "result": "PASS"}
47
+ probe no-kwargs correct-decline {"content": "391", "reasoning_len": 0, "tool_calls": [], "leaks": []}
48
+ probe no-kwargs single-word {"content": "ready", "reasoning_len": 0, "tool_calls": [], "leaks": []}
49
+ probe no-kwargs multi-arg {"content": "", "reasoning_len": 0, "tool_calls": ["get_weather"], "leaks": []}
50
+ probe enable_thinking=false correct-decline {"content": "391", "reasoning_len": 0, "tool_calls": [], "leaks": []}
51
+ probe enable_thinking=false single-word {"content": "ready", "reasoning_len": 0, "tool_calls": [], "leaks": []}
52
+ probe enable_thinking=false multi-arg {"content": "", "reasoning_len": 0, "tool_calls": ["get_weather"], "leaks": []}
53
+ probe reasoning_effort=high correct-decline {"content": "We need answer directly. 391.\n</think>\n\n391", "reasoning_len": 0, "tool_calls": [], "leaks": ["</think>"]}
54
+ probe reasoning_effort=high single-word {"content": "We need need output exactly ready.\n</think>\n\nready", "reasoning_len": 0, "tool_calls": [], "leaks": ["</think>"]}
55
+ probe reasoning_effort=high multi-arg {"content": "We need need tool. Current weather Paris celsius.\n</think>\n\n", "reasoning_len": 0, "tool_calls": ["get_weather"], "leaks": ["</think>"]}
56
+ probe reasoning_effort=medium correct-decline {"content": "\n\n</think>\n\n391", "reasoning_len": 0, "tool_calls": [], "leaks": ["</think>"]}
57
+ probe reasoning_effort=medium single-word {"content": "\n\n</think>\n\nready", "reasoning_len": 0, "tool_calls": [], "leaks": ["</think>"]}
58
+ probe reasoning_effort=medium multi-arg {"content": "\n\n</think>\n\n", "reasoning_len": 0, "tool_calls": ["get_weather"], "leaks": ["</think>"]}
59
+ probe reasoning_effort=none correct-decline {"content": "391", "reasoning_len": 0, "tool_calls": [], "leaks": []}
60
+ probe reasoning_effort=none single-word {"content": "ready", "reasoning_len": 0, "tool_calls": [], "leaks": []}
61
+ probe reasoning_effort=none multi-arg {"content": "", "reasoning_len": 0, "tool_calls": ["get_weather"], "leaks": []}
62
+ NEX_TOOLS_TPL_DONE
63
+ rc=0
recipe/logs/N8b_seats.log ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ [2026-09-17T01:06:02Z] plan: [('max1-nex-fast', 'ROCm0', 'fa on', 262144, '31000M', True), ('max1-nex-fast-imat', 'ROCm0', 'fa on', 262144, '31000M', True)]
2
+ [2026-09-17T01:06:04Z] max1-nex-fast written (ROCm0, -fa on, ctx 262144, MemoryMax 31000M) -> smoke test
3
+ {"unit": "max1-nex-fast", "port": 8097, "load_s": 25, "time": "2026-09-17T01:06:29Z", "direct_reply": "ready", "direct_tg": 61.724584902166534, "default_reply": "", "default_reasoning_len": 5, "default_leak": false, "gateway_model": "nex-n2.5-mini-fast@max1", "gateway_reply": "ready", "result": "FAIL"}
4
+ [2026-09-17T01:06:30Z] max1-nex-fast stopped (enabled: disabled)
5
+ [2026-09-17T01:06:36Z] max1-nex-fast-imat written (ROCm0, -fa on, ctx 262144, MemoryMax 31000M) -> smoke test
6
+ {"unit": "max1-nex-fast-imat", "port": 8098, "load_s": 25, "time": "2026-09-17T01:07:02Z", "direct_reply": "ready", "direct_tg": 47.69058349428906, "default_reply": "", "default_reasoning_len": 5, "default_leak": false, "gateway_model": "nex-n2.5-mini-fast-imatrix@max1", "gateway_reply": "ready", "result": "FAIL"}
7
+ [2026-09-17T01:07:03Z] max1-nex-fast-imat stopped (enabled: disabled)
8
+ [2026-09-17T01:07:08Z] NEX_SEATS_DONE fail=1
recipe/logs/N8c_seats.log ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ [2026-09-17T01:19:09Z] plan: [('max1-nex-fast', 'ROCm0', 'fa on', 262144, '31000M', True), ('max1-nex-fast-imat', 'ROCm0', 'fa on', 262144, '31000M', True)]
2
+ [2026-09-17T01:19:10Z] max1-nex-fast written (ROCm0, -fa on, ctx 262144, MemoryMax 31000M) -> smoke test
3
+ {"unit": "max1-nex-fast", "port": 8097, "load_s": 30, "time": "2026-09-17T01:19:40Z", "direct_reply": "ready", "direct_tg": 42.57493188010899, "default_reply": "ready", "default_reasoning_len": 0, "default_leak": false, "thinking_reply": "", "thinking_reasoning_len": 5, "thinking_leak": false, "gateway_model": "nex-n2.5-mini-fast@max1", "gateway_reply": "ready", "result": "FAIL"}
4
+ [2026-09-17T01:19:42Z] max1-nex-fast stopped (enabled: disabled)
5
+ [2026-09-17T01:19:48Z] max1-nex-fast-imat written (ROCm0, -fa on, ctx 262144, MemoryMax 31000M) -> smoke test
6
+ {"unit": "max1-nex-fast-imat", "port": 8098, "load_s": 25, "time": "2026-09-17T01:20:13Z", "direct_reply": "ready", "direct_tg": 45.33297066956798, "default_reply": "ready", "default_reasoning_len": 0, "default_leak": false, "thinking_reply": "", "thinking_reasoning_len": 5, "thinking_leak": false, "gateway_model": "nex-n2.5-mini-fast-imatrix@max1", "gateway_reply": "ready", "result": "FAIL"}
7
+ [2026-09-17T01:20:15Z] max1-nex-fast-imat stopped (enabled: disabled)
8
+ [2026-09-17T01:20:20Z] NEX_SEATS_DONE fail=1
recipe/logs/Q1_q106.log ADDED
The diff for this file is too large to render. See raw diff
 
recipe/logs/b_n-tools-q106-roff-probe.log ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 0.00.108.543 I log_info: verbosity = 3 (adjust with the `-lv N` CLI arg)
2
+ 0.00.108.553 I device_info:
3
+ 0.00.108.699 I - ROCm0 : AMD Radeon Graphics (131072 MiB, 123524 MiB free)
4
+ 0.00.108.869 I - Vulkan0 : AMD Radeon Graphics (RADV GFX1151) (132096 MiB, 131922 MiB free)
5
+ 0.00.108.878 I - CPU : AMD RYZEN AI MAX+ 395 w/ Radeon 8060S (127438 MiB, 127438 MiB free)
6
+ 0.00.108.975 I system_info: n_threads = 16 (n_threads_batch = 16) / 32 | ROCm : NO_VMM = 1 | PEER_MAX_BATCH_SIZE = 128 | FA_ALL_QUANTS = 1 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX_VNNI = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | AVX512 = 1 | AVX512_VBMI = 1 | AVX512_VNNI = 1 | AVX512_BF16 = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 |
7
+ 0.00.109.043 I srv init: running without SSL
8
+ 0.00.109.069 I srv init: using 31 threads for HTTP server
9
+ 0.00.109.070 I srv init: the WebUI is disabled
10
+ 0.00.109.152 I srv start: binding port with default address family
11
+ 0.00.110.377 I srv main: loading model
12
+ 0.00.110.386 I srv load_model: loading model '/mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf'
13
+ 0.00.167.016 W llama_model_loader: direct I/O is enabled, disabling mmap
14
+ 0.22.284.156 W llama_context: n_ctx_seq (65536) < n_ctx_train (262144) -- the full capacity of the model will not be utilized
15
+ 0.22.593.161 W common_init_from_params: warming up the model with an empty run - please wait ... (--no-warmup to disable)
16
+ 0.22.997.376 I srv load_model: initializing slots, n_slots = 1
17
+ 0.23.238.804 W srv load_model: speculative decoding will use checkpoints
18
+ 0.23.238.818 W common_speculative_init: no implementations specified for speculative decoding
19
+ 0.23.238.821 I slot load_model: id 0 | task -1 | new slot, n_ctx = 65536
20
+ 0.23.239.043 I srv load_model: prompt cache RAM enabled: limit_mib=8192
21
+ 0.23.239.047 I srv load_model: for more info see https://github.com/ggml-org/llama.cpp/pull/16391
22
+ 0.23.239.108 I srv init: idle slots will be saved to prompt cache upon starting a new task
23
+ 0.23.286.447 I init: chat template, example_format: '<|im_start|>system
24
+ You are a helpful assistant<|im_end|>
25
+ <|im_start|>user
26
+ Hello<|im_end|>
27
+ <|im_start|>assistant
28
+ <think>
29
+
30
+ </think>
31
+
32
+ Hi there<|im_end|>
33
+ <|im_start|>user
34
+ How are you?<|im_end|>
35
+ <|im_start|>assistant
36
+ <think>
37
+
38
+ </think>
39
+
40
+ '
41
+ 0.23.329.268 I srv init: init: chat template, thinking = 0
42
+ 0.23.329.322 I srv main: model loaded
43
+ 0.23.329.333 I srv main: server is listening on http://127.0.0.1:18652
44
+ 0.23.329.348 I srv update_slots: all slots are idle
45
+ 0.24.570.143 I srv params_from_: Chat format: peg-native
46
+ 0.24.570.532 I slot get_availabl: id 0 | task -1 | selected slot by LRU, t_last = -1
47
+ 0.24.570.537 I srv get_availabl: updating prompt cache
48
+ 0.24.570.545 I srv load: - looking for better prompt, base f_keep = -1.000, sim = 0.000
49
+ 0.24.570.551 I srv update: - cache state: 0 prompts, 0.000 MiB (limits: 8192.000 MiB, 65536 tokens, 8589934592 est)
50
+ 0.24.570.554 I srv get_availabl: prompt cache update took 0.01 ms
51
+ 0.24.570.926 I reasoning-budget: activated, budget=2147483647 tokens
52
+ 0.24.570.930 I reasoning-budget: deactivated (natural end)
53
+ 0.24.570.950 I slot launch_slot_: id 0 | task 0 | processing task, is_child = 0
54
+ 0.25.270.625 I slot create_check: id 0 | task 0 | created context checkpoint 1 of 32 (pos_min = 422, pos_max = 422, n_tokens = 423, size = 62.813 MiB)
55
+ 0.25.485.037 I slot print_timing: id 0 | task 0 |
56
+ prompt eval time = 747.50 ms / 427 tokens ( 1.75 ms per token, 571.23 tokens per second)
57
+ eval time = 166.53 ms / 4 tokens ( 41.63 ms per token, 24.02 tokens per second)
58
+ total time = 914.04 ms / 431 tokens
59
+ 0.25.485.248 I slot release: id 0 | task 0 | stop processing: n_tokens = 430, truncated = 0
60
+ 0.25.485.267 I srv update_slots: all slots are idle
61
+ 0.25.528.499 I srv params_from_: Chat format: peg-native
62
+ 0.25.530.258 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.962 (> 0.100 thold), f_keep = 0.942
63
+ 0.25.530.747 I reasoning-budget: activated, budget=2147483647 tokens
64
+ 0.25.530.752 I reasoning-budget: deactivated (natural end)
65
+ 0.25.530.840 I slot launch_slot_: id 0 | task 6 | processing task, is_child = 0
66
+ 0.25.530.860 W slot update_slots: id 0 | task 6 | n_past = 405, slot.prompt.tokens.size() = 430, seq_id = 0, pos_min = 429, n_swa = 0
67
+ 0.25.530.863 I slot update_slots: id 0 | task 6 | Checking checkpoint with [422, 422] against 405...
68
+ 0.25.530.865 W slot update_slots: id 0 | task 6 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
69
+ 0.25.530.870 W slot update_slots: id 0 | task 6 | erased invalidated context checkpoint (pos_min = 422, pos_max = 422, n_tokens = 423, n_swa = 0, pos_next = 0, size = 62.813 MiB)
70
+ 0.26.123.530 I slot create_check: id 0 | task 6 | created context checkpoint 1 of 32 (pos_min = 416, pos_max = 416, n_tokens = 417, size = 62.813 MiB)
71
+ 0.26.214.070 I slot print_timing: id 0 | task 6 |
72
+ prompt eval time = 644.28 ms / 421 tokens ( 1.53 ms per token, 653.44 tokens per second)
73
+ eval time = 38.90 ms / 2 tokens ( 19.45 ms per token, 51.42 tokens per second)
74
+ total time = 683.18 ms / 423 tokens
75
+ 0.26.214.297 I slot release: id 0 | task 6 | stop processing: n_tokens = 422, truncated = 0
76
+ 0.26.214.362 I srv update_slots: all slots are idle
77
+ 0.26.263.300 I srv params_from_: Chat format: peg-native
78
+ 0.26.263.827 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.955 (> 0.100 thold), f_keep = 0.960
79
+ 0.26.264.204 I reasoning-budget: activated, budget=2147483647 tokens
80
+ 0.26.264.213 I reasoning-budget: deactivated (natural end)
81
+ 0.26.264.273 I slot launch_slot_: id 0 | task 10 | processing task, is_child = 0
82
+ 0.26.264.297 W slot update_slots: id 0 | task 10 | n_past = 405, slot.prompt.tokens.size() = 422, seq_id = 0, pos_min = 421, n_swa = 0
83
+ 0.26.264.300 I slot update_slots: id 0 | task 10 | Checking checkpoint with [416, 416] against 405...
84
+ 0.26.264.302 W slot update_slots: id 0 | task 10 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
85
+ 0.26.264.309 W slot update_slots: id 0 | task 10 | erased invalidated context checkpoint (pos_min = 416, pos_max = 416, n_tokens = 417, n_swa = 0, pos_next = 0, size = 62.813 MiB)
86
+ 0.26.862.333 I slot create_check: id 0 | task 10 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
87
+ 0.27.692.349 I slot print_timing: id 0 | task 10 |
88
+ prompt eval time = 646.46 ms / 424 tokens ( 1.52 ms per token, 655.88 tokens per second)
89
+ eval time = 781.59 ms / 39 tokens ( 20.04 ms per token, 49.90 tokens per second)
90
+ total time = 1428.04 ms / 463 tokens
91
+ 0.27.692.422 I slot release: id 0 | task 10 | stop processing: n_tokens = 462, truncated = 0
92
+ 0.27.692.446 I srv update_slots: all slots are idle
93
+ 0.27.714.727 I srv params_from_: Chat format: peg-native
94
+ 0.27.715.273 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.951 (> 0.100 thold), f_keep = 0.879
95
+ 0.27.715.596 I reasoning-budget: activated, budget=2147483647 tokens
96
+ 0.27.715.599 I reasoning-budget: deactivated (natural end)
97
+ 0.27.715.649 I slot launch_slot_: id 0 | task 51 | processing task, is_child = 0
98
+ 0.27.715.665 W slot update_slots: id 0 | task 51 | n_past = 406, slot.prompt.tokens.size() = 462, seq_id = 0, pos_min = 461, n_swa = 0
99
+ 0.27.715.666 I slot update_slots: id 0 | task 51 | Checking checkpoint with [419, 419] against 406...
100
+ 0.27.715.667 W slot update_slots: id 0 | task 51 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
101
+ 0.27.715.671 W slot update_slots: id 0 | task 51 | erased invalidated context checkpoint (pos_min = 419, pos_max = 419, n_tokens = 420, n_swa = 0, pos_next = 0, size = 62.813 MiB)
102
+ 0.28.253.015 I slot create_check: id 0 | task 51 | created context checkpoint 1 of 32 (pos_min = 422, pos_max = 422, n_tokens = 423, size = 62.813 MiB)
103
+ 0.28.373.714 I slot print_timing: id 0 | task 51 |
104
+ prompt eval time = 579.69 ms / 427 tokens ( 1.36 ms per token, 736.60 tokens per second)
105
+ eval time = 78.34 ms / 4 tokens ( 19.59 ms per token, 51.06 tokens per second)
106
+ total time = 658.04 ms / 431 tokens
107
+ 0.28.373.794 I slot release: id 0 | task 51 | stop processing: n_tokens = 430, truncated = 0
108
+ 0.28.373.824 I srv update_slots: all slots are idle
109
+ 0.28.388.433 I srv params_from_: Chat format: peg-native
110
+ 0.28.388.929 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.962 (> 0.100 thold), f_keep = 0.942
111
+ 0.28.389.500 I reasoning-budget: activated, budget=2147483647 tokens
112
+ 0.28.389.507 I reasoning-budget: deactivated (natural end)
113
+ 0.28.389.598 I slot launch_slot_: id 0 | task 57 | processing task, is_child = 0
114
+ 0.28.389.627 W slot update_slots: id 0 | task 57 | n_past = 405, slot.prompt.tokens.size() = 430, seq_id = 0, pos_min = 429, n_swa = 0
115
+ 0.28.389.631 I slot update_slots: id 0 | task 57 | Checking checkpoint with [422, 422] against 405...
116
+ 0.28.389.633 W slot update_slots: id 0 | task 57 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
117
+ 0.28.389.641 W slot update_slots: id 0 | task 57 | erased invalidated context checkpoint (pos_min = 422, pos_max = 422, n_tokens = 423, n_swa = 0, pos_next = 0, size = 62.813 MiB)
118
+ 0.28.926.082 I slot create_check: id 0 | task 57 | created context checkpoint 1 of 32 (pos_min = 416, pos_max = 416, n_tokens = 417, size = 62.813 MiB)
119
+ 0.28.986.227 I slot print_timing: id 0 | task 57 |
120
+ prompt eval time = 569.23 ms / 421 tokens ( 1.35 ms per token, 739.59 tokens per second)
121
+ eval time = 27.35 ms / 2 tokens ( 13.67 ms per token, 73.13 tokens per second)
122
+ total time = 596.58 ms / 423 tokens
123
+ 0.28.986.366 I slot release: id 0 | task 57 | stop processing: n_tokens = 422, truncated = 0
124
+ 0.28.986.404 I srv update_slots: all slots are idle
125
+ 0.29.001.891 I srv params_from_: Chat format: peg-native
126
+ 0.29.002.333 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.955 (> 0.100 thold), f_keep = 0.960
127
+ 0.29.002.794 I reasoning-budget: activated, budget=2147483647 tokens
128
+ 0.29.002.796 I reasoning-budget: deactivated (natural end)
129
+ 0.29.002.839 I slot launch_slot_: id 0 | task 61 | processing task, is_child = 0
130
+ 0.29.002.854 W slot update_slots: id 0 | task 61 | n_past = 405, slot.prompt.tokens.size() = 422, seq_id = 0, pos_min = 421, n_swa = 0
131
+ 0.29.002.855 I slot update_slots: id 0 | task 61 | Checking checkpoint with [416, 416] against 405...
132
+ 0.29.002.857 W slot update_slots: id 0 | task 61 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
133
+ 0.29.002.861 W slot update_slots: id 0 | task 61 | erased invalidated context checkpoint (pos_min = 416, pos_max = 416, n_tokens = 417, n_swa = 0, pos_next = 0, size = 62.813 MiB)
134
+ 0.29.671.242 I slot create_check: id 0 | task 61 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
135
+ 0.30.481.274 I slot print_timing: id 0 | task 61 |
136
+ prompt eval time = 711.37 ms / 424 tokens ( 1.68 ms per token, 596.03 tokens per second)
137
+ eval time = 767.02 ms / 39 tokens ( 19.67 ms per token, 50.85 tokens per second)
138
+ total time = 1478.38 ms / 463 tokens
139
+ 0.30.481.478 I slot release: id 0 | task 61 | stop processing: n_tokens = 462, truncated = 0
140
+ 0.30.481.535 I srv update_slots: all slots are idle
141
+ 0.30.525.398 I srv params_from_: Chat format: peg-native
142
+ 0.30.527.228 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.955 (> 0.100 thold), f_keep = 0.879
143
+ 0.30.527.832 I reasoning-budget: activated, budget=2147483647 tokens
144
+ 0.30.527.839 I reasoning-budget: deactivated (natural end)
145
+ 0.30.527.933 I slot launch_slot_: id 0 | task 102 | processing task, is_child = 0
146
+ 0.30.527.959 W slot update_slots: id 0 | task 102 | n_past = 406, slot.prompt.tokens.size() = 462, seq_id = 0, pos_min = 461, n_swa = 0
147
+ 0.30.527.963 I slot update_slots: id 0 | task 102 | Checking checkpoint with [419, 419] against 406...
148
+ 0.30.527.965 W slot update_slots: id 0 | task 102 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
149
+ 0.30.527.974 W slot update_slots: id 0 | task 102 | erased invalidated context checkpoint (pos_min = 419, pos_max = 419, n_tokens = 420, n_swa = 0, pos_next = 0, size = 62.813 MiB)
150
+ 0.31.124.220 I slot create_check: id 0 | task 102 | created context checkpoint 1 of 32 (pos_min = 420, pos_max = 420, n_tokens = 421, size = 62.813 MiB)
151
+ 0.31.601.068 I slot print_timing: id 0 | task 102 |
152
+ prompt eval time = 634.63 ms / 425 tokens ( 1.49 ms per token, 669.68 tokens per second)
153
+ eval time = 438.43 ms / 17 tokens ( 25.79 ms per token, 38.77 tokens per second)
154
+ total time = 1073.07 ms / 442 tokens
155
+ 0.31.601.327 I slot release: id 0 | task 102 | stop processing: n_tokens = 441, truncated = 0
156
+ 0.31.601.391 I srv update_slots: all slots are idle
157
+ 0.31.656.355 I srv params_from_: Chat format: peg-native
158
+ 0.31.658.634 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.967 (> 0.100 thold), f_keep = 0.918
159
+ 0.31.659.308 I reasoning-budget: activated, budget=2147483647 tokens
160
+ 0.31.659.314 I reasoning-budget: deactivated (natural end)
161
+ 0.31.659.409 I slot launch_slot_: id 0 | task 121 | processing task, is_child = 0
162
+ 0.31.659.433 W slot update_slots: id 0 | task 121 | n_past = 405, slot.prompt.tokens.size() = 441, seq_id = 0, pos_min = 440, n_swa = 0
163
+ 0.31.659.436 I slot update_slots: id 0 | task 121 | Checking checkpoint with [420, 420] against 405...
164
+ 0.31.659.438 W slot update_slots: id 0 | task 121 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
165
+ 0.31.659.444 W slot update_slots: id 0 | task 121 | erased invalidated context checkpoint (pos_min = 420, pos_max = 420, n_tokens = 421, n_swa = 0, pos_next = 0, size = 62.813 MiB)
166
+ 0.32.257.720 I slot create_check: id 0 | task 121 | created context checkpoint 1 of 32 (pos_min = 414, pos_max = 414, n_tokens = 415, size = 62.813 MiB)
167
+ 0.32.614.361 I slot print_timing: id 0 | task 121 |
168
+ prompt eval time = 643.10 ms / 419 tokens ( 1.53 ms per token, 651.54 tokens per second)
169
+ eval time = 311.81 ms / 12 tokens ( 25.98 ms per token, 38.49 tokens per second)
170
+ total time = 954.90 ms / 431 tokens
171
+ 0.32.614.571 I slot release: id 0 | task 121 | stop processing: n_tokens = 430, truncated = 0
172
+ 0.32.614.632 I srv update_slots: all slots are idle
173
+ 0.32.639.909 I srv params_from_: Chat format: peg-native
174
+ 0.32.640.349 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.960 (> 0.100 thold), f_keep = 0.942
175
+ 0.32.640.975 I reasoning-budget: activated, budget=2147483647 tokens
176
+ 0.32.640.982 I reasoning-budget: deactivated (natural end)
177
+ 0.32.641.069 I slot launch_slot_: id 0 | task 135 | processing task, is_child = 0
178
+ 0.32.641.093 W slot update_slots: id 0 | task 135 | n_past = 405, slot.prompt.tokens.size() = 430, seq_id = 0, pos_min = 429, n_swa = 0
179
+ 0.32.641.097 I slot update_slots: id 0 | task 135 | Checking checkpoint with [414, 414] against 405...
180
+ 0.32.641.099 W slot update_slots: id 0 | task 135 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
181
+ 0.32.641.107 W slot update_slots: id 0 | task 135 | erased invalidated context checkpoint (pos_min = 414, pos_max = 414, n_tokens = 415, n_swa = 0, pos_next = 0, size = 62.813 MiB)
182
+ 0.33.188.406 I slot create_check: id 0 | task 135 | created context checkpoint 1 of 32 (pos_min = 417, pos_max = 417, n_tokens = 418, size = 62.813 MiB)
183
+ 0.34.408.355 I slot print_timing: id 0 | task 135 |
184
+ prompt eval time = 604.54 ms / 422 tokens ( 1.43 ms per token, 698.05 tokens per second)
185
+ eval time = 1162.69 ms / 53 tokens ( 21.94 ms per token, 45.58 tokens per second)
186
+ total time = 1767.23 ms / 475 tokens
187
+ 0.34.408.563 I slot release: id 0 | task 135 | stop processing: n_tokens = 474, truncated = 0
188
+ 0.34.408.627 I srv update_slots: all slots are idle
189
+ 0.34.455.891 I srv params_from_: Chat format: peg-native
190
+ 0.34.457.714 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.958 (> 0.100 thold), f_keep = 0.857
191
+ 0.34.458.254 I reasoning-budget: activated, budget=2147483647 tokens
192
+ 0.34.458.261 I reasoning-budget: deactivated (natural end)
193
+ 0.34.458.355 I slot launch_slot_: id 0 | task 190 | processing task, is_child = 0
194
+ 0.34.458.379 W slot update_slots: id 0 | task 190 | n_past = 406, slot.prompt.tokens.size() = 474, seq_id = 0, pos_min = 473, n_swa = 0
195
+ 0.34.458.382 I slot update_slots: id 0 | task 190 | Checking checkpoint with [417, 417] against 406...
196
+ 0.34.458.384 W slot update_slots: id 0 | task 190 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
197
+ 0.34.458.391 W slot update_slots: id 0 | task 190 | erased invalidated context checkpoint (pos_min = 417, pos_max = 417, n_tokens = 418, n_swa = 0, pos_next = 0, size = 62.813 MiB)
198
+ 0.35.097.680 I slot create_check: id 0 | task 190 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
199
+ 0.35.342.520 I slot print_timing: id 0 | task 190 |
200
+ prompt eval time = 694.85 ms / 424 tokens ( 1.64 ms per token, 610.21 tokens per second)
201
+ eval time = 189.28 ms / 7 tokens ( 27.04 ms per token, 36.98 tokens per second)
202
+ total time = 884.13 ms / 431 tokens
203
+ 0.35.342.606 I slot release: id 0 | task 190 | stop processing: n_tokens = 430, truncated = 0
204
+ 0.35.342.636 I srv update_slots: all slots are idle
205
+ 0.35.396.955 I srv params_from_: Chat format: peg-native
206
+ 0.35.399.122 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.969 (> 0.100 thold), f_keep = 0.942
207
+ 0.35.399.482 I reasoning-budget: activated, budget=2147483647 tokens
208
+ 0.35.399.485 I reasoning-budget: deactivated (natural end)
209
+ 0.35.399.534 I slot launch_slot_: id 0 | task 199 | processing task, is_child = 0
210
+ 0.35.399.550 W slot update_slots: id 0 | task 199 | n_past = 405, slot.prompt.tokens.size() = 430, seq_id = 0, pos_min = 429, n_swa = 0
211
+ 0.35.399.552 I slot update_slots: id 0 | task 199 | Checking checkpoint with [419, 419] against 405...
212
+ 0.35.399.553 W slot update_slots: id 0 | task 199 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
213
+ 0.35.399.556 W slot update_slots: id 0 | task 199 | erased invalidated context checkpoint (pos_min = 419, pos_max = 419, n_tokens = 420, n_swa = 0, pos_next = 0, size = 62.813 MiB)
214
+ 0.35.975.338 I slot create_check: id 0 | task 199 | created context checkpoint 1 of 32 (pos_min = 413, pos_max = 413, n_tokens = 414, size = 62.813 MiB)
215
+ 0.36.211.213 I slot print_timing: id 0 | task 199 |
216
+ prompt eval time = 638.31 ms / 418 tokens ( 1.53 ms per token, 654.86 tokens per second)
217
+ eval time = 173.34 ms / 5 tokens ( 34.67 ms per token, 28.84 tokens per second)
218
+ total time = 811.65 ms / 423 tokens
219
+ 0.36.211.296 I slot release: id 0 | task 199 | stop processing: n_tokens = 422, truncated = 0
220
+ 0.36.211.327 I srv update_slots: all slots are idle
221
+ 0.36.257.343 I srv params_from_: Chat format: peg-native
222
+ 0.36.259.204 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.962 (> 0.100 thold), f_keep = 0.960
223
+ 0.36.259.770 I reasoning-budget: activated, budget=2147483647 tokens
224
+ 0.36.259.773 I reasoning-budget: deactivated (natural end)
225
+ 0.36.259.860 I slot launch_slot_: id 0 | task 206 | processing task, is_child = 0
226
+ 0.36.259.881 W slot update_slots: id 0 | task 206 | n_past = 405, slot.prompt.tokens.size() = 422, seq_id = 0, pos_min = 421, n_swa = 0
227
+ 0.36.259.884 I slot update_slots: id 0 | task 206 | Checking checkpoint with [413, 413] against 405...
228
+ 0.36.259.886 W slot update_slots: id 0 | task 206 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
229
+ 0.36.259.891 W slot update_slots: id 0 | task 206 | erased invalidated context checkpoint (pos_min = 413, pos_max = 413, n_tokens = 414, n_swa = 0, pos_next = 0, size = 62.813 MiB)
230
+ 0.36.853.203 I slot create_check: id 0 | task 206 | created context checkpoint 1 of 32 (pos_min = 416, pos_max = 416, n_tokens = 417, size = 62.813 MiB)
231
+ 0.37.881.460 I slot print_timing: id 0 | task 206 |
232
+ prompt eval time = 638.50 ms / 421 tokens ( 1.52 ms per token, 659.35 tokens per second)
233
+ eval time = 983.06 ms / 42 tokens ( 23.41 ms per token, 42.72 tokens per second)
234
+ total time = 1621.57 ms / 463 tokens
235
+ 0.37.881.529 I slot release: id 0 | task 206 | stop processing: n_tokens = 462, truncated = 0
236
+ 0.37.881.557 I srv update_slots: all slots are idle
237
+ 0.37.893.541 I srv params_from_: Chat format: peg-native
238
+ 0.37.894.001 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.951 (> 0.100 thold), f_keep = 0.879
239
+ 0.37.894.205 I reasoning-budget: activated, budget=2147483647 tokens
240
+ 0.37.894.207 I reasoning-budget: deactivated (natural end)
241
+ 0.37.894.246 I slot launch_slot_: id 0 | task 250 | processing task, is_child = 0
242
+ 0.37.894.256 W slot update_slots: id 0 | task 250 | n_past = 406, slot.prompt.tokens.size() = 462, seq_id = 0, pos_min = 461, n_swa = 0
243
+ 0.37.894.257 I slot update_slots: id 0 | task 250 | Checking checkpoint with [416, 416] against 406...
244
+ 0.37.894.258 W slot update_slots: id 0 | task 250 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
245
+ 0.37.894.260 W slot update_slots: id 0 | task 250 | erased invalidated context checkpoint (pos_min = 416, pos_max = 416, n_tokens = 417, n_swa = 0, pos_next = 0, size = 62.813 MiB)
246
+ 0.38.426.246 I slot create_check: id 0 | task 250 | created context checkpoint 1 of 32 (pos_min = 422, pos_max = 422, n_tokens = 423, size = 62.813 MiB)
247
+ 0.38.626.110 I slot print_timing: id 0 | task 250 |
248
+ prompt eval time = 594.65 ms / 427 tokens ( 1.39 ms per token, 718.07 tokens per second)
249
+ eval time = 137.18 ms / 4 tokens ( 34.29 ms per token, 29.16 tokens per second)
250
+ total time = 731.83 ms / 431 tokens
251
+ 0.38.626.211 I slot release: id 0 | task 250 | stop processing: n_tokens = 430, truncated = 0
252
+ 0.38.626.244 I srv update_slots: all slots are idle
253
+ 0.38.640.241 I srv params_from_: Chat format: peg-native
254
+ 0.38.640.929 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.962 (> 0.100 thold), f_keep = 0.942
255
+ 0.38.641.272 I reasoning-budget: activated, budget=2147483647 tokens
256
+ 0.38.641.274 I reasoning-budget: deactivated (natural end)
257
+ 0.38.641.328 I slot launch_slot_: id 0 | task 256 | processing task, is_child = 0
258
+ 0.38.641.341 W slot update_slots: id 0 | task 256 | n_past = 405, slot.prompt.tokens.size() = 430, seq_id = 0, pos_min = 429, n_swa = 0
259
+ 0.38.641.343 I slot update_slots: id 0 | task 256 | Checking checkpoint with [422, 422] against 405...
260
+ 0.38.641.344 W slot update_slots: id 0 | task 256 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
261
+ 0.38.641.348 W slot update_slots: id 0 | task 256 | erased invalidated context checkpoint (pos_min = 422, pos_max = 422, n_tokens = 423, n_swa = 0, pos_next = 0, size = 62.813 MiB)
262
+ 0.39.216.267 I slot create_check: id 0 | task 256 | created context checkpoint 1 of 32 (pos_min = 416, pos_max = 416, n_tokens = 417, size = 62.813 MiB)
263
+ 0.39.278.250 I slot print_timing: id 0 | task 256 |
264
+ prompt eval time = 607.81 ms / 421 tokens ( 1.44 ms per token, 692.65 tokens per second)
265
+ eval time = 29.08 ms / 2 tokens ( 14.54 ms per token, 68.78 tokens per second)
266
+ total time = 636.89 ms / 423 tokens
267
+ 0.39.278.403 I slot release: id 0 | task 256 | stop processing: n_tokens = 422, truncated = 0
268
+ 0.39.278.445 I srv update_slots: all slots are idle
269
+ 0.39.315.466 I srv params_from_: Chat format: peg-native
270
+ 0.39.315.935 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.955 (> 0.100 thold), f_keep = 0.960
271
+ 0.39.316.462 I reasoning-budget: activated, budget=2147483647 tokens
272
+ 0.39.316.465 I reasoning-budget: deactivated (natural end)
273
+ 0.39.316.537 I slot launch_slot_: id 0 | task 260 | processing task, is_child = 0
274
+ 0.39.316.555 W slot update_slots: id 0 | task 260 | n_past = 405, slot.prompt.tokens.size() = 422, seq_id = 0, pos_min = 421, n_swa = 0
275
+ 0.39.316.557 I slot update_slots: id 0 | task 260 | Checking checkpoint with [416, 416] against 405...
276
+ 0.39.316.559 W slot update_slots: id 0 | task 260 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
277
+ 0.39.316.565 W slot update_slots: id 0 | task 260 | erased invalidated context checkpoint (pos_min = 416, pos_max = 416, n_tokens = 417, n_swa = 0, pos_next = 0, size = 62.813 MiB)
278
+ 0.39.992.109 I slot create_check: id 0 | task 260 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
279
+ 0.40.804.656 I slot print_timing: id 0 | task 260 |
280
+ prompt eval time = 726.64 ms / 424 tokens ( 1.71 ms per token, 583.51 tokens per second)
281
+ eval time = 761.44 ms / 39 tokens ( 19.52 ms per token, 51.22 tokens per second)
282
+ total time = 1488.09 ms / 463 tokens
283
+ 0.40.804.764 I slot release: id 0 | task 260 | stop processing: n_tokens = 462, truncated = 0
284
+ 0.40.804.795 I srv update_slots: all slots are idle
285
+ 0.40.806.202 I srv operator(): operator(): cleaning up before exit...
recipe/logs/b_n-tools-q106-roff-r2.log ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 0.00.115.039 I log_info: verbosity = 3 (adjust with the `-lv N` CLI arg)
2
+ 0.00.115.043 I device_info:
3
+ 0.00.115.119 I - ROCm0 : AMD Radeon Graphics (131072 MiB, 123866 MiB free)
4
+ 0.00.115.243 I - Vulkan0 : AMD Radeon Graphics (RADV GFX1151) (132096 MiB, 131922 MiB free)
5
+ 0.00.115.248 I - CPU : AMD RYZEN AI MAX+ 395 w/ Radeon 8060S (127438 MiB, 127438 MiB free)
6
+ 0.00.115.311 I system_info: n_threads = 16 (n_threads_batch = 16) / 32 | ROCm : NO_VMM = 1 | PEER_MAX_BATCH_SIZE = 128 | FA_ALL_QUANTS = 1 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX_VNNI = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | AVX512 = 1 | AVX512_VBMI = 1 | AVX512_VNNI = 1 | AVX512_BF16 = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 |
7
+ 0.00.115.325 I srv init: running without SSL
8
+ 0.00.115.360 I srv init: using 31 threads for HTTP server
9
+ 0.00.115.361 I srv init: the WebUI is disabled
10
+ 0.00.115.422 I srv start: binding port with default address family
11
+ 0.00.116.607 I srv main: loading model
12
+ 0.00.116.616 I srv load_model: loading model '/mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf'
13
+ 0.00.167.815 W llama_model_loader: direct I/O is enabled, disabling mmap
14
+ 0.22.638.462 W llama_context: n_ctx_seq (65536) < n_ctx_train (262144) -- the full capacity of the model will not be utilized
15
+ 0.22.931.507 W common_init_from_params: warming up the model with an empty run - please wait ... (--no-warmup to disable)
16
+ 0.23.329.767 I srv load_model: initializing slots, n_slots = 1
17
+ 0.23.568.311 W srv load_model: speculative decoding will use checkpoints
18
+ 0.23.568.330 W common_speculative_init: no implementations specified for speculative decoding
19
+ 0.23.568.334 I slot load_model: id 0 | task -1 | new slot, n_ctx = 65536
20
+ 0.23.568.522 I srv load_model: prompt cache RAM enabled: limit_mib=8192
21
+ 0.23.568.527 I srv load_model: for more info see https://github.com/ggml-org/llama.cpp/pull/16391
22
+ 0.23.568.581 I srv init: idle slots will be saved to prompt cache upon starting a new task
23
+ 0.23.617.611 I init: chat template, example_format: '<|im_start|>system
24
+ You are a helpful assistant<|im_end|>
25
+ <|im_start|>user
26
+ Hello<|im_end|>
27
+ <|im_start|>assistant
28
+ <think>
29
+
30
+ </think>
31
+
32
+ Hi there<|im_end|>
33
+ <|im_start|>user
34
+ How are you?<|im_end|>
35
+ <|im_start|>assistant
36
+ <think>
37
+
38
+ </think>
39
+
40
+ '
41
+ 0.23.662.046 I srv init: init: chat template, thinking = 0
42
+ 0.23.662.133 I srv main: model loaded
43
+ 0.23.662.139 I srv main: server is listening on http://127.0.0.1:18600
44
+ 0.23.662.179 I srv update_slots: all slots are idle
45
+ 0.24.822.880 I srv params_from_: Chat format: peg-native
46
+ 0.24.825.218 I slot get_availabl: id 0 | task -1 | selected slot by LRU, t_last = -1
47
+ 0.24.825.223 I srv get_availabl: updating prompt cache
48
+ 0.24.825.232 I srv load: - looking for better prompt, base f_keep = -1.000, sim = 0.000
49
+ 0.24.825.240 I srv update: - cache state: 0 prompts, 0.000 MiB (limits: 8192.000 MiB, 65536 tokens, 8589934592 est)
50
+ 0.24.825.243 I srv get_availabl: prompt cache update took 0.02 ms
51
+ 0.24.825.968 I reasoning-budget: activated, budget=2147483647 tokens
52
+ 0.24.825.999 I slot launch_slot_: id 0 | task 0 | processing task, is_child = 0
53
+ 0.25.491.127 I slot create_check: id 0 | task 0 | created context checkpoint 1 of 32 (pos_min = 417, pos_max = 417, n_tokens = 418, size = 62.813 MiB)
54
+ 0.25.806.479 I reasoning-budget: deactivated (natural end)
55
+ 0.26.592.455 I slot print_timing: id 0 | task 0 |
56
+ prompt eval time = 699.89 ms / 422 tokens ( 1.66 ms per token, 602.95 tokens per second)
57
+ eval time = 1066.52 ms / 52 tokens ( 20.51 ms per token, 48.76 tokens per second)
58
+ total time = 1766.41 ms / 474 tokens
59
+ 0.26.592.534 I slot release: id 0 | task 0 | stop processing: n_tokens = 473, truncated = 0
60
+ 0.26.592.543 I srv update_slots: all slots are idle
61
+ 0.26.605.042 I srv params_from_: Chat format: peg-native
62
+ 0.26.605.398 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.906 (> 0.100 thold), f_keep = 0.856
63
+ 0.26.605.730 I reasoning-budget: activated, budget=2147483647 tokens
64
+ 0.26.605.800 I slot launch_slot_: id 0 | task 54 | processing task, is_child = 0
65
+ 0.26.605.816 W slot update_slots: id 0 | task 54 | n_past = 405, slot.prompt.tokens.size() = 473, seq_id = 0, pos_min = 472, n_swa = 0
66
+ 0.26.605.818 I slot update_slots: id 0 | task 54 | Checking checkpoint with [417, 417] against 405...
67
+ 0.26.605.820 W slot update_slots: id 0 | task 54 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
68
+ 0.26.605.826 W slot update_slots: id 0 | task 54 | erased invalidated context checkpoint (pos_min = 417, pos_max = 417, n_tokens = 418, n_swa = 0, pos_next = 0, size = 62.813 MiB)
69
+ 0.27.159.769 I slot create_check: id 0 | task 54 | created context checkpoint 1 of 32 (pos_min = 442, pos_max = 442, n_tokens = 443, size = 62.813 MiB)
70
+ 0.27.788.657 I reasoning-budget: deactivated (natural end)
71
+ 0.29.292.130 I slot print_timing: id 0 | task 54 | n_decoded = 100, tg = 47.73 t/s
72
+ 0.29.582.323 I slot print_timing: id 0 | task 54 |
73
+ prompt eval time = 591.18 ms / 447 tokens ( 1.32 ms per token, 756.11 tokens per second)
74
+ eval time = 2385.31 ms / 115 tokens ( 20.74 ms per token, 48.21 tokens per second)
75
+ total time = 2976.49 ms / 562 tokens
76
+ 0.29.582.414 I slot release: id 0 | task 54 | stop processing: n_tokens = 561, truncated = 0
77
+ 0.29.582.457 I srv update_slots: all slots are idle
78
+ 0.29.597.465 I srv params_from_: Chat format: peg-native
79
+ 0.29.597.831 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.953 (> 0.100 thold), f_keep = 0.722
80
+ 0.29.598.059 I reasoning-budget: activated, budget=2147483647 tokens
81
+ 0.29.598.094 I slot launch_slot_: id 0 | task 171 | processing task, is_child = 0
82
+ 0.29.598.104 W slot update_slots: id 0 | task 171 | n_past = 405, slot.prompt.tokens.size() = 561, seq_id = 0, pos_min = 560, n_swa = 0
83
+ 0.29.598.104 I slot update_slots: id 0 | task 171 | Checking checkpoint with [442, 442] against 405...
84
+ 0.29.598.105 W slot update_slots: id 0 | task 171 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
85
+ 0.29.598.107 W slot update_slots: id 0 | task 171 | erased invalidated context checkpoint (pos_min = 442, pos_max = 442, n_tokens = 443, n_swa = 0, pos_next = 0, size = 62.813 MiB)
86
+ 0.30.126.859 I slot create_check: id 0 | task 171 | created context checkpoint 1 of 32 (pos_min = 420, pos_max = 420, n_tokens = 421, size = 62.813 MiB)
87
+ 0.30.663.476 I reasoning-budget: deactivated (natural end)
88
+ 0.31.461.262 I slot print_timing: id 0 | task 171 |
89
+ prompt eval time = 582.92 ms / 425 tokens ( 1.37 ms per token, 729.09 tokens per second)
90
+ eval time = 1280.22 ms / 63 tokens ( 20.32 ms per token, 49.21 tokens per second)
91
+ total time = 1863.14 ms / 488 tokens
92
+ 0.31.461.343 I slot release: id 0 | task 171 | stop processing: n_tokens = 487, truncated = 0
93
+ 0.31.461.374 I srv update_slots: all slots are idle
94
+ 0.31.475.859 I srv params_from_: Chat format: peg-native
95
+ 0.31.476.263 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.953 (> 0.100 thold), f_keep = 0.832
96
+ 0.31.476.455 I reasoning-budget: activated, budget=2147483647 tokens
97
+ 0.31.476.489 I slot launch_slot_: id 0 | task 236 | processing task, is_child = 0
98
+ 0.31.476.500 W slot update_slots: id 0 | task 236 | n_past = 405, slot.prompt.tokens.size() = 487, seq_id = 0, pos_min = 486, n_swa = 0
99
+ 0.31.476.501 I slot update_slots: id 0 | task 236 | Checking checkpoint with [420, 420] against 405...
100
+ 0.31.476.502 W slot update_slots: id 0 | task 236 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
101
+ 0.31.476.505 W slot update_slots: id 0 | task 236 | erased invalidated context checkpoint (pos_min = 420, pos_max = 420, n_tokens = 421, n_swa = 0, pos_next = 0, size = 62.813 MiB)
102
+ 0.32.014.645 I slot create_check: id 0 | task 236 | created context checkpoint 1 of 32 (pos_min = 420, pos_max = 420, n_tokens = 421, size = 62.813 MiB)
103
+ 0.32.309.451 I reasoning-budget: deactivated (natural end)
104
+ 0.32.409.234 I slot print_timing: id 0 | task 236 |
105
+ prompt eval time = 590.97 ms / 425 tokens ( 1.39 ms per token, 719.16 tokens per second)
106
+ eval time = 341.75 ms / 17 tokens ( 20.10 ms per token, 49.74 tokens per second)
107
+ total time = 932.72 ms / 442 tokens
108
+ 0.32.409.323 I slot release: id 0 | task 236 | stop processing: n_tokens = 441, truncated = 0
109
+ 0.32.409.352 I srv update_slots: all slots are idle
110
+ 0.32.432.559 I srv params_from_: Chat format: peg-native
111
+ 0.32.432.999 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.962 (> 0.100 thold), f_keep = 0.921
112
+ 0.32.433.226 I reasoning-budget: activated, budget=2147483647 tokens
113
+ 0.32.433.266 I slot launch_slot_: id 0 | task 255 | processing task, is_child = 0
114
+ 0.32.433.278 W slot update_slots: id 0 | task 255 | n_past = 406, slot.prompt.tokens.size() = 441, seq_id = 0, pos_min = 440, n_swa = 0
115
+ 0.32.433.279 I slot update_slots: id 0 | task 255 | Checking checkpoint with [420, 420] against 406...
116
+ 0.32.433.280 W slot update_slots: id 0 | task 255 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
117
+ 0.32.433.284 W slot update_slots: id 0 | task 255 | erased invalidated context checkpoint (pos_min = 420, pos_max = 420, n_tokens = 421, n_swa = 0, pos_next = 0, size = 62.813 MiB)
118
+ 0.32.967.808 I slot create_check: id 0 | task 255 | created context checkpoint 1 of 32 (pos_min = 417, pos_max = 417, n_tokens = 418, size = 62.813 MiB)
119
+ 0.33.683.392 I reasoning-budget: deactivated (natural end)
120
+ 0.34.620.880 I slot print_timing: id 0 | task 255 |
121
+ prompt eval time = 589.92 ms / 422 tokens ( 1.40 ms per token, 715.35 tokens per second)
122
+ eval time = 1597.65 ms / 69 tokens ( 23.15 ms per token, 43.19 tokens per second)
123
+ total time = 2187.57 ms / 491 tokens
124
+ 0.34.621.091 I slot release: id 0 | task 255 | stop processing: n_tokens = 490, truncated = 0
125
+ 0.34.621.151 I srv update_slots: all slots are idle
126
+ 0.34.685.806 I srv params_from_: Chat format: peg-native
127
+ 0.34.687.624 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.854 (> 0.100 thold), f_keep = 0.859
128
+ 0.34.688.188 I reasoning-budget: activated, budget=2147483647 tokens
129
+ 0.34.688.287 I slot launch_slot_: id 0 | task 326 | processing task, is_child = 0
130
+ 0.34.688.310 W slot update_slots: id 0 | task 326 | n_past = 421, slot.prompt.tokens.size() = 490, seq_id = 0, pos_min = 489, n_swa = 0
131
+ 0.34.688.313 I slot update_slots: id 0 | task 326 | Checking checkpoint with [417, 417] against 421...
132
+ 0.34.696.358 W slot update_slots: id 0 | task 326 | restored context checkpoint (pos_min = 417, pos_max = 417, n_tokens = 418, n_past = 418, size = 62.813 MiB)
133
+ 0.34.932.382 I slot create_check: id 0 | task 326 | created context checkpoint 2 of 32 (pos_min = 488, pos_max = 488, n_tokens = 489, size = 62.813 MiB)
134
+ 0.35.494.281 I reasoning-budget: deactivated (natural end)
135
+ 0.35.771.860 I slot print_timing: id 0 | task 326 |
136
+ prompt eval time = 289.45 ms / 75 tokens ( 3.86 ms per token, 259.11 tokens per second)
137
+ eval time = 794.07 ms / 36 tokens ( 22.06 ms per token, 45.34 tokens per second)
138
+ total time = 1083.52 ms / 111 tokens
139
+ 0.35.772.048 I slot release: id 0 | task 326 | stop processing: n_tokens = 528, truncated = 0
140
+ 0.35.772.102 I srv update_slots: all slots are idle
141
+ 0.35.790.981 I srv params_from_: Chat format: peg-native
142
+ 0.35.791.515 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.972 (> 0.100 thold), f_keep = 0.777
143
+ 0.35.792.014 I reasoning-budget: activated, budget=2147483647 tokens
144
+ 0.35.792.106 I slot launch_slot_: id 0 | task 364 | processing task, is_child = 0
145
+ 0.35.792.127 W slot update_slots: id 0 | task 364 | n_past = 410, slot.prompt.tokens.size() = 528, seq_id = 0, pos_min = 527, n_swa = 0
146
+ 0.35.792.130 I slot update_slots: id 0 | task 364 | Checking checkpoint with [488, 488] against 410...
147
+ 0.35.792.132 I slot update_slots: id 0 | task 364 | Checking checkpoint with [417, 417] against 410...
148
+ 0.35.792.133 W slot update_slots: id 0 | task 364 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
149
+ 0.35.792.140 W slot update_slots: id 0 | task 364 | erased invalidated context checkpoint (pos_min = 417, pos_max = 417, n_tokens = 418, n_swa = 0, pos_next = 0, size = 62.813 MiB)
150
+ 0.35.793.559 W slot update_slots: id 0 | task 364 | erased invalidated context checkpoint (pos_min = 488, pos_max = 488, n_tokens = 489, n_swa = 0, pos_next = 0, size = 62.813 MiB)
151
+ 0.36.350.507 I slot create_check: id 0 | task 364 | created context checkpoint 1 of 32 (pos_min = 417, pos_max = 417, n_tokens = 418, size = 62.813 MiB)
152
+ 0.36.640.348 I reasoning-budget: deactivated (natural end)
153
+ 0.37.440.104 I slot print_timing: id 0 | task 364 |
154
+ prompt eval time = 591.78 ms / 422 tokens ( 1.40 ms per token, 713.10 tokens per second)
155
+ eval time = 1056.18 ms / 52 tokens ( 20.31 ms per token, 49.23 tokens per second)
156
+ total time = 1647.97 ms / 474 tokens
157
+ 0.37.440.166 I slot release: id 0 | task 364 | stop processing: n_tokens = 473, truncated = 0
158
+ 0.37.440.190 I srv update_slots: all slots are idle
159
+ 0.37.456.395 I srv params_from_: Chat format: peg-native
160
+ 0.37.456.822 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.935 (> 0.100 thold), f_keep = 0.856
161
+ 0.37.457.040 I reasoning-budget: activated, budget=2147483647 tokens
162
+ 0.37.457.081 I slot launch_slot_: id 0 | task 418 | processing task, is_child = 0
163
+ 0.37.457.090 W slot update_slots: id 0 | task 418 | n_past = 405, slot.prompt.tokens.size() = 473, seq_id = 0, pos_min = 472, n_swa = 0
164
+ 0.37.457.092 I slot update_slots: id 0 | task 418 | Checking checkpoint with [417, 417] against 405...
165
+ 0.37.457.092 W slot update_slots: id 0 | task 418 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
166
+ 0.37.457.095 W slot update_slots: id 0 | task 418 | erased invalidated context checkpoint (pos_min = 417, pos_max = 417, n_tokens = 418, n_swa = 0, pos_next = 0, size = 62.813 MiB)
167
+ 0.37.989.158 I slot create_check: id 0 | task 418 | created context checkpoint 1 of 32 (pos_min = 428, pos_max = 428, n_tokens = 429, size = 62.813 MiB)
168
+ 0.39.035.888 I reasoning-budget: deactivated (natural end)
169
+ 0.39.898.949 I slot print_timing: id 0 | task 418 |
170
+ prompt eval time = 571.43 ms / 433 tokens ( 1.32 ms per token, 757.75 tokens per second)
171
+ eval time = 1870.42 ms / 92 tokens ( 20.33 ms per token, 49.19 tokens per second)
172
+ total time = 2441.84 ms / 525 tokens
173
+ 0.39.899.036 I slot release: id 0 | task 418 | stop processing: n_tokens = 524, truncated = 0
174
+ 0.39.899.069 I srv update_slots: all slots are idle
175
+ 0.39.931.009 I srv params_from_: Chat format: peg-native
176
+ 0.39.931.485 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.955 (> 0.100 thold), f_keep = 0.773
177
+ 0.39.932.043 I reasoning-budget: activated, budget=2147483647 tokens
178
+ 0.39.932.046 I reasoning-budget: deactivated (natural end)
179
+ 0.39.932.130 I slot launch_slot_: id 0 | task 512 | processing task, is_child = 0
180
+ 0.39.932.153 W slot update_slots: id 0 | task 512 | n_past = 405, slot.prompt.tokens.size() = 524, seq_id = 0, pos_min = 523, n_swa = 0
181
+ 0.39.932.156 I slot update_slots: id 0 | task 512 | Checking checkpoint with [428, 428] against 405...
182
+ 0.39.932.157 W slot update_slots: id 0 | task 512 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
183
+ 0.39.932.162 W slot update_slots: id 0 | task 512 | erased invalidated context checkpoint (pos_min = 428, pos_max = 428, n_tokens = 429, n_swa = 0, pos_next = 0, size = 62.813 MiB)
184
+ 0.40.516.543 I slot create_check: id 0 | task 512 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
185
+ 0.41.428.023 I slot print_timing: id 0 | task 512 |
186
+ prompt eval time = 630.82 ms / 424 tokens ( 1.49 ms per token, 672.15 tokens per second)
187
+ eval time = 865.02 ms / 39 tokens ( 22.18 ms per token, 45.09 tokens per second)
188
+ total time = 1495.84 ms / 463 tokens
189
+ 0.41.428.279 I slot release: id 0 | task 512 | stop processing: n_tokens = 462, truncated = 0
190
+ 0.41.428.346 I srv update_slots: all slots are idle
191
+ 0.41.471.490 I srv params_from_: Chat format: peg-native
192
+ 0.41.472.003 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.902 (> 0.100 thold), f_keep = 0.877
193
+ 0.41.472.302 I reasoning-budget: activated, budget=2147483647 tokens
194
+ 0.41.472.304 I reasoning-budget: deactivated (natural end)
195
+ 0.41.472.355 I slot launch_slot_: id 0 | task 553 | processing task, is_child = 0
196
+ 0.41.472.368 W slot update_slots: id 0 | task 553 | n_past = 405, slot.prompt.tokens.size() = 462, seq_id = 0, pos_min = 461, n_swa = 0
197
+ 0.41.472.369 I slot update_slots: id 0 | task 553 | Checking checkpoint with [419, 419] against 405...
198
+ 0.41.472.370 W slot update_slots: id 0 | task 553 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
199
+ 0.41.472.373 W slot update_slots: id 0 | task 553 | erased invalidated context checkpoint (pos_min = 419, pos_max = 419, n_tokens = 420, n_swa = 0, pos_next = 0, size = 62.813 MiB)
200
+ 0.42.065.024 I slot create_check: id 0 | task 553 | created context checkpoint 1 of 32 (pos_min = 444, pos_max = 444, n_tokens = 445, size = 62.813 MiB)
201
+ 0.44.104.338 I slot print_timing: id 0 | task 553 |
202
+ prompt eval time = 633.39 ms / 449 tokens ( 1.41 ms per token, 708.88 tokens per second)
203
+ eval time = 1998.54 ms / 86 tokens ( 23.24 ms per token, 43.03 tokens per second)
204
+ total time = 2631.93 ms / 535 tokens
205
+ 0.44.104.526 I slot release: id 0 | task 553 | stop processing: n_tokens = 534, truncated = 0
206
+ 0.44.104.644 I srv update_slots: all slots are idle
207
+ 0.44.130.603 I srv params_from_: Chat format: peg-native
208
+ 0.44.130.995 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.948 (> 0.100 thold), f_keep = 0.758
209
+ 0.44.131.303 I reasoning-budget: activated, budget=2147483647 tokens
210
+ 0.44.131.305 I reasoning-budget: deactivated (natural end)
211
+ 0.44.131.351 I slot launch_slot_: id 0 | task 641 | processing task, is_child = 0
212
+ 0.44.131.364 W slot update_slots: id 0 | task 641 | n_past = 405, slot.prompt.tokens.size() = 534, seq_id = 0, pos_min = 533, n_swa = 0
213
+ 0.44.131.365 I slot update_slots: id 0 | task 641 | Checking checkpoint with [444, 444] against 405...
214
+ 0.44.131.366 W slot update_slots: id 0 | task 641 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
215
+ 0.44.131.369 W slot update_slots: id 0 | task 641 | erased invalidated context checkpoint (pos_min = 444, pos_max = 444, n_tokens = 445, n_swa = 0, pos_next = 0, size = 62.813 MiB)
216
+ 0.44.685.484 I slot create_check: id 0 | task 641 | created context checkpoint 1 of 32 (pos_min = 422, pos_max = 422, n_tokens = 423, size = 62.813 MiB)
217
+ 0.45.671.889 I slot print_timing: id 0 | task 641 |
218
+ prompt eval time = 602.32 ms / 427 tokens ( 1.41 ms per token, 708.93 tokens per second)
219
+ eval time = 938.19 ms / 39 tokens ( 24.06 ms per token, 41.57 tokens per second)
220
+ total time = 1540.51 ms / 466 tokens
221
+ 0.45.671.971 I slot release: id 0 | task 641 | stop processing: n_tokens = 465, truncated = 0
222
+ 0.45.671.999 I srv update_slots: all slots are idle
223
+ 0.45.686.558 I srv params_from_: Chat format: peg-native
224
+ 0.45.686.878 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.948 (> 0.100 thold), f_keep = 0.871
225
+ 0.45.687.125 I reasoning-budget: activated, budget=2147483647 tokens
226
+ 0.45.687.126 I reasoning-budget: deactivated (natural end)
227
+ 0.45.687.183 I slot launch_slot_: id 0 | task 682 | processing task, is_child = 0
228
+ 0.45.687.196 W slot update_slots: id 0 | task 682 | n_past = 405, slot.prompt.tokens.size() = 465, seq_id = 0, pos_min = 464, n_swa = 0
229
+ 0.45.687.197 I slot update_slots: id 0 | task 682 | Checking checkpoint with [422, 422] against 405...
230
+ 0.45.687.199 W slot update_slots: id 0 | task 682 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
231
+ 0.45.687.202 W slot update_slots: id 0 | task 682 | erased invalidated context checkpoint (pos_min = 422, pos_max = 422, n_tokens = 423, n_swa = 0, pos_next = 0, size = 62.813 MiB)
232
+ 0.46.216.440 I slot create_check: id 0 | task 682 | created context checkpoint 1 of 32 (pos_min = 422, pos_max = 422, n_tokens = 423, size = 62.813 MiB)
233
+ 0.46.339.458 I slot print_timing: id 0 | task 682 |
234
+ prompt eval time = 571.41 ms / 427 tokens ( 1.34 ms per token, 747.28 tokens per second)
235
+ eval time = 80.84 ms / 4 tokens ( 20.21 ms per token, 49.48 tokens per second)
236
+ total time = 652.25 ms / 431 tokens
237
+ 0.46.339.548 I slot release: id 0 | task 682 | stop processing: n_tokens = 430, truncated = 0
238
+ 0.46.339.578 I srv update_slots: all slots are idle
239
+ 0.46.360.275 I srv params_from_: Chat format: peg-native
240
+ 0.46.360.733 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.958 (> 0.100 thold), f_keep = 0.944
241
+ 0.46.361.269 I reasoning-budget: activated, budget=2147483647 tokens
242
+ 0.46.361.274 I reasoning-budget: deactivated (natural end)
243
+ 0.46.361.357 I slot launch_slot_: id 0 | task 688 | processing task, is_child = 0
244
+ 0.46.361.380 W slot update_slots: id 0 | task 688 | n_past = 406, slot.prompt.tokens.size() = 430, seq_id = 0, pos_min = 429, n_swa = 0
245
+ 0.46.361.383 I slot update_slots: id 0 | task 688 | Checking checkpoint with [422, 422] against 406...
246
+ 0.46.361.385 W slot update_slots: id 0 | task 688 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
247
+ 0.46.361.392 W slot update_slots: id 0 | task 688 | erased invalidated context checkpoint (pos_min = 422, pos_max = 422, n_tokens = 423, n_swa = 0, pos_next = 0, size = 62.813 MiB)
248
+ 0.46.930.125 I slot create_check: id 0 | task 688 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
249
+ 0.47.764.185 I slot print_timing: id 0 | task 688 |
250
+ prompt eval time = 611.34 ms / 424 tokens ( 1.44 ms per token, 693.56 tokens per second)
251
+ eval time = 791.43 ms / 40 tokens ( 19.79 ms per token, 50.54 tokens per second)
252
+ total time = 1402.77 ms / 464 tokens
253
+ 0.47.764.366 I slot release: id 0 | task 688 | stop processing: n_tokens = 463, truncated = 0
254
+ 0.47.764.400 I srv update_slots: all slots are idle
255
+ 0.47.803.235 I srv params_from_: Chat format: peg-native
256
+ 0.47.803.673 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.935 (> 0.100 thold), f_keep = 1.000
257
+ 0.47.804.329 I reasoning-budget: activated, budget=2147483647 tokens
258
+ 0.47.804.335 I reasoning-budget: deactivated (natural end)
259
+ 0.47.804.467 I slot launch_slot_: id 0 | task 730 | processing task, is_child = 0
260
+ 0.48.002.540 I slot create_check: id 0 | task 730 | created context checkpoint 2 of 32 (pos_min = 490, pos_max = 490, n_tokens = 491, size = 62.813 MiB)
261
+ 0.48.372.317 I slot print_timing: id 0 | task 730 |
262
+ prompt eval time = 256.59 ms / 32 tokens ( 8.02 ms per token, 124.71 tokens per second)
263
+ eval time = 311.22 ms / 14 tokens ( 22.23 ms per token, 44.98 tokens per second)
264
+ total time = 567.81 ms / 46 tokens
265
+ 0.48.372.410 I slot release: id 0 | task 730 | stop processing: n_tokens = 508, truncated = 0
266
+ 0.48.372.439 I srv update_slots: all slots are idle
267
+ 0.48.412.286 I srv params_from_: Chat format: peg-native
268
+ 0.48.412.805 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.967 (> 0.100 thold), f_keep = 0.807
269
+ 0.48.413.102 I reasoning-budget: activated, budget=2147483647 tokens
270
+ 0.48.413.104 I reasoning-budget: deactivated (natural end)
271
+ 0.48.413.157 I slot launch_slot_: id 0 | task 746 | processing task, is_child = 0
272
+ 0.48.413.170 W slot update_slots: id 0 | task 746 | n_past = 410, slot.prompt.tokens.size() = 508, seq_id = 0, pos_min = 507, n_swa = 0
273
+ 0.48.413.172 I slot update_slots: id 0 | task 746 | Checking checkpoint with [490, 490] against 410...
274
+ 0.48.413.172 I slot update_slots: id 0 | task 746 | Checking checkpoint with [419, 419] against 410...
275
+ 0.48.413.173 W slot update_slots: id 0 | task 746 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
276
+ 0.48.413.176 W slot update_slots: id 0 | task 746 | erased invalidated context checkpoint (pos_min = 419, pos_max = 419, n_tokens = 420, n_swa = 0, pos_next = 0, size = 62.813 MiB)
277
+ 0.48.414.558 W slot update_slots: id 0 | task 746 | erased invalidated context checkpoint (pos_min = 490, pos_max = 490, n_tokens = 491, n_swa = 0, pos_next = 0, size = 62.813 MiB)
278
+ 0.48.958.571 I slot create_check: id 0 | task 746 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
279
+ 0.49.822.447 I slot print_timing: id 0 | task 746 |
280
+ prompt eval time = 585.25 ms / 424 tokens ( 1.38 ms per token, 724.47 tokens per second)
281
+ eval time = 824.00 ms / 40 tokens ( 20.60 ms per token, 48.54 tokens per second)
282
+ total time = 1409.26 ms / 464 tokens
283
+ 0.49.822.516 I slot release: id 0 | task 746 | stop processing: n_tokens = 463, truncated = 0
284
+ 0.49.822.541 I srv update_slots: all slots are idle
285
+ 0.49.837.403 I srv params_from_: Chat format: peg-native
286
+ 0.49.837.865 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.931 (> 0.100 thold), f_keep = 0.875
287
+ 0.49.838.376 I reasoning-budget: activated, budget=2147483647 tokens
288
+ 0.49.838.380 I reasoning-budget: deactivated (natural end)
289
+ 0.49.838.465 I slot launch_slot_: id 0 | task 788 | processing task, is_child = 0
290
+ 0.49.838.487 W slot update_slots: id 0 | task 788 | n_past = 405, slot.prompt.tokens.size() = 463, seq_id = 0, pos_min = 462, n_swa = 0
291
+ 0.49.838.490 I slot update_slots: id 0 | task 788 | Checking checkpoint with [419, 419] against 405...
292
+ 0.49.838.491 W slot update_slots: id 0 | task 788 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
293
+ 0.49.838.496 W slot update_slots: id 0 | task 788 | erased invalidated context checkpoint (pos_min = 419, pos_max = 419, n_tokens = 420, n_swa = 0, pos_next = 0, size = 62.813 MiB)
294
+ 0.50.402.186 I slot create_check: id 0 | task 788 | created context checkpoint 1 of 32 (pos_min = 430, pos_max = 430, n_tokens = 431, size = 62.813 MiB)
295
+ 0.52.152.175 I slot print_timing: id 0 | task 788 |
296
+ prompt eval time = 613.67 ms / 435 tokens ( 1.41 ms per token, 708.85 tokens per second)
297
+ eval time = 1699.98 ms / 80 tokens ( 21.25 ms per token, 47.06 tokens per second)
298
+ total time = 2313.65 ms / 515 tokens
299
+ 0.52.152.608 I slot release: id 0 | task 788 | stop processing: n_tokens = 514, truncated = 0
300
+ 0.52.152.669 I srv update_slots: all slots are idle
301
+ 0.52.154.330 I srv operator(): operator(): cleaning up before exit...
recipe/logs/b_n-tools-q106-tpl-probe.log ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 0.00.135.941 I log_info: verbosity = 3 (adjust with the `-lv N` CLI arg)
2
+ 0.00.135.945 I device_info:
3
+ 0.00.136.023 I - ROCm0 : AMD Radeon Graphics (131072 MiB, 122347 MiB free)
4
+ 0.00.136.132 I - Vulkan0 : AMD Radeon Graphics (RADV GFX1151) (132096 MiB, 131922 MiB free)
5
+ 0.00.136.137 I - CPU : AMD RYZEN AI MAX+ 395 w/ Radeon 8060S (127438 MiB, 127438 MiB free)
6
+ 0.00.136.208 I system_info: n_threads = 16 (n_threads_batch = 16) / 32 | ROCm : NO_VMM = 1 | PEER_MAX_BATCH_SIZE = 128 | FA_ALL_QUANTS = 1 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX_VNNI = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | AVX512 = 1 | AVX512_VBMI = 1 | AVX512_VNNI = 1 | AVX512_BF16 = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 |
7
+ 0.00.136.238 I srv init: running without SSL
8
+ 0.00.136.260 I srv init: using 31 threads for HTTP server
9
+ 0.00.136.261 I srv init: the WebUI is disabled
10
+ 0.00.136.327 I srv start: binding port with default address family
11
+ 0.00.137.600 I srv main: loading model
12
+ 0.00.137.603 I srv load_model: loading model '/mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf'
13
+ 0.00.256.612 W llama_model_loader: direct I/O is enabled, disabling mmap
14
+ 0.24.306.998 W llama_context: n_ctx_seq (65536) < n_ctx_train (262144) -- the full capacity of the model will not be utilized
15
+ 0.24.593.444 W common_init_from_params: warming up the model with an empty run - please wait ... (--no-warmup to disable)
16
+ 0.24.922.506 I srv load_model: initializing slots, n_slots = 1
17
+ 0.25.146.190 W srv load_model: speculative decoding will use checkpoints
18
+ 0.25.146.203 W common_speculative_init: no implementations specified for speculative decoding
19
+ 0.25.146.206 I slot load_model: id 0 | task -1 | new slot, n_ctx = 65536
20
+ 0.25.146.286 I srv load_model: prompt cache RAM enabled: limit_mib=8192
21
+ 0.25.146.287 I srv load_model: for more info see https://github.com/ggml-org/llama.cpp/pull/16391
22
+ 0.25.146.331 I srv init: idle slots will be saved to prompt cache upon starting a new task
23
+ 0.25.160.750 I init: chat template, example_format: '<|im_start|>system
24
+ You are a helpful assistant<|im_end|>
25
+ <|im_start|>user
26
+ Hello<|im_end|>
27
+ <|im_start|>assistant
28
+ <think>
29
+
30
+ </think>
31
+
32
+ Hi there<|im_end|>
33
+ <|im_start|>user
34
+ How are you?<|im_end|>
35
+ <|im_start|>assistant
36
+ <think>
37
+ '
38
+ 0.25.170.675 I srv init: init: chat template, thinking = 1
39
+ 0.25.170.721 I srv main: model loaded
40
+ 0.25.170.724 I srv main: server is listening on http://127.0.0.1:18652
41
+ 0.25.170.745 I srv update_slots: all slots are idle
42
+ 0.26.899.613 I srv params_from_: Chat format: peg-native
43
+ 0.26.900.013 I slot get_availabl: id 0 | task -1 | selected slot by LRU, t_last = -1
44
+ 0.26.900.015 I srv get_availabl: updating prompt cache
45
+ 0.26.900.021 I srv load: - looking for better prompt, base f_keep = -1.000, sim = 0.000
46
+ 0.26.900.027 I srv update: - cache state: 0 prompts, 0.000 MiB (limits: 8192.000 MiB, 65536 tokens, 8589934592 est)
47
+ 0.26.900.029 I srv get_availabl: prompt cache update took 0.01 ms
48
+ 0.26.900.306 I reasoning-budget: activated, budget=2147483647 tokens
49
+ 0.26.900.326 I slot launch_slot_: id 0 | task 0 | processing task, is_child = 0
50
+ 0.27.527.394 I slot create_check: id 0 | task 0 | created context checkpoint 1 of 32 (pos_min = 420, pos_max = 420, n_tokens = 421, size = 62.813 MiB)
51
+ 0.27.799.897 I reasoning-budget: deactivated (natural end)
52
+ 0.27.893.084 I slot print_timing: id 0 | task 0 |
53
+ prompt eval time = 660.83 ms / 425 tokens ( 1.55 ms per token, 643.13 tokens per second)
54
+ eval time = 331.90 ms / 17 tokens ( 19.52 ms per token, 51.22 tokens per second)
55
+ total time = 992.73 ms / 442 tokens
56
+ 0.27.893.160 I slot release: id 0 | task 0 | stop processing: n_tokens = 441, truncated = 0
57
+ 0.27.893.171 I srv update_slots: all slots are idle
58
+ 0.27.910.042 I srv params_from_: Chat format: peg-native
59
+ 0.27.910.501 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.962 (> 0.100 thold), f_keep = 0.921
60
+ 0.27.910.926 I reasoning-budget: activated, budget=2147483647 tokens
61
+ 0.27.911.011 I slot launch_slot_: id 0 | task 19 | processing task, is_child = 0
62
+ 0.27.911.034 W slot update_slots: id 0 | task 19 | n_past = 406, slot.prompt.tokens.size() = 441, seq_id = 0, pos_min = 440, n_swa = 0
63
+ 0.27.911.036 I slot update_slots: id 0 | task 19 | Checking checkpoint with [420, 420] against 406...
64
+ 0.27.911.038 W slot update_slots: id 0 | task 19 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
65
+ 0.27.911.042 W slot update_slots: id 0 | task 19 | erased invalidated context checkpoint (pos_min = 420, pos_max = 420, n_tokens = 421, n_swa = 0, pos_next = 0, size = 62.813 MiB)
66
+ 0.28.555.134 I slot create_check: id 0 | task 19 | created context checkpoint 1 of 32 (pos_min = 417, pos_max = 417, n_tokens = 418, size = 62.813 MiB)
67
+ 0.28.851.175 I reasoning-budget: deactivated (natural end)
68
+ 0.29.588.543 I slot print_timing: id 0 | task 19 |
69
+ prompt eval time = 695.53 ms / 422 tokens ( 1.65 ms per token, 606.73 tokens per second)
70
+ eval time = 981.97 ms / 53 tokens ( 18.53 ms per token, 53.97 tokens per second)
71
+ total time = 1677.50 ms / 475 tokens
72
+ 0.29.588.615 I slot release: id 0 | task 19 | stop processing: n_tokens = 474, truncated = 0
73
+ 0.29.588.642 I srv update_slots: all slots are idle
74
+ 0.29.622.104 I srv params_from_: Chat format: peg-native
75
+ 0.29.622.588 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.958 (> 0.100 thold), f_keep = 0.857
76
+ 0.29.623.144 I reasoning-budget: activated, budget=2147483647 tokens
77
+ 0.29.623.228 I slot launch_slot_: id 0 | task 74 | processing task, is_child = 0
78
+ 0.29.623.250 W slot update_slots: id 0 | task 74 | n_past = 406, slot.prompt.tokens.size() = 474, seq_id = 0, pos_min = 473, n_swa = 0
79
+ 0.29.623.253 I slot update_slots: id 0 | task 74 | Checking checkpoint with [417, 417] against 406...
80
+ 0.29.623.255 W slot update_slots: id 0 | task 74 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
81
+ 0.29.623.260 W slot update_slots: id 0 | task 74 | erased invalidated context checkpoint (pos_min = 417, pos_max = 417, n_tokens = 418, n_swa = 0, pos_next = 0, size = 62.813 MiB)
82
+ 0.30.170.371 I slot create_check: id 0 | task 74 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
83
+ 0.30.268.328 I reasoning-budget: deactivated (natural end)
84
+ 0.30.408.646 I slot print_timing: id 0 | task 74 |
85
+ prompt eval time = 594.93 ms / 424 tokens ( 1.40 ms per token, 712.68 tokens per second)
86
+ eval time = 190.44 ms / 7 tokens ( 27.21 ms per token, 36.76 tokens per second)
87
+ total time = 785.37 ms / 431 tokens
88
+ 0.30.408.832 I slot release: id 0 | task 74 | stop processing: n_tokens = 430, truncated = 0
89
+ 0.30.408.910 I srv update_slots: all slots are idle
90
+ 0.30.423.352 I srv params_from_: Chat format: peg-native
91
+ 0.30.423.958 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.964 (> 0.100 thold), f_keep = 0.944
92
+ 0.30.424.428 I reasoning-budget: activated, budget=2147483647 tokens
93
+ 0.30.424.483 I slot launch_slot_: id 0 | task 83 | processing task, is_child = 0
94
+ 0.30.424.498 W slot update_slots: id 0 | task 83 | n_past = 406, slot.prompt.tokens.size() = 430, seq_id = 0, pos_min = 429, n_swa = 0
95
+ 0.30.424.499 I slot update_slots: id 0 | task 83 | Checking checkpoint with [419, 419] against 406...
96
+ 0.30.424.500 W slot update_slots: id 0 | task 83 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
97
+ 0.30.424.505 W slot update_slots: id 0 | task 83 | erased invalidated context checkpoint (pos_min = 419, pos_max = 419, n_tokens = 420, n_swa = 0, pos_next = 0, size = 62.813 MiB)
98
+ 0.30.909.972 I slot create_check: id 0 | task 83 | created context checkpoint 1 of 32 (pos_min = 416, pos_max = 416, n_tokens = 417, size = 62.813 MiB)
99
+ 0.30.972.923 I reasoning-budget: deactivated (natural end)
100
+ 0.31.775.290 I slot print_timing: id 0 | task 83 |
101
+ prompt eval time = 521.51 ms / 421 tokens ( 1.24 ms per token, 807.27 tokens per second)
102
+ eval time = 829.27 ms / 42 tokens ( 19.74 ms per token, 50.65 tokens per second)
103
+ total time = 1350.78 ms / 463 tokens
104
+ 0.31.775.369 I slot release: id 0 | task 83 | stop processing: n_tokens = 462, truncated = 0
105
+ 0.31.775.395 I srv update_slots: all slots are idle
106
+ 0.31.814.609 I srv params_from_: Chat format: peg-native
107
+ 0.31.815.041 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.951 (> 0.100 thold), f_keep = 0.879
108
+ 0.31.815.337 I reasoning-budget: activated, budget=2147483647 tokens
109
+ 0.31.815.385 I slot launch_slot_: id 0 | task 127 | processing task, is_child = 0
110
+ 0.31.815.397 W slot update_slots: id 0 | task 127 | n_past = 406, slot.prompt.tokens.size() = 462, seq_id = 0, pos_min = 461, n_swa = 0
111
+ 0.31.815.398 I slot update_slots: id 0 | task 127 | Checking checkpoint with [416, 416] against 406...
112
+ 0.31.815.399 W slot update_slots: id 0 | task 127 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
113
+ 0.31.815.402 W slot update_slots: id 0 | task 127 | erased invalidated context checkpoint (pos_min = 416, pos_max = 416, n_tokens = 417, n_swa = 0, pos_next = 0, size = 62.813 MiB)
114
+ 0.32.362.167 I slot create_check: id 0 | task 127 | created context checkpoint 1 of 32 (pos_min = 422, pos_max = 422, n_tokens = 423, size = 62.813 MiB)
115
+ 0.32.500.485 I slot print_timing: id 0 | task 127 |
116
+ prompt eval time = 585.39 ms / 427 tokens ( 1.37 ms per token, 729.43 tokens per second)
117
+ eval time = 99.68 ms / 4 tokens ( 24.92 ms per token, 40.13 tokens per second)
118
+ total time = 685.07 ms / 431 tokens
119
+ 0.32.500.582 I slot release: id 0 | task 127 | stop processing: n_tokens = 430, truncated = 0
120
+ 0.32.500.610 I srv update_slots: all slots are idle
121
+ 0.32.535.431 I srv params_from_: Chat format: peg-native
122
+ 0.32.535.929 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.958 (> 0.100 thold), f_keep = 0.944
123
+ 0.32.536.504 I reasoning-budget: activated, budget=2147483647 tokens
124
+ 0.32.536.587 I slot launch_slot_: id 0 | task 133 | processing task, is_child = 0
125
+ 0.32.536.611 W slot update_slots: id 0 | task 133 | n_past = 406, slot.prompt.tokens.size() = 430, seq_id = 0, pos_min = 429, n_swa = 0
126
+ 0.32.536.614 I slot update_slots: id 0 | task 133 | Checking checkpoint with [422, 422] against 406...
127
+ 0.32.536.616 W slot update_slots: id 0 | task 133 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
128
+ 0.32.536.622 W slot update_slots: id 0 | task 133 | erased invalidated context checkpoint (pos_min = 422, pos_max = 422, n_tokens = 423, n_swa = 0, pos_next = 0, size = 62.813 MiB)
129
+ 0.33.112.942 I slot create_check: id 0 | task 133 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
130
+ 0.34.067.962 I slot print_timing: id 0 | task 133 |
131
+ prompt eval time = 615.83 ms / 424 tokens ( 1.45 ms per token, 688.51 tokens per second)
132
+ eval time = 915.49 ms / 39 tokens ( 23.47 ms per token, 42.60 tokens per second)
133
+ total time = 1531.32 ms / 463 tokens
134
+ 0.34.068.202 I slot release: id 0 | task 133 | stop processing: n_tokens = 462, truncated = 0
135
+ 0.34.068.265 I srv update_slots: all slots are idle
136
+ 0.34.070.064 I srv operator(): operator(): cleaning up before exit...
recipe/logs/b_n-tools-q106-tpl.log ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 0.00.148.040 I log_info: verbosity = 3 (adjust with the `-lv N` CLI arg)
2
+ 0.00.148.048 I device_info:
3
+ 0.00.148.185 I - ROCm0 : AMD Radeon Graphics (131072 MiB, 122384 MiB free)
4
+ 0.00.148.371 I - Vulkan0 : AMD Radeon Graphics (RADV GFX1151) (132096 MiB, 131922 MiB free)
5
+ 0.00.148.380 I - CPU : AMD RYZEN AI MAX+ 395 w/ Radeon 8060S (127438 MiB, 127438 MiB free)
6
+ 0.00.148.475 I system_info: n_threads = 16 (n_threads_batch = 16) / 32 | ROCm : NO_VMM = 1 | PEER_MAX_BATCH_SIZE = 128 | FA_ALL_QUANTS = 1 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX_VNNI = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | AVX512 = 1 | AVX512_VBMI = 1 | AVX512_VNNI = 1 | AVX512_BF16 = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 |
7
+ 0.00.148.535 I srv init: running without SSL
8
+ 0.00.148.567 I srv init: using 31 threads for HTTP server
9
+ 0.00.148.569 I srv init: the WebUI is disabled
10
+ 0.00.148.676 I srv start: binding port with default address family
11
+ 0.00.149.917 I srv main: loading model
12
+ 0.00.149.927 I srv load_model: loading model '/mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf'
13
+ 0.00.318.164 W llama_model_loader: direct I/O is enabled, disabling mmap
14
+ 0.24.651.499 W llama_context: n_ctx_seq (65536) < n_ctx_train (262144) -- the full capacity of the model will not be utilized
15
+ 0.24.848.592 W common_init_from_params: warming up the model with an empty run - please wait ... (--no-warmup to disable)
16
+ 0.25.156.208 I srv load_model: initializing slots, n_slots = 1
17
+ 0.25.370.167 W srv load_model: speculative decoding will use checkpoints
18
+ 0.25.370.182 W common_speculative_init: no implementations specified for speculative decoding
19
+ 0.25.370.188 I slot load_model: id 0 | task -1 | new slot, n_ctx = 65536
20
+ 0.25.370.351 I srv load_model: prompt cache RAM enabled: limit_mib=8192
21
+ 0.25.370.398 I srv load_model: for more info see https://github.com/ggml-org/llama.cpp/pull/16391
22
+ 0.25.370.453 I srv init: idle slots will be saved to prompt cache upon starting a new task
23
+ 0.25.419.174 I init: chat template, example_format: '<|im_start|>system
24
+ You are a helpful assistant<|im_end|>
25
+ <|im_start|>user
26
+ Hello<|im_end|>
27
+ <|im_start|>assistant
28
+ <think>
29
+
30
+ </think>
31
+
32
+ Hi there<|im_end|>
33
+ <|im_start|>user
34
+ How are you?<|im_end|>
35
+ <|im_start|>assistant
36
+ <think>
37
+ '
38
+ 0.25.441.368 I srv init: init: chat template, thinking = 1
39
+ 0.25.441.453 I srv main: model loaded
40
+ 0.25.441.460 I srv main: server is listening on http://127.0.0.1:18600
41
+ 0.25.441.468 I srv update_slots: all slots are idle
42
+ 0.26.789.568 I srv params_from_: Chat format: peg-native
43
+ 0.26.789.991 I slot get_availabl: id 0 | task -1 | selected slot by LRU, t_last = -1
44
+ 0.26.789.993 I srv get_availabl: updating prompt cache
45
+ 0.26.790.000 I srv load: - looking for better prompt, base f_keep = -1.000, sim = 0.000
46
+ 0.26.790.006 I srv update: - cache state: 0 prompts, 0.000 MiB (limits: 8192.000 MiB, 65536 tokens, 8589934592 est)
47
+ 0.26.790.010 I srv get_availabl: prompt cache update took 0.01 ms
48
+ 0.26.790.277 I reasoning-budget: activated, budget=2147483647 tokens
49
+ 0.26.790.294 I slot launch_slot_: id 0 | task 0 | processing task, is_child = 0
50
+ 0.27.476.977 I slot create_check: id 0 | task 0 | created context checkpoint 1 of 32 (pos_min = 417, pos_max = 417, n_tokens = 418, size = 62.813 MiB)
51
+ 0.27.881.416 I reasoning-budget: deactivated (natural end)
52
+ 0.28.806.104 I slot print_timing: id 0 | task 0 |
53
+ prompt eval time = 751.68 ms / 422 tokens ( 1.78 ms per token, 561.41 tokens per second)
54
+ eval time = 1264.10 ms / 52 tokens ( 24.31 ms per token, 41.14 tokens per second)
55
+ total time = 2015.78 ms / 474 tokens
56
+ 0.28.806.213 I slot release: id 0 | task 0 | stop processing: n_tokens = 473, truncated = 0
57
+ 0.28.806.225 I srv update_slots: all slots are idle
58
+ 0.28.824.839 I srv params_from_: Chat format: peg-native
59
+ 0.28.825.237 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.906 (> 0.100 thold), f_keep = 0.856
60
+ 0.28.825.422 I reasoning-budget: activated, budget=2147483647 tokens
61
+ 0.28.825.471 I slot launch_slot_: id 0 | task 54 | processing task, is_child = 0
62
+ 0.28.825.483 W slot update_slots: id 0 | task 54 | n_past = 405, slot.prompt.tokens.size() = 473, seq_id = 0, pos_min = 472, n_swa = 0
63
+ 0.28.825.485 I slot update_slots: id 0 | task 54 | Checking checkpoint with [417, 417] against 405...
64
+ 0.28.825.486 W slot update_slots: id 0 | task 54 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
65
+ 0.28.825.489 W slot update_slots: id 0 | task 54 | erased invalidated context checkpoint (pos_min = 417, pos_max = 417, n_tokens = 418, n_swa = 0, pos_next = 0, size = 62.813 MiB)
66
+ 0.29.247.541 I slot create_check: id 0 | task 54 | created context checkpoint 1 of 32 (pos_min = 442, pos_max = 442, n_tokens = 443, size = 62.813 MiB)
67
+ 0.29.847.933 I reasoning-budget: deactivated (natural end)
68
+ 0.31.561.799 I slot print_timing: id 0 | task 54 | n_decoded = 100, tg = 43.85 t/s
69
+ 0.31.768.383 I slot print_timing: id 0 | task 54 |
70
+ prompt eval time = 455.75 ms / 447 tokens ( 1.02 ms per token, 980.80 tokens per second)
71
+ eval time = 2487.14 ms / 110 tokens ( 22.61 ms per token, 44.23 tokens per second)
72
+ total time = 2942.89 ms / 557 tokens
73
+ 0.31.768.453 I slot release: id 0 | task 54 | stop processing: n_tokens = 556, truncated = 0
74
+ 0.31.768.488 I srv update_slots: all slots are idle
75
+ 0.31.780.986 I srv params_from_: Chat format: peg-native
76
+ 0.31.781.515 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.953 (> 0.100 thold), f_keep = 0.728
77
+ 0.31.781.866 I reasoning-budget: activated, budget=2147483647 tokens
78
+ 0.31.781.944 I slot launch_slot_: id 0 | task 166 | processing task, is_child = 0
79
+ 0.31.781.959 W slot update_slots: id 0 | task 166 | n_past = 405, slot.prompt.tokens.size() = 556, seq_id = 0, pos_min = 555, n_swa = 0
80
+ 0.31.781.960 I slot update_slots: id 0 | task 166 | Checking checkpoint with [442, 442] against 405...
81
+ 0.31.781.961 W slot update_slots: id 0 | task 166 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
82
+ 0.31.781.965 W slot update_slots: id 0 | task 166 | erased invalidated context checkpoint (pos_min = 442, pos_max = 442, n_tokens = 443, n_swa = 0, pos_next = 0, size = 62.813 MiB)
83
+ 0.32.284.242 I slot create_check: id 0 | task 166 | created context checkpoint 1 of 32 (pos_min = 420, pos_max = 420, n_tokens = 421, size = 62.813 MiB)
84
+ 0.32.618.089 I reasoning-budget: deactivated (natural end)
85
+ 0.33.467.501 I slot print_timing: id 0 | task 166 |
86
+ prompt eval time = 568.15 ms / 425 tokens ( 1.34 ms per token, 748.05 tokens per second)
87
+ eval time = 1117.36 ms / 52 tokens ( 21.49 ms per token, 46.54 tokens per second)
88
+ total time = 1685.50 ms / 477 tokens
89
+ 0.33.467.767 I slot release: id 0 | task 166 | stop processing: n_tokens = 476, truncated = 0
90
+ 0.33.467.836 I srv update_slots: all slots are idle
91
+ 0.33.510.830 I srv params_from_: Chat format: peg-native
92
+ 0.33.511.252 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.953 (> 0.100 thold), f_keep = 0.851
93
+ 0.33.511.444 I reasoning-budget: activated, budget=2147483647 tokens
94
+ 0.33.511.478 I slot launch_slot_: id 0 | task 220 | processing task, is_child = 0
95
+ 0.33.511.488 W slot update_slots: id 0 | task 220 | n_past = 405, slot.prompt.tokens.size() = 476, seq_id = 0, pos_min = 475, n_swa = 0
96
+ 0.33.511.489 I slot update_slots: id 0 | task 220 | Checking checkpoint with [420, 420] against 405...
97
+ 0.33.511.490 W slot update_slots: id 0 | task 220 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
98
+ 0.33.511.494 W slot update_slots: id 0 | task 220 | erased invalidated context checkpoint (pos_min = 420, pos_max = 420, n_tokens = 421, n_swa = 0, pos_next = 0, size = 62.813 MiB)
99
+ 0.34.023.181 I slot create_check: id 0 | task 220 | created context checkpoint 1 of 32 (pos_min = 420, pos_max = 420, n_tokens = 421, size = 62.813 MiB)
100
+ 0.34.447.908 I reasoning-budget: deactivated (natural end)
101
+ 0.34.540.055 I slot print_timing: id 0 | task 220 |
102
+ prompt eval time = 555.59 ms / 425 tokens ( 1.31 ms per token, 764.95 tokens per second)
103
+ eval time = 472.93 ms / 23 tokens ( 20.56 ms per token, 48.63 tokens per second)
104
+ total time = 1028.52 ms / 448 tokens
105
+ 0.34.540.230 I slot release: id 0 | task 220 | stop processing: n_tokens = 447, truncated = 0
106
+ 0.34.540.267 I srv update_slots: all slots are idle
107
+ 0.34.592.769 I srv params_from_: Chat format: peg-native
108
+ 0.34.593.328 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.962 (> 0.100 thold), f_keep = 0.908
109
+ 0.34.593.568 I reasoning-budget: activated, budget=2147483647 tokens
110
+ 0.34.593.618 I slot launch_slot_: id 0 | task 245 | processing task, is_child = 0
111
+ 0.34.593.629 W slot update_slots: id 0 | task 245 | n_past = 406, slot.prompt.tokens.size() = 447, seq_id = 0, pos_min = 446, n_swa = 0
112
+ 0.34.593.631 I slot update_slots: id 0 | task 245 | Checking checkpoint with [420, 420] against 406...
113
+ 0.34.593.632 W slot update_slots: id 0 | task 245 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
114
+ 0.34.593.635 W slot update_slots: id 0 | task 245 | erased invalidated context checkpoint (pos_min = 420, pos_max = 420, n_tokens = 421, n_swa = 0, pos_next = 0, size = 62.813 MiB)
115
+ 0.35.150.983 I slot create_check: id 0 | task 245 | created context checkpoint 1 of 32 (pos_min = 417, pos_max = 417, n_tokens = 418, size = 62.813 MiB)
116
+ 0.35.748.562 I reasoning-budget: deactivated (natural end)
117
+ 0.36.564.011 I slot print_timing: id 0 | task 245 |
118
+ prompt eval time = 621.88 ms / 422 tokens ( 1.47 ms per token, 678.58 tokens per second)
119
+ eval time = 1348.48 ms / 64 tokens ( 21.07 ms per token, 47.46 tokens per second)
120
+ total time = 1970.37 ms / 486 tokens
121
+ 0.36.564.097 I slot release: id 0 | task 245 | stop processing: n_tokens = 485, truncated = 0
122
+ 0.36.564.126 I srv update_slots: all slots are idle
123
+ 0.36.618.709 I srv params_from_: Chat format: peg-native
124
+ 0.36.619.282 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.854 (> 0.100 thold), f_keep = 0.868
125
+ 0.36.619.528 I reasoning-budget: activated, budget=2147483647 tokens
126
+ 0.36.619.573 I slot launch_slot_: id 0 | task 311 | processing task, is_child = 0
127
+ 0.36.619.585 W slot update_slots: id 0 | task 311 | n_past = 421, slot.prompt.tokens.size() = 485, seq_id = 0, pos_min = 484, n_swa = 0
128
+ 0.36.619.587 I slot update_slots: id 0 | task 311 | Checking checkpoint with [417, 417] against 421...
129
+ 0.36.623.567 W slot update_slots: id 0 | task 311 | restored context checkpoint (pos_min = 417, pos_max = 417, n_tokens = 418, n_past = 418, size = 62.813 MiB)
130
+ 0.36.859.461 I slot create_check: id 0 | task 311 | created context checkpoint 2 of 32 (pos_min = 488, pos_max = 488, n_tokens = 489, size = 62.813 MiB)
131
+ 0.37.463.364 I reasoning-budget: deactivated (natural end)
132
+ 0.37.731.529 I slot print_timing: id 0 | task 311 |
133
+ prompt eval time = 287.07 ms / 75 tokens ( 3.83 ms per token, 261.26 tokens per second)
134
+ eval time = 824.84 ms / 39 tokens ( 21.15 ms per token, 47.28 tokens per second)
135
+ total time = 1111.91 ms / 114 tokens
136
+ 0.37.731.631 I slot release: id 0 | task 311 | stop processing: n_tokens = 531, truncated = 0
137
+ 0.37.731.658 I srv update_slots: all slots are idle
138
+ 0.37.774.243 I srv params_from_: Chat format: peg-native
139
+ 0.37.774.624 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.972 (> 0.100 thold), f_keep = 0.772
140
+ 0.37.774.821 I reasoning-budget: activated, budget=2147483647 tokens
141
+ 0.37.774.854 I slot launch_slot_: id 0 | task 352 | processing task, is_child = 0
142
+ 0.37.774.864 W slot update_slots: id 0 | task 352 | n_past = 410, slot.prompt.tokens.size() = 531, seq_id = 0, pos_min = 530, n_swa = 0
143
+ 0.37.774.865 I slot update_slots: id 0 | task 352 | Checking checkpoint with [488, 488] against 410...
144
+ 0.37.774.866 I slot update_slots: id 0 | task 352 | Checking checkpoint with [417, 417] against 410...
145
+ 0.37.774.867 W slot update_slots: id 0 | task 352 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
146
+ 0.37.774.870 W slot update_slots: id 0 | task 352 | erased invalidated context checkpoint (pos_min = 417, pos_max = 417, n_tokens = 418, n_swa = 0, pos_next = 0, size = 62.813 MiB)
147
+ 0.37.775.796 W slot update_slots: id 0 | task 352 | erased invalidated context checkpoint (pos_min = 488, pos_max = 488, n_tokens = 489, n_swa = 0, pos_next = 0, size = 62.813 MiB)
148
+ 0.38.322.268 I slot create_check: id 0 | task 352 | created context checkpoint 1 of 32 (pos_min = 417, pos_max = 417, n_tokens = 418, size = 62.813 MiB)
149
+ 0.38.647.904 I reasoning-budget: deactivated (natural end)
150
+ 0.39.470.609 I slot print_timing: id 0 | task 352 |
151
+ prompt eval time = 598.33 ms / 422 tokens ( 1.42 ms per token, 705.29 tokens per second)
152
+ eval time = 1097.37 ms / 54 tokens ( 20.32 ms per token, 49.21 tokens per second)
153
+ total time = 1695.70 ms / 476 tokens
154
+ 0.39.470.815 I slot release: id 0 | task 352 | stop processing: n_tokens = 475, truncated = 0
155
+ 0.39.470.868 I srv update_slots: all slots are idle
156
+ 0.39.526.260 I srv params_from_: Chat format: peg-native
157
+ 0.39.528.818 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.935 (> 0.100 thold), f_keep = 0.853
158
+ 0.39.529.421 I reasoning-budget: activated, budget=2147483647 tokens
159
+ 0.39.529.515 I slot launch_slot_: id 0 | task 408 | processing task, is_child = 0
160
+ 0.39.529.535 W slot update_slots: id 0 | task 408 | n_past = 405, slot.prompt.tokens.size() = 475, seq_id = 0, pos_min = 474, n_swa = 0
161
+ 0.39.529.537 I slot update_slots: id 0 | task 408 | Checking checkpoint with [417, 417] against 405...
162
+ 0.39.529.539 W slot update_slots: id 0 | task 408 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
163
+ 0.39.529.547 W slot update_slots: id 0 | task 408 | erased invalidated context checkpoint (pos_min = 417, pos_max = 417, n_tokens = 418, n_swa = 0, pos_next = 0, size = 62.813 MiB)
164
+ 0.40.127.515 I slot create_check: id 0 | task 408 | created context checkpoint 1 of 32 (pos_min = 428, pos_max = 428, n_tokens = 429, size = 62.813 MiB)
165
+ 0.40.699.453 I reasoning-budget: deactivated (natural end)
166
+ 0.42.177.715 I slot print_timing: id 0 | task 408 | n_decoded = 100, tg = 49.81 t/s
167
+ 0.42.310.602 I slot print_timing: id 0 | task 408 |
168
+ prompt eval time = 640.38 ms / 433 tokens ( 1.48 ms per token, 676.16 tokens per second)
169
+ eval time = 2140.67 ms / 107 tokens ( 20.01 ms per token, 49.98 tokens per second)
170
+ total time = 2781.05 ms / 540 tokens
171
+ 0.42.310.711 I slot release: id 0 | task 408 | stop processing: n_tokens = 539, truncated = 0
172
+ 0.42.310.745 I srv update_slots: all slots are idle
173
+ 0.42.345.777 I srv params_from_: Chat format: peg-native
174
+ 0.42.346.201 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.955 (> 0.100 thold), f_keep = 0.751
175
+ 0.42.346.446 I reasoning-budget: activated, budget=2147483647 tokens
176
+ 0.42.346.448 I reasoning-budget: deactivated (natural end)
177
+ 0.42.346.491 I slot launch_slot_: id 0 | task 517 | processing task, is_child = 0
178
+ 0.42.346.503 W slot update_slots: id 0 | task 517 | n_past = 405, slot.prompt.tokens.size() = 539, seq_id = 0, pos_min = 538, n_swa = 0
179
+ 0.42.346.504 I slot update_slots: id 0 | task 517 | Checking checkpoint with [428, 428] against 405...
180
+ 0.42.346.506 W slot update_slots: id 0 | task 517 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
181
+ 0.42.346.509 W slot update_slots: id 0 | task 517 | erased invalidated context checkpoint (pos_min = 428, pos_max = 428, n_tokens = 429, n_swa = 0, pos_next = 0, size = 62.813 MiB)
182
+ 0.42.884.527 I slot create_check: id 0 | task 517 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
183
+ 0.43.790.791 I slot print_timing: id 0 | task 517 |
184
+ prompt eval time = 576.47 ms / 424 tokens ( 1.36 ms per token, 735.51 tokens per second)
185
+ eval time = 867.80 ms / 39 tokens ( 22.25 ms per token, 44.94 tokens per second)
186
+ total time = 1444.27 ms / 463 tokens
187
+ 0.43.790.894 I slot release: id 0 | task 517 | stop processing: n_tokens = 462, truncated = 0
188
+ 0.43.790.929 I srv update_slots: all slots are idle
189
+ 0.43.803.670 I srv params_from_: Chat format: peg-native
190
+ 0.43.804.041 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.902 (> 0.100 thold), f_keep = 0.877
191
+ 0.43.804.257 I reasoning-budget: activated, budget=2147483647 tokens
192
+ 0.43.804.260 I reasoning-budget: deactivated (natural end)
193
+ 0.43.804.297 I slot launch_slot_: id 0 | task 558 | processing task, is_child = 0
194
+ 0.43.804.307 W slot update_slots: id 0 | task 558 | n_past = 405, slot.prompt.tokens.size() = 462, seq_id = 0, pos_min = 461, n_swa = 0
195
+ 0.43.804.307 I slot update_slots: id 0 | task 558 | Checking checkpoint with [419, 419] against 405...
196
+ 0.43.804.308 W slot update_slots: id 0 | task 558 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
197
+ 0.43.804.311 W slot update_slots: id 0 | task 558 | erased invalidated context checkpoint (pos_min = 419, pos_max = 419, n_tokens = 420, n_swa = 0, pos_next = 0, size = 62.813 MiB)
198
+ 0.44.348.687 I slot create_check: id 0 | task 558 | created context checkpoint 1 of 32 (pos_min = 444, pos_max = 444, n_tokens = 445, size = 62.813 MiB)
199
+ 0.46.245.975 I slot print_timing: id 0 | task 558 |
200
+ prompt eval time = 596.97 ms / 449 tokens ( 1.33 ms per token, 752.13 tokens per second)
201
+ eval time = 1844.68 ms / 86 tokens ( 21.45 ms per token, 46.62 tokens per second)
202
+ total time = 2441.65 ms / 535 tokens
203
+ 0.46.246.065 I slot release: id 0 | task 558 | stop processing: n_tokens = 534, truncated = 0
204
+ 0.46.246.093 I srv update_slots: all slots are idle
205
+ 0.46.272.193 I srv params_from_: Chat format: peg-native
206
+ 0.46.272.663 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.948 (> 0.100 thold), f_keep = 0.758
207
+ 0.46.273.230 I reasoning-budget: activated, budget=2147483647 tokens
208
+ 0.46.273.238 I reasoning-budget: deactivated (natural end)
209
+ 0.46.273.319 I slot launch_slot_: id 0 | task 646 | processing task, is_child = 0
210
+ 0.46.273.341 W slot update_slots: id 0 | task 646 | n_past = 405, slot.prompt.tokens.size() = 534, seq_id = 0, pos_min = 533, n_swa = 0
211
+ 0.46.273.345 I slot update_slots: id 0 | task 646 | Checking checkpoint with [444, 444] against 405...
212
+ 0.46.273.347 W slot update_slots: id 0 | task 646 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
213
+ 0.46.273.352 W slot update_slots: id 0 | task 646 | erased invalidated context checkpoint (pos_min = 444, pos_max = 444, n_tokens = 445, n_swa = 0, pos_next = 0, size = 62.813 MiB)
214
+ 0.46.832.222 I slot create_check: id 0 | task 646 | created context checkpoint 1 of 32 (pos_min = 422, pos_max = 422, n_tokens = 423, size = 62.813 MiB)
215
+ 0.47.645.063 I slot print_timing: id 0 | task 646 |
216
+ prompt eval time = 593.12 ms / 427 tokens ( 1.39 ms per token, 719.92 tokens per second)
217
+ eval time = 778.59 ms / 39 tokens ( 19.96 ms per token, 50.09 tokens per second)
218
+ total time = 1371.71 ms / 466 tokens
219
+ 0.47.645.151 I slot release: id 0 | task 646 | stop processing: n_tokens = 465, truncated = 0
220
+ 0.47.645.177 I srv update_slots: all slots are idle
221
+ 0.47.664.123 I srv params_from_: Chat format: peg-native
222
+ 0.47.664.583 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.948 (> 0.100 thold), f_keep = 0.871
223
+ 0.47.665.092 I reasoning-budget: activated, budget=2147483647 tokens
224
+ 0.47.665.095 I reasoning-budget: deactivated (natural end)
225
+ 0.47.665.179 I slot launch_slot_: id 0 | task 687 | processing task, is_child = 0
226
+ 0.47.665.201 W slot update_slots: id 0 | task 687 | n_past = 405, slot.prompt.tokens.size() = 465, seq_id = 0, pos_min = 464, n_swa = 0
227
+ 0.47.665.204 I slot update_slots: id 0 | task 687 | Checking checkpoint with [422, 422] against 405...
228
+ 0.47.665.206 W slot update_slots: id 0 | task 687 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
229
+ 0.47.665.212 W slot update_slots: id 0 | task 687 | erased invalidated context checkpoint (pos_min = 422, pos_max = 422, n_tokens = 423, n_swa = 0, pos_next = 0, size = 62.813 MiB)
230
+ 0.48.219.459 I slot create_check: id 0 | task 687 | created context checkpoint 1 of 32 (pos_min = 422, pos_max = 422, n_tokens = 423, size = 62.813 MiB)
231
+ 0.48.341.963 I slot print_timing: id 0 | task 687 |
232
+ prompt eval time = 588.36 ms / 427 tokens ( 1.38 ms per token, 725.75 tokens per second)
233
+ eval time = 88.39 ms / 4 tokens ( 22.10 ms per token, 45.25 tokens per second)
234
+ total time = 676.75 ms / 431 tokens
235
+ 0.48.342.059 I slot release: id 0 | task 687 | stop processing: n_tokens = 430, truncated = 0
236
+ 0.48.342.091 I srv update_slots: all slots are idle
237
+ 0.48.357.137 I srv params_from_: Chat format: peg-native
238
+ 0.48.357.617 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.958 (> 0.100 thold), f_keep = 0.944
239
+ 0.48.358.008 I reasoning-budget: activated, budget=2147483647 tokens
240
+ 0.48.358.014 I reasoning-budget: deactivated (natural end)
241
+ 0.48.358.075 I slot launch_slot_: id 0 | task 693 | processing task, is_child = 0
242
+ 0.48.358.093 W slot update_slots: id 0 | task 693 | n_past = 406, slot.prompt.tokens.size() = 430, seq_id = 0, pos_min = 429, n_swa = 0
243
+ 0.48.358.095 I slot update_slots: id 0 | task 693 | Checking checkpoint with [422, 422] against 406...
244
+ 0.48.358.096 W slot update_slots: id 0 | task 693 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
245
+ 0.48.358.101 W slot update_slots: id 0 | task 693 | erased invalidated context checkpoint (pos_min = 422, pos_max = 422, n_tokens = 423, n_swa = 0, pos_next = 0, size = 62.813 MiB)
246
+ 0.49.035.367 I slot create_check: id 0 | task 693 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
247
+ 0.49.869.527 I slot print_timing: id 0 | task 693 |
248
+ prompt eval time = 708.91 ms / 424 tokens ( 1.67 ms per token, 598.10 tokens per second)
249
+ eval time = 802.48 ms / 40 tokens ( 20.06 ms per token, 49.85 tokens per second)
250
+ total time = 1511.39 ms / 464 tokens
251
+ 0.49.869.785 I slot release: id 0 | task 693 | stop processing: n_tokens = 463, truncated = 0
252
+ 0.49.869.856 I srv update_slots: all slots are idle
253
+ 0.49.916.557 I srv params_from_: Chat format: peg-native
254
+ 0.49.916.971 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.935 (> 0.100 thold), f_keep = 1.000
255
+ 0.49.917.213 I reasoning-budget: activated, budget=2147483647 tokens
256
+ 0.49.917.215 I reasoning-budget: deactivated (natural end)
257
+ 0.49.917.257 I slot launch_slot_: id 0 | task 735 | processing task, is_child = 0
258
+ 0.50.095.825 I slot create_check: id 0 | task 735 | created context checkpoint 2 of 32 (pos_min = 490, pos_max = 490, n_tokens = 491, size = 62.813 MiB)
259
+ 0.50.567.914 I slot print_timing: id 0 | task 735 |
260
+ prompt eval time = 242.43 ms / 32 tokens ( 7.58 ms per token, 132.00 tokens per second)
261
+ eval time = 408.20 ms / 15 tokens ( 27.21 ms per token, 36.75 tokens per second)
262
+ total time = 650.63 ms / 47 tokens
263
+ 0.50.567.999 I slot release: id 0 | task 735 | stop processing: n_tokens = 509, truncated = 0
264
+ 0.50.568.024 I srv update_slots: all slots are idle
265
+ 0.50.583.295 I srv params_from_: Chat format: peg-native
266
+ 0.50.584.124 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.967 (> 0.100 thold), f_keep = 0.806
267
+ 0.50.584.432 I reasoning-budget: activated, budget=2147483647 tokens
268
+ 0.50.584.436 I reasoning-budget: deactivated (natural end)
269
+ 0.50.584.488 I slot launch_slot_: id 0 | task 752 | processing task, is_child = 0
270
+ 0.50.584.503 W slot update_slots: id 0 | task 752 | n_past = 410, slot.prompt.tokens.size() = 509, seq_id = 0, pos_min = 508, n_swa = 0
271
+ 0.50.584.505 I slot update_slots: id 0 | task 752 | Checking checkpoint with [490, 490] against 410...
272
+ 0.50.584.506 I slot update_slots: id 0 | task 752 | Checking checkpoint with [419, 419] against 410...
273
+ 0.50.584.507 W slot update_slots: id 0 | task 752 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
274
+ 0.50.584.510 W slot update_slots: id 0 | task 752 | erased invalidated context checkpoint (pos_min = 419, pos_max = 419, n_tokens = 420, n_swa = 0, pos_next = 0, size = 62.813 MiB)
275
+ 0.50.585.691 W slot update_slots: id 0 | task 752 | erased invalidated context checkpoint (pos_min = 490, pos_max = 490, n_tokens = 491, n_swa = 0, pos_next = 0, size = 62.813 MiB)
276
+ 0.51.126.714 I slot create_check: id 0 | task 752 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
277
+ 0.52.045.755 I slot print_timing: id 0 | task 752 |
278
+ prompt eval time = 592.34 ms / 424 tokens ( 1.40 ms per token, 715.81 tokens per second)
279
+ eval time = 868.87 ms / 40 tokens ( 21.72 ms per token, 46.04 tokens per second)
280
+ total time = 1461.21 ms / 464 tokens
281
+ 0.52.045.943 I slot release: id 0 | task 752 | stop processing: n_tokens = 463, truncated = 0
282
+ 0.52.045.996 I srv update_slots: all slots are idle
283
+ 0.52.104.739 I srv params_from_: Chat format: peg-native
284
+ 0.52.107.431 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.931 (> 0.100 thold), f_keep = 0.875
285
+ 0.52.108.068 I reasoning-budget: activated, budget=2147483647 tokens
286
+ 0.52.108.073 I reasoning-budget: deactivated (natural end)
287
+ 0.52.108.179 I slot launch_slot_: id 0 | task 794 | processing task, is_child = 0
288
+ 0.52.108.202 W slot update_slots: id 0 | task 794 | n_past = 405, slot.prompt.tokens.size() = 463, seq_id = 0, pos_min = 462, n_swa = 0
289
+ 0.52.108.206 I slot update_slots: id 0 | task 794 | Checking checkpoint with [419, 419] against 405...
290
+ 0.52.108.208 W slot update_slots: id 0 | task 794 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
291
+ 0.52.108.217 W slot update_slots: id 0 | task 794 | erased invalidated context checkpoint (pos_min = 419, pos_max = 419, n_tokens = 420, n_swa = 0, pos_next = 0, size = 62.813 MiB)
292
+ 0.52.715.448 I slot create_check: id 0 | task 794 | created context checkpoint 1 of 32 (pos_min = 430, pos_max = 430, n_tokens = 431, size = 62.813 MiB)
293
+ 0.54.554.592 I slot print_timing: id 0 | task 794 |
294
+ prompt eval time = 642.08 ms / 435 tokens ( 1.48 ms per token, 677.48 tokens per second)
295
+ eval time = 1804.29 ms / 80 tokens ( 22.55 ms per token, 44.34 tokens per second)
296
+ total time = 2446.37 ms / 515 tokens
297
+ 0.54.554.809 I slot release: id 0 | task 794 | stop processing: n_tokens = 514, truncated = 0
298
+ 0.54.554.839 I srv update_slots: all slots are idle
299
+ 0.54.555.755 I srv operator(): operator(): cleaning up before exit...
recipe/logs/b_n-vision-q106-c1-faon.log ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 0.00.059.279 W Setting 'enable_thinking' via --chat-template-kwargs is deprecated. Use --reasoning on / --reasoning off instead.
2
+ 0.00.069.767 I log_info: verbosity = 3 (adjust with the `-lv N` CLI arg)
3
+ 0.00.069.776 I device_info:
4
+ 0.00.069.939 I - ROCm0 : AMD Radeon Graphics (131072 MiB, 123862 MiB free)
5
+ 0.00.070.129 I - Vulkan0 : AMD Radeon Graphics (RADV GFX1151) (132096 MiB, 131922 MiB free)
6
+ 0.00.070.138 I - CPU : AMD RYZEN AI MAX+ 395 w/ Radeon 8060S (127438 MiB, 127438 MiB free)
7
+ 0.00.070.226 I system_info: n_threads = 16 (n_threads_batch = 16) / 32 | ROCm : NO_VMM = 1 | PEER_MAX_BATCH_SIZE = 128 | FA_ALL_QUANTS = 1 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX_VNNI = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | AVX512 = 1 | AVX512_VBMI = 1 | AVX512_VNNI = 1 | AVX512_BF16 = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 |
8
+ 0.00.070.307 I srv init: running without SSL
9
+ 0.00.070.398 I srv init: using 31 threads for HTTP server
10
+ 0.00.070.401 I srv init: the WebUI is disabled
11
+ 0.00.070.610 I srv start: binding port with default address family
12
+ 0.00.071.886 I srv main: loading model
13
+ 0.00.071.903 I srv load_model: loading model '/mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf'
14
+ 0.00.118.721 W llama_model_loader: direct I/O is enabled, disabling mmap
15
+ 0.21.623.100 W llama_context: n_ctx_seq (65536) < n_ctx_train (262144) -- the full capacity of the model will not be utilized
16
+ 0.21.824.309 W common_init_from_params: warming up the model with an empty run - please wait ... (--no-warmup to disable)
17
+ 0.22.126.084 W load_hparams: Qwen-VL models require at minimum 1024 image tokens to function correctly on grounding tasks
18
+ 0.22.126.088 W load_hparams: if you encounter problems with accuracy, try adding --image-min-tokens 1024
19
+ 0.22.126.088 W load_hparams: more info: https://github.com/ggml-org/llama.cpp/issues/16842
20
+
21
+ 0.22.393.368 I srv load_model: loaded multimodal model, '/mnt/models/nex-n2.5-mini/out/mmproj-Nex-N2.5-mini-BF16.gguf'
22
+ 0.22.393.383 I srv load_model: initializing slots, n_slots = 1
23
+ 0.22.705.455 W srv load_model: speculative decoding will use checkpoints
24
+ 0.22.705.465 W common_speculative_init: no implementations specified for speculative decoding
25
+ 0.22.705.468 I slot load_model: id 0 | task -1 | new slot, n_ctx = 65536
26
+ 0.22.705.551 I srv load_model: prompt cache RAM enabled: limit_mib=8192
27
+ 0.22.705.569 I srv load_model: for more info see https://github.com/ggml-org/llama.cpp/pull/16391
28
+ 0.22.705.622 I srv init: idle slots will be saved to prompt cache upon starting a new task
29
+ 0.22.759.943 I init: chat template, example_format: '<|im_start|>system
30
+ You are a helpful assistant<|im_end|>
31
+ <|im_start|>user
32
+ Hello<|im_end|>
33
+ <|im_start|>assistant
34
+ <think>
35
+
36
+ </think>
37
+
38
+ Hi there<|im_end|>
39
+ <|im_start|>user
40
+ How are you?<|im_end|>
41
+ <|im_start|>assistant
42
+ <think>
43
+
44
+ </think>
45
+
46
+ '
47
+ 0.22.797.944 I srv init: init: chat template, thinking = 1
48
+ 0.22.798.029 I srv main: model loaded
49
+ 0.22.798.044 I srv main: server is listening on http://127.0.0.1:18600
50
+ 0.22.798.080 I srv update_slots: all slots are idle
51
+ 0.23.997.761 I srv params_from_: Chat format: peg-native
52
+ 0.23.998.009 I slot get_availabl: id 0 | task -1 | selected slot by LRU, t_last = -1
53
+ 0.23.998.016 I srv get_availabl: updating prompt cache
54
+ 0.23.998.027 I srv load: - looking for better prompt, base f_keep = -1.000, sim = 0.000
55
+ 0.23.998.035 I srv update: - cache state: 0 prompts, 0.000 MiB (limits: 8192.000 MiB, 65536 tokens, 8589934592 est)
56
+ 0.23.998.038 I srv get_availabl: prompt cache update took 0.02 ms
57
+ 0.23.998.225 I slot launch_slot_: id 0 | task 0 | processing task, is_child = 0
58
+ 0.24.059.202 I srv process_chun: processing image...
59
+ 0.24.395.132 W find_slot: non-consecutive token position 4 after 3 for sequence 0 with 196 new tokens
60
+ 0.24.395.722 W find_slot: non-consecutive token position 4 after 3 for sequence 0 with 196 new tokens
61
+ 0.24.862.757 I srv process_chun: image processed in 803 ms
62
+ 0.24.863.042 W find_slot: non-consecutive token position 34 after 4 for sequence 0 with 17 new tokens
63
+ 0.24.863.090 W find_slot: non-consecutive token position 34 after 4 for sequence 0 with 17 new tokens
64
+ 0.24.963.440 I slot create_check: id 0 | task 0 | created context checkpoint 1 of 32 (pos_min = 34, pos_max = 34, n_tokens = 217, size = 62.813 MiB)
65
+ 0.25.458.909 I slot print_timing: id 0 | task 0 |
66
+ prompt eval time = 1019.46 ms / 221 tokens ( 4.61 ms per token, 216.78 tokens per second)
67
+ eval time = 441.18 ms / 21 tokens ( 21.01 ms per token, 47.60 tokens per second)
68
+ total time = 1460.64 ms / 242 tokens
69
+ 0.25.458.950 I slot release: id 0 | task 0 | stop processing: n_tokens = 241, truncated = 0
70
+ 0.25.458.959 I srv update_slots: all slots are idle
71
+ 0.26.459.931 I srv operator(): operator(): cleaning up before exit...
recipe/logs/probe_reasoning.log ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ default correct-decline {"content": "We need answer directly. 391.\n</think>\n\n391", "reasoning": "", "tool_calls": [], "leaks": ["</think>"]}
2
+ default multi-arg {"content": "We need need tool. Current weather Paris celsius.\n</think>\n\n", "reasoning": "", "tool_calls": ["get_weather"], "leaks": ["</think>"]}
3
+ default parallel {"content": "We need need call each city. Parallel okay. Must use commentary tool. Then summarize.\n</think>\n\n", "reasoning": "", "tool_calls": ["get_weather", "get_weather"], "leaks": ["</think>"]}
4
+ fmt-deepseek correct-decline {"content": "We need answer directly. 391.\n</think>\n\n391", "reasoning": "", "tool_calls": [], "leaks": ["</think>"]}
5
+ fmt-deepseek multi-arg {"content": "We need need tool. Current weather Paris celsius.\n</think>\n\n", "reasoning": "", "tool_calls": ["get_weather"], "leaks": ["</think>"]}
6
+ fmt-deepseek parallel {"content": "We need need call each city. Parallel okay. Must use commentary tool. Then summarize.\n</think>\n\n", "reasoning": "", "tool_calls": ["get_weather", "get_weather"], "leaks": ["</think>"]}
7
+ srv-kwargs-high correct-decline {"content": "We need answer directly. 391.\n</think>\n\n391", "reasoning": "", "tool_calls": [], "leaks": ["</think>"]}
8
+ srv-kwargs-high multi-arg {"content": "We need need tool. Current weather Paris celsius.\n</think>\n\n", "reasoning": "", "tool_calls": ["get_weather"], "leaks": ["</think>"]}
9
+ srv-kwargs-high parallel {"content": "We need need call each city. Parallel okay. Must use commentary tool. Then summarize.\n</think>\n\n", "reasoning": "", "tool_calls": ["get_weather", "get_weather"], "leaks": ["</think>"]}
10
+ reasoning-on correct-decline {"content": "We need answer directly. 391.\n</think>\n\n391", "reasoning": "", "tool_calls": [], "leaks": ["</think>"]}
11
+ reasoning-on multi-arg {"content": "We need need tool. Current weather Paris celsius.\n</think>\n\n", "reasoning": "", "tool_calls": ["get_weather"], "leaks": ["</think>"]}
12
+ reasoning-on parallel {"content": "We need need call each city. Parallel okay. Must use commentary tool. Then summarize.\n</think>\n\n", "reasoning": "", "tool_calls": ["get_weather", "get_weather"], "leaks": ["</think>"]}
13
+ tpl-enable-thinking correct-decline {"content": "391", "reasoning": "We need answer directly. 391.\n", "tool_calls": [], "leaks": []}
14
+ tpl-enable-thinking multi-arg {"content": "", "reasoning": "We need need tool. Current weather Paris celsius.\n", "tool_calls": ["get_weather"], "leaks": []}
15
+ tpl-enable-thinking parallel {"content": "", "reasoning": "We need need call each city. Parallel okay. Must use commentary tool. Then summarize.\n", "tool_calls": ["get_weather", "get_weather"], "leaks": []}
16
+ NEX_REASONING_PROBE_DONE /mnt/models/nex-n2.5-mini/results/nex_reasoning_probe.json
recipe/logs/probe_seat_default.log ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ C1 no-kwargs correct-decline {"content": "391", "reasoning_len": 0, "tool_calls": [], "leaks": []}
2
+ C1 no-kwargs single-word {"content": "ready", "reasoning_len": 0, "tool_calls": [], "leaks": []}
3
+ C1 no-kwargs multi-arg {"content": "", "reasoning_len": 0, "tool_calls": ["get_weather"], "leaks": []}
4
+ C1 enable_thinking=true correct-decline {"content": "391", "reasoning_len": 30, "tool_calls": [], "leaks": []}
5
+ C1 enable_thinking=true single-word {"content": "ready", "reasoning_len": 35, "tool_calls": [], "leaks": []}
6
+ C1 enable_thinking=true multi-arg {"content": "", "reasoning_len": 50, "tool_calls": ["get_weather"], "leaks": []}
7
+ C1 enable_thinking=false correct-decline {"content": "391", "reasoning_len": 0, "tool_calls": [], "leaks": []}
8
+ C1 enable_thinking=false single-word {"content": "ready", "reasoning_len": 0, "tool_calls": [], "leaks": []}
9
+ C1 enable_thinking=false multi-arg {"content": "", "reasoning_len": 0, "tool_calls": ["get_weather"], "leaks": []}
10
+ C2 no-kwargs correct-decline {"content": "391", "reasoning_len": 0, "tool_calls": [], "leaks": []}
11
+ C2 no-kwargs single-word {"content": "ready", "reasoning_len": 0, "tool_calls": [], "leaks": []}
12
+ C2 no-kwargs multi-arg {"content": "", "reasoning_len": 0, "tool_calls": ["get_weather"], "leaks": []}
13
+ C2 enable_thinking=true correct-decline {"content": "391", "reasoning_len": 0, "tool_calls": [], "leaks": []}
14
+ C2 enable_thinking=true single-word {"content": "ready", "reasoning_len": 0, "tool_calls": [], "leaks": []}
15
+ C2 enable_thinking=true multi-arg {"content": "", "reasoning_len": 0, "tool_calls": ["get_weather"], "leaks": []}
16
+ C2 enable_thinking=false correct-decline {"content": "391", "reasoning_len": 0, "tool_calls": [], "leaks": []}
17
+ C2 enable_thinking=false single-word {"content": "ready", "reasoning_len": 0, "tool_calls": [], "leaks": []}
18
+ C2 enable_thinking=false multi-arg {"content": "", "reasoning_len": 0, "tool_calls": ["get_weather"], "leaks": []}
19
+ NEX_SEAT_DEFAULT_PROBE_DONE
recipe/logs/probe_seat_default_C2.log ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 0.00.244.374 I log_info: verbosity = 3 (adjust with the `-lv N` CLI arg)
2
+ 0.00.244.393 I device_info:
3
+ 0.00.244.653 I - ROCm0 : AMD Radeon Graphics (131072 MiB, 123682 MiB free)
4
+ 0.00.245.094 I - Vulkan0 : AMD Radeon Graphics (RADV GFX1151) (132096 MiB, 131922 MiB free)
5
+ 0.00.245.113 I - CPU : AMD RYZEN AI MAX+ 395 w/ Radeon 8060S (127438 MiB, 127438 MiB free)
6
+ 0.00.245.304 I system_info: n_threads = 16 (n_threads_batch = 16) / 32 | ROCm : NO_VMM = 1 | PEER_MAX_BATCH_SIZE = 128 | FA_ALL_QUANTS = 1 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX_VNNI = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | AVX512 = 1 | AVX512_VBMI = 1 | AVX512_VNNI = 1 | AVX512_BF16 = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 |
7
+ 0.00.245.404 I srv init: running without SSL
8
+ 0.00.245.477 I srv init: using 31 threads for HTTP server
9
+ 0.00.245.479 I srv init: the WebUI is disabled
10
+ 0.00.245.698 I srv start: binding port with default address family
11
+ 0.00.247.040 I srv main: loading model
12
+ 0.00.247.045 I srv load_model: loading model '/mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf'
13
+ 0.00.310.751 W llama_model_loader: direct I/O is enabled, disabling mmap
14
+ 0.22.302.525 W llama_context: n_ctx_seq (16384) < n_ctx_train (262144) -- the full capacity of the model will not be utilized
15
+ 0.22.428.373 W common_init_from_params: warming up the model with an empty run - please wait ... (--no-warmup to disable)
16
+ 0.22.720.526 I srv load_model: initializing slots, n_slots = 1
17
+ 0.23.006.696 W srv load_model: speculative decoding will use checkpoints
18
+ 0.23.006.713 W common_speculative_init: no implementations specified for speculative decoding
19
+ 0.23.006.717 I slot load_model: id 0 | task -1 | new slot, n_ctx = 16384
20
+ 0.23.006.919 I srv load_model: prompt cache RAM enabled: limit_mib=8192
21
+ 0.23.006.923 I srv load_model: for more info see https://github.com/ggml-org/llama.cpp/pull/16391
22
+ 0.23.006.964 I srv init: idle slots will be saved to prompt cache upon starting a new task
23
+ 0.23.066.942 I init: chat template, example_format: '<|im_start|>system
24
+ You are a helpful assistant<|im_end|>
25
+ <|im_start|>user
26
+ Hello<|im_end|>
27
+ <|im_start|>assistant
28
+ <think>
29
+
30
+ </think>
31
+
32
+ Hi there<|im_end|>
33
+ <|im_start|>user
34
+ How are you?<|im_end|>
35
+ <|im_start|>assistant
36
+ <think>'
37
+ 0.23.112.988 I srv init: init: chat template, thinking = 1
38
+ 0.23.113.079 I srv main: model loaded
39
+ 0.23.113.093 I srv main: server is listening on http://127.0.0.1:18653
40
+ 0.23.113.102 I srv update_slots: all slots are idle
41
+ 0.24.535.309 I srv params_from_: Chat format: peg-native
42
+ 0.24.535.740 I slot get_availabl: id 0 | task -1 | selected slot by LRU, t_last = -1
43
+ 0.24.535.743 I srv get_availabl: updating prompt cache
44
+ 0.24.535.749 I srv load: - looking for better prompt, base f_keep = -1.000, sim = 0.000
45
+ 0.24.535.754 I srv update: - cache state: 0 prompts, 0.000 MiB (limits: 8192.000 MiB, 16384 tokens, 8589934592 est)
46
+ 0.24.535.757 I srv get_availabl: prompt cache update took 0.01 ms
47
+ 0.24.536.006 I reasoning-budget: activated, budget=2147483647 tokens
48
+ 0.24.536.022 I slot launch_slot_: id 0 | task 0 | processing task, is_child = 0
49
+ 0.25.228.510 I slot create_check: id 0 | task 0 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
50
+ 0.25.312.278 I reasoning-budget: deactivated (natural end)
51
+ 0.25.454.972 I slot print_timing: id 0 | task 0 |
52
+ prompt eval time = 749.65 ms / 424 tokens ( 1.77 ms per token, 565.60 tokens per second)
53
+ eval time = 169.27 ms / 7 tokens ( 24.18 ms per token, 41.35 tokens per second)
54
+ total time = 918.92 ms / 431 tokens
55
+ 0.25.455.052 I slot release: id 0 | task 0 | stop processing: n_tokens = 430, truncated = 0
56
+ 0.25.455.062 I srv update_slots: all slots are idle
57
+ 0.25.515.651 I srv params_from_: Chat format: peg-native
58
+ 0.25.518.171 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.969 (> 0.100 thold), f_keep = 0.942
59
+ 0.25.518.665 I reasoning-budget: activated, budget=2147483647 tokens
60
+ 0.25.518.762 I slot launch_slot_: id 0 | task 9 | processing task, is_child = 0
61
+ 0.25.518.786 W slot update_slots: id 0 | task 9 | n_past = 405, slot.prompt.tokens.size() = 430, seq_id = 0, pos_min = 429, n_swa = 0
62
+ 0.25.518.790 I slot update_slots: id 0 | task 9 | Checking checkpoint with [419, 419] against 405...
63
+ 0.25.518.793 W slot update_slots: id 0 | task 9 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
64
+ 0.25.518.809 W slot update_slots: id 0 | task 9 | erased invalidated context checkpoint (pos_min = 419, pos_max = 419, n_tokens = 420, n_swa = 0, pos_next = 0, size = 62.813 MiB)
65
+ 0.26.100.410 I slot create_check: id 0 | task 9 | created context checkpoint 1 of 32 (pos_min = 413, pos_max = 413, n_tokens = 414, size = 62.813 MiB)
66
+ 0.26.190.265 I reasoning-budget: deactivated (natural end)
67
+ 0.26.318.946 I slot print_timing: id 0 | task 9 |
68
+ prompt eval time = 636.97 ms / 418 tokens ( 1.52 ms per token, 656.23 tokens per second)
69
+ eval time = 163.18 ms / 5 tokens ( 32.64 ms per token, 30.64 tokens per second)
70
+ total time = 800.14 ms / 423 tokens
71
+ 0.26.319.036 I slot release: id 0 | task 9 | stop processing: n_tokens = 422, truncated = 0
72
+ 0.26.319.067 I srv update_slots: all slots are idle
73
+ 0.26.365.926 I srv params_from_: Chat format: peg-native
74
+ 0.26.367.996 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.962 (> 0.100 thold), f_keep = 0.960
75
+ 0.26.368.525 I reasoning-budget: activated, budget=2147483647 tokens
76
+ 0.26.368.597 I slot launch_slot_: id 0 | task 16 | processing task, is_child = 0
77
+ 0.26.368.617 W slot update_slots: id 0 | task 16 | n_past = 405, slot.prompt.tokens.size() = 422, seq_id = 0, pos_min = 421, n_swa = 0
78
+ 0.26.368.621 I slot update_slots: id 0 | task 16 | Checking checkpoint with [413, 413] against 405...
79
+ 0.26.368.623 W slot update_slots: id 0 | task 16 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
80
+ 0.26.368.628 W slot update_slots: id 0 | task 16 | erased invalidated context checkpoint (pos_min = 413, pos_max = 413, n_tokens = 414, n_swa = 0, pos_next = 0, size = 62.813 MiB)
81
+ 0.26.955.113 I slot create_check: id 0 | task 16 | created context checkpoint 1 of 32 (pos_min = 416, pos_max = 416, n_tokens = 417, size = 62.813 MiB)
82
+ 0.27.041.682 I reasoning-budget: deactivated (natural end)
83
+ 0.27.918.891 I slot print_timing: id 0 | task 16 |
84
+ prompt eval time = 644.55 ms / 421 tokens ( 1.53 ms per token, 653.16 tokens per second)
85
+ eval time = 905.71 ms / 42 tokens ( 21.56 ms per token, 46.37 tokens per second)
86
+ total time = 1550.26 ms / 463 tokens
87
+ 0.27.918.973 I slot release: id 0 | task 16 | stop processing: n_tokens = 462, truncated = 0
88
+ 0.27.919.004 I srv update_slots: all slots are idle
89
+ 0.27.975.579 I srv params_from_: Chat format: peg-native
90
+ 0.27.977.357 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.958 (> 0.100 thold), f_keep = 0.879
91
+ 0.27.977.785 I reasoning-budget: activated, budget=2147483647 tokens
92
+ 0.27.977.885 I slot launch_slot_: id 0 | task 60 | processing task, is_child = 0
93
+ 0.27.977.912 W slot update_slots: id 0 | task 60 | n_past = 406, slot.prompt.tokens.size() = 462, seq_id = 0, pos_min = 461, n_swa = 0
94
+ 0.27.977.913 I slot update_slots: id 0 | task 60 | Checking checkpoint with [416, 416] against 406...
95
+ 0.27.977.915 W slot update_slots: id 0 | task 60 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
96
+ 0.27.977.920 W slot update_slots: id 0 | task 60 | erased invalidated context checkpoint (pos_min = 416, pos_max = 416, n_tokens = 417, n_swa = 0, pos_next = 0, size = 62.813 MiB)
97
+ 0.28.575.881 I slot create_check: id 0 | task 60 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
98
+ 0.28.639.525 I reasoning-budget: deactivated (natural end)
99
+ 0.28.760.322 I slot print_timing: id 0 | task 60 |
100
+ prompt eval time = 636.60 ms / 424 tokens ( 1.50 ms per token, 666.03 tokens per second)
101
+ eval time = 145.80 ms / 7 tokens ( 20.83 ms per token, 48.01 tokens per second)
102
+ total time = 782.40 ms / 431 tokens
103
+ 0.28.760.399 I slot release: id 0 | task 60 | stop processing: n_tokens = 430, truncated = 0
104
+ 0.28.760.426 I srv update_slots: all slots are idle
105
+ 0.28.773.374 I srv params_from_: Chat format: peg-native
106
+ 0.28.773.718 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.969 (> 0.100 thold), f_keep = 0.942
107
+ 0.28.773.919 I reasoning-budget: activated, budget=2147483647 tokens
108
+ 0.28.773.955 I slot launch_slot_: id 0 | task 69 | processing task, is_child = 0
109
+ 0.28.773.965 W slot update_slots: id 0 | task 69 | n_past = 405, slot.prompt.tokens.size() = 430, seq_id = 0, pos_min = 429, n_swa = 0
110
+ 0.28.773.967 I slot update_slots: id 0 | task 69 | Checking checkpoint with [419, 419] against 405...
111
+ 0.28.773.968 W slot update_slots: id 0 | task 69 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
112
+ 0.28.773.971 W slot update_slots: id 0 | task 69 | erased invalidated context checkpoint (pos_min = 419, pos_max = 419, n_tokens = 420, n_swa = 0, pos_next = 0, size = 62.813 MiB)
113
+ 0.29.251.924 I slot create_check: id 0 | task 69 | created context checkpoint 1 of 32 (pos_min = 413, pos_max = 413, n_tokens = 414, size = 62.813 MiB)
114
+ 0.29.313.310 I reasoning-budget: deactivated (natural end)
115
+ 0.29.391.023 I slot print_timing: id 0 | task 69 |
116
+ prompt eval time = 514.69 ms / 418 tokens ( 1.23 ms per token, 812.15 tokens per second)
117
+ eval time = 102.36 ms / 5 tokens ( 20.47 ms per token, 48.85 tokens per second)
118
+ total time = 617.04 ms / 423 tokens
119
+ 0.29.391.120 I slot release: id 0 | task 69 | stop processing: n_tokens = 422, truncated = 0
120
+ 0.29.391.150 I srv update_slots: all slots are idle
121
+ 0.29.426.233 I srv params_from_: Chat format: peg-native
122
+ 0.29.426.716 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.962 (> 0.100 thold), f_keep = 0.960
123
+ 0.29.426.958 I reasoning-budget: activated, budget=2147483647 tokens
124
+ 0.29.427.000 I slot launch_slot_: id 0 | task 76 | processing task, is_child = 0
125
+ 0.29.427.011 W slot update_slots: id 0 | task 76 | n_past = 405, slot.prompt.tokens.size() = 422, seq_id = 0, pos_min = 421, n_swa = 0
126
+ 0.29.427.013 I slot update_slots: id 0 | task 76 | Checking checkpoint with [413, 413] against 405...
127
+ 0.29.427.014 W slot update_slots: id 0 | task 76 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
128
+ 0.29.427.017 W slot update_slots: id 0 | task 76 | erased invalidated context checkpoint (pos_min = 413, pos_max = 413, n_tokens = 414, n_swa = 0, pos_next = 0, size = 62.813 MiB)
129
+ 0.29.922.653 I slot create_check: id 0 | task 76 | created context checkpoint 1 of 32 (pos_min = 416, pos_max = 416, n_tokens = 417, size = 62.813 MiB)
130
+ 0.29.984.421 I reasoning-budget: deactivated (natural end)
131
+ 0.30.786.431 I slot print_timing: id 0 | task 76 |
132
+ prompt eval time = 529.05 ms / 421 tokens ( 1.26 ms per token, 795.76 tokens per second)
133
+ eval time = 830.35 ms / 42 tokens ( 19.77 ms per token, 50.58 tokens per second)
134
+ total time = 1359.40 ms / 463 tokens
135
+ 0.30.786.507 I slot release: id 0 | task 76 | stop processing: n_tokens = 462, truncated = 0
136
+ 0.30.786.534 I srv update_slots: all slots are idle
137
+ 0.30.827.357 I srv params_from_: Chat format: peg-native
138
+ 0.30.827.975 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.951 (> 0.100 thold), f_keep = 0.879
139
+ 0.30.828.455 I reasoning-budget: activated, budget=2147483647 tokens
140
+ 0.30.828.460 I reasoning-budget: deactivated (natural end)
141
+ 0.30.828.579 I slot launch_slot_: id 0 | task 120 | processing task, is_child = 0
142
+ 0.30.828.602 W slot update_slots: id 0 | task 120 | n_past = 406, slot.prompt.tokens.size() = 462, seq_id = 0, pos_min = 461, n_swa = 0
143
+ 0.30.828.605 I slot update_slots: id 0 | task 120 | Checking checkpoint with [416, 416] against 406...
144
+ 0.30.828.608 W slot update_slots: id 0 | task 120 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
145
+ 0.30.828.615 W slot update_slots: id 0 | task 120 | erased invalidated context checkpoint (pos_min = 416, pos_max = 416, n_tokens = 417, n_swa = 0, pos_next = 0, size = 62.813 MiB)
146
+ 0.31.403.843 I slot create_check: id 0 | task 120 | created context checkpoint 1 of 32 (pos_min = 422, pos_max = 422, n_tokens = 423, size = 62.813 MiB)
147
+ 0.31.535.343 I slot print_timing: id 0 | task 120 |
148
+ prompt eval time = 610.22 ms / 427 tokens ( 1.43 ms per token, 699.75 tokens per second)
149
+ eval time = 96.52 ms / 4 tokens ( 24.13 ms per token, 41.44 tokens per second)
150
+ total time = 706.74 ms / 431 tokens
151
+ 0.31.535.416 I slot release: id 0 | task 120 | stop processing: n_tokens = 430, truncated = 0
152
+ 0.31.535.442 I srv update_slots: all slots are idle
153
+ 0.31.579.928 I srv params_from_: Chat format: peg-native
154
+ 0.31.582.191 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.962 (> 0.100 thold), f_keep = 0.942
155
+ 0.31.582.782 I reasoning-budget: activated, budget=2147483647 tokens
156
+ 0.31.582.789 I reasoning-budget: deactivated (natural end)
157
+ 0.31.582.964 I slot launch_slot_: id 0 | task 126 | processing task, is_child = 0
158
+ 0.31.582.991 W slot update_slots: id 0 | task 126 | n_past = 405, slot.prompt.tokens.size() = 430, seq_id = 0, pos_min = 429, n_swa = 0
159
+ 0.31.582.995 I slot update_slots: id 0 | task 126 | Checking checkpoint with [422, 422] against 405...
160
+ 0.31.582.997 W slot update_slots: id 0 | task 126 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
161
+ 0.31.583.004 W slot update_slots: id 0 | task 126 | erased invalidated context checkpoint (pos_min = 422, pos_max = 422, n_tokens = 423, n_swa = 0, pos_next = 0, size = 62.813 MiB)
162
+ 0.32.142.847 I slot create_check: id 0 | task 126 | created context checkpoint 1 of 32 (pos_min = 416, pos_max = 416, n_tokens = 417, size = 62.813 MiB)
163
+ 0.32.249.462 I slot print_timing: id 0 | task 126 |
164
+ prompt eval time = 617.07 ms / 421 tokens ( 1.47 ms per token, 682.25 tokens per second)
165
+ eval time = 49.39 ms / 2 tokens ( 24.70 ms per token, 40.49 tokens per second)
166
+ total time = 666.46 ms / 423 tokens
167
+ 0.32.249.559 I slot release: id 0 | task 126 | stop processing: n_tokens = 422, truncated = 0
168
+ 0.32.249.590 I srv update_slots: all slots are idle
169
+ 0.32.262.258 I srv params_from_: Chat format: peg-native
170
+ 0.32.262.613 I slot get_availabl: id 0 | task -1 | selected slot by LCP similarity, sim_best = 0.955 (> 0.100 thold), f_keep = 0.960
171
+ 0.32.262.803 I reasoning-budget: activated, budget=2147483647 tokens
172
+ 0.32.262.808 I reasoning-budget: deactivated (natural end)
173
+ 0.32.262.842 I slot launch_slot_: id 0 | task 130 | processing task, is_child = 0
174
+ 0.32.262.852 W slot update_slots: id 0 | task 130 | n_past = 405, slot.prompt.tokens.size() = 422, seq_id = 0, pos_min = 421, n_swa = 0
175
+ 0.32.262.852 I slot update_slots: id 0 | task 130 | Checking checkpoint with [416, 416] against 405...
176
+ 0.32.262.853 W slot update_slots: id 0 | task 130 | forcing full prompt re-processing due to lack of cache data (likely due to SWA or hybrid/recurrent memory, see https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
177
+ 0.32.262.856 W slot update_slots: id 0 | task 130 | erased invalidated context checkpoint (pos_min = 416, pos_max = 416, n_tokens = 417, n_swa = 0, pos_next = 0, size = 62.813 MiB)
178
+ 0.32.810.656 I slot create_check: id 0 | task 130 | created context checkpoint 1 of 32 (pos_min = 419, pos_max = 419, n_tokens = 420, size = 62.813 MiB)
179
+ 0.33.748.645 I slot print_timing: id 0 | task 130 |
180
+ prompt eval time = 596.89 ms / 424 tokens ( 1.41 ms per token, 710.35 tokens per second)
181
+ eval time = 888.89 ms / 39 tokens ( 22.79 ms per token, 43.88 tokens per second)
182
+ total time = 1485.78 ms / 463 tokens
183
+ 0.33.748.736 I slot release: id 0 | task 130 | stop processing: n_tokens = 462, truncated = 0
184
+ 0.33.748.767 I srv update_slots: all slots are idle
185
+ 0.33.749.943 I srv operator(): operator(): cleaning up before exit...
recipe/pipeline/diag_bf16.sh ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Which backend computes the Nex BF16 GGUF correctly? d3ca537 ROCm0 (-fa on) gave PPL 139-171 on the first chunks while
3
+ # the 4-bit STRIX_LEAN gave 6.28-7.84 on the same chunks. Same text, same -c/-b; only device / -fa change.
4
+ set -uo pipefail
5
+ W=/mnt/models/nex-n2.5-mini; B=/opt/llama-rocm/rocmfpx-724/build-hipvk/bin; A=/mnt/models/agnes-3.0-flash
6
+ export LD_LIBRARY_PATH=$B:/opt/rocm-7.2.4/lib HSA_OVERRIDE_GFX_VERSION=11.5.1 GGML_HIP_ENABLE_UNIFIED_MEMORY=1
7
+ cd $W; prlimit --pid $$ --core=1:1
8
+ log(){ echo "[$(date -u +%FT%TZ)] $*"; }
9
+ BF=gguf/Nex-N2.5-mini-BF16.gguf; Q=out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf
10
+ T=$A/calib/wikitext-2-raw/wiki.test.raw
11
+ run(){ # label chunks model args...
12
+ local lab=$1 ch=$2 m=$3; shift 3
13
+ timeout 1800 $B/llama-perplexity -m $m -f $T -c 2048 -b 2048 --chunks $ch "$@" > logs/diag_$lab.log 2>&1
14
+ log "$lab rc=$? $(grep -oE '\[[0-9]+\][0-9.]+' logs/diag_$lab.log | tr '\n' ' ')"
15
+ }
16
+ run bf16_rocm_faoff 4 $BF -ngl 999 -fa off -dev ROCm0
17
+ run bf16_vk_faon 4 $BF -ngl 999 -fa on -dev Vulkan0
18
+ run q106_vk_faon 4 $Q -ngl 999 -fa on -dev Vulkan0
19
+ run bf16_cpu 2 $BF -ngl 0 -t 16
20
+ log "DIAG_BF16_DONE"
recipe/pipeline/diag_tools_run.sh ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # start the tools diagnostic as soon as the N8 seat smoke tests are finished (so it does not disturb them),
3
+ # capped at 32G; OxCoder phase 2 waits for GPU-free and therefore starts after it.
4
+ cd /mnt/models/nex-n2.5-mini
5
+ until grep -q "nex_seats exit=" logs/N8_unice.log 2>/dev/null; do sleep 5; done
6
+ echo "[$(date -u +%FT%TZ)] seats done -> diag"
7
+ systemd-run --scope --quiet --unit=nex-tools-diag-$(date +%s) -p MemoryMax=32G -p MemorySwapMax=0 python3 nex_tools_diag.py
8
+ echo "[$(date -u +%FT%TZ)] diag exit=$?"
recipe/pipeline/nex_aggregate.py ADDED
@@ -0,0 +1,408 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Collect every measured number for the Nex-N2.5-mini ROCmFP4 cards into results/summary.json.
3
+ Nothing is typed by hand except model facts and protocol constants. Each value is parsed from a log,
4
+ a results file, or the GGUF itself; missing => None."""
5
+ import hashlib, json, os, re, sys
6
+ sys.path.insert(0, "/opt/llama-rocm/rocmfpx-724/gguf-py")
7
+ import gguf # noqa: E402
8
+
9
+ W = "/mnt/models/nex-n2.5-mini"
10
+ A = "/mnt/models/agnes-3.0-flash"
11
+ N = "Nex-N2.5-mini"
12
+ OB = "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin"
13
+ FAST = os.environ.get("AGG_FAST") == "1"
14
+ OUT = os.environ.get("AGG_OUT", f"{W}/results/summary.json")
15
+ UB = 1024 # llama-server -ub; cache checkpoints land 4 + n_ubatch tokens before prompt end
16
+
17
+
18
+ def rd(p):
19
+ try:
20
+ return open(p, errors="replace").read()
21
+ except FileNotFoundError:
22
+ return ""
23
+
24
+
25
+ def f(rx, s, g=1, cast=float):
26
+ m = re.search(rx, s)
27
+ return cast(m.group(g)) if m else None
28
+
29
+
30
+ def jl(p):
31
+ return [json.loads(l) for l in rd(p).splitlines() if l.strip()]
32
+
33
+
34
+ def pubname(fn):
35
+ """Published filename: the Hub cannot parse an underscore-glued quant token."""
36
+ return fn.replace("Q4_0_ROCMFP4_", "Q4_0-ROCmFP4-")
37
+
38
+
39
+ STAGED = {}
40
+ for _k in ("std", "imat"):
41
+ for _l in rd(f"{W}/hf-upload/{_k}/SHA256SUMS").splitlines():
42
+ _h, _n = _l.split(maxsplit=1)
43
+ STAGED[_n.strip()] = _h
44
+
45
+
46
+ def sha_file(p):
47
+ if not os.path.exists(p):
48
+ return None
49
+ if pubname(os.path.basename(p)) in STAGED:
50
+ return STAGED[pubname(os.path.basename(p))]
51
+ if os.path.basename(p) in STAGED:
52
+ return STAGED[os.path.basename(p)]
53
+ if FAST and os.path.getsize(p) > 1 << 30:
54
+ return None
55
+ h = hashlib.sha256()
56
+ with open(p, "rb") as fh:
57
+ for c in iter(lambda: fh.read(64 << 20), b""):
58
+ h.update(c)
59
+ return h.hexdigest()
60
+
61
+
62
+ def tensors(p):
63
+ """name -> (type, bytes); {} if the file cannot be read (e.g. still being written by a running quantize)."""
64
+ out = {}
65
+ try:
66
+ reader = gguf.GGUFReader(p)
67
+ except (ValueError, OSError) as e:
68
+ print(f"WARN unreadable GGUF {p}: {e}", file=sys.stderr)
69
+ return out
70
+ for t in reader.tensors:
71
+ try:
72
+ tn = t.tensor_type.name
73
+ except Exception:
74
+ tn = f"TYPE_{int(t.tensor_type)}"
75
+ out[t.name] = (tn, int(t.n_bytes))
76
+ return out
77
+
78
+
79
+ def rb_line(blob, fn):
80
+ return next((l for l in blob.splitlines() if len(l.split()) > 1 and l.split()[1] == fn), "")
81
+
82
+
83
+ def kld_stats(k):
84
+ return {
85
+ "ppl": f(r"Mean PPL\(Q\)\s*:\s*([\d.]+)", k),
86
+ "ppl_err": f(r"Mean PPL\(Q\)\s*:\s*[\d.]+\s*±\s*([\d.]+)", k),
87
+ "ppl_ratio": f(r"Mean PPL\(Q\)/PPL\(base\)\s*:\s*([\d.]+)", k),
88
+ "kld_mean": f(r"Mean\s+KLD:\s*([\d.]+)", k),
89
+ "kld_err": f(r"Mean\s+KLD:\s*[\d.]+\s*±\s*([\d.]+)", k),
90
+ "kld_p99": f(r"99\.0%\s+KLD:\s*([\d.]+)", k),
91
+ "kld_median": f(r"Median\s+KLD:\s*([\d.]+)", k),
92
+ "same_top_p": f(r"Same top p:\s*([\d.]+)", k),
93
+ "rms_dp": f(r"RMS Δp\s*:\s*([\d.]+)", k),
94
+ }
95
+
96
+
97
+ def exists_size(p):
98
+ return os.path.getsize(p) if os.path.exists(p) else None
99
+
100
+
101
+ S = {
102
+ "layout": "no MTP (checkpoint declares mtp_num_hidden_layers=1 but ships no mtp.* tensors)",
103
+ "model": N,
104
+ "model_repo_std": f"kingjones777/{N}-ROCmFP4-GGUF",
105
+ "model_repo_imat": f"kingjones777/{N}-ROCmFP4-imatrix-GGUF",
106
+ "source": {
107
+ "repo": "nex-agi/Nex-N2.5-mini",
108
+ "revision": "87420286149d9cce9bd46cd335ef9bda33c37c1b",
109
+ "license": "apache-2.0",
110
+ "gated": False,
111
+ "params": 35107181936,
112
+ },
113
+ "arch": {
114
+ "name": "qwen3_5_moe",
115
+ "llama_cpp": "qwen35moe",
116
+ "layers": 40,
117
+ "linear_attn_layers": 30,
118
+ "full_attn_layers": 10,
119
+ "full_attention_interval": 4,
120
+ "hidden": 2048,
121
+ "num_experts": 256,
122
+ "num_experts_per_tok": 8,
123
+ "expert_width": 512,
124
+ "shared_expert_width": 512,
125
+ "attn_heads": 16,
126
+ "kv_heads": 2,
127
+ "head_dim": 256,
128
+ "linear_key_heads": 16,
129
+ "linear_value_heads": 32,
130
+ "linear_head_dim": 128,
131
+ "vocab": 248320,
132
+ "max_position_embeddings": 262144,
133
+ "tie_word_embeddings": False,
134
+ "vision_layers": 27,
135
+ "vision_width": 1152,
136
+ "hf_tensors": 1026,
137
+ "mtp_num_hidden_layers_declared": 1,
138
+ },
139
+ }
140
+
141
+ # ---------- BF16 reference ----------
142
+ # phase 2b: this build's ROCm0 path computes the BF16 GGUF of this MoE wrong, so the reference ran on pure CPU
143
+ b1 = rd(f"{W}/logs/N1c_ppl_bf16_cpu.log")
144
+ k106 = rd(f"{W}/logs/N4_kld_q106.log")
145
+ crb = rd(f"{W}/logs/C_readback.log")
146
+ chunks = f(r"calculating perplexity over (\d+) chunks", b1, cast=int)
147
+ nctx = f(r"n_ctx=(\d+)", b1, cast=int)
148
+ bf_fn = f"{N}-BF16.gguf"
149
+ bf_line = rb_line(crb, bf_fn)
150
+ bf_path = f"{W}/gguf/{bf_fn}"
151
+ bf_ten = tensors(bf_path) if os.path.exists(bf_path) else {}
152
+ S["bf16"] = {
153
+ "ppl": f(r"Final estimate: PPL = ([\d.]+)", b1),
154
+ "ppl_err": f(r"Final estimate: PPL = [\d.]+ \+/- ([\d.]+)", b1),
155
+ "ppl_paired": f(r"Mean PPL\(base\)\s*:\s*([\d.]+)", k106),
156
+ "ppl_paired_err": f(r"Mean PPL\(base\)\s*:\s*[\d.]+\s*±\s*([\d.]+)", k106),
157
+ "chunks": chunks,
158
+ "n_ctx": nctx,
159
+ "scored_tokens": chunks * (nctx // 2 - 1) if chunks and nctx else None,
160
+ "size_bytes": exists_size(bf_path),
161
+ "file": bf_fn,
162
+ "readback": bf_line.split()[0] if bf_line else None,
163
+ "arch": f(r"arch=(\S+)", bf_line, cast=str),
164
+ "ftype": f(r"ftype=(\d+)", bf_line, cast=int),
165
+ "tensors": f(r"tensors=(\d+)", bf_line, cast=int) or (len(bf_ten) or None),
166
+ "nextn_tensors": f(r"nextn=(\d+)", bf_line, cast=int),
167
+ "output_weight": f(r"output\.weight=(\S+)", bf_line, cast=str),
168
+ "token_embd": f(r"token_embd\.weight=(\S+)", bf_line, cast=str),
169
+ "mtp_named_tensors": sum(1 for n in bf_ten if n.startswith("mtp.")) if bf_ten else None,
170
+ "nextn_named_tensors": sum(1 for n in bf_ten if ".nextn." in n) if bf_ten else None,
171
+ }
172
+
173
+ # ---------- binaries ----------
174
+ qlog = rd(f"{W}/logs/Q1_q106.log")
175
+ S["binary"] = {
176
+ "repo": "https://github.com/charlie12345/ROCmFPX",
177
+ "commit": f(r"llama_print_build_info: build = \d+ \(([0-9a-f]+)\)", qlog, cast=str),
178
+ "dir": OB,
179
+ "sha256": {x: sha_file(f"{OB}/{x}") for x in
180
+ ("llama-server", "llama-quantize", "llama-imatrix", "llama-perplexity")},
181
+ }
182
+
183
+ vp = f"{A}/calib/vision_probe.png"
184
+ if os.path.exists(vp):
185
+ raw = open(vp, "rb").read()
186
+ S["vision_probe"] = {
187
+ "width": int.from_bytes(raw[16:20], "big"),
188
+ "height": int.from_bytes(raw[20:24], "big"),
189
+ "bytes": len(raw),
190
+ "sha256": hashlib.sha256(raw).hexdigest(),
191
+ }
192
+
193
+ imat = rd(f"{W}/logs/N2c_imatrix_cpu.log")
194
+ S["imatrix"] = {
195
+ "chunks": f(r"computing over (\d+) chunks", imat, cast=int),
196
+ "n_ctx": f(r"n_ctx=(\d+)", imat, cast=int),
197
+ "calibration": "bartowski calibration_datav3.txt",
198
+ "file": f"{N}.imatrix",
199
+ "sha256": (rd(f"{W}/imat/{N}.imatrix.sha256").split() or [None])[0],
200
+ "size_bytes": exists_size(f"{W}/imat/{N}.imatrix"),
201
+ }
202
+
203
+ hc_raw = rd(f"{W}/results/hub_check.json").strip()
204
+ if hc_raw:
205
+ try:
206
+ S["hub_check"] = json.loads(hc_raw)
207
+ except json.JSONDecodeError:
208
+ S["hub_check"] = None
209
+ else:
210
+ S["hub_check"] = None
211
+
212
+
213
+ def type_name(i):
214
+ try:
215
+ return gguf.GGMLQuantizationType(int(i)).name
216
+ except (TypeError, ValueError):
217
+ return None
218
+
219
+
220
+ for _h in (S["hub_check"] or {}).get("header_checks") or []:
221
+ # ids were read from the other repo's GGUF header; names come from this fork's gguf-py enum
222
+ _h["output_weight_type"] = type_name(_h.get("output_weight_type_id"))
223
+ _h["token_embd_type"] = type_name(_h.get("token_embd_type_id"))
224
+
225
+ REP = jl(f"{W}/results/nex_repeat.jsonl")
226
+ S["repeat"] = next((d for d in REP if d.get("step") == "N5"), None) # ROCm0
227
+ S["repeat_vk"] = next((d for d in REP if d.get("step") == "N5v"), None) # Vulkan0
228
+ S["reference"] = next((d for d in jl(f"{W}/results/nex_reference.jsonl") if d.get("step") == "N1c"), None)
229
+ S["reference_device"] = "CPU" if S["reference"] else None
230
+ S["imatrix"]["device"] = "CPU" if imat else None
231
+
232
+ # ---------- tiers ----------
233
+ TIERS = {
234
+ "q106": ("out", f"{N}-Q4_0_ROCMFP4_STRIX_LEAN.gguf", "Q1_q106", "Q_readback.log", 106),
235
+ "q102": ("out", f"{N}-Q4_0_ROCMFP4_COHERENT.gguf", "Q1_q102", "Q_readback.log", 102),
236
+ "q103": ("out", f"{N}-Q4_0_ROCMFP4_FAST.gguf", "Q1_q103", "Q_readback.log", 103),
237
+ "q106i": ("out-imat", f"{N}-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf", "N3_q106i", "N3_readback.log", 106),
238
+ "q102i": ("out-imat", f"{N}-imatrix-Q4_0_ROCMFP4_COHERENT.gguf", "N3_q102i", "N3_readback.log", 102),
239
+ "q103i": ("out-imat", f"{N}-imatrix-Q4_0_ROCMFP4_FAST.gguf", "N3_q103i", "N3_readback.log", 103),
240
+ }
241
+ RB = {name: rd(f"{W}/logs/{name}") for name in ("Q_readback.log", "N3_readback.log")}
242
+
243
+ S["tiers"] = {}
244
+ TEN = {}
245
+ for tag, (d, fn, qlog_stem, rblog, ft) in TIERS.items():
246
+ p = f"{W}/{d}/{fn}"
247
+ q = rd(f"{W}/logs/{qlog_stem}.log")
248
+ k = rd(f"{W}/logs/N4_kld_{tag}.log")
249
+ line = rb_line(RB.get(rblog, ""), fn)
250
+ ten = tensors(p) if os.path.exists(p) else {}
251
+ TEN[tag] = ten
252
+ qs = f(r"quantize time\s*=\s*([\d.]+) ms", q)
253
+ t = {
254
+ "file": pubname(fn),
255
+ "local_file": fn,
256
+ "dir": d,
257
+ "ftype": ft,
258
+ "size_bytes": exists_size(p),
259
+ "quant_mib": f(r"quant size\s*=\s*([\d.]+) MiB", q),
260
+ "bpw": f(r"quant size\s*=\s*[\d.]+ MiB \(([\d.]+) BPW\)", q),
261
+ "quant_seconds": (qs / 1000) if qs is not None else None,
262
+ "imatrix_entries": f(r"loaded (\d+) importance matrix entries", q, cast=int),
263
+ "readback": line.split()[0] if line else None,
264
+ "arch": f(r"arch=(\S+)", line, cast=str),
265
+ "tensors": f(r"tensors=(\d+)", line, cast=int),
266
+ "nextn_tensors": f(r"nextn=(\d+)", line, cast=int),
267
+ "output_weight": f(r"output\.weight=(\S+)", line, cast=str),
268
+ "token_embd": f(r"token_embd\.weight=(\S+)", line, cast=str),
269
+ "quality_measured": f(r"Mean\s+KLD:\s*([\d.]+)", k) is not None,
270
+ }
271
+ t.update(kld_stats(k) if t["quality_measured"] else {x: None for x in kld_stats("")})
272
+ kv = rd(f"{W}/logs/N4v_kld_{tag}.log") # the same file graded on Vulkan0
273
+ t["vk"] = kld_stats(kv) if f(r"Mean\s+KLD:\s*([\d.]+)", kv) is not None else None
274
+ S["tiers"][tag] = t
275
+
276
+ TWINS = (("q106i", "q106"), ("q102i", "q102"), ("q103i", "q103"))
277
+ for im, st in TWINS:
278
+ pa = f"{W}/{TIERS[st][0]}/{TIERS[st][1]}"
279
+ pb = f"{W}/{TIERS[im][0]}/{TIERS[im][1]}"
280
+ if TEN.get(st) and TEN.get(im):
281
+ S["tiers"][im]["same_tensor_types_as_standard"] = TEN[st] == TEN[im]
282
+ else:
283
+ S["tiers"][im]["same_tensor_types_as_standard"] = None
284
+ sa, sb = S["tiers"][st]["size_bytes"], S["tiers"][im]["size_bytes"]
285
+ S["tiers"][im]["file_size_delta_bytes"] = (sb - sa) if None not in (sa, sb) else None
286
+ ha, hb = (sha_file(pa), sha_file(pb)) if os.path.exists(pa) and os.path.exists(pb) else (None, None)
287
+ S["tiers"][im]["differs_from_standard"] = (ha != hb) if ha and hb else None
288
+
289
+ mm_fn = f"mmproj-{N}-BF16.gguf"
290
+ mm_line = rb_line(crb, mm_fn)
291
+ S["aux"] = {mm_fn: exists_size(f"{W}/out/{mm_fn}")}
292
+ S["mmproj"] = {
293
+ "file": mm_fn,
294
+ "size_bytes": S["aux"][mm_fn],
295
+ "readback": mm_line.split()[0] if mm_line else None,
296
+ "arch": f(r"arch=(\S+)", mm_line, cast=str),
297
+ "ftype": f(r"ftype=(\d+)", mm_line, cast=int),
298
+ "tensors": f(r"tensors=(\d+)", mm_line, cast=int),
299
+ }
300
+
301
+ # ---------- measurements ----------
302
+ S["bench"], S["gates"] = [], []
303
+ for d in jl(f"{W}/results/nex_bench.jsonl"):
304
+ if "tg_median" in d:
305
+ row = {k: v for k, v in d.items() if k != "runs"}
306
+ pns = [r.get("prompt_n") for r in d.get("runs") or [] if r.get("prompt_n") is not None]
307
+ row["prompt_n_min"], row["prompt_n_max"] = (min(pns), max(pns)) if pns else (None, None)
308
+ S["bench"].append(row)
309
+ else:
310
+ S["gates"].append(d)
311
+
312
+ PE = re.compile(r"prompt eval time =\s*([\d.]+) ms /\s*(\d+) tokens")
313
+ for g_ in S["gates"]:
314
+ if g_.get("label") != "n-c3-q106" or not g_.get("rows"):
315
+ continue
316
+ ev = [(float(a), int(b)) for a, b in PE.findall(rd(f"{W}/logs/b_{g_['label']}.log"))]
317
+ per = 3 # warm-up, warm, cold — one server log line each, in order
318
+ for i, r_ in enumerate(g_["rows"]):
319
+ blk = ev[per * i: per * i + per]
320
+ if len(blk) == per and blk[1][1] == r_["warm_prompt_n"] and blk[2][1] == r_["cold_prompt_n"]:
321
+ r_["warm_prompt_ms"], r_["cold_prompt_ms"] = blk[1][0], blk[2][0]
322
+ else:
323
+ r_["warm_prompt_ms"] = r_["cold_prompt_ms"] = None
324
+
325
+ S["sizing"] = jl(f"{W}/results/nex_sizing.jsonl")
326
+ S["n_ubatch"] = UB
327
+
328
+
329
+ def _jobj(p):
330
+ raw = rd(p).strip()
331
+ try:
332
+ return json.loads(raw) if raw else None
333
+ except json.JSONDecodeError:
334
+ return None
335
+
336
+
337
+ # ---------- chat template fix (tool calls / reasoning) ----------
338
+ TPLF = "chat_template_enable_thinking.jinja"
339
+ S["aux"][TPLF] = exists_size(f"{W}/tpl/{TPLF}")
340
+ shim = {k: _jobj(f"{W}/results/nex_template_shim{k}.json") for k in ("", "_medium", "_c1", "_roff")}
341
+ _roff = shim["_roff"] or {}
342
+ S["template_fix"] = {
343
+ "file": TPLF,
344
+ "size_bytes": S["aux"][TPLF],
345
+ "sha256": _roff.get("sha256"),
346
+ "source_sha256": _roff.get("source_sha256"),
347
+ "shim": _roff.get("shim"),
348
+ "server_flags": ["--chat-template-file", TPLF, "--reasoning", "off"],
349
+ "probes_roff": _roff.get("probes"), # the recommended configuration
350
+ "probes_high_default_on": (shim[""] or {}).get("probes"), # same template, thinking on by default
351
+ "medium_mapping_label": (shim["_medium"] or {}).get("label"),
352
+ }
353
+ _diag = _jobj(f"{W}/results/nex_tools_diag.json") or {}
354
+ _v = _diag.get("variants") or {}
355
+ _on = [r.get("first") or {} for r in (_v.get("gate_on") or {}).values()]
356
+ _nested = [(_v.get("gate_off") or {}).get("nested-object", {}).get("first") or {}] + list(_v.get("nested_off_x3") or [])
357
+ _rp = _jobj(f"{W}/results/nex_reasoning_probe.json") or {}
358
+ S["tools_diag"] = {
359
+ # stock template, the gate's own sampling: replies with reasoning left in content, of all thinking-on replies
360
+ "stock_on_replies": len(_on) if _on else None,
361
+ "stock_on_leaks": sum(1 for r in _on if r.get("leaks_in_content")) if _on else None,
362
+ "stock_on_reasoning_extracted": sum(1 for r in _on if r.get("reasoning_len")) if _on else None,
363
+ # stock template, thinking off, the nested-object request repeated: HTTP 500 "does not match peg-native"
364
+ "nested_off_attempts": len(_nested) if _v else None,
365
+ "nested_off_http500": sum(1 for r in _nested if r.get("http_error") == 500) if _v else None,
366
+ "gate_http500_logged": "does not match the expected peg-native format" in rd(f"{W}/logs/b_n-tools-q106.log"),
367
+ # server-side switches that did NOT fix the stock template (reasoning still in content)
368
+ "flag_probes": {k: {"leaks": sum(1 for r in (c.get("results") or {}).values() if r.get("leaks")),
369
+ "n": len(c.get("results") or {})}
370
+ for k, c in (_rp.get("configs") or {}).items()},
371
+ }
372
+ _seats = {}
373
+ for r_ in jl(f"{W}/results/nex_seats.jsonl"):
374
+ _seats[r_.get("unit")] = r_ # last row per unit = the current unit files
375
+ S["seats"] = _seats
376
+ S["measured"] = (
377
+ f(r"\[(\d{4}-\d{2}-\d{2})T", rd(f"{W}/logs/N6_bench.log"), cast=str)
378
+ or f(r"\[(\d{4}-\d{2}-\d{2})T", b1, cast=str)
379
+ or f(r"\[(\d{4}-\d{2}-\d{2})T", rd(f"{W}/logs/N1_ppl_bf16.log"), cast=str)
380
+ )
381
+
382
+ _dates = sorted(set(re.findall(r"(\d{4}-\d{2}-\d{2})T\d", rd(f"{W}/logs/N6_bench.log") + rd(f"{W}/logs/N6t_tools_roff.log")
383
+ + rd(f"{W}/results/nex_seats.jsonl"))))
384
+ S["measured_range"] = [_dates[0], _dates[-1]] if len(_dates) > 1 else (_dates or None)
385
+
386
+
387
+ def _kv_keys(p):
388
+ try:
389
+ return set(gguf.GGUFReader(p).fields)
390
+ except (ValueError, OSError):
391
+ return None
392
+
393
+
394
+ for im, st in TWINS:
395
+ ka = _kv_keys(f"{W}/{TIERS[st][0]}/{TIERS[st][1]}") if FAST is False else None
396
+ kb = _kv_keys(f"{W}/{TIERS[im][0]}/{TIERS[im][1]}") if FAST is False else None
397
+ S["tiers"][im]["header_keys_only_in_imatrix"] = sorted(kb - ka) if ka is not None and kb is not None else None
398
+ S["tiers"][im]["header_keys_only_in_standard"] = sorted(ka - kb) if ka is not None and kb is not None else None
399
+
400
+ os.makedirs(os.path.dirname(OUT), exist_ok=True)
401
+ json.dump(S, open(OUT, "w"), indent=2)
402
+
403
+ print("bench rows", len(S["bench"]), "| gate rows", len(S["gates"]),
404
+ "| sizing rows", len(S["sizing"]), "| hub_check", S["hub_check"] is not None,
405
+ "| repeat", (S["repeat"] or {}).get("result"))
406
+ for tg_, v in S["tiers"].items():
407
+ print(tg_, {k: v[k] for k in ("size_bytes", "bpw", "readback", "tensors", "quality_measured", "kld_mean")})
408
+ print("binary", json.dumps(S["binary"], indent=1))
recipe/pipeline/nex_bench.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Nex-N2.5-mini speed + gates. Every 4-bit file x backend, no draft head (the checkpoint ships no MTP weights),
3
+ same house protocol as Agnes (nex_harness.py). Then gates on STRIX_LEAN: aligned prompt-cache identity, tool calls
4
+ (thinking on + off), vision with -fa on and off. Sequential GPU; results/nex_bench.jsonl."""
5
+ import fcntl, os, subprocess, time
6
+ W = "/mnt/models/nex-n2.5-mini"; N = "Nex-N2.5-mini"; A = "/mnt/models/agnes-3.0-flash"
7
+ J = f"{W}/results/nex_bench.jsonl"
8
+ OB = "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin"
9
+ T = {"q106": f"{W}/out/{N}-Q4_0_ROCMFP4_STRIX_LEAN.gguf", "q102": f"{W}/out/{N}-Q4_0_ROCMFP4_COHERENT.gguf",
10
+ "q103": f"{W}/out/{N}-Q4_0_ROCMFP4_FAST.gguf",
11
+ "q106i": f"{W}/out-imat/{N}-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf",
12
+ "q102i": f"{W}/out-imat/{N}-imatrix-Q4_0_ROCMFP4_COHERENT.gguf",
13
+ "q103i": f"{W}/out-imat/{N}-imatrix-Q4_0_ROCMFP4_FAST.gguf"}
14
+ ENV = dict(os.environ, AGNES_BIN=OB)
15
+
16
+
17
+ def log(m): print(f"[{time.strftime('%FT%TZ', time.gmtime())}] {m}", flush=True)
18
+
19
+
20
+ def run(argv, label):
21
+ log(label)
22
+ r = subprocess.run(argv, capture_output=True, text=True, env=ENV)
23
+ print(r.stdout.strip()[-800:], flush=True)
24
+ if r.returncode != 0:
25
+ print(" RC", r.returncode, r.stderr.strip()[-600:], flush=True)
26
+ return r.returncode
27
+
28
+
29
+ def harness(cmd, label, model, dev="ROCm0", reps=3, workload="code", extra=()):
30
+ return run(["python3", f"{W}/nex_harness.py", cmd, "--model", model, "--dev", dev, "--label", label,
31
+ "--reps", str(reps), "--jsonl", J, "--serverlog", f"{W}/logs/b_{label}.log", "--workload", workload,
32
+ *extra], f"{cmd} {label}")
33
+
34
+
35
+ # One quiet box: publish_v2.sh upload takes the same lock, so an HF upload never overlaps the speed runs.
36
+ QUIET = open("/mnt/models/.quiet-box.lock", "w")
37
+ log("waiting for the quiet-box lock (no HF upload during speed runs)")
38
+ fcntl.flock(QUIET, fcntl.LOCK_EX)
39
+ log("quiet-box lock held")
40
+ for tag in ("q106", "q102", "q103", "q106i", "q102i", "q103i"):
41
+ for dev, sh in (("ROCm0", "rocm"), ("Vulkan0", "vk")):
42
+ harness("bench", f"n-{tag}-{sh}", T[tag], dev=dev)
43
+ harness("bench", "n-q106-rocm-prose", T["q106"], workload="prose")
44
+ harness("bench", "n-q106-vk-prose", T["q106"], dev="Vulkan0", workload="prose")
45
+ run(["python3", f"{W}/nex_cachegate.py", "--model", T["q106"], "--label", "n-c3-q106", "--reps", "5",
46
+ "--jsonl", J, "--serverlog", f"{W}/logs/b_n-c3-q106.log"], "cachegate n-c3-q106")
47
+ harness("tools", "n-tools-q106", T["q106"])
48
+ for fa in ("on", "off"):
49
+ harness("vision", f"n-vision-q106-fa{fa}", T["q106"],
50
+ extra=("--fa", fa, "--mmproj", f"{W}/out/mmproj-{N}-BF16.gguf", "--image", f"{A}/calib/vision_probe.png",
51
+ "--question", "Describe the two shapes in this image and their colors.",
52
+ "--expect", "red,blue,circle,square"))
53
+ log("NEX_BENCH_DONE")
recipe/pipeline/nex_cachegate.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Chunk-ALIGNED warm/cold identity gate (Nex-N2.5-mini: unpatched server, no draft head).
3
+ Written for the Agnes MTP prompt-cache patch; here it checks the stock server's own checkpoint restore for this
4
+ hybrid (gated-delta + attention) model.
5
+
6
+ Why a third gate: llama-server splits every prompt so that context checkpoints land (4 + n_ubatch) and 4 tokens
7
+ before its end (tools/server/server-context.cpp `checkpoint_offsets`, upstream PR #20288). A warm request restores a
8
+ checkpoint whose position was fixed by the length of the request that CREATED it. When those lengths differ, the warm
9
+ tail is processed in different chunks than a cold run of the same prompt, so float rounding differs and a greedy
10
+ token can flip - with or without a draft head. cachegate2 mixed prompt lengths and hit exactly that.
11
+
12
+ Here every prompt in the run is padded to ONE token length L, so warm and cold see identical chunking. What is left
13
+ under test is whether the restored checkpoint (attention KV + recurrent state) is exact.
14
+ Per variant: warm-up A (cache on) -> B warm (cache on, must restore L-(4+ub)) -> B cold (cache off). PASS = every
15
+ warm B reused the cache at the aligned position AND is byte-identical to its cold twin, over all variants."""
16
+ import argparse, hashlib, json, os, sys
17
+ sys.path.insert(0, "/mnt/models/nex-n2.5-mini")
18
+ from nex_harness import Server, post, prompt_8k, THINK_OFF # noqa: E402 (reads AGNES_BIN at import)
19
+
20
+ UB = 1024 # agnes_harness.Server passes -ub 1024
21
+ WARM = "Summarise this file."
22
+ INSTR = ["Write a function that lists every tensor name in this file.",
23
+ "Write a function that counts the model classes registered in this file.",
24
+ "Write a function that finds the longest method in this file.",
25
+ "Write a function that returns every regular expression used in this file.",
26
+ "Write a function that maps each class in this file to its base classes.",
27
+ "Write a function that extracts all string constants from this file.",
28
+ "Write a function that reports which imports in this file are unused.",
29
+ "Write a function that lists every method that raises an exception in this file.",
30
+ "Write a function that counts the lines of code per class in this file.",
31
+ "Write a function that finds duplicate method names across classes in this file."]
32
+ KW = THINK_OFF
33
+
34
+
35
+ def plen(port, content):
36
+ p = post(port, "/apply-template", {"messages": [{"role": "user", "content": content}],
37
+ "chat_template_kwargs": KW})["prompt"]
38
+ return len(post(port, "/tokenize", {"content": p, "add_special": True, "parse_special": True})["tokens"])
39
+
40
+
41
+ def pad(port, ctx, instr, L):
42
+ s = instr
43
+ n = plen(port, ctx + "\n\n" + s)
44
+ for filler in (" ok", ".", " x"):
45
+ while n < L:
46
+ t = s + filler
47
+ m = plen(port, ctx + "\n\n" + t)
48
+ if m > L:
49
+ break
50
+ s, n = t, m
51
+ if n == L:
52
+ return s
53
+ raise SystemExit(f"could not pad {instr!r} to {L} (stuck at {n})")
54
+
55
+
56
+ def req(port, ctx, instr, n, cache):
57
+ body = {"messages": [{"role": "user", "content": ctx + "\n\n" + instr}], "max_tokens": n,
58
+ "temperature": 0, "top_k": 1, "ignore_eos": True, "cache_prompt": cache, "chat_template_kwargs": KW}
59
+ r = post(port, "/v1/chat/completions", body)
60
+ tm = r.get("timings", {})
61
+ return (r["choices"][0]["message"].get("content") or ""), tm.get("prompt_n"), tm.get("cache_n"), \
62
+ tm.get("draft_n"), tm.get("draft_n_accepted")
63
+
64
+
65
+ def first_diff(x, y):
66
+ if x == y:
67
+ return None
68
+ return next((i for i, (p, q) in enumerate(zip(x, y)) if p != q), min(len(x), len(y)))
69
+
70
+
71
+ def main(a):
72
+ s = Server(a, a.port)
73
+ rows = []
74
+ try:
75
+ ctx, _ = prompt_8k("code")
76
+ instr = INSTR[:a.reps]
77
+ warm = [f"{WARM} (warm-up {i})" for i in range(len(instr))]
78
+ # L over the FULL prompt set, whatever --reps is: runs with different --reps then share byte-identical
79
+ # prompts, so their outputs can be compared across configs (e.g. MTP vs no draft head).
80
+ allp = INSTR + [f"{WARM} (warm-up {i})" for i in range(len(INSTR))]
81
+ L = max(plen(a.port, ctx + "\n\n" + t) for t in allp) + 1
82
+ instr = [pad(a.port, ctx, t, L) for t in instr]
83
+ warm = [pad(a.port, ctx, t, L) for t in warm]
84
+ expect_cache = L - (4 + UB)
85
+ for i, (wa, vb) in enumerate(zip(warm, instr)):
86
+ req(a.port, ctx, wa, 16, True)
87
+ tw, pw, cw, dw, aw = req(a.port, ctx, vb, 192, True)
88
+ tc, pc, cc, dc, ac = req(a.port, ctx, vb, 192, False)
89
+ rows.append({"variant": i, "L": L, "warm_prompt_n": pw, "warm_cache_n": cw, "cold_prompt_n": pc,
90
+ "cold_cache_n": cc, "aligned": (cw == expect_cache and pc == L),
91
+ "warm_draft": [aw, dw], "cold_draft": [ac, dc], "identical": tw == tc,
92
+ "first_diff_char": first_diff(tw, tc),
93
+ "warm_sha": hashlib.sha256(tw.encode()).hexdigest()[:12],
94
+ "cold_sha": hashlib.sha256(tc.encode()).hexdigest()[:12], "instr": vb, "warm_instr": wa,
95
+ "warm_text": tw, "cold_text": tc})
96
+ print(" ", json.dumps({k: v for k, v in rows[-1].items() if not k.endswith("_text")}), flush=True)
97
+ finally:
98
+ s.stop()
99
+ reused = all((r["warm_cache_n"] or 0) > 0 for r in rows)
100
+ aligned = all(r["aligned"] for r in rows)
101
+ ident = all(r["identical"] for r in rows)
102
+ res = {"label": a.label, "gate": "cachegate3-aligned", "n": len(rows), "L": rows[0]["L"] if rows else None,
103
+ "expect_cache_n": expect_cache if rows else None, "all_reused": reused, "all_aligned": aligned,
104
+ "identical": sum(r["identical"] for r in rows), "rows": rows,
105
+ "result": "PASS" if (rows and reused and aligned and ident) else "FAIL"}
106
+ print(json.dumps({k: v for k, v in res.items() if k != "rows"}), flush=True)
107
+ with open(a.jsonl, "a") as f:
108
+ f.write(json.dumps(res) + "\n")
109
+ sys.exit(0 if res["result"] == "PASS" else 1)
110
+
111
+
112
+ if __name__ == "__main__":
113
+ ap = argparse.ArgumentParser()
114
+ ap.add_argument("--model", required=True); ap.add_argument("--draft")
115
+ ap.add_argument("--nmax", type=int, default=4); ap.add_argument("--pmin", type=float, default=0.0)
116
+ ap.add_argument("--dev", default="ROCm0"); ap.add_argument("--ctx", type=int, default=65536)
117
+ ap.add_argument("--port", type=int, default=18600); ap.add_argument("--reps", type=int, default=10)
118
+ ap.add_argument("--label", required=True); ap.add_argument("--jsonl", required=True)
119
+ ap.add_argument("--serverlog", required=True)
120
+ ap.add_argument("--mtp-infile", action="store_true"); ap.add_argument("--strict", action="store_true")
121
+ main(ap.parse_args())
recipe/pipeline/nex_cards.sh ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # nex_cards.sh cards|upload|verify — Nex-N2.5-mini cards on real data, then the two SEPARATE repos.
3
+ # cards : summary (fast, to satisfy stage's recipe check) -> stage std+imat (hashes) -> summary with staged hashes
4
+ # -> refresh the staged summary copy -> judge -> render (prints pending judgments)
5
+ # upload: behind the quiet-box lock; each repo through upload_watchdog.sh (40G cap, niced, stall kill + retry). verify: size + sha256 + recipe + separation.
6
+ set -euo pipefail
7
+ W=/mnt/models/nex-n2.5-mini; cd $W
8
+ export HF_XET_CACHE=/mnt/models/.hf-xet-cache TMPDIR=/mnt/models/.tmp HF_HUB_DISABLE_TELEMETRY=1 PYTHONUNBUFFERED=1
9
+ mkdir -p "$HF_XET_CACHE" "$TMPDIR"
10
+ log(){ echo "[$(date -u +%FT%TZ)] $*"; }
11
+ case "${1:-}" in
12
+ cards)
13
+ grep -q NEX_PHASE2_DONE logs/phase2.log || { log "phase 2 not done -> refuse"; exit 3; }
14
+ AGG_FAST=1 nice -n 10 python3 nex_aggregate.py > logs/aggregate_fast.log 2>&1
15
+ for k in std imat; do log "stage $k"; nice -n 10 python3 nex_publish.py stage $k; done
16
+ nice -n 10 python3 nex_aggregate.py > logs/aggregate.log 2>&1; tail -12 logs/aggregate.log
17
+ for k in std imat; do cp results/summary.json hf-upload/$k/recipe/results_summary.json; done
18
+ python3 - <<'PY'
19
+ import json
20
+ d = {}
21
+ for k in ("std", "imat"):
22
+ d.update(json.load(open(f"hf-upload/staged_sizes_{k}.json")))
23
+ json.dump(d, open("hf-upload/staged_sizes.json", "w"), indent=1)
24
+ print("staged sizes:", len(d))
25
+ PY
26
+ python3 nex_judge.py results/summary.json results/judgments.json > logs/judge.log 2>&1; head -1 logs/judge.log
27
+ rm -rf cards
28
+ python3 nex_render.py results/summary.json cards results/judgments.json \
29
+ hf-upload/std/SHA256SUMS hf-upload/imat/SHA256SUMS hf-upload/staged_sizes.json
30
+ ls -la cards; log "NEX_CARDS_DONE" ;;
31
+ upload)
32
+ exec 9>/mnt/models/.quiet-box.lock; log "waiting for the quiet-box lock"; flock 9; log "quiet-box lock held"
33
+ for k in std imat; do
34
+ bash upload_watchdog.sh nex-upload-$k $W python3 nex_publish.py upload $k || { log "upload $k FAILED"; exit 1; }
35
+ done
36
+ log "NEX_UPLOAD_ALL_DONE" ;;
37
+ verify)
38
+ rc=0; for k in std imat; do python3 nex_publish.py verify $k || rc=1; done
39
+ log "NEX_VERIFY rc=$rc"; exit $rc ;;
40
+ *) echo "usage: $0 cards|upload|verify"; exit 2 ;;
41
+ esac
recipe/pipeline/nex_download.sh ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Nex-N2.5-mini: pinned download + byte/sha256 gate. Runs inside a capped scope (2 cores, 16 GiB, idle I/O) so the
3
+ # Agnes measurements still running on this box are not disturbed. HF_HOME stays default (token lives there).
4
+ set -uo pipefail
5
+ R=nex-agi/Nex-N2.5-mini; REV=87420286149d9cce9bd46cd335ef9bda33c37c1b
6
+ W=/mnt/models/nex-n2.5-mini; mkdir -p $W/hf $W/logs
7
+ # 8 parallel files x default range concurrency grew hf to 5.6 GiB RSS and the 6 GiB cap OOM-killed it (20:56Z).
8
+ export HF_XET_CACHE=/mnt/models/.hf-xet-cache TMPDIR=/mnt/models/.tmp HF_HUB_DISABLE_TELEMETRY=1 HF_XET_NUM_CONCURRENT_RANGE_GETS=8
9
+ mkdir -p "$HF_XET_CACHE" "$TMPDIR"
10
+ log(){ echo "[$(date -u +%FT%TZ)] $*"; }
11
+ t0=$(date +%s)
12
+ log "download $R @ $REV -> $W/hf"
13
+ hf download "$R" --revision "$REV" --local-dir "$W/hf" --max-workers 4
14
+ rc=$?
15
+ log "DONE_RC=$rc elapsed=$(( $(date +%s) - t0 ))s on disk: $(du -sh --apparent-size $W/hf | cut -f1)"
16
+ if [ $rc -eq 0 ]; then
17
+ log "verify (size + sha256 vs the tree API lfs.oid at the pinned revision)"
18
+ python3 $W/verify_download.py "$R" "$REV" "$W/hf" > $W/logs/D2_verify_download.log 2>&1; vrc=$?
19
+ tail -3 $W/logs/D2_verify_download.log
20
+ log "VERIFY_RC=$vrc"
21
+ echo "$vrc" > $W/logs/DOWNLOAD_VERIFY_RC
22
+ fi
23
+ echo "$rc" > $W/logs/DOWNLOAD_RC
24
+ log "NEX_DOWNLOAD_END"
recipe/pipeline/nex_harness.py ADDED
@@ -0,0 +1,326 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Measurement harness for Nex-N2.5-mini on MAX-1 (stdlib only) - derived from the Agnes harness.
3
+ Nex's template has no thinking on/off flag: thinking is `reasoning_effort` = none (off) | high (on) | anything else
4
+ (adaptive). Tool calls use the upstream sampling (temp 0.7, top_p 0.95, top_k 40).
5
+ House protocol (Qwen3.8-27B card): ctx 65536, batch 1, greedy (temp 0, top_k 1), ignore_eos -> exactly
6
+ 256 tokens, unique nonce + cache_prompt:false (cached tokens asserted 0), median of reps after 1 warm-up.
7
+ Subcommands: bench | cachegate | tools | vision (see argparse)"""
8
+ import argparse, base64, json, os, signal, statistics, subprocess, sys, time, urllib.request, uuid
9
+
10
+ W = "/mnt/models/nex-n2.5-mini"
11
+ CAL = "/mnt/models/agnes-3.0-flash/calib" # shared calibration / prose corpora
12
+ THINK_OFF = {"reasoning_effort": "none"}
13
+ THINK_ON = {"reasoning_effort": "high"}
14
+ BIN = os.environ.get("AGNES_BIN", "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin")
15
+ ENV = dict(os.environ, LD_LIBRARY_PATH=f"{BIN}:/opt/rocm-7.2.4/lib", HSA_OVERRIDE_GFX_VERSION="11.5.1",
16
+ GGML_HIP_ENABLE_UNIFIED_MEMORY="1")
17
+
18
+ def post(port, path, body, timeout=1800):
19
+ req = urllib.request.Request(f"http://127.0.0.1:{port}{path}", data=json.dumps(body).encode(),
20
+ headers={"Content-Type": "application/json"})
21
+ return json.load(urllib.request.urlopen(req, timeout=timeout))
22
+
23
+ class Server:
24
+ def __init__(self, a, port, mmproj=None, fa="on"):
25
+ self.port = port
26
+ cmd = [f"{BIN}/llama-server", "-m", a.model, "-dev", a.dev, "-ngl", "999", "-fa", fa, "-dio",
27
+ "--jinja", "-fit", "off", "--parallel", "1", "-c", str(a.ctx), "-b", "2048", "-ub", "1024",
28
+ "--host", "127.0.0.1", "--port", str(port), "--no-webui"]
29
+ if a.draft or a.mtp_infile:
30
+ cmd += ["--spec-type", "draft-mtp"]
31
+ if a.draft:
32
+ cmd += ["--model-draft", a.draft, "--spec-draft-ngl", "99", "--spec-draft-device", a.dev]
33
+ cmd += ["--spec-draft-n-max", str(a.nmax), "--spec-draft-n-min", "0", "--spec-draft-p-min", str(a.pmin)]
34
+ if a.strict:
35
+ cmd += ["--spec-mtp-strict-qwen"]
36
+ if mmproj:
37
+ cmd += ["--mmproj", mmproj]
38
+ self.cmd = cmd
39
+ self.logf = open(a.serverlog, "w")
40
+ self.t0 = time.time()
41
+ self.p = subprocess.Popen(cmd, env=ENV, stdout=self.logf, stderr=subprocess.STDOUT, start_new_session=True)
42
+ while True:
43
+ if self.p.poll() is not None:
44
+ raise SystemExit(f"SERVER DIED rc={self.p.returncode} see {a.serverlog}")
45
+ try:
46
+ if json.load(urllib.request.urlopen(f"http://127.0.0.1:{port}/health", timeout=3)).get("status") == "ok":
47
+ break
48
+ except Exception:
49
+ pass
50
+ if time.time() - self.t0 > 900:
51
+ self.stop(); raise SystemExit("SERVER LOAD TIMEOUT")
52
+ time.sleep(2)
53
+ self.load_s = time.time() - self.t0
54
+ def stop(self):
55
+ try: os.killpg(self.p.pid, signal.SIGTERM); self.p.wait(60)
56
+ except Exception:
57
+ try: os.killpg(self.p.pid, signal.SIGKILL)
58
+ except Exception: pass
59
+ self.logf.close()
60
+
61
+ def prompt_8k(kind):
62
+ if kind == "code":
63
+ src = open("/opt/llama-rocm/rocmfpx-724/convert_hf_to_gguf.py").read()[:30000]
64
+ return src, "Above is part of a model converter. Write a new, complete Python function that validates a GGUF tensor-name map against a list of HF tensor names and reports unmapped names. Code only."
65
+ txt = open(f"{CAL}/wikitext-2-raw/wiki.train.raw").read()[:34000]
66
+ return txt, "Above are encyclopedia excerpts. Write a long, detailed new encyclopedia article in the same style about the history of lighthouses."
67
+
68
+ def one_request(port, ctx_text, instr, n=256, cache=False, nonce=True):
69
+ tag = f"[req {uuid.uuid4()}]\n" if nonce else ""
70
+ body = {"messages": [{"role": "user", "content": tag + ctx_text + "\n\n" + instr}],
71
+ "max_tokens": n, "temperature": 0, "top_k": 1, "ignore_eos": True, "cache_prompt": cache,
72
+ "chat_template_kwargs": THINK_OFF}
73
+ t = time.time(); r = post(port, "/v1/chat/completions", body); el = time.time() - t
74
+ tm = r.get("timings", {})
75
+ return {"pred_n": tm.get("predicted_n"), "tg": tm.get("predicted_per_second"),
76
+ "pp": tm.get("prompt_per_second"), "prompt_n": tm.get("prompt_n"), "cache_n": tm.get("cache_n"),
77
+ "draft_n": tm.get("draft_n"), "draft_acc": tm.get("draft_n_accepted"), "wall": el,
78
+ "usage": r.get("usage", {})}
79
+
80
+ def cmd_bench(a):
81
+ s = Server(a, a.port)
82
+ out = {"label": a.label, "model": os.path.basename(a.model),
83
+ "draft": os.path.basename(a.draft) if a.draft else ("in-file" if a.mtp_infile else None),
84
+ "nmax": a.nmax if (a.draft or a.mtp_infile) else None, "strict": bool(a.strict), "bin": BIN, "dev": a.dev, "ctx": a.ctx, "workload": a.workload,
85
+ "load_s": round(s.load_s, 1), "cmd": " ".join(s.cmd), "runs": []}
86
+ try:
87
+ ctx_text, instr = prompt_8k(a.workload)
88
+ one_request(a.port, ctx_text, instr) # warm-up, discarded
89
+ for _ in range(a.reps):
90
+ r = one_request(a.port, ctx_text, instr)
91
+ cached = (r["usage"].get("prompt_tokens_details") or {}).get("cached_tokens", 0) or 0
92
+ if r["pred_n"] != 256: raise SystemExit(f"GATE FAIL: predicted_n={r['pred_n']} != 256")
93
+ if (r["cache_n"] or 0) != 0 or cached != 0: raise SystemExit(f"GATE FAIL: cache hit cache_n={r['cache_n']} cached={cached}")
94
+ out["runs"].append(r)
95
+ finally:
96
+ s.stop()
97
+ tg = [r["tg"] for r in out["runs"]]; pp = [r["pp"] for r in out["runs"]]
98
+ dn = sum(r["draft_n"] or 0 for r in out["runs"]); da = sum(r["draft_acc"] or 0 for r in out["runs"])
99
+ out.update(tg_median=round(statistics.median(tg), 2), tg_min=round(min(tg), 2), tg_max=round(max(tg), 2),
100
+ pp_median=round(statistics.median(pp), 1), prompt_n=out["runs"][0]["prompt_n"],
101
+ accept=(round(da / dn, 3) if dn else None))
102
+ print(json.dumps({k: v for k, v in out.items() if k != "runs"}))
103
+ with open(a.jsonl, "a") as f: f.write(json.dumps(out) + "\n")
104
+
105
+ def cmd_identity(a):
106
+ """Fixed prompt, no nonce, no cache, greedy: return the exact generated text for cross-config diffing."""
107
+ s = Server(a, a.port)
108
+ texts = []
109
+ try:
110
+ ctx_text, instr = prompt_8k(a.workload)
111
+ for _ in range(a.reps):
112
+ body = {"messages": [{"role": "user", "content": ctx_text + "\n\n" + instr}], "max_tokens": 256,
113
+ "temperature": 0, "top_k": 1, "ignore_eos": True, "cache_prompt": False,
114
+ "chat_template_kwargs": THINK_OFF}
115
+ r = post(a.port, "/v1/chat/completions", body)
116
+ texts.append(r["choices"][0]["message"].get("content") or "")
117
+ finally:
118
+ s.stop()
119
+ import hashlib
120
+ res = {"label": a.label, "reps": a.reps, "sha256": [hashlib.sha256(t.encode()).hexdigest()[:16] for t in texts],
121
+ "self_consistent": len(set(texts)) == 1, "text": texts[0]}
122
+ print(json.dumps({k: v for k, v in res.items() if k != "text"}))
123
+ with open(a.jsonl, "a") as f: f.write(json.dumps(res) + "\n")
124
+
125
+ def cmd_cachegate2(a):
126
+ """Partial-prefix reuse WITH output identity: warm on A, run B warm (partial reuse), run B cold, diff outputs."""
127
+ import hashlib
128
+ s = Server(a, a.port)
129
+ rows = []
130
+ try:
131
+ ctx_text, _ = prompt_8k("code")
132
+ variants = ["Write a function that lists every tensor name in this file.",
133
+ "Write a function that counts the model classes registered in this file.",
134
+ "Write a function that finds the longest method in this file."]
135
+ for i, vb in enumerate(variants[:a.reps]):
136
+ def req(instr, n, cache):
137
+ body = {"messages": [{"role": "user", "content": ctx_text + "\n\n" + instr}], "max_tokens": n,
138
+ "temperature": 0, "top_k": 1, "ignore_eos": True, "cache_prompt": cache,
139
+ "chat_template_kwargs": THINK_OFF}
140
+ r = post(a.port, "/v1/chat/completions", body)
141
+ tm = r.get("timings", {})
142
+ return (r["choices"][0]["message"].get("content") or ""), tm.get("prompt_n"), tm.get("cache_n")
143
+ req(f"Summarise this file. (warm-up {i})", 16, True)
144
+ tw, pw, cw = req(vb, 192, True)
145
+ tc, pc, cc = req(vb, 192, False)
146
+ rows.append({"variant": i, "warm_prompt_n": pw, "warm_cache_n": cw, "cold_prompt_n": pc, "cold_cache_n": cc,
147
+ "identical": tw == tc, "warm_sha": hashlib.sha256(tw.encode()).hexdigest()[:12],
148
+ "cold_sha": hashlib.sha256(tc.encode()).hexdigest()[:12]})
149
+ print(" ", json.dumps(rows[-1]), flush=True)
150
+ finally:
151
+ s.stop()
152
+ reused = all((r["warm_cache_n"] or 0) > 0 for r in rows)
153
+ ident = all(r["identical"] for r in rows)
154
+ res = {"label": a.label, "rows": rows, "all_reused": reused, "all_identical": ident,
155
+ "result": "PASS" if (reused and ident) else "FAIL"}
156
+ print(json.dumps({k: v for k, v in res.items() if k != "rows"}))
157
+ with open(a.jsonl, "a") as f: f.write(json.dumps(res) + "\n")
158
+ sys.exit(0 if res["result"] == "PASS" else 1)
159
+
160
+ def cmd_cachegate(a):
161
+ """Repeat-prompt test WITH the draft head loaded: turn 2 must reuse turn 1's prefix."""
162
+ s = Server(a, a.port)
163
+ try:
164
+ ctx_text, instr = prompt_8k("code")
165
+ r1 = one_request(a.port, ctx_text, instr, n=32, cache=True, nonce=False)
166
+ r2 = one_request(a.port, ctx_text, instr + " Also add type hints.", n=32, cache=True, nonce=False)
167
+ finally:
168
+ s.stop()
169
+ res = {"label": a.label, "turn1_prompt_n": r1["prompt_n"], "turn2_prompt_n": r2["prompt_n"],
170
+ "turn2_cache_n": r2["cache_n"]}
171
+ # hybrid recurrent models resume only from context checkpoints (~1024-token spacing), so the test is
172
+ # "any prefix reuse" -- report the fraction rather than demand near-total reuse.
173
+ ok = isinstance(r2["cache_n"], int) and r2["cache_n"] > 0
174
+ res["reuse_fraction"] = round(r2["cache_n"] / r1["prompt_n"], 3) if ok and r1["prompt_n"] else 0.0
175
+ res["result"] = "PASS" if ok else "FAIL"
176
+ print(json.dumps(res))
177
+ with open(a.jsonl, "a") as f: f.write(json.dumps(res) + "\n")
178
+ sys.exit(0 if ok else 1)
179
+
180
+ TOOLS = [
181
+ {"type": "function", "function": {"name": "get_weather", "description": "Current weather for a city",
182
+ "parameters": {"type": "object", "properties": {"city": {"type": "string"},
183
+ "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city", "unit"]}}},
184
+ {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event",
185
+ "parameters": {"type": "object", "properties": {"title": {"type": "string"},
186
+ "when": {"type": "object", "properties": {"date": {"type": "string"}, "time": {"type": "string"}},
187
+ "required": ["date", "time"]},
188
+ "attendees": {"type": "array", "items": {"type": "string"}}}, "required": ["title", "when", "attendees"]}}},
189
+ ]
190
+ LEAK = ("<tool_call>", "<function=", "<parameter=", "<think>", "</think>")
191
+
192
+ def chat(port, msgs, think, stream=False, tools=TOOLS):
193
+ body = {"messages": msgs, "tools": tools, "tool_choice": "auto", "temperature": 0.7, "top_p": 0.95,
194
+ "top_k": 40, "max_tokens": 8192,
195
+ "chat_template_kwargs": (THINK_ON if think else THINK_OFF)}
196
+ if not stream:
197
+ return post(port, "/v1/chat/completions", body)["choices"][0]["message"]
198
+ body["stream"] = True
199
+ req = urllib.request.Request(f"http://127.0.0.1:{port}/v1/chat/completions", data=json.dumps(body).encode(),
200
+ headers={"Content-Type": "application/json"})
201
+ calls, content = {}, ""
202
+ for line in urllib.request.urlopen(req, timeout=1800):
203
+ line = line.decode().strip()
204
+ if not line.startswith("data:") or line.endswith("[DONE]"): continue
205
+ d = json.loads(line[5:])["choices"][0]["delta"]
206
+ content += d.get("content") or ""
207
+ for tc in d.get("tool_calls") or []:
208
+ c = calls.setdefault(tc["index"], {"name": "", "arguments": ""})
209
+ c["name"] += (tc.get("function") or {}).get("name") or ""
210
+ c["arguments"] += (tc.get("function") or {}).get("arguments") or ""
211
+ return {"content": content, "tool_calls": [{"function": v} for _, v in sorted(calls.items())]}
212
+
213
+ def args_of(m, i=0):
214
+ return json.loads(m["tool_calls"][i]["function"]["arguments"])
215
+
216
+ def cmd_tools(a):
217
+ s = Server(a, a.port)
218
+ results = {}
219
+ try:
220
+ for think in (True, False):
221
+ def check(name, fn):
222
+ try: ok, why = fn()
223
+ except Exception as e: ok, why = False, f"exception {e!r}"[:160]
224
+ results[f"{name}|think={think}"] = (ok, why)
225
+ print(f" {'PASS' if ok else 'FAIL'} think={think!s:5} {name}: {why}", flush=True)
226
+ def clean(m): return not any(x in (m.get("content") or "") for x in LEAK)
227
+ def t1():
228
+ m = chat(a.port, [{"role": "user", "content": "What's the weather in Paris in celsius?"}], think)
229
+ ag = args_of(m); return (m["tool_calls"][0]["function"]["name"] == "get_weather" and ag.get("city", "").lower().startswith("paris")
230
+ and ag.get("unit") == "celsius" and clean(m)), f"args={ag}"
231
+ def t2():
232
+ m = chat(a.port, [{"role": "user", "content": "Book 'Design review' on 2026-10-02 at 14:00 with ana@x.io and bo@x.io."}], think)
233
+ ag = args_of(m); return (isinstance(ag.get("when"), dict) and ag["when"].get("date") == "2026-10-02"
234
+ and sorted(ag.get("attendees", [])) == ["ana@x.io", "bo@x.io"] and clean(m)), f"args={ag}"
235
+ def t3():
236
+ m = chat(a.port, [{"role": "user", "content": "Weather in Denver, and give it to me in fahrenheit."}], think)
237
+ return args_of(m).get("unit") == "fahrenheit" and clean(m), f"unit={args_of(m).get('unit')}"
238
+ def t4():
239
+ m = chat(a.port, [{"role": "user", "content": "What is 17 times 23? Answer directly."}], think)
240
+ c = m.get("content") or ""
241
+ return (not m.get("tool_calls")) and "391" in c and clean(m), f"content={c[:60]!r}"
242
+ def t5():
243
+ msgs = [{"role": "user", "content": "What's the weather in Tokyo in celsius?"}]
244
+ m = chat(a.port, msgs, think)
245
+ tc = m["tool_calls"][0]
246
+ msgs += [{"role": "assistant", "content": m.get("content") or "", "tool_calls": [
247
+ {"id": "call_1", "type": "function", "function": tc["function"]}]},
248
+ {"role": "tool", "tool_call_id": "call_1", "content": json.dumps({"temp_c": 21, "sky": "clear"})}]
249
+ m2 = chat(a.port, msgs, think)
250
+ c = m2.get("content") or ""
251
+ return ("21" in c and not m2.get("tool_calls") and clean(m2)), f"final={c[:70]!r}"
252
+ def t6():
253
+ m = chat(a.port, [{"role": "user", "content": "What's the weather in Rome in celsius?"}], think, stream=True)
254
+ ag = args_of(m); return (m["tool_calls"][0]["function"]["name"] == "get_weather"
255
+ and ag.get("city", "").lower().startswith("rome") and clean(m)), f"stream args={ag}"
256
+ def t7():
257
+ m = chat(a.port, [{"role": "user", "content": "Get the weather in Oslo AND in Lima, both in celsius. Call the tool for each city."}], think)
258
+ cities = sorted(args_of(m, i).get("city", "").lower() for i in range(len(m.get("tool_calls") or [])))
259
+ return (len(cities) == 2 and cities[0].startswith("lima") and cities[1].startswith("oslo") and clean(m)), f"calls={cities}"
260
+ for nm, fn in (("multi-arg", t1), ("nested-object", t2), ("enum", t3), ("correct-decline", t4),
261
+ ("multi-turn", t5), ("streaming", t6), ("parallel", t7)):
262
+ check(nm, fn)
263
+ finally:
264
+ s.stop()
265
+ n_ok = sum(v[0] for v in results.values())
266
+ summary = {"label": a.label, "passed": n_ok, "total": len(results),
267
+ "detail": {k: v[0] for k, v in results.items()}}
268
+ print(json.dumps(summary))
269
+ with open(a.jsonl, "a") as f: f.write(json.dumps(summary) + "\n")
270
+
271
+ def cmd_vision(a):
272
+ """Image gate. A server that fails to load or dies on the image is a RESULT (FAIL row), not a harness crash."""
273
+ fa = a.fa or "off"
274
+ res = {"label": a.label, "fa": fa, "mtp": bool(a.draft or a.mtp_infile), "expected": a.expect,
275
+ "answer": "", "hits": [], "error": None, "server_died": False, "server_log_errors": []}
276
+ c = ""
277
+ try:
278
+ s = Server(a, a.port, mmproj=a.mmproj, fa=fa)
279
+ except SystemExit as e:
280
+ res.update(error=f"server did not start: {e}", server_died=True); s = None
281
+ if s is not None:
282
+ try:
283
+ img = base64.b64encode(open(a.image, "rb").read()).decode()
284
+ body = {"messages": [{"role": "user", "content": [
285
+ {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{img}"}},
286
+ {"type": "text", "text": a.question}]}],
287
+ "temperature": 0, "top_k": 1, "max_tokens": 300, "chat_template_kwargs": THINK_OFF}
288
+ try:
289
+ r = post(a.port, "/v1/chat/completions", body, timeout=900)
290
+ c = r["choices"][0]["message"].get("content") or ""
291
+ except Exception as e:
292
+ res["error"] = f"{type(e).__name__}: {e}"[:300]
293
+ time.sleep(1)
294
+ res["server_died"] = s.p.poll() is not None
295
+ finally:
296
+ s.stop()
297
+ try:
298
+ res["server_log_errors"] = [l.strip()[-200:] for l in open(a.serverlog, errors="replace")
299
+ if any(k in l for k in ("GGML_ABORT", "abort", "failed to process", " E "))][-5:]
300
+ except OSError:
301
+ pass
302
+ res["answer"] = c[:300]
303
+ res["hits"] = [w for w in a.expect.split(",") if w.lower() in c.lower()]
304
+ ok = res["error"] is None and not res["server_died"] and len(res["hits"]) == len(a.expect.split(","))
305
+ res["result"] = "PASS" if ok else "FAIL"
306
+ print(json.dumps(res))
307
+ with open(a.jsonl, "a") as f: f.write(json.dumps(res) + "\n")
308
+ sys.exit(0 if ok else 1)
309
+
310
+ if __name__ == "__main__":
311
+ ap = argparse.ArgumentParser()
312
+ ap.add_argument("cmd", choices=["bench", "cachegate", "cachegate2", "tools", "vision", "identity"])
313
+ ap.add_argument("--model", required=True); ap.add_argument("--draft")
314
+ ap.add_argument("--nmax", type=int, default=4); ap.add_argument("--pmin", type=float, default=0.0)
315
+ ap.add_argument("--dev", default="ROCm0"); ap.add_argument("--ctx", type=int, default=65536)
316
+ ap.add_argument("--port", type=int, default=18600); ap.add_argument("--reps", type=int, default=3)
317
+ ap.add_argument("--workload", default="code", choices=["code", "prose"])
318
+ ap.add_argument("--label", default=""); ap.add_argument("--jsonl", default=f"{W}/results/phase_b.jsonl")
319
+ ap.add_argument("--serverlog", default=f"{W}/logs/server_last.log")
320
+ ap.add_argument("--mmproj"); ap.add_argument("--image"); ap.add_argument("--question"); ap.add_argument("--expect")
321
+ ap.add_argument("--mtp-infile", action="store_true"); ap.add_argument("--strict", action="store_true")
322
+ ap.add_argument("--fa", choices=["on", "off", "auto"], help="vision only; default off")
323
+ a = ap.parse_args()
324
+ os.makedirs(os.path.dirname(a.jsonl), exist_ok=True)
325
+ {"bench": cmd_bench, "cachegate": cmd_cachegate, "tools": cmd_tools, "vision": cmd_vision,
326
+ "identity": cmd_identity, "cachegate2": cmd_cachegate2}[a.cmd](a)
recipe/pipeline/nex_judge.py ADDED
@@ -0,0 +1,584 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Write judgments.json for the Nex-N2.5-mini cards. Sentence structure is authored; every number is
3
+ computed from summary.json. A judgment whose inputs are missing is NOT emitted (the renderer then
4
+ shows JUDGMENT PENDING). usage: nex_judge.py <summary.json> <judgments.json>"""
5
+ import json, math, statistics, sys
6
+
7
+ S = json.load(open(sys.argv[1])); T = S.get("tiers") or {}; J = {}
8
+ MiB = 1024 ** 2
9
+ UB = S.get("n_ubatch") if S.get("n_ubatch") is not None else 1024
10
+ SPEED_EQ = 3.0 # % — tiers closer than this are called speed-equivalent
11
+ TWINS = (("q106i", "q106"), ("q102i", "q102"), ("q103i", "q103"))
12
+ STD_TAGS = ("q106", "q102", "q103")
13
+ IMAT_TAGS = ("q106i", "q102i", "q103i")
14
+ NAMES = {"q106": "STRIX_LEAN", "q102": "COHERENT", "q103": "FAST",
15
+ "q106i": "STRIX_LEAN", "q102i": "COHERENT", "q103i": "FAST"}
16
+
17
+
18
+ def pct(a, b):
19
+ return (b - a) / a * 100
20
+
21
+
22
+ def sig(a, ea, b, eb):
23
+ return abs(b - a) / math.sqrt(ea * ea + eb * eb)
24
+
25
+
26
+ def have(*v):
27
+ return all(x is not None for x in v)
28
+
29
+
30
+ def bench(label): # last row wins: a re-run supersedes an earlier row with the same label
31
+ return next((x for x in reversed(S.get("bench") or []) if x["label"] == label), None)
32
+
33
+
34
+ def gate(label):
35
+ return next((x for x in reversed(S.get("gates") or []) if x.get("label") == label), None)
36
+
37
+
38
+ def bn(tag, dev):
39
+ return bench(f"n-{tag}-{dev}")
40
+
41
+
42
+ def twin_spread(key):
43
+ """Largest |gap| between an imatrix file and its standard twin: a measured noise floor."""
44
+ if not all(T.get(i, {}).get("same_tensor_types_as_standard") is True for i, _ in TWINS):
45
+ return None
46
+ vals = []
47
+ for ti, ts in TWINS:
48
+ for dev in ("rocm", "vk"):
49
+ x, y = bn(ti, dev), bn(ts, dev)
50
+ if not (x and y and x.get(key) is not None and y.get(key) is not None):
51
+ return None
52
+ vals.append(abs(pct(y[key], x[key])))
53
+ return max(vals) if vals else None
54
+
55
+
56
+ TG_NOISE, PP_NOISE = twin_spread("tg_median"), twin_spread("pp_median")
57
+ DEC_EQ = max(SPEED_EQ, TG_NOISE) if TG_NOISE is not None else None
58
+ PRE_EQ = max(SPEED_EQ, PP_NOISE) if PP_NOISE is not None else None
59
+
60
+
61
+ def rel(g, what, eq):
62
+ if abs(g) < eq:
63
+ return f"{what} within {abs(g):.1f} % of"
64
+ return f"{what} {abs(g):.1f} % {'faster' if g > 0 else 'slower'} than"
65
+
66
+
67
+ def cmp_line(a_tag, b_tag, a_nm, b_nm):
68
+ """-> (text, a_advantage, a_disadvantage) or (None, None, None)."""
69
+ ra, rb, va, vb = bn(a_tag, "rocm"), bn(b_tag, "rocm"), bn(a_tag, "vk"), bn(b_tag, "vk")
70
+ if not all((ra, rb, va, vb)) or DEC_EQ is None or PRE_EQ is None:
71
+ return None, None, None
72
+ if not have(ra.get("tg_median"), rb.get("tg_median"), va.get("tg_median"), vb.get("tg_median"),
73
+ ra.get("pp_median"), rb.get("pp_median"),
74
+ ra.get("tg_min"), ra.get("tg_max"), rb.get("tg_min"), rb.get("tg_max")):
75
+ return None, None, None
76
+ g_r, g_v = pct(rb["tg_median"], ra["tg_median"]), pct(vb["tg_median"], va["tg_median"])
77
+ g_p = pct(rb["pp_median"], ra["pp_median"])
78
+ txt = (f"`{a_nm}` {rel(g_r, 'decodes', DEC_EQ)} `{b_nm}` on ROCm0 ({ra['tg_median']:.2f} vs "
79
+ f"{rb['tg_median']:.2f} tok/s; per-run ranges {ra['tg_min']:.2f}–{ra['tg_max']:.2f} and "
80
+ f"{rb['tg_min']:.2f}–{rb['tg_max']:.2f}) and {rel(g_v, 'decodes', DEC_EQ)[len('decodes '):]} it on Vulkan0 "
81
+ f"({va['tg_median']:.2f} vs {vb['tg_median']:.2f}), and {rel(g_p, 'prefills', PRE_EQ)} it on ROCm0 "
82
+ f"({ra['pp_median']:.0f} vs {rb['pp_median']:.0f} tok/s)")
83
+ adv = g_p >= PRE_EQ or g_r >= DEC_EQ or g_v >= DEC_EQ
84
+ dis = g_p <= -PRE_EQ or g_r <= -DEC_EQ or g_v <= -DEC_EQ
85
+ return txt, adv, dis
86
+
87
+
88
+ NOISE_NOTE = ("" if DEC_EQ is None or PRE_EQ is None else
89
+ f"Speed gaps below {DEC_EQ:.1f} % (decode) and {PRE_EQ:.1f} % (prefill) are called a tie: the larger of "
90
+ f"{SPEED_EQ:.0f} % and the widest gap measured between files that do identical work per token (each imatrix "
91
+ f"file and its standard twin: decode {TG_NOISE:.1f} %, prefill {PP_NOISE:.1f} %).")
92
+
93
+
94
+ def kld_cmp(a, b):
95
+ """KLD of tag a against tag b -> (pct change b->a, sigma, word). 'lower'/'higher' only at >= 2 sigma."""
96
+ x, y = T[a], T[b]
97
+ d = pct(y["kld_mean"], x["kld_mean"])
98
+ sg = sig(y["kld_mean"], y["kld_err"], x["kld_mean"], x["kld_err"])
99
+ word = "within noise of" if sg < 2 else ("lower than" if d < 0 else "higher than")
100
+ return d, sg, word
101
+
102
+
103
+ def kld_ready(tags):
104
+ return all(have(T.get(k, {}).get("kld_mean"), T.get(k, {}).get("kld_err"),
105
+ T.get(k, {}).get("size_bytes")) for k in tags)
106
+
107
+
108
+ def kld_rank_text(tags):
109
+ items = sorted(tags, key=lambda t: T[t]["kld_mean"])
110
+ parts = []
111
+ for i, tag in enumerate(items):
112
+ x = T[tag]
113
+ bit = f"`{NAMES[tag]}` {x['kld_mean']:.4f}"
114
+ if i > 0:
115
+ lo = T[items[0]]["kld_mean"]
116
+ parts.append(f"{bit} ({pct(lo, x['kld_mean']):+.1f} % vs `{NAMES[items[0]]}`)")
117
+ else:
118
+ parts.append(bit)
119
+ return ", ".join(parts)
120
+
121
+
122
+ def size_vs(a, b):
123
+ da, db = T[a]["size_bytes"], T[b]["size_bytes"]
124
+ if da == db:
125
+ return f"`{NAMES[a]}` and `{NAMES[b]}` are the same size ({da / MiB:.0f} MiB)"
126
+ smaller, larger = (a, b) if da < db else (b, a)
127
+ return (f"`{NAMES[smaller]}` is {(T[larger]['size_bytes'] - T[smaller]['size_bytes']) / MiB:.0f} MiB "
128
+ f"smaller than `{NAMES[larger]}`")
129
+
130
+
131
+ # ---------- quality provenance ----------
132
+ rep, rep_v, ref = S.get("repeat") or {}, S.get("repeat_vk") or {}, S.get("reference") or {}
133
+ if rep.get("result") == "MATCH" and rep.get("rows") is not None and have(ref.get("cpu_chunk1"), ref.get("vulkan0_chunk1")):
134
+ both = rep_v.get("result") == "MATCH" and rep_v.get("rows") is not None
135
+ J["quality_provenance"] = (
136
+ f"Measured directly on these files, against BF16 logits computed **on the CPU** in the same session "
137
+ f"(first-window perplexity {ref['cpu_chunk1']:.4f}; Vulkan0 gave {ref['vulkan0_chunk1']:.4f} for the same "
138
+ f"window). Every file was graded on ROCm0 (the columns above) and again on Vulkan0. The STRIX_LEAN grade was run "
139
+ f"twice {'on each backend' if both else 'on ROCm0'} and every per-chunk row matched: {rep['rows']} of "
140
+ f"{rep['rows']} on ROCm0" + (f", {rep_v['rows']} of {rep_v['rows']} on Vulkan0." if both else ".")
141
+ + " Why not the GPU for the reference: see [Known issues](#known-issues-and-limits).")
142
+
143
+ # ---------- quality by backend ----------
144
+ vk_rows = [(t, T[t]["vk"]) for t in STD_TAGS + IMAT_TAGS if (T.get(t) or {}).get("vk") and have(
145
+ T[t].get("kld_mean"), T[t].get("kld_err"), T[t]["vk"].get("kld_mean"), T[t]["vk"].get("kld_err"))]
146
+ if len(vk_rows) == 6:
147
+ parts_b, lower_vk, lower_rocm = [], 0, 0
148
+ for t, v in vk_rows:
149
+ a_, b_ = T[t]["kld_mean"], v["kld_mean"]
150
+ sg_ = sig(a_, T[t]["kld_err"], b_, v["kld_err"])
151
+ if sg_ >= 2:
152
+ lower_vk += b_ < a_; lower_rocm += a_ < b_
153
+ pc_ = f"{pct(a_, b_):+.1f}"
154
+ pc_ = "0.0" if pc_ in ("+0.0", "-0.0") else pc_
155
+ parts_b.append(f"{'imatrix ' if t.endswith('i') else ''}{NAMES[t]} {a_:.4f} / {b_:.4f} ({pc_} %, {sg_:.1f}σ)")
156
+ verdict = ("The two backends agree within noise on every file." if not (lower_vk or lower_rocm) else
157
+ f"Vulkan0's output is measurably closer to BF16 on {lower_vk} of 6 files and ROCm0's on {lower_rocm}.")
158
+ J["backend_quality_note"] = (
159
+ f"**Same files, same reference, graded on each backend** — KLD ROCm0 / Vulkan0: " + "; ".join(parts_b) + f". {verdict}")
160
+
161
+
162
+ # ---------- imatrix verdict ----------
163
+ def twin_kld_ok(st, im):
164
+ keys = ("kld_mean", "kld_err", "kld_median", "kld_p99", "same_top_p")
165
+ return have(*(T.get(st, {}).get(k) for k in keys), *(T.get(im, {}).get(k) for k in keys))
166
+
167
+
168
+ if all(twin_kld_ok(st, im) for im, st in TWINS):
169
+ bits = []
170
+ improved, worse = [], []
171
+ for im, st in TWINS:
172
+ nm = NAMES[st]
173
+ a, b = T[st], T[im]
174
+ dk = pct(a["kld_mean"], b["kld_mean"])
175
+ sg = sig(a["kld_mean"], a["kld_err"], b["kld_mean"], b["kld_err"])
176
+ dmed = pct(a["kld_median"], b["kld_median"])
177
+ dp99 = pct(a["kld_p99"], b["kld_p99"])
178
+ dtop = b["same_top_p"] - a["same_top_p"]
179
+ if dk < 0 and sg >= 2:
180
+ verb = "improves"
181
+ improved.append(nm)
182
+ elif dk > 0 and sg >= 2:
183
+ verb = "is measurably worse than"
184
+ worse.append(nm)
185
+ else:
186
+ verb = "is within noise of"
187
+ bits.append(
188
+ f"**{nm}** {verb} the standard file on mean KLD "
189
+ f"({dk:+.1f} %, {sg:.1f}σ; {a['kld_mean']:.4f} → {b['kld_mean']:.4f}); "
190
+ f"median {dmed:+.1f} %, 99th-pct {dp99:+.1f} %, top-1 {dtop:+.2f} pp")
191
+ if len(improved) == 3:
192
+ head = "**The imatrix measurably improves all three tiers.** "
193
+ elif improved:
194
+ head = f"**The imatrix measurably improves {', '.join(improved)}.** "
195
+ else:
196
+ head = "**The imatrix does not measurably improve any of the three tiers on this corpus.** "
197
+ if worse:
198
+ head += f"**It is measurably worse on {', '.join(worse)}.** "
199
+ J["imat_verdict"] = head + "; ".join(bits) + "."
200
+
201
+
202
+ # ---------- speed_note (standard card) ----------
203
+ def backend_line(tag):
204
+ r, v = bn(tag, "rocm"), bn(tag, "vk")
205
+ if not have(r, v) or DEC_EQ is None or PRE_EQ is None:
206
+ return None
207
+ if not have(r.get("tg_median"), v.get("tg_median"), r.get("pp_median"), v.get("pp_median"),
208
+ r.get("tg_min"), r.get("tg_max"), v.get("tg_min"), v.get("tg_max")):
209
+ return None
210
+ g_t, g_p = pct(v["tg_median"], r["tg_median"]), pct(v["pp_median"], r["pp_median"])
211
+ return (f"`{NAMES[tag]}`: ROCm0 {rel(g_t, 'decodes', DEC_EQ)} Vulkan0 "
212
+ f"({r['tg_median']:.2f} vs {v['tg_median']:.2f} tok/s; ranges "
213
+ f"{r['tg_min']:.2f}–{r['tg_max']:.2f} / {v['tg_min']:.2f}–{v['tg_max']:.2f}) and "
214
+ f"{rel(g_p, 'prefills', PRE_EQ)} it ({r['pp_median']:.0f} vs {v['pp_median']:.0f} tok/s)")
215
+
216
+
217
+ if DEC_EQ is not None and PRE_EQ is not None:
218
+ lines = [backend_line(t) for t in STD_TAGS]
219
+ cr, pr = bench("n-q106-rocm"), bench("n-q106-rocm-prose")
220
+ cv, pv = bench("n-q106-vk"), bench("n-q106-vk-prose")
221
+ prose = None
222
+ if have(cr, pr, cr and cr.get("tg_median"), pr and pr.get("tg_median")):
223
+ g = pct(cr["tg_median"], pr["tg_median"])
224
+ prose = (f"STRIX_LEAN workload range on ROCm0: code {cr['tg_median']:.2f} tok/s vs prose "
225
+ f"{pr['tg_median']:.2f} ({rel(g, 'prose decodes', DEC_EQ)} code)")
226
+ if have(cv, pv, cv and cv.get("tg_median"), pv and pv.get("tg_median")):
227
+ gv = pct(cv["tg_median"], pv["tg_median"])
228
+ prose += (f"; Vulkan0 code {cv['tg_median']:.2f} vs prose {pv['tg_median']:.2f} "
229
+ f"({rel(gv, 'prose decodes', DEC_EQ)} code)")
230
+ prose += "."
231
+
232
+ def _span(wl):
233
+ v = [(b_.get("prompt_n_min") if b_.get("prompt_n_min") is not None else b_.get("prompt_n"),
234
+ b_.get("prompt_n_max") if b_.get("prompt_n_max") is not None else b_.get("prompt_n"))
235
+ for b_ in S.get("bench") or [] if b_.get("workload") == wl]
236
+ v = [x for x in v if None not in x]
237
+ if not v:
238
+ return None
239
+ lo, hi = min(a for a, _ in v), max(b for _, b in v)
240
+ return f"{lo:,}" if lo == hi else f"{lo:,}–{hi:,}"
241
+ sc, sp = _span("code"), _span("prose")
242
+ if sc and sp:
243
+ prose += (f" Prompt lengths: code {sc} tokens (the first 30,000 characters of `convert_hf_to_gguf.py` plus "
244
+ f"an instruction), prose {sp} tokens (the first 34,000 characters of wikitext-2 *train* plus a "
245
+ f"writing instruction).")
246
+ if all(lines) and prose:
247
+ J["speed_note"] = " ".join(x + "." for x in lines) + " " + prose + (f" {NOISE_NOTE}" if NOISE_NOTE else "")
248
+
249
+
250
+ # ---------- cache ----------
251
+ d = gate("n-c3-q106")
252
+ if d and d.get("all_reused") and d.get("all_aligned") and have(d.get("n"), d.get("L"), d.get("expect_cache_n"),
253
+ d.get("identical")):
254
+ wm = [r_["warm_prompt_ms"] for r_ in d.get("rows") or [] if r_.get("warm_prompt_ms") is not None]
255
+ cm = [r_["cold_prompt_ms"] for r_ in d.get("rows") or [] if r_.get("cold_prompt_ms") is not None]
256
+ t_line = ""
257
+ if wm and cm:
258
+ t_line = (f" — median prefill **{statistics.median(wm) / 1000:.1f} s instead of "
259
+ f"{statistics.median(cm) / 1000:.1f} s** cold "
260
+ f"({statistics.median(cm) / statistics.median(wm):.1f}× faster)")
261
+ J["cache_note"] = (
262
+ f"In {d['n']} request pairs sharing a long prefix at one fixed prompt length of {d['L']:,} tokens, every "
263
+ f"second request resumed from the checkpoint the first one left {4 + UB:,} tokens before its end — "
264
+ f"**{d['expect_cache_n']:,} tokens reused "
265
+ f"({d['expect_cache_n'] / d['L'] * 100:.0f} %), {d['L'] - d['expect_cache_n']:,} processed**{t_line}. "
266
+ f"Each warm reply was byte-identical to a cold run of the same prompt in **{d['identical']}/{d['n']}** "
267
+ f"exchanges.\n\n"
268
+ f"llama-server processes the last `n_ubatch` + 4 tokens of every prompt as two batches so it can checkpoint "
269
+ f"there ({UB:,} + 4 = {4 + UB:,} tokens with the `-ub {UB}` used in these measurements, where the server "
270
+ f"default is `-ub 512`; [upstream PR #20288](https://github.com/ggml-org/llama.cpp/pull/20288)). A turn that "
271
+ f"resumes from a checkpoint left by a prompt of a *different* length therefore splits its tail differently "
272
+ f"from a cold run, and float rounding can flip a greedy token.")
273
+
274
+
275
+ # ---------- tools ----------
276
+ def _tools_ok(x):
277
+ return bool(x) and have(x.get("passed"), x.get("total"), x.get("detail"))
278
+
279
+
280
+ tl = gate("n-tools-q106") # stock template
281
+ FX = [gate(l) for l in ("n-tools-q106-roff", "n-tools-q106-roff-r2", "n-tools-q106-roff-r3")] # quick-start config
282
+ TD = S.get("tools_diag") or {}
283
+ TF = S.get("template_fix") or {}
284
+ if _tools_ok(tl) and all(_tools_ok(x) for x in FX) and have(
285
+ TD.get("stock_on_leaks"), TD.get("stock_on_replies"), TD.get("stock_on_reasoning_extracted"),
286
+ TD.get("nested_off_http500"), TD.get("nested_off_attempts")):
287
+ misses, on_n, on_ok, off_n, off_ok = [], 0, 0, 0, 0
288
+ for i, x in enumerate(FX, 1):
289
+ for k, v in x["detail"].items():
290
+ name, think = k.split("|think=")
291
+ if think == "True":
292
+ on_n += 1; on_ok += bool(v)
293
+ else:
294
+ off_n += 1; off_ok += bool(v)
295
+ if not v:
296
+ misses.append("`%s` with thinking %s (pass %d)" % (name, "on" if think == "True" else "off", i))
297
+ fp = TD.get("flag_probes") or {}
298
+ flag_txt = "; ".join("%s: %d of %d replies still had reasoning in `content`" % (lab, fp[key]["leaks"], fp[key]["n"])
299
+ for key, lab in (("fmt-deepseek", "`--reasoning-format deepseek`"),
300
+ ("srv-kwargs-high", "`--chat-template-kwargs` with `reasoning_effort`"),
301
+ ("reasoning-on", "`--reasoning on`")) if key in fp)
302
+ J["tools_note"] = (
303
+ "**Stock chat template: %d/%d.** Every thinking-on check failed. Re-run with the raw replies kept, %d of %d "
304
+ "thinking-on replies carried the reasoning and a `</think>` in `content`, and %d had any "
305
+ "`reasoning_content`. llama-server builds its reasoning parser by rendering the template with "
306
+ "`enable_thinking` on and off; this template ignores `enable_thinking` (it switches on `reasoning_effort`), "
307
+ "so the parser finds no reasoning markers and extracts nothing. Server switches did not help (%s). With "
308
+ "thinking off, `nested-object` failed on an HTTP 500 — see [Known issues](#known-issues-and-limits).\n\n"
309
+ "**With the included `%s` and `--reasoning off` (the quick start): %s over three passes of the same suite "
310
+ "(%d/%d)** — thinking off %d/%d, thinking on %d/%d; the misses were %s. A pass requires a native "
311
+ "`tool_calls` entry with the right arguments and no think tags in `content`. Each check is a single sample at "
312
+ "the recommended temperature 0.7." % (
313
+ tl["passed"], tl["total"], TD["stock_on_leaks"], TD["stock_on_replies"],
314
+ TD["stock_on_reasoning_extracted"], flag_txt or "not measured", TF.get("file") or "—",
315
+ ", ".join("%d/%d" % (x["passed"], x["total"]) for x in FX),
316
+ sum(x["passed"] for x in FX), sum(x["total"] for x in FX), off_ok, off_n, on_ok, on_n,
317
+ ", ".join(misses) if misses else "none"))
318
+
319
+
320
+ # ---------- the template fix: what each request option does (recommended configuration) ----------
321
+ PR = TF.get("probes_roff") or {}
322
+ if PR and all(_tools_ok(x) for x in FX):
323
+ def _probe(prefix):
324
+ rows_ = [v for k, v in PR.items() if k.split("|")[0] == prefix]
325
+ return len(rows_), sum(1 for v in rows_ if v.get("leaks")), sum(1 for v in rows_ if v.get("reasoning_len"))
326
+ on_ok = sum(bool(v) for x in FX for k, v in x["detail"].items() if k.endswith("|think=True"))
327
+ on_n = sum(1 for x in FX for k in x["detail"] if k.endswith("|think=True"))
328
+ off_ok = sum(bool(v) for x in FX for k, v in x["detail"].items() if k.endswith("|think=False"))
329
+ off_n = sum(1 for x in FX for k in x["detail"] if k.endswith("|think=False"))
330
+ lines = []
331
+ for label, prefix, think, dest in (
332
+ ("no `chat_template_kwargs`", "no-kwargs", "off (the server default with `--reasoning off`)", "—"),
333
+ ("`\"enable_thinking\": false`", "enable_thinking=false", "off", "—"),
334
+ ("`\"reasoning_effort\": \"none\"`", "reasoning_effort=none", "off", "—"),
335
+ ("`\"reasoning_effort\": \"high\"`", "reasoning_effort=high", "on", "**`content`** — do not use"),
336
+ ("`\"reasoning_effort\": \"medium\"`", "reasoning_effort=medium", "adaptive", "**`content`** — do not use")):
337
+ n, leaks, _ = _probe(prefix)
338
+ if n:
339
+ lines.append("| %s | %s | %s | %d of %d replies with think tags in `content` |" % (label, think, dest, leaks, n))
340
+ lines.insert(1 if lines else 0,
341
+ "| `\"enable_thinking\": true` | on | `reasoning_content` | tool suite with thinking on: %d/%d "
342
+ "(a pass requires no think tags in `content`) |" % (on_ok, on_n))
343
+ J["template_note"] = (
344
+ "Measured on the standard STRIX_LEAN file with the included template file and `--reasoning off` (greedy "
345
+ "probes: a direct question, a "
346
+ "one-word instruction and a tool request, each with the tool schema attached; tool suite: 3 passes):\n\n"
347
+ "| request | thinking | reasoning ends up in | measured |\n| --- | --- | --- | --- |\n" + "\n".join(lines)
348
+ + "\n\nSo: switch thinking with `enable_thinking` only. Thinking-off tool checks: %d/%d." % (off_ok, off_n))
349
+
350
+
351
+ # ---------- vision ----------
352
+ def vwhy(x):
353
+ if x.get("server_died"):
354
+ import re as _re
355
+ errs = [_re.sub(r"^[0-9.]+ [IWE] (srv +)?", "", e).strip() for e in x.get("server_log_errors") or []]
356
+ first = next((e for e in errs if "failed" in e.lower() or "error" in e.lower() or "abort" in e.lower()),
357
+ None) or (errs[0] if errs else None)
358
+ return ("the server aborted" + (f" (`{first[:90]}`)" if first else ""))
359
+ if x.get("error"):
360
+ return f"the request failed ({x['error'][:80]})"
361
+ exp = x.get("expected") or ""
362
+ nexp = len(exp.split(",")) if exp else None
363
+ hits = x.get("hits") or []
364
+ if nexp:
365
+ return f"the reply named {len(hits)} of {nexp} expected terms"
366
+ return "the reply did not pass"
367
+
368
+
369
+ on, off = gate("n-vision-q106-faon"), gate("n-vision-q106-faoff")
370
+ if on and off:
371
+ def vok(x):
372
+ return x.get("result") == "PASS"
373
+ if vok(on) and vok(off):
374
+ J["vision_note"] = "✅ **Images work with `-fa on` and `-fa off`.**"
375
+ elif vok(off) and not vok(on):
376
+ J["vision_note"] = (f"⛔ **With `-fa on`, image requests fail** — {vwhy(on)}. With `-fa off` they work. "
377
+ f"**For image input, serve with `-fa off`.**")
378
+ J["vision_quickstart_warning"] = ("> ⛔ **Images:** with `-fa on`, image requests fail on this build "
379
+ "([measured](#vision)). If you send images, use `-fa off`.")
380
+ elif vok(on) and not vok(off):
381
+ J["vision_note"] = (f"⛔ **With `-fa off`, image requests fail** — {vwhy(off)}. With `-fa on` they work. "
382
+ f"**For image input, keep `-fa on` (the quick-start default).**")
383
+ else:
384
+ J["vision_note"] = (f"⛔ **Images failed in both `-fa` settings.** `-fa on`: {vwhy(on)}; "
385
+ f"`-fa off`: {vwhy(off)}.")
386
+ vfx = gate("n-vision-q106-roff-faon")
387
+ if vfx and "vision_note" in J:
388
+ J["vision_note"] += (" The `-fa on` image test was repeated with the included template file and "
389
+ f"`--reasoning off` (the quick start): {'✅ passed' if vok(vfx) else '❌ ' + vwhy(vfx)}.")
390
+
391
+
392
+ # ---------- memory ----------
393
+ rows_sz = [r for r in (S.get("sizing") or []) if r.get("label") == "strix-lean"]
394
+ if rows_sz:
395
+ def mem_cell(r, key):
396
+ if r.get("result") == "LOAD_FAIL":
397
+ return "did not load"
398
+ v = r.get(key)
399
+ return f"{v:.2f} GiB" if v is not None else "—"
400
+ body = "\n".join(
401
+ f"| {r['ctx']:,} | {mem_cell(r, 'footprint_loaded_gib')} | {mem_cell(r, 'footprint_after_8k_gib')} |"
402
+ for r in rows_sz if r.get("ctx") is not None)
403
+ J["memory_note"] = (
404
+ "Measured footprint (drop in `MemAvailable`) of STRIX_LEAN with the vision projector, q8_0 KV cache, "
405
+ "`-cram 512`, one slot, no draft head:\n\n"
406
+ "| context | after load | after one request (30,000-character code prompt) |\n"
407
+ "| ---: | ---: | ---: |\n" + body +
408
+ "\n\nNo row was decode-benchmarked beyond that one request. Nothing beyond these rows was measured.")
409
+
410
+
411
+ # ---------- recommendations ----------
412
+ def recommend(lean, coh, fast):
413
+ """STRIX_LEAN is the flagship tier; the data decides whether COHERENT's quality or FAST's speed is worth taking
414
+ instead. -> (default tag, markdown) or (None, None) when an input is missing."""
415
+ lc, lc_adv, lc_dis = cmp_line(lean, coh, "STRIX_LEAN", "COHERENT")
416
+ fl, fl_adv, fl_dis = cmp_line(fast, lean, "FAST", "STRIX_LEAN")
417
+ if lc is None or fl is None:
418
+ return None, None
419
+ L, C, F = T[lean], T[coh], T[fast]
420
+ d_c, s_c, w_c = kld_cmp(coh, lean)
421
+ more = (C["size_bytes"] - L["size_bytes"]) / MiB
422
+ size_c = f"{abs(more):.0f} MiB {'more' if more > 0 else 'less'}"
423
+ if w_c == "lower than" and lc_adv and not lc_dis:
424
+ default = lean
425
+ head = (f"**Start with `STRIX_LEAN`; take `COHERENT` if quality matters more than speed.** {lc}. `COHERENT`'s "
426
+ f"KLD is {abs(d_c):.1f} % lower ({s_c:.1f}σ) for {size_c}.")
427
+ elif w_c == "lower than":
428
+ default = coh
429
+ head = (f"**Start with `COHERENT`.** Its KLD is {abs(d_c):.1f} % lower than `STRIX_LEAN`'s ({s_c:.1f}σ) for "
430
+ f"{size_c}, and the speed comparison does not clearly favour `STRIX_LEAN`: {lc}.")
431
+ elif w_c == "within noise of" and lc_dis and not lc_adv:
432
+ default = coh
433
+ head = (f"**Start with `COHERENT`.** Its KLD is {w_c} `STRIX_LEAN`'s ({d_c:+.1f} %, {s_c:.1f}σ) and it is "
434
+ f"measurably faster: {lc}. It costs {size_c}.")
435
+ else:
436
+ default = lean
437
+ head = (f"**Start with `STRIX_LEAN`.** `COHERENT`'s KLD is {w_c} it ({d_c:+.1f} %, {s_c:.1f}σ) for "
438
+ f"{size_c}; {lc}.")
439
+ d_f, s_f, w_f = kld_cmp(fast, lean)
440
+ kf = f"its KLD is {w_f} `STRIX_LEAN`'s ({F['kld_mean']:.4f} vs {L['kld_mean']:.4f}, {d_f:+.1f} %, {s_f:.1f}σ)"
441
+ if fl_adv and not fl_dis:
442
+ fast_txt = f"**Take `FAST` for speed:** {fl}; {kf}."
443
+ else:
444
+ fast_txt = f"`FAST` does not buy a clear speed gain here: {fl}; {kf}."
445
+ sizes = f"{size_vs(lean, coh)}; {size_vs(lean, fast)}."
446
+ body = (f"{head}\n\n{fast_txt}\n\nKLD order (lower is closer to BF16): {kld_rank_text((lean, coh, fast))}. "
447
+ f"{sizes} {NOISE_NOTE}")
448
+ return default, body
449
+
450
+
451
+ def imat_pointer():
452
+ """Point the standard card at the imatrix repo; name only measurable (>= 2 sigma) twin improvements."""
453
+ repo = S.get("model_repo_imat")
454
+ if not repo:
455
+ return ""
456
+ link = f"[imatrix build](https://huggingface.co/{repo})"
457
+ bits = []
458
+ for im, st in TWINS:
459
+ if not twin_kld_ok(st, im):
460
+ return ""
461
+ d, sg, w = kld_cmp(im, st)
462
+ if w == "lower than":
463
+ bits.append(f"`{NAMES[st]}` {T[st]['kld_mean']:.4f} → {T[im]['kld_mean']:.4f} ({d:+.1f} %, {sg:.1f}σ)")
464
+ if bits:
465
+ return f"**The {link} is measurably closer to BF16 at the same size:** " + "; ".join(bits) + "."
466
+ return f"Importance-matrix twins of all three files: **{link}** (not measurably closer to BF16 on this corpus)."
467
+
468
+
469
+ if kld_ready(STD_TAGS) and DEC_EQ is not None and PRE_EQ is not None:
470
+ default, body = recommend("q106", "q102", "q103")
471
+ if default:
472
+ ptr = imat_pointer()
473
+ J["std_recommendation"] = body + (f"\n\n{ptr}" if ptr else "")
474
+ J["std_default"] = T[default]["file"]
475
+
476
+ if kld_ready(IMAT_TAGS) and DEC_EQ is not None and PRE_EQ is not None:
477
+ default_i, body_i = recommend("q106i", "q102i", "q103i")
478
+ if default_i:
479
+ cross = ""
480
+ if kld_ready(("q102",)):
481
+ d, sg, w = kld_cmp("q106i", "q102")
482
+ cross = (f"\n\nFor scale: the imatrix `STRIX_LEAN`'s KLD is {w} the *standard* `COHERENT`'s "
483
+ f"({T['q106i']['kld_mean']:.4f} vs {T['q102']['kld_mean']:.4f}, {d:+.1f} %, {sg:.1f}σ), "
484
+ f"{size_vs('q106i', 'q102')}.")
485
+ J["imat_recommendation"] = body_i + cross
486
+ J["imat_default"] = T[default_i]["file"]
487
+
488
+ parts = []
489
+ for nm, ti, ts in (("STRIX_LEAN", "q106i", "q106"), ("COHERENT", "q102i", "q102"), ("FAST", "q103i", "q103")):
490
+ for dev, dn in (("rocm", "ROCm0"), ("vk", "Vulkan0")):
491
+ a_, b_ = bn(ti, dev), bn(ts, dev)
492
+ if a_ and b_ and have(a_.get("tg_median"), b_.get("tg_median")):
493
+ parts.append(f"{nm} on {dn} {a_['tg_median']:.2f} vs {b_['tg_median']:.2f} tok/s")
494
+ same = [T.get(i, {}).get("same_tensor_types_as_standard") for i, _ in TWINS]
495
+ _hk = [T.get(i, {}).get("header_keys_only_in_imatrix") for i, _ in TWINS]
496
+ _hs = [T.get(i, {}).get("header_keys_only_in_standard") for i, _ in TWINS]
497
+ HDR = ""
498
+ if all(x is not None for x in _hk + _hs) and not any(_hs) and len({tuple(x) for x in _hk}) == 1 and _hk[0]:
499
+ HDR = ", all in the GGUF header, which carries %d extra keys in each imatrix file: %s" % (
500
+ len(_hk[0]), ", ".join("`%s`" % k for k in _hk[0]))
501
+ deltas = [T.get(i, {}).get("file_size_delta_bytes") for i, _ in TWINS]
502
+ if len(parts) == 6 and all(x is True for x in same) and all(d is not None for d in deltas):
503
+ J["imat_speed_note"] = (
504
+ f"The imatrix changes scale values, not tensor types or sizes: tensor by tensor, each imatrix file has the "
505
+ f"same names, types and byte sizes as its standard twin, so the work per token is the same (the files differ "
506
+ f"in size by {deltas[0]} / {deltas[1]} / {deltas[2]} bytes{HDR})." + " "
507
+ f"Measured speed still differs — imatrix vs standard: " + "; ".join(parts) + "."
508
+ + (f" The largest of these decode gaps is {TG_NOISE:.1f} %; both cards call decode gaps below {DEC_EQ:.1f} % "
509
+ f"a tie." if TG_NOISE is not None and DEC_EQ is not None else ""))
510
+
511
+
512
+ # ---------- known issues (model facts + protocol; always emit) ----------
513
+ ki = [
514
+ "- **No MTP head.** The checkpoint's `config.json` declares `mtp_num_hidden_layers: 1`, but the weights contain "
515
+ "**no** `mtp.*` tensors (1,026 tensors total). There is no multi-token-prediction head and no speculative decoding "
516
+ "on these files — do not pass `--spec-type draft-mtp`.",
517
+ "- **The stock chat template ignores `enable_thinking`, and llama-server cannot separate its reasoning** "
518
+ "(see [Tool calling](#tool-calling)). Serve with the included `chat_template_enable_thinking.jinja` and "
519
+ "`--reasoning off`, and switch thinking per request with `enable_thinking` — see "
520
+ "[Reasoning controls](#reasoning-controls).",
521
+ "- **Earlier assistant turns are re-rendered with their reasoning**, so multi-turn contexts grow faster than with "
522
+ "templates that drop it.",
523
+ "- **`llama-server`'s host-RAM prompt cache defaults to 8 GiB** (`-cram 8192`). On a shared box, set `-cram` explicitly.",
524
+ "- Measured on Linux only (Ryzen AI Max+ 395, ROCm 7.2.4, unpatched `d3ca537`).",
525
+ ]
526
+ _pn_vals = [b_.get("prompt_n_max") if b_.get("prompt_n_max") is not None else b_.get("prompt_n")
527
+ for b_ in (S.get("bench") or [])]
528
+ _pn = max((v for v in _pn_vals if v is not None), default=None) # longest prompt any timed decode followed
529
+ _sz = {r_.get("ctx"): r_ for r_ in (S.get("sizing") or []) if r_.get("label") == "strix-lean"}
530
+ _big = max(_sz) if _sz else None
531
+ _ctx_txt = ("" if _big is None else
532
+ f" (a {_big:,}-token context was loaded in the memory test, not benchmarked)"
533
+ if _sz[_big].get("result") != "LOAD_FAIL" else "")
534
+ for _c, _r in sorted(_sz.items()):
535
+ if _r.get("result") == "LOAD_FAIL":
536
+ ki.append(f"- **A {_c:,}-token context did not load** in the memory test (STRIX_LEAN + vision projector, "
537
+ f"q8_0 KV cache, one slot) on this box.")
538
+ ki.append(f"- **Not measured:** decode beyond a {_pn:,}-token prompt{_ctx_txt}, " if _pn is not None else
539
+ "- **Not measured:** decode at long context, ")
540
+ ki[-1] += ("long-context quality, video input, concurrency above 1, and task-level accuracy. Perplexity/KLD measure "
541
+ "next-token fidelity to BF16 on prose, not reasoning or code correctness.")
542
+ if have(ref.get("hip_rocm0_chunk1"), ref.get("cpu_chunk1"), ref.get("hip_rocm0_final")) and have(S.get("bf16", {}).get("ppl")):
543
+ ki.insert(0, f"- **Do not run the BF16 GGUF of this model on ROCm0 with this build.** `d3ca537` computes it wrong on "
544
+ f"that path: wikitext-2 perplexity {ref['hip_rocm0_final']:.1f} on ROCm0 vs {S['bf16']['ppl']:.2f} on the CPU "
545
+ f"(first window {ref['hip_rocm0_chunk1']:.1f} vs {ref['cpu_chunk1']:.2f}; also wrong with `-fa off`). "
546
+ f"The 4-bit files are not affected — their ROCm0 grades are in the table — and the BF16 file is not "
547
+ f"published here; the quality reference was computed on the CPU instead.")
548
+ if have(TD.get("nested_off_http500"), TD.get("nested_off_attempts")):
549
+ ki.insert(1, "- **llama-server rejects a tool call whose required arguments are not in the order the schema lists "
550
+ "them** — HTTP 500, *The model produced output that does not match the expected peg-native format*: "
551
+ "this build's parser for the XML tool-call format expects required arguments in definition order. "
552
+ "On the standard STRIX_LEAN file with the stock template and thinking off, the `nested-object` "
553
+ "request (three required arguments) "
554
+ "hit it in the tool suite%s and in %d of %d repeats; the model had written a well-formed call with "
555
+ "the arguments reordered. Be ready to retry on this error." % (
556
+ "" if TD.get("gate_http500_logged") else " (not confirmed in the suite's server log)",
557
+ TD["nested_off_http500"], TD["nested_off_attempts"]))
558
+ _PR = (S.get("template_fix") or {}).get("probes_roff") or {}
559
+ _lk = [v for k, v in _PR.items() if k.split("|")[0] in ("reasoning_effort=high", "reasoning_effort=medium")]
560
+ if _lk:
561
+ ki.insert(2, "- **With the included template, do not set `reasoning_effort` to `high` or `medium`** — the reasoning "
562
+ "goes back into `content` (%d of %d probe replies). `enable_thinking: true` is the way to turn "
563
+ "thinking on." % (sum(1 for v in _lk if v.get("leaks")), len(_lk)))
564
+ _seat = [r_ for r_ in (S.get("seats") or {}).values() if r_.get("thinking_reasoning_len") is not None]
565
+ _short = [r_ for r_ in _seat if not r_.get("thinking_reply") and r_.get("thinking_reasoning_len")]
566
+ if _short:
567
+ ki.insert(3, "- **With thinking on, a very short answer can stay inside the think block.** Served as in the quick "
568
+ "start, `Reply with the single word: ready` (no tools, `enable_thinking: true`, temperature 0) came "
569
+ "back with the word in `reasoning_content` and an empty `content` on %d of %d FAST files tested.%s" % (
570
+ len(_short), len(_seat),
571
+ " With thinking off the same request returned `ready` in `content`."
572
+ if all((r_.get("default_reply") or "").strip().lower().startswith("ready") for r_ in _seat) else ""))
573
+ J["std_known_issues"] = "\n".join(ki)
574
+ J["imat_known_issues"] = "\n".join([
575
+ "- Calibration text is general-purpose English/code (bartowski `calibration_datav3.txt`); an imatrix built from "
576
+ "your own domain can do better on that domain.",
577
+ "- Graded on wikitext-2 *test*, a different corpus from the calibration text. Improvements on reasoning/code "
578
+ "tasks were not measured.",
579
+ ] + ki)
580
+
581
+ json.dump(J, open(sys.argv[2], "w"), indent=2)
582
+ print("judgments written:", sorted(J))
583
+ for k, v in J.items():
584
+ print(f"\n[{k}]\n{v}")
recipe/pipeline/nex_phase1.sh ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Nex-N2.5-mini phase 1 (CPU): verified download -> BF16 GGUF + vision projector -> the three standard 4-bit tiers
3
+ # (King: STRIX_LEAN + COHERENT + FAST; no Q8/Q6) with head protection, read back by exact tensor name.
4
+ # Runs in the capped scope `nex-conv` (Agnes memory sizing waits for nex-* scopes). Waits until the Agnes BF16
5
+ # re-grade (60 GiB on the GPU) is finished so the two large memory users never overlap.
6
+ set -uo pipefail
7
+ W=/mnt/models/nex-n2.5-mini; T=/opt/llama-rocm/rocmfpx-724; B=$T/build-hipvk/bin; N=Nex-N2.5-mini
8
+ A=/mnt/models/agnes-3.0-flash
9
+ export LD_LIBRARY_PATH=$B:/opt/rocm-7.2.4/lib TMPDIR=/mnt/models/.tmp PYTHONUNBUFFERED=1
10
+ cd $W; mkdir -p gguf out logs
11
+ log(){ echo "[$(date -u +%FT%TZ)] $*"; }
12
+ until [ -f logs/DOWNLOAD_RC ]; do sleep 20; done
13
+ if [ "$(cat logs/DOWNLOAD_RC)" != 0 ] || [ "$(cat logs/DOWNLOAD_VERIFY_RC 2>/dev/null)" != 0 ]; then
14
+ log "download or verify failed -> stop"; log "NEX_PHASE1_FAILED"; exit 1
15
+ fi
16
+ log "download verified; waiting for the Agnes BF16 re-grade to leave the GPU"
17
+ until grep -q "R3 grade" $A/logs/regrade.log 2>/dev/null; do sleep 20; done
18
+
19
+ log "C1 convert BF16 (the checkpoint has no mtp.* tensors, so no MTP block is emitted)"
20
+ python3 $T/convert_hf_to_gguf.py hf --outtype bf16 --model-name "$N" --outfile gguf/$N-BF16.gguf > logs/C1_convert.log 2>&1
21
+ rc=$?; log "C1 exit=$rc"; [ $rc -eq 0 ] || { tail -30 logs/C1_convert.log; log "NEX_PHASE1_FAILED"; exit 2; }
22
+ log "C2 convert vision projector"
23
+ python3 $T/convert_hf_to_gguf.py hf --outtype bf16 --mmproj --model-name "$N" --outfile out/mmproj-$N-BF16.gguf > logs/C2_mmproj.log 2>&1
24
+ rc=$?; log "C2 exit=$rc"; [ $rc -eq 0 ] || { tail -30 logs/C2_mmproj.log; log "NEX_PHASE1_FAILED"; exit 3; }
25
+ python3 readback.py - - gguf/$N-BF16.gguf | tee logs/C_readback.log
26
+ python3 readback.py - - out/mmproj-$N-BF16.gguf | tee -a logs/C_readback.log
27
+
28
+ BF=gguf/$N-BF16.gguf; Q=$B/llama-quantize
29
+ log "Q1 standard tiers"
30
+ $Q --output-tensor-type q6_K $BF out/$N-Q4_0_ROCMFP4_STRIX_LEAN.gguf Q4_0_ROCMFP4_STRIX_LEAN 16 > logs/Q1_q106.log 2>&1; log " q106 exit=$?"
31
+ $Q --output-tensor-type q6_K --token-embedding-type q6_K $BF out/$N-Q4_0_ROCMFP4_COHERENT.gguf Q4_0_ROCMFP4_COHERENT 16 > logs/Q1_q102.log 2>&1; log " q102 exit=$?"
32
+ $Q --output-tensor-type q6_K $BF out/$N-Q4_0_ROCMFP4_FAST.gguf Q4_0_ROCMFP4_FAST 16 > logs/Q1_q103.log 2>&1; log " q103 exit=$?"
33
+ python3 readback.py Q6_K Q5_K out/$N-Q4_0_ROCMFP4_STRIX_LEAN.gguf | tee logs/Q_readback.log
34
+ python3 readback.py Q6_K Q6_K out/$N-Q4_0_ROCMFP4_COHERENT.gguf | tee -a logs/Q_readback.log
35
+ python3 readback.py Q6_K - out/$N-Q4_0_ROCMFP4_FAST.gguf | tee -a logs/Q_readback.log
36
+ for l in Q1_q106 Q1_q102 Q1_q103; do printf "%-8s " $l; grep -oE "quant size\s*=\s*[0-9.]+ MiB \([0-9.]+ BPW\)" logs/$l.log; done | tee logs/Q_sizes.log
37
+ log "NEX_PHASE1_DONE"
recipe/pipeline/nex_phase2.sh ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Nex-N2.5-mini phase 2 (GPU, box iced): BF16 reference + imatrix -> imatrix tiers (CPU, alongside the standard grades)
3
+ # -> KLD grade of all six 4-bit files + a repeat run -> speed on both backends + gates -> memory sizing -> un-ice.
4
+ set -uo pipefail
5
+ W=/mnt/models/nex-n2.5-mini; A=/mnt/models/agnes-3.0-flash; B=/opt/llama-rocm/rocmfpx-724/build-hipvk/bin; N=Nex-N2.5-mini
6
+ export LD_LIBRARY_PATH=$B:/opt/rocm-7.2.4/lib HSA_OVERRIDE_GFX_VERSION=11.5.1 GGML_HIP_ENABLE_UNIFIED_MEMORY=1
7
+ cd $W; mkdir -p kld imat out-imat results
8
+ ulimit -c 1 # a crashing server must not pipe a multi-GiB core into apport on the full root disk
9
+ log(){ echo "[$(date -u +%FT%TZ)] $*"; }
10
+ table(){
11
+ python3 - "$1" <<'EOF'
12
+ import sys
13
+ out = []
14
+ for l in open(sys.argv[1], errors="replace"):
15
+ t = l.split()
16
+ if len(t) > 2 and t[0].isdigit() and l.rstrip().endswith("%") and l.count("%") == 2:
17
+ out.append(" ".join(t))
18
+ print("\n".join(out))
19
+ EOF
20
+ }
21
+ until grep -q -E "NEX_PHASE1_(DONE|FAILED)" logs/phase1.log 2>/dev/null; do sleep 30; done
22
+ grep -q NEX_PHASE1_DONE logs/phase1.log || { log "phase 1 failed -> stop (box stays iced)"; log "NEX_PHASE2_FAILED"; exit 1; }
23
+ until grep -q AGNES_FINISH_DONE $A/logs/agnes_finish.log 2>/dev/null; do sleep 30; done
24
+ log "box handed over from Agnes"
25
+ PPL="$B/llama-perplexity -c 2048 -b 2048 -ngl 999 -fa on -dio -dev ROCm0"
26
+ BF=gguf/$N-BF16.gguf; Q=$B/llama-quantize
27
+
28
+ log "N1 BF16 perplexity + base logits (wikitext-2 test, 40 chunks)"
29
+ $PPL -m $BF -f $A/calib/wikitext-2-raw/wiki.test.raw --chunks 40 --kl-divergence-base kld/bf16.kld > logs/N1_ppl_bf16.log 2>&1
30
+ log "N1 exit=$? $(grep -E 'Final estimate' logs/N1_ppl_bf16.log)"
31
+
32
+ log "N2 imatrix (BF16, bartowski calibration_datav3, c=512)"
33
+ $B/llama-imatrix -m $BF -f $A/calib/calibration_datav3.txt -o imat/$N.imatrix -ngl 999 -c 512 -b 512 -fa on -dio -dev ROCm0 \
34
+ > logs/N2_imatrix.log 2>&1
35
+ rc=$?; log "N2 exit=$rc"
36
+ [ $rc -eq 0 ] && [ -s imat/$N.imatrix ] || { log "imatrix failed -> stop (box stays iced)"; log "NEX_PHASE2_FAILED"; exit 2; }
37
+ sha256sum imat/$N.imatrix > imat/$N.imatrix.sha256
38
+
39
+ log "N3 imatrix tiers on CPU (background) while N4a grades the standard tiers on the GPU"
40
+ (
41
+ systemd-run --scope --quiet -p MemoryMax=24G -p MemorySwapMax=0 nice -n 5 bash -c "
42
+ $Q --imatrix imat/$N.imatrix --output-tensor-type q6_K $BF out-imat/$N-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf Q4_0_ROCMFP4_STRIX_LEAN 16 > logs/N3_q106i.log 2>&1
43
+ $Q --imatrix imat/$N.imatrix --output-tensor-type q6_K --token-embedding-type q6_K $BF out-imat/$N-imatrix-Q4_0_ROCMFP4_COHERENT.gguf Q4_0_ROCMFP4_COHERENT 16 > logs/N3_q102i.log 2>&1
44
+ $Q --imatrix imat/$N.imatrix --output-tensor-type q6_K $BF out-imat/$N-imatrix-Q4_0_ROCMFP4_FAST.gguf Q4_0_ROCMFP4_FAST 16 > logs/N3_q103i.log 2>&1"
45
+ python3 readback.py Q6_K Q5_K out-imat/$N-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf > logs/N3_readback.log
46
+ python3 readback.py Q6_K Q6_K out-imat/$N-imatrix-Q4_0_ROCMFP4_COHERENT.gguf >> logs/N3_readback.log
47
+ python3 readback.py Q6_K - out-imat/$N-imatrix-Q4_0_ROCMFP4_FAST.gguf >> logs/N3_readback.log
48
+ echo N3_DONE >> logs/N3_readback.log
49
+ ) &
50
+ n3=$!
51
+ grade(){ $PPL -m "$2" --kl-divergence-base kld/bf16.kld --kl-divergence > logs/N4_kld_$1.log 2>&1
52
+ log " $1 exit=$? $(grep -E 'Mean +KLD' logs/N4_kld_$1.log | tr -s ' ')"; }
53
+ grade q106 out/$N-Q4_0_ROCMFP4_STRIX_LEAN.gguf
54
+ grade q102 out/$N-Q4_0_ROCMFP4_COHERENT.gguf
55
+ grade q103 out/$N-Q4_0_ROCMFP4_FAST.gguf
56
+ wait $n3; log "N3 done: $(grep -c ^PASS logs/N3_readback.log)/3 read-back PASS"; cat logs/N3_readback.log
57
+ for l in N3_q106i N3_q102i N3_q103i; do printf "%-9s " $l; grep -oE "quant size\s*=\s*[0-9.]+ MiB \([0-9.]+ BPW\)" logs/$l.log; done | tee -a logs/Q_sizes.log
58
+ log "N4b grade the imatrix tiers"
59
+ grade q106i out-imat/$N-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf
60
+ grade q102i out-imat/$N-imatrix-Q4_0_ROCMFP4_COHERENT.gguf
61
+ grade q103i out-imat/$N-imatrix-Q4_0_ROCMFP4_FAST.gguf
62
+
63
+ log "N5 repeat the STRIX_LEAN grade; every per-chunk row must match"
64
+ $PPL -m out/$N-Q4_0_ROCMFP4_STRIX_LEAN.gguf --kl-divergence-base kld/bf16.kld --kl-divergence > logs/N5_kld_q106_repeat.log 2>&1
65
+ a=$(table logs/N5_kld_q106_repeat.log); b=$(table logs/N4_kld_q106.log); n=$(printf '%s\n' "$a" | grep -c .)
66
+ echo "{\"step\":\"N5\",\"rows\":$n,\"result\":\"$( [ "$n" -ge 40 ] && [ "$a" = "$b" ] && echo MATCH || echo MISMATCH )\"}" | tee results/nex_repeat.jsonl
67
+
68
+ log "N6 speed + gates"
69
+ python3 nex_bench.py > logs/N6_bench.log 2>&1; log "N6 exit=$?"
70
+ log "N7 memory sizing"
71
+ bash nex_sizing.sh > logs/N7_sizing.log 2>&1; log "N7 exit=$?"
72
+ log "N8 un-ice"
73
+ bash $A/unice.sh > logs/N8_unice.log 2>&1; log "N8 exit=$? $(tail -1 logs/N8_unice.log)"
74
+ log "NEX_PHASE2_DONE"
recipe/pipeline/nex_phase2b.sh ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Nex-N2.5-mini phase 2b. Phase 2 stopped at 22:24Z: this build's ROCm0 path computes the BF16 MoE GGUF wrong
3
+ # (wikitext PPL 106 vs 7.8 for its own 4-bit quant; -fa off and "-ngl 0" with the default op offload are wrong too).
4
+ # Controls, chunk 1: pure CPU (-dev none --no-op-offload) 5.6964, Vulkan0 5.6953.
5
+ # => BF16 reference logits and the imatrix are computed on PURE CPU; every 4-bit file is graded on BOTH GPU backends
6
+ # against that reference; then speed + gates -> memory sizing -> Nex FAST seats -> un-ice (as phase 2).
7
+ set -uo pipefail
8
+ W=/mnt/models/nex-n2.5-mini; A=/mnt/models/agnes-3.0-flash; B=/opt/llama-rocm/rocmfpx-724/build-hipvk/bin; N=Nex-N2.5-mini
9
+ export LD_LIBRARY_PATH=$B:/opt/rocm-7.2.4/lib HSA_OVERRIDE_GFX_VERSION=11.5.1 GGML_HIP_ENABLE_UNIFIED_MEMORY=1
10
+ cd $W; mkdir -p kld imat out-imat results
11
+ prlimit --pid $$ --core=1:1 # RLIMIT_CORE of exactly 1 BYTE (bash `ulimit -c 1` is 1 KiB and does not stop apport)
12
+ log(){ echo "[$(date -u +%FT%TZ)] $*"; }
13
+ table(){
14
+ python3 - "$1" <<'EOF'
15
+ import sys
16
+ out = []
17
+ for l in open(sys.argv[1], errors="replace"):
18
+ t = l.split()
19
+ if len(t) > 2 and t[0].isdigit() and l.rstrip().endswith("%") and l.count("%") == 2:
20
+ out.append(" ".join(t))
21
+ print("\n".join(out))
22
+ EOF
23
+ }
24
+ chunk1(){ grep -oE '\[1\][0-9.]+' "$1" | head -1 | cut -d']' -f2; }
25
+ CPU="-dev none -ngl 0 --no-op-offload -t 16"
26
+ PPL="$B/llama-perplexity -c 2048 -b 2048"
27
+ BF=gguf/$N-BF16.gguf; Q=$B/llama-quantize; TXT=$A/calib/wikitext-2-raw/wiki.test.raw
28
+
29
+ log "N1c BF16 perplexity + base logits on pure CPU (wikitext-2 test, 40 chunks)"
30
+ $PPL -m $BF -f $TXT --chunks 40 --kl-divergence-base kld/bf16.kld $CPU > logs/N1c_ppl_bf16_cpu.log 2>&1
31
+ log "N1c exit=$? $(grep -E 'Final estimate' logs/N1c_ppl_bf16_cpu.log)"
32
+ a=$(chunk1 logs/N1c_ppl_bf16_cpu.log); b=$(chunk1 logs/diag_bf16_vk_faon.log)
33
+ if ! python3 -c "import sys; a, b = float('${a:-nan}'), float('${b:-nan}'); sys.exit(0 if abs(a - b) / b < 0.005 else 1)"; then
34
+ log "GATE FAIL: CPU chunk-1 PPL ${a:-missing} vs Vulkan0 control ${b:-missing} -> stop (box stays iced)"; log "NEX_PHASE2B_FAILED"; exit 1
35
+ fi
36
+ echo "{\"step\":\"N1c\",\"cpu_chunk1\":$a,\"vulkan0_chunk1\":$b,\"hip_rocm0_chunk1\":$(chunk1 logs/N1_ppl_bf16.log),\"hip_rocm0_faoff_chunk1\":$(chunk1 logs/diag_bf16_rocm_faoff.log),\"hip_rocm0_final\":$(grep -oE 'Final estimate: PPL = [0-9.]+' logs/N1_ppl_bf16.log | grep -oE '[0-9.]+$'),\"result\":\"PASS\"}" | tee results/nex_reference.jsonl
37
+ log "N1c gate PASS (CPU $a vs Vulkan0 $b)"
38
+
39
+ log "N2c imatrix on pure CPU (BF16, bartowski calibration_datav3, c=512)"
40
+ $B/llama-imatrix -m $BF -f $A/calib/calibration_datav3.txt -o imat/$N.imatrix -c 512 -b 512 $CPU > logs/N2c_imatrix_cpu.log 2>&1
41
+ rc=$?; log "N2c exit=$rc"
42
+ [ $rc -eq 0 ] && [ -s imat/$N.imatrix ] || { log "imatrix failed -> stop (box stays iced)"; log "NEX_PHASE2B_FAILED"; exit 2; }
43
+ sha256sum imat/$N.imatrix > imat/$N.imatrix.sha256
44
+
45
+ log "N3 imatrix tiers on CPU (background) while the standard tiers are graded on the GPU"
46
+ (
47
+ systemd-run --scope --quiet -p MemoryMax=24G -p MemorySwapMax=0 nice -n 5 bash -c "
48
+ $Q --imatrix imat/$N.imatrix --output-tensor-type q6_K $BF out-imat/$N-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf Q4_0_ROCMFP4_STRIX_LEAN 16 > logs/N3_q106i.log 2>&1
49
+ $Q --imatrix imat/$N.imatrix --output-tensor-type q6_K --token-embedding-type q6_K $BF out-imat/$N-imatrix-Q4_0_ROCMFP4_COHERENT.gguf Q4_0_ROCMFP4_COHERENT 16 > logs/N3_q102i.log 2>&1
50
+ $Q --imatrix imat/$N.imatrix --output-tensor-type q6_K $BF out-imat/$N-imatrix-Q4_0_ROCMFP4_FAST.gguf Q4_0_ROCMFP4_FAST 16 > logs/N3_q103i.log 2>&1"
51
+ python3 readback.py Q6_K Q5_K out-imat/$N-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf > logs/N3_readback.log
52
+ python3 readback.py Q6_K Q6_K out-imat/$N-imatrix-Q4_0_ROCMFP4_COHERENT.gguf >> logs/N3_readback.log
53
+ python3 readback.py Q6_K - out-imat/$N-imatrix-Q4_0_ROCMFP4_FAST.gguf >> logs/N3_readback.log
54
+ echo N3_DONE >> logs/N3_readback.log
55
+ ) &
56
+ n3=$!
57
+ grade(){ # tag file device logprefix
58
+ $PPL -m "$2" --kl-divergence-base kld/bf16.kld --kl-divergence -ngl 999 -fa on -dio -dev $3 > logs/$4_kld_$1.log 2>&1
59
+ log " $4 $1 exit=$? $(grep -E 'Mean +KLD' logs/$4_kld_$1.log | tr -s ' ')"
60
+ }
61
+ for t in "q106 out/$N-Q4_0_ROCMFP4_STRIX_LEAN.gguf" "q102 out/$N-Q4_0_ROCMFP4_COHERENT.gguf" "q103 out/$N-Q4_0_ROCMFP4_FAST.gguf"; do
62
+ set -- $t; grade $1 $2 ROCm0 N4; grade $1 $2 Vulkan0 N4v
63
+ done
64
+ wait $n3; log "N3 done: $(grep -c ^PASS logs/N3_readback.log)/3 read-back PASS"; cat logs/N3_readback.log
65
+ for l in N3_q106i N3_q102i N3_q103i; do printf "%-9s " $l; grep -oE "quant size\s*=\s*[0-9.]+ MiB \([0-9.]+ BPW\)" logs/$l.log; done | tee -a logs/Q_sizes.log
66
+ log "N4 grade the imatrix tiers (both backends)"
67
+ for t in "q106i out-imat/$N-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf" "q102i out-imat/$N-imatrix-Q4_0_ROCMFP4_COHERENT.gguf" "q103i out-imat/$N-imatrix-Q4_0_ROCMFP4_FAST.gguf"; do
68
+ set -- $t; grade $1 $2 ROCm0 N4; grade $1 $2 Vulkan0 N4v
69
+ done
70
+
71
+ log "N5 repeat the STRIX_LEAN grade on both backends; every per-chunk row must match"
72
+ : > results/nex_repeat.jsonl
73
+ for pair in "ROCm0 N4 N5" "Vulkan0 N4v N5v"; do
74
+ set -- $pair
75
+ $PPL -m out/$N-Q4_0_ROCMFP4_STRIX_LEAN.gguf --kl-divergence-base kld/bf16.kld --kl-divergence -ngl 999 -fa on -dio -dev $1 \
76
+ > logs/$3_kld_q106_repeat.log 2>&1
77
+ x=$(table logs/$3_kld_q106_repeat.log); y=$(table logs/$2_kld_q106.log); n=$(printf '%s\n' "$x" | grep -c .)
78
+ echo "{\"step\":\"$3\",\"device\":\"$1\",\"rows\":$n,\"result\":\"$( [ "$n" -ge 40 ] && [ "$x" = "$y" ] && echo MATCH || echo MISMATCH )\"}" | tee -a results/nex_repeat.jsonl
79
+ done
80
+
81
+ log "N6 speed + gates"
82
+ python3 nex_bench.py > logs/N6_bench.log 2>&1; log "N6 exit=$?"
83
+ log "N7 memory sizing"
84
+ bash nex_sizing.sh > logs/N7_sizing.log 2>&1; log "N7 exit=$?"
85
+ log "N8 Nex FAST seats + un-ice"
86
+ bash $A/unice.sh > logs/N8_unice.log 2>&1; log "N8 exit=$? $(tail -1 logs/N8_unice.log)"
87
+ log "NEX_PHASE2_DONE"
recipe/pipeline/nex_publish.py ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Stage (hardlinks), upload, and byte-verify the two Nex-N2.5-mini repos.
3
+ usage: nex_publish.py stage|upload|verify|readme <std|imat> [README path]
4
+ Upload through upload_watchdog.sh (40G cap, stall kill + retry) - see nex_cards.sh upload
5
+ Env: default HF_HOME (token); HF_XET_CACHE / TMPDIR pinned to /mnt/models by the caller."""
6
+ import hashlib, json, os, shutil, sys, urllib.request
7
+
8
+ W = "/mnt/models/nex-n2.5-mini"; N = "Nex-N2.5-mini"; U = "kingjones777"
9
+ REPOS = {"std": f"{U}/{N}-ROCmFP4-GGUF", "imat": f"{U}/{N}-ROCmFP4-imatrix-GGUF"}
10
+
11
+
12
+ def pubname(fn):
13
+ """Published filename: the quant token must be hyphen-delimited or the Hub cannot parse the variant
14
+ (`Q4_0_ROCMFP4_STRIX_LEAN` reads as the garbage label `Q4_0_ROCMFP`)."""
15
+ return fn.replace("Q4_0_ROCMFP4_", "Q4_0-ROCmFP4-")
16
+
17
+
18
+ MMPROJ = {f"mmproj-{N}-BF16.gguf": (f"{W}/out", f"mmproj-{N}-BF16.gguf")}
19
+ # the stock chat template plus one line that maps enable_thinking onto reasoning_effort (served with
20
+ # --chat-template-file; see the card's Reasoning controls) - shipped in both repos
21
+ TPL = {"chat_template_enable_thinking.jinja": (f"{W}/tpl", "chat_template_enable_thinking.jinja")}
22
+ TIERS = ("Q4_0_ROCMFP4_STRIX_LEAN", "Q4_0_ROCMFP4_COHERENT", "Q4_0_ROCMFP4_FAST")
23
+ FILES = {
24
+ "std": {**{pubname(f"{N}-{t}.gguf"): (f"{W}/out", f"{N}-{t}.gguf") for t in TIERS}, **MMPROJ, **TPL},
25
+ "imat": {**{pubname(f"{N}-imatrix-{t}.gguf"): (f"{W}/out-imat", f"{N}-imatrix-{t}.gguf") for t in TIERS},
26
+ f"{N}.imatrix": (f"{W}/imat", f"{N}.imatrix"), **MMPROJ, **TPL},
27
+ }
28
+ P = "recipe/pipeline/"
29
+ SCRIPTS = ("nex_download.sh", "verify_download.py", "nex_phase1.sh", "nex_phase2.sh", "diag_bf16.sh", "nex_phase2b.sh",
30
+ "nex_harness.py", "nex_bench.py", "nex_sizing.sh",
31
+ "nex_cachegate.py", "readback.py", "nex_aggregate.py", "nex_judge.py", "nex_render.py", "nex_publish.py",
32
+ "nex_cards.sh", "upload_watchdog.sh", "nex_seats.sh",
33
+ # tool-call / reasoning diagnosis (stock template 6/14) and the template fix
34
+ "diag_tools_run.sh", "nex_tools_diag.py", "nex_reasoning_probe.py", "nex_tools_tpl.py",
35
+ "nex_seat_default_probe.py", "run_tools_c1.sh", "run_tools_roff.sh", "nex_refresh_cards.sh", "nex_publish_finish.sh")
36
+ LOGS = (
37
+ "D2_verify_download.log", "phase1.log", "phase2.log", "Q_sizes.log", "N6_bench.log", "N7_sizing.log",
38
+ "b_n-vision-q106-faon.log", "b_n-vision-q106-faoff.log",
39
+ "C1_convert.log", "C2_mmproj.log", "C_readback.log",
40
+ "Q1_q106.log", "Q1_q102.log", "Q1_q103.log", "Q_readback.log",
41
+ "N1c_ppl_bf16_cpu.log", "N2c_imatrix_cpu.log",
42
+ # the stopped first attempt on ROCm0 and the backend diagnosis that followed (the Known issues evidence)
43
+ "N1_ppl_bf16.log", "diag_ppl_q106_rocm_c4.log", "diag_bf16.log", "diag_bf16_rocm_faoff.log", "diag_bf16_vk_faon.log",
44
+ "diag_q106_vk_faon.log", "diag_bf16_cpu.log", "diag_bf16_purecpu_c1.log",
45
+ "N3_q106i.log", "N3_q102i.log", "N3_q103i.log", "N3_readback.log",
46
+ *(f"{p}_kld_{t}.log" for p in ("N4", "N4v") for t in ("q106", "q102", "q103", "q106i", "q102i", "q103i")),
47
+ "N5_kld_q106_repeat.log", "N5v_kld_q106_repeat.log", "b_n-c3-q106.log",
48
+ "b_n-tools-q106.log", "diag_tools.log", "diag_tools_server.log",
49
+ "probe_reasoning.log", *(f"probe_reasoning_{c}.log" for c in
50
+ ("default", "fmt-deepseek", "srv-kwargs-high", "reasoning-on", "tpl-enable-thinking")),
51
+ "N6t_tools_tpl.log", "b_n-tools-q106-tpl.log", "b_n-tools-q106-tpl-probe.log",
52
+ "N6t_tools_tpl_medium.log", "b_n-tools-q106-tpl-medium.log", "b_n-tools-q106-tpl-medium-probe.log",
53
+ "probe_seat_default.log", "probe_seat_default_C1.log", "probe_seat_default_C2.log",
54
+ "N6t_tools_c1.log", "b_n-tools-q106-c1.log", "b_n-tools-q106-c1-probe.log", "b_n-vision-q106-c1-faon.log",
55
+ "N6t_tools_roff.log", "b_n-tools-q106-roff.log", "b_n-tools-q106-roff-r2.log", "b_n-tools-q106-roff-r3.log",
56
+ "b_n-tools-q106-roff-probe.log", "b_n-vision-q106-roff-faon.log",
57
+ "N8_unice.log", "N8a_seats.log", "N8b_seats.log", "N8c_seats.log", "N8d_seats.log",
58
+ )
59
+ RAW = ("nex_repeat.jsonl", "nex_reference.jsonl", "nex_bench.jsonl", "nex_sizing.jsonl", "hub_check.json",
60
+ "nex_tools_diag.json", "nex_reasoning_probe.json", "nex_seat_default_probe.json", "nex_template_shim.json",
61
+ "nex_template_shim_medium.json", "nex_template_shim_c1.json", "nex_template_shim_roff.json",
62
+ "nex_seats.jsonl", "nex_seats_plan.json")
63
+ TEMPLATES = ("chat_template_enable_thinking_medium.jinja", "chat_template_enable_thinking_v2.jinja") # tested, not used
64
+ RECIPE = {
65
+ "recipe/results_summary.json": "results/summary.json",
66
+ **{P + x: x for x in SCRIPTS},
67
+ **{f"recipe/raw/{x}": f"results/{x}" for x in RAW},
68
+ **{f"recipe/logs/{x}": f"logs/{x}" for x in LOGS},
69
+ **{f"recipe/templates/{x}": f"tpl/{x}" for x in TEMPLATES},
70
+ "recipe/templates/chat_template_stock.jinja": "hf/chat_template.jinja",
71
+ }
72
+
73
+
74
+ def separation_errors(kind, names):
75
+ """The imatrix build is its OWN repo (King): no imatrix weights in the standard repo, no standard weights in the
76
+ imatrix repo. The vision projector is the only model file both carry."""
77
+ errs = []
78
+ for fn in names:
79
+ if not fn.endswith(".gguf") or fn.startswith("mmproj-"):
80
+ continue
81
+ is_imat = "-imatrix-" in fn
82
+ if kind == "std" and is_imat:
83
+ errs.append(f"imatrix model file in the standard repo: {fn}")
84
+ if kind == "imat" and not is_imat:
85
+ errs.append(f"standard model file in the imatrix repo: {fn}")
86
+ if kind == "imat" and f"{N}.imatrix" not in names:
87
+ errs.append("imatrix repo is missing the .imatrix file")
88
+ return errs
89
+
90
+
91
+ assert REPOS["std"] != REPOS["imat"]
92
+ assert set(FILES["std"]) & set(FILES["imat"]) == set(MMPROJ) | set(TPL), "only the projector + template may be shared"
93
+ for _k in FILES:
94
+ assert not separation_errors(_k, list(FILES[_k])), separation_errors(_k, list(FILES[_k]))
95
+
96
+
97
+ def git_blob_sha1(p):
98
+ """What the Hub reports as `oid` for a file stored in plain git (no LFS/Xet pointer)."""
99
+ h = hashlib.sha1(b"blob %d\0" % os.path.getsize(p))
100
+ with open(p, "rb") as fh:
101
+ for b in iter(lambda: fh.read(64 << 20), b""):
102
+ h.update(b)
103
+ return h.hexdigest()
104
+
105
+
106
+ def sha(p):
107
+ h = hashlib.sha256()
108
+ with open(p, "rb") as fh:
109
+ for b in iter(lambda: fh.read(64 << 20), b""):
110
+ h.update(b)
111
+ return h.hexdigest()
112
+
113
+
114
+ kind = sys.argv[2]; stage = f"{W}/hf-upload/{kind}"; repo = REPOS[kind]
115
+ if sys.argv[1] == "stage":
116
+ missing = [f"{d}/{src}" for fn, (d, src) in FILES[kind].items() if not os.path.exists(f"{d}/{src}")] + \
117
+ [src for src in RECIPE.values() if not os.path.exists(f"{W}/{src}")]
118
+ if missing:
119
+ raise SystemExit(f"STAGE ABORT - missing: {missing}")
120
+ shutil.rmtree(stage, ignore_errors=True)
121
+ for fn, (d, src) in FILES[kind].items():
122
+ os.makedirs(stage, exist_ok=True); os.link(f"{d}/{src}", f"{stage}/{fn}")
123
+ for dst, src in RECIPE.items():
124
+ os.makedirs(os.path.dirname(f"{stage}/{dst}"), exist_ok=True); shutil.copy2(f"{W}/{src}", f"{stage}/{dst}")
125
+ sums = {fn: sha(f"{stage}/{fn}") for fn in sorted(FILES[kind])}
126
+ with open(f"{stage}/SHA256SUMS", "w") as fh:
127
+ for fn, h in sums.items():
128
+ fh.write(f"{h} {fn}\n")
129
+ sizes = {x: os.path.getsize(f"{stage}/{x}") for x in sums}
130
+ json.dump(sizes, open(f"{stage}/../staged_sizes_{kind}.json", "w"))
131
+ print(json.dumps({"stage": stage, "files": len(sums), "bytes": sum(sizes.values()), "recipe_files": len(RECIPE)}))
132
+ elif sys.argv[1] == "upload":
133
+ from huggingface_hub import HfApi
134
+ api = HfApi()
135
+ print("whoami:", api.whoami()["name"], flush=True)
136
+ api.create_repo(repo, repo_type="model", private=False, exist_ok=True)
137
+ api.upload_large_folder(repo_id=repo, repo_type="model", folder_path=stage,
138
+ ignore_patterns=["README.md", ".cache/**"], num_workers=2)
139
+ print("UPLOAD_DONE", repo, flush=True)
140
+ elif sys.argv[1] == "verify":
141
+ tree = json.load(urllib.request.urlopen(f"https://huggingface.co/api/models/{repo}/tree/main?recursive=true", timeout=60))
142
+ remote = {t["path"]: t for t in tree if t.get("type") == "file"}
143
+ local = dict(l.split()[::-1] for l in open(f"{stage}/SHA256SUMS").read().splitlines())
144
+ bad = []
145
+ for fn, h in local.items():
146
+ r = remote.get(fn)
147
+ if not r:
148
+ bad.append((fn, "MISSING remote")); continue
149
+ if r["size"] != os.path.getsize(f"{stage}/{fn}"):
150
+ bad.append((fn, f"size {r['size']}")); continue
151
+ lfs = r.get("lfs")
152
+ if lfs:
153
+ if lfs.get("oid") != h:
154
+ bad.append((fn, f"sha {lfs.get('oid')} != {h[:12]}"))
155
+ elif r.get("oid") != git_blob_sha1(f"{stage}/{fn}"):
156
+ bad.append((fn, f"git oid {r.get('oid')} does not match the staged bytes"))
157
+ for fn in list(RECIPE) + ["SHA256SUMS"]:
158
+ if fn not in remote:
159
+ bad.append((fn, "MISSING remote"))
160
+ stale = sorted(x for x in remote if x not in local and x not in RECIPE and x not in ("SHA256SUMS", "README.md", ".gitattributes"))
161
+ bad += [(x, "SEPARATION") for x in separation_errors(kind, list(remote))]
162
+ print(json.dumps({"repo": repo, "checked": len(local), "bad": bad, "unexpected_remote_files": stale,
163
+ "result": "PASS" if not bad and not stale else "FAIL"}))
164
+ sys.exit(0 if not bad and not stale else 1)
165
+ elif sys.argv[1] == "readme":
166
+ from huggingface_hub import HfApi
167
+ HfApi().upload_file(path_or_fileobj=sys.argv[3], path_in_repo="README.md", repo_id=repo, repo_type="model",
168
+ commit_message="Model card: measured results, reproduction, known issues")
169
+ print("README_DONE", repo)
170
+ else:
171
+ raise SystemExit(f"usage: {sys.argv[0]} stage|upload|verify|readme <std|imat> [README path]")
recipe/pipeline/nex_publish_finish.sh ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Publish the two Nex repos (Jay, 2026-09-17). Order:
3
+ # 1. wait until the OxCoder speed + memory runs are finished (its phase-2 log reaches "O7 exit"), so this upload never
4
+ # holds the quiet-box lock they need;
5
+ # 2. upload std, then imat, through upload_watchdog.sh (40G cap, stall kill + retry) under the quiet-box lock;
6
+ # 3. verify both repos: model files by size + sha256, every recipe file by content (git sha1 / LFS sha256);
7
+ # 4. push the READMEs only once cards/.factcheck_ok exists (created by hand after the lane fact-checks are reviewed).
8
+ set -uo pipefail
9
+ W=/mnt/models/nex-n2.5-mini; O=/mnt/models/oxcoder-9b; cd $W
10
+ export HF_XET_CACHE=/mnt/models/.hf-xet-cache TMPDIR=/mnt/models/.tmp HF_HUB_DISABLE_TELEMETRY=1 PYTHONUNBUFFERED=1
11
+ log(){ echo "[$(date -u +%FT%TZ)] $*"; }
12
+ log "waiting for the OxCoder speed + memory runs to finish (phase-2 log reaches O7)"
13
+ until grep -q -E "O7 exit=|OXCODER_PHASE2_(DONE|FAILED)" $O/logs/phase2.log 2>/dev/null; do sleep 30; done
14
+ exec 9>/mnt/models/.quiet-box.lock; log "waiting for the quiet-box lock"; flock 9; log "quiet-box lock held"
15
+ ok=1
16
+ for k in std imat; do
17
+ bash upload_watchdog.sh nex-upload-$k $W python3 nex_publish.py upload $k || { log "upload $k FAILED"; ok=0; }
18
+ done
19
+ exec 9>&-; log "quiet-box lock released"
20
+ for k in std imat; do
21
+ python3 nex_publish.py verify $k > logs/verify_$k.log 2>&1 || ok=0
22
+ log "verify $k: $(tail -c 300 logs/verify_$k.log)"
23
+ done
24
+ python3 - > logs/verify_recipe_content.log 2>&1 <<'PY' || ok=0
25
+ import hashlib, json, os, sys, urllib.request
26
+ W = "/mnt/models/nex-n2.5-mini"
27
+ REPOS = {"std": "kingjones777/Nex-N2.5-mini-ROCmFP4-GGUF", "imat": "kingjones777/Nex-N2.5-mini-ROCmFP4-imatrix-GGUF"}
28
+ bad, n = [], 0
29
+ for k, repo in REPOS.items():
30
+ tree = json.load(urllib.request.urlopen(
31
+ "https://huggingface.co/api/models/%s/tree/main?recursive=true" % repo, timeout=60))
32
+ remote = {t["path"]: t for t in tree if t.get("type") == "file"}
33
+ root = "%s/hf-upload/%s" % (W, k)
34
+ for dp, _, fns in os.walk(root + "/recipe"):
35
+ for fn in fns:
36
+ p = os.path.join(dp, fn)
37
+ rel = os.path.relpath(p, root)
38
+ r = remote.get(rel)
39
+ n += 1
40
+ if r is None:
41
+ bad.append((k, rel, "missing remote"))
42
+ continue
43
+ data = open(p, "rb").read()
44
+ if r.get("lfs"):
45
+ same = r["lfs"].get("oid") == hashlib.sha256(data).hexdigest()
46
+ else:
47
+ same = r.get("oid") == hashlib.sha1(b"blob %d\0" % len(data) + data).hexdigest()
48
+ if not same:
49
+ bad.append((k, rel, "content differs"))
50
+ print(json.dumps({"recipe_files_checked": n, "bad": bad, "result": "PASS" if not bad else "FAIL"}))
51
+ sys.exit(1 if bad else 0)
52
+ PY
53
+ log "recipe content: $(tail -c 300 logs/verify_recipe_content.log)"
54
+ if [ $ok -ne 1 ]; then log "NEX_PUBLISH_FAILED (files)"; exit 1; fi
55
+ log "files verified; waiting for cards/.factcheck_ok before the READMEs"
56
+ until [ -f cards/.factcheck_ok ]; do sleep 30; done
57
+ for k in std imat; do
58
+ python3 nex_publish.py readme $k cards/README_$k.md > logs/readme_$k.log 2>&1 || ok=0
59
+ log "readme $k: $(tail -1 logs/readme_$k.log)"
60
+ done
61
+ [ $ok -eq 1 ] && log "NEX_PUBLISH_DONE" || log "NEX_PUBLISH_FAILED (readme)"
recipe/pipeline/nex_reasoning_probe.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Find a llama-server configuration that separates Nex's reasoning from `content` when thinking is on.
3
+ Diagnostic follow-up to nex_tools_diag.py (reasoning_content empty, `...</think>` left in content for
4
+ reasoning_effort=high and for the template's default). Each config: start the unpatched server with extra flags
5
+ (and, for the last one, a template copy in which enable_thinking drives reasoning_effort), send the same three
6
+ thinking-on requests, record content / reasoning_content / tool calls. Diagnostic only -> results/nex_reasoning_probe.json."""
7
+ import json, os, re, sys, time
8
+ from types import SimpleNamespace
9
+
10
+ os.environ["AGNES_BIN"] = "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin"
11
+ sys.path.insert(0, "/mnt/models/nex-n2.5-mini")
12
+ import nex_harness as H # noqa: E402
13
+
14
+ W = H.W
15
+ PORT = 18651
16
+ OUT = f"{W}/results/nex_reasoning_probe.json"
17
+ TPL_SRC = f"{W}/hf/chat_template.jinja"
18
+ TPL_PATCHED = f"{W}/results/nex_template_enable_thinking.jinja"
19
+
20
+ # template copy: if the caller passes enable_thinking (and no reasoning_effort), map it onto reasoning_effort
21
+ src = open(TPL_SRC).read()
22
+ shim = ("{%- if reasoning_effort is not defined and enable_thinking is defined %}"
23
+ "{%- set reasoning_effort = 'high' if enable_thinking else 'none' %}{%- endif %}\n")
24
+ open(TPL_PATCHED, "w").write(shim + src)
25
+
26
+ CONFIGS = [
27
+ ("default", [], {"reasoning_effort": "high"}),
28
+ ("fmt-deepseek", ["--reasoning-format", "deepseek"], {"reasoning_effort": "high"}),
29
+ ("srv-kwargs-high", ["--chat-template-kwargs", json.dumps({"reasoning_effort": "high"})], {}),
30
+ ("reasoning-on", ["--reasoning", "on"], {"reasoning_effort": "high"}),
31
+ ("tpl-enable-thinking", ["--chat-template-file", TPL_PATCHED], {"enable_thinking": True}),
32
+ ]
33
+ REQS = [
34
+ ("correct-decline", "What is 17 times 23? Answer directly."),
35
+ ("multi-arg", "What's the weather in Paris in celsius?"),
36
+ ("parallel", "Get the weather in Oslo AND in Lima, both in celsius. Call the tool for each city."),
37
+ ]
38
+
39
+
40
+ def patched_popen_cmd(a, port, extra):
41
+ """H.Server builds and launches its argv in __init__; append the extra flags through a temporary Popen hook."""
42
+ import subprocess
43
+ orig = subprocess.Popen
44
+
45
+ def popen(cmd, *args, **kw):
46
+ if cmd and str(cmd[0]).endswith("llama-server"):
47
+ cmd = list(cmd) + list(extra)
48
+ return orig(cmd, *args, **kw)
49
+ subprocess.Popen = popen
50
+ try:
51
+ return H.Server(a, port)
52
+ finally:
53
+ subprocess.Popen = orig
54
+
55
+
56
+ report = {"template_shim": shim, "configs": {}}
57
+ for name, extra, kwargs in CONFIGS:
58
+ a = SimpleNamespace(model=f"{W}/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf", dev="ROCm0", ctx=16384,
59
+ draft=None, mtp_infile=False, nmax=4, pmin=0.0, strict=False,
60
+ serverlog=f"{W}/logs/probe_reasoning_{name}.log")
61
+ rec = {"extra": extra, "kwargs": kwargs, "results": {}}
62
+ try:
63
+ s = patched_popen_cmd(a, PORT, extra)
64
+ except SystemExit as e:
65
+ rec["error"] = str(e)
66
+ report["configs"][name] = rec
67
+ print(name, "SERVER FAILED", e, flush=True)
68
+ continue
69
+ try:
70
+ for rn, prompt in REQS:
71
+ body = {"messages": [{"role": "user", "content": prompt}], "tools": H.TOOLS, "tool_choice": "auto",
72
+ "temperature": 0, "top_k": 1, "max_tokens": 2048, "chat_template_kwargs": kwargs}
73
+ try:
74
+ m = H.post(PORT, "/v1/chat/completions", body)["choices"][0]["message"]
75
+ c = m.get("content") or ""
76
+ rec["results"][rn] = {"content": c[:300], "reasoning": (m.get("reasoning_content") or "")[:300],
77
+ "tool_calls": [(t.get("function") or {}).get("name") for t in m.get("tool_calls") or []],
78
+ "leaks": [x for x in H.LEAK if x in c]}
79
+ except Exception as e: # noqa: BLE001
80
+ rec["results"][rn] = {"error": repr(e)[:300]}
81
+ print(name, rn, json.dumps(rec["results"][rn])[:300], flush=True)
82
+ log = open(a.serverlog, errors="replace").read()
83
+ rec["chat_format_lines"] = sorted(set(re.findall(r"Chat format: \S+", log)))
84
+ rec["thinking_line"] = next((l.strip()[-80:] for l in log.splitlines() if "thinking =" in l), None)
85
+ finally:
86
+ s.stop()
87
+ report["configs"][name] = rec
88
+ time.sleep(3)
89
+ json.dump(report, open(OUT, "w"), indent=1)
90
+ print("NEX_REASONING_PROBE_DONE", OUT)
recipe/pipeline/nex_refresh_cards.sh ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Re-render the Nex cards after script or text fixes without re-staging the model files: summary (reuses the staged
3
+ # sha256), refresh every recipe copy in both stages with a FRESH mtime (plain cp; `cp -p` can hide a change from
4
+ # upload_large_folder's cache), judge, render. Light work, niced; no HF traffic.
5
+ set -euo pipefail
6
+ W=/mnt/models/nex-n2.5-mini; cd $W
7
+ log(){ echo "[$(date -u +%FT%TZ)] $*"; }
8
+ [ -s hf-upload/std/SHA256SUMS ] && [ -s hf-upload/imat/SHA256SUMS ] || { log "not staged yet -> run nex_cards.sh cards"; exit 3; }
9
+ nice -n 19 ionice -c3 python3 nex_aggregate.py > logs/aggregate_refresh.log 2>&1; tail -3 logs/aggregate_refresh.log
10
+ python3 - <<'PY'
11
+ import os, shutil, sys
12
+ sys.argv = ["nex_publish.py", "noop", "std"]
13
+ src = open("nex_publish.py").read()
14
+ ns = {}
15
+ exec(compile(src[:src.index("kind = sys.argv[2]")], "nex_publish_head", "exec"), ns)
16
+ W = ns["W"]
17
+ changed = 0
18
+ for kind in ("std", "imat"):
19
+ stage = f"{W}/hf-upload/{kind}"
20
+ for dst, s in ns["RECIPE"].items():
21
+ a, b = f"{W}/{s}", f"{stage}/{dst}"
22
+ if not os.path.exists(b) or open(a, "rb").read() != open(b, "rb").read():
23
+ os.makedirs(os.path.dirname(b), exist_ok=True)
24
+ shutil.copyfile(a, b) # fresh mtime on purpose
25
+ changed += 1
26
+ print("refreshed", kind, dst)
27
+ print("recipe files refreshed:", changed)
28
+ PY
29
+ python3 nex_judge.py results/summary.json results/judgments.json > logs/judge.log 2>&1; head -1 logs/judge.log | cut -c1-200
30
+ rm -rf cards
31
+ python3 nex_render.py results/summary.json cards results/judgments.json \
32
+ hf-upload/std/SHA256SUMS hf-upload/imat/SHA256SUMS hf-upload/staged_sizes.json
33
+ log "NEX_CARDS_REFRESHED"
recipe/pipeline/nex_render.py ADDED
@@ -0,0 +1,752 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Render both HF cards from summary.json + judgments.json. Every number comes from the summary;
3
+ absent => '—'. Judgment prose lives in nex_judge.py and only ever references computed values.
4
+ usage: nex_render.py <summary.json> <outdir> <judgments.json> <SHA256SUMS_std> <SHA256SUMS_imat> <staged_sizes.json>"""
5
+ import json, math, os, sys
6
+
7
+ S = json.load(open(sys.argv[1])); OUT = sys.argv[2]; os.makedirs(OUT, exist_ok=True)
8
+ JUDGE = json.load(open(sys.argv[3]))
9
+ SUMS = {}
10
+ for sf in sys.argv[4:6]:
11
+ if os.path.exists(sf):
12
+ for line in open(sf):
13
+ h, fn = line.split(maxsplit=1); SUMS[fn.strip()] = h
14
+ SIZES = json.load(open(sys.argv[6])) if len(sys.argv) > 6 and os.path.exists(sys.argv[6]) else {}
15
+ N = S["model"]; STD, IMAT = S["model_repo_std"], S["model_repo_imat"]
16
+ T = S.get("tiers") or {}; B = S.get("binary") or {}; SRC = S.get("source") or {}; AR = S.get("arch") or {}
17
+ GiB, MiB = 1024 ** 3, 1024 ** 2
18
+ UB = S.get("n_ubatch") if S.get("n_ubatch") is not None else 1024
19
+ CTX, GEN, REPS = 65536, 256, 3
20
+ STD_TAGS, IMAT_TAGS = ("q106", "q102", "q103"), ("q106i", "q102i", "q103i")
21
+ NAMES = {"q106": "STRIX_LEAN", "q102": "COHERENT", "q103": "FAST",
22
+ "q106i": "STRIX_LEAN", "q102i": "COHERENT", "q103i": "FAST"}
23
+
24
+
25
+ def g(v, fmt="{:.2f}"):
26
+ return "—" if v is None else fmt.format(v)
27
+
28
+
29
+ def gib(b):
30
+ return g(None if b is None else b / GiB, "{:.2f} GiB")
31
+
32
+
33
+ def pm(v, e, fmt="{:.4f}"):
34
+ return "—" if v is None else (fmt.format(v) + ("" if e is None else " ± " + fmt.format(e)))
35
+
36
+
37
+ def bench(label):
38
+ return next((x for x in S.get("bench") or [] if x["label"] == label), None)
39
+
40
+
41
+ def tg(label):
42
+ x = bench(label)
43
+ return None if x is None else x.get("tg_median")
44
+
45
+
46
+ def pp(label):
47
+ x = bench(label)
48
+ return None if x is None else x.get("pp_median")
49
+
50
+
51
+ def gate(label):
52
+ return next((x for x in S.get("gates") or [] if x.get("label") == label), None)
53
+
54
+
55
+ def J(k):
56
+ return JUDGE.get(k, f"**[JUDGMENT PENDING: {k}]**")
57
+
58
+
59
+ def Jopt(k):
60
+ return JUDGE.get(k, "")
61
+
62
+
63
+ def speed_label(tag, dev):
64
+ return f"n-{tag}-{dev}"
65
+
66
+
67
+ def prompt_range(workload="code"):
68
+ """Prompt tokens processed by the timed requests of one workload (each carries a unique nonce)."""
69
+ lo, hi = [], []
70
+ for b in S.get("bench") or []:
71
+ if b.get("workload") != workload:
72
+ continue
73
+ a_ = b.get("prompt_n_min") if b.get("prompt_n_min") is not None else b.get("prompt_n")
74
+ z_ = b.get("prompt_n_max") if b.get("prompt_n_max") is not None else b.get("prompt_n")
75
+ if a_ is not None and z_ is not None:
76
+ lo.append(a_); hi.append(z_)
77
+ if not lo:
78
+ return "—"
79
+ return f"{min(lo):,}" if min(lo) == max(hi) else f"{min(lo):,}–{max(hi):,}"
80
+
81
+
82
+ def tier(tag):
83
+ return T.get(tag) or {}
84
+
85
+
86
+ def tier_row(tag):
87
+ t = tier(tag); ratio = t.get("ppl_ratio")
88
+ r = [f"`{t.get('file') or '—'}`", g(t.get("ftype"), "{}"), gib(t.get("size_bytes")), g(t.get("bpw")),
89
+ pm(t.get("kld_mean"), t.get("kld_err")), g(t.get("same_top_p"), "{:.2f} %"),
90
+ pm(t.get("ppl"), t.get("ppl_err")) + ("" if ratio is None else f" (×{ratio:.4f})"),
91
+ g(tg(speed_label(tag, "rocm"))), g(tg(speed_label(tag, "vk"))),
92
+ g(pp(speed_label(tag, "rocm")), "{:.0f}")]
93
+ return "| " + " | ".join(r) + " |"
94
+
95
+
96
+ PN_TXT = prompt_range("code")
97
+ PROTOCOL = (
98
+ f"Ryzen AI Max+ 395 (MAX-1), ROCm 7.2.4, unpatched `llama-server` at `d3ca537` (see [Quick start](#quick-start)), "
99
+ f"`-c {CTX}`, one request at a time (`--parallel 1`), greedy (`temp 0`, `top_k 1`), `ignore_eos` so every arm "
100
+ f"generates exactly {GEN} tokens "
101
+ f"after a code prompt of {PN_TXT} tokens (the first 30,000 characters of `convert_hf_to_gguf.py` plus an "
102
+ f"instruction), a unique nonce per request and `cache_prompt: false` (`cache_n = 0` asserted on "
103
+ f"every timed request), 1 warm-up then the median of {REPS}. Decode numbers are the server's own "
104
+ f"`predicted_per_second`. Box iced: no other model loaded.")
105
+ TABLE_HEAD = ("| File | ftype | Size | BPW | KLD vs BF16 ↓² | Same top-1 ↑ | PPL (× BF16) | TG ROCm0 | TG Vulkan0 | PP ROCm0 |\n"
106
+ "| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |")
107
+ TG_NOTE = f"TG = decode tokens/s after the {PN_TXT}-token code prompt, no draft head. PP = prefill tokens/s on ROCm0."
108
+
109
+
110
+ def quality_blurb():
111
+ b = S.get("bf16") or {}
112
+ ch, nc, st = b.get("chunks"), b.get("n_ctx"), b.get("scored_tokens")
113
+ if ch is not None and nc is not None and st is not None:
114
+ scored = (f"{ch} chunks × {nc // 2 - 1:,} scored tokens each — the second half of every window, less its first token — = {st:,}")
115
+ else:
116
+ scored = "— chunks × — scored tokens"
117
+ return (f"Quality is graded against the **BF16 GGUF** (reference logits computed on the CPU) on a **held-out** corpus (wikitext-2 *test*, `-c 2048`, "
118
+ f"{scored}), never on the imatrix calibration text. **KLD** is the per-token KL divergence of each "
119
+ "quant's next-token distribution from BF16's on the same tokens — far more sensitive than perplexity.")
120
+
121
+
122
+ def bf16_row():
123
+ b = S.get("bf16") or {}
124
+ return (f"| *BF16 reference* | {g(b.get('ftype'), '{}')} | {gib(b.get('size_bytes'))}³ | 16 | 0 | 100 % | "
125
+ f"{pm(b.get('ppl_paired'), b.get('ppl_paired_err'))}¹ | — | — | — |")
126
+
127
+
128
+ def footnotes(where="below"):
129
+ b = S.get("bf16") or {}
130
+ return (f"{TG_NOTE}\n"
131
+ f"¹ The BF16 PPL shown is the paired base every \"×\" ratio is computed against (averaged over the same scored tokens "
132
+ f"in the KL-divergence runs). The standalone BF16 run's own summary line reads {pm(b.get('ppl'), b.get('ppl_err'))}.\n"
133
+ f"² Quality columns: see *Where the quality numbers come from* {where}.\n"
134
+ f"³ BF16 conversion of the checkpoint; not published.")
135
+
136
+
137
+ YAML = """---
138
+ license: apache-2.0
139
+ base_model: nex-agi/Nex-N2.5-mini
140
+ base_model_relation: quantized
141
+ pipeline_tag: image-text-to-text
142
+ library_name: gguf
143
+ tags:
144
+ - gguf
145
+ - llama.cpp
146
+ - rocm
147
+ - amd
148
+ - rocmfp4
149
+ - rocmfpx
150
+ - strix-halo
151
+ - amd-strix-halo
152
+ - gfx1151
153
+ - ryzen-ai-max
154
+ - ryzen-ai-max-395
155
+ - radeon-8060s
156
+ - moe
157
+ - reasoning
158
+ - multimodal
159
+ - vision
160
+ - nex
161
+ - qwen3.5
162
+ - quantized{extra}
163
+ ---
164
+ """
165
+
166
+
167
+ def cmake_block():
168
+ commit = B.get("commit") or "d3ca537"
169
+ return f"""```bash
170
+ git clone https://github.com/charlie12345/ROCmFPX.git && cd ROCmFPX
171
+ git checkout {commit}
172
+ HIPCXX="$(hipconfig -l)/clang" HIP_PATH="$(hipconfig -R)" \\
173
+ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \\
174
+ -DGGML_HIP=ON -DGGML_VULKAN=ON -DGPU_TARGETS=gfx1151 \\
175
+ -DGGML_HIP_GRAPHS=ON -DGGML_HIP_NO_VMM=ON -DLLAMA_CURL=OFF
176
+ cmake --build build --target llama-server -j
177
+ ```"""
178
+
179
+
180
+ def serve_block(model_file):
181
+ env = ("env LD_LIBRARY_PATH=$PWD/build/bin:/opt/rocm/lib HSA_OVERRIDE_GFX_VERSION=11.5.1 "
182
+ "GGML_HIP_ENABLE_UNIFIED_MEMORY=1 \\\n")
183
+ mm = f" --mmproj ~/models/nex/mmproj-{N}-BF16.gguf \\\n"
184
+ tpl = (" --chat-template-file ~/models/nex/chat_template_enable_thinking.jinja --reasoning off \\\n")
185
+ tail = f" -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -dev ROCm0 \\\n -c {CTX} --host 127.0.0.1 --port 8080"
186
+ head = f"build/bin/llama-server \\\n -m ~/models/nex/{model_file} \\\n"
187
+ cmd = f"```bash\n{env}{head}{mm}{tpl}{tail}\n```"
188
+ w = Jopt("vision_quickstart_warning")
189
+ return cmd + ("\n\n" + w if w else "")
190
+
191
+
192
+ def curl_block():
193
+ return """```bash
194
+ curl http://127.0.0.1:8080/v1/chat/completions \\
195
+ -H 'Content-Type: application/json' \\
196
+ -d '{
197
+ "messages": [{"role": "user", "content": "Hello"}],
198
+ "temperature": 0.7,
199
+ "top_p": 0.95,
200
+ "top_k": 40,
201
+ "chat_template_kwargs": {"enable_thinking": true}
202
+ }'
203
+ ```"""
204
+
205
+
206
+ def quick_start(model_file, repo):
207
+ return f"""**1. Download**
208
+
209
+ ```bash
210
+ hf download {repo} --local-dir ~/models/nex
211
+ ```
212
+
213
+ **2. Build `llama-server`** — ROCmFPX at the measured commit (ROCm and Vulkan
214
+ prerequisites: the project's [build guide](https://github.com/charlie12345/ROCmFPX/blob/{B.get('commit') or 'd3ca537'}/docs/build.md)). No patch.
215
+
216
+ {cmake_block()}
217
+
218
+ (The CMake options of the measured build are listed in [Reproduction](#reproduction).)
219
+
220
+ `d3ca537` is also in the history of the official [ROCmFPX/ROCmFPX](https://github.com/ROCmFPX/ROCmFPX) repository.
221
+
222
+ **3. Serve**
223
+
224
+ {serve_block(model_file)}
225
+
226
+ (`LD_LIBRARY_PATH` avoids a soname clash on machines that also have a Vulkan-only llama.cpp build.) The exact measured
227
+ argv is in [Reproduction](#reproduction).
228
+
229
+ **4. Call** — upstream sampling. Thinking is off unless the request sets `"enable_thinking": true` (as here; drop that
230
+ line for a direct answer):
231
+
232
+ {curl_block()}
233
+
234
+ | Flag | Why |
235
+ | --- | --- |
236
+ | `--chat-template-file …/chat_template_enable_thinking.jinja` | The model's own template plus one line (see [Reasoning controls](#reasoning-controls)). Without it llama-server leaves the reasoning in `content` and thinking-on tool calls fail ([measured](#tool-calling)). |
237
+ | `--reasoning off` | Thinking stays off unless a request passes `"enable_thinking": true`. |
238
+ | `--jinja` | Already on by default in this build; keep it on — the reasoning controls (`chat_template_kwargs`) and tool calling rely on the Jinja chat template. |
239
+ | `-fit off` | Autofit reads `MemAvailable` on integrated GPUs and can silently shrink context or push tensors to CPU. |
240
+ | `-cram <MiB>` | Not set above (default 8 GiB of host RAM for saved prompts). Set it on a shared box — see [Known issues](#known-issues-and-limits). |
241
+ | `--mmproj` | Loads the {AR.get('vision_layers', '—')}-layer vision tower. Drop the flag for text-only. |
242
+
243
+ Requires a llama.cpp build with ROCmFP4 / ROCmFPX tensor-type support; stock llama.cpp rejects these tensor types."""
244
+
245
+
246
+ def reasoning_block():
247
+ tf = S.get("template_fix") or {}
248
+ shim = (tf.get("shim") or "").rstrip("\n")
249
+ shim_md = ("```jinja\n" + shim + "\n```") if shim else "**[JUDGMENT PENDING: template shim]**"
250
+ return f"""## Reasoning controls
251
+
252
+ The model's own chat template switches thinking with `chat_template_kwargs.reasoning_effort` and ignores
253
+ `enable_thinking`:
254
+
255
+ | `reasoning_effort` | What the stock template emits |
256
+ | --- | --- |
257
+ | `"none"` | empty `<think>\\n\\n</think>` (no thinking) |
258
+ | `"high"` | opens `<think>\\n` (always think) |
259
+ | `"medium"`, unset, or anything else | opens `<think>` and lets the model decide (adaptive; upstream default is `"medium"`) |
260
+
261
+ llama-server decides how to split reasoning from the answer by rendering the template with `enable_thinking` on and
262
+ off. With this template both renders are the same, so it never extracts the reasoning ([measured](#tool-calling)).
263
+ `chat_template_enable_thinking.jinja` in this repo is the model's `chat_template.jinja` (sha256
264
+ `{tf.get('source_sha256') or '—'}`) with one line added at the top (file sha256 `{tf.get('sha256') or '—'}`):
265
+
266
+ {shim_md}
267
+
268
+ Serve it with `--chat-template-file` and `--reasoning off`.
269
+
270
+ {J('template_note')}
271
+
272
+ Upstream serving (SGLang) uses `--reasoning-parser qwen3 --tool-call-parser qwen3_coder`. Recommended sampling:
273
+ temperature 0.7, top_p 0.95, top_k 40.
274
+
275
+ Earlier assistant turns are re-rendered **with** their reasoning (contexts grow faster than with templates that drop
276
+ it). With thinking on and a small `max_tokens`, the whole budget can go to reasoning and `content` comes back empty —
277
+ raise `max_tokens` before concluding the model is broken.
278
+
279
+ Tool calls use the XML-style `<tool_call><function=…><parameter=…>` format, which llama.cpp parses natively
280
+ through the Jinja chat template (on by default)."""
281
+
282
+
283
+ def speed_table():
284
+ rows = ["| File | Backend | Workload | Decode tok/s (min–max) | Prefill tok/s |",
285
+ "| --- | --- | --- | ---: | ---: |"]
286
+ for tag in STD_TAGS + IMAT_TAGS:
287
+ t = tier(tag)
288
+ fn = t.get("file") or "—"
289
+ for dev, dn in (("rocm", "ROCm0"), ("vk", "Vulkan0")):
290
+ b = bench(speed_label(tag, dev))
291
+ if b is None or b.get("tg_median") is None:
292
+ rows.append(f"| `{fn}` | {dn} | code | — | — |")
293
+ else:
294
+ rows.append(f"| `{fn}` | {dn} | code | {b['tg_median']:.2f} ({g(b.get('tg_min'))}–{g(b.get('tg_max'))}) | "
295
+ f"{g(b.get('pp_median'), '{:.0f}')} |")
296
+ for lab, dn in (("n-q106-rocm-prose", "ROCm0"), ("n-q106-vk-prose", "Vulkan0")):
297
+ b = bench(lab)
298
+ fn = tier("q106").get("file") or "—"
299
+ if b is None or b.get("tg_median") is None:
300
+ rows.append(f"| `{fn}` | {dn} | prose | — | — |")
301
+ else:
302
+ rows.append(f"| `{fn}` | {dn} | prose | {b['tg_median']:.2f} ({g(b.get('tg_min'))}–{g(b.get('tg_max'))}) | "
303
+ f"{g(b.get('pp_median'), '{:.0f}')} |")
304
+ return "\n".join(rows)
305
+
306
+
307
+ def cache_table():
308
+ x = gate("n-c3-q106")
309
+ rows = ["| server | second-request prompt tokens reused | processed | warm reply = cold reply |",
310
+ "| --- | ---: | ---: | :---: |"]
311
+ if not x:
312
+ rows.append("| d3ca537, unpatched | — | — | — |")
313
+ return "\n".join(rows)
314
+ n, L, ident = x.get("n"), x.get("L"), x.get("identical")
315
+ got = sorted({r_.get("warm_cache_n") for r_ in x.get("rows") or []}, key=lambda v: (v is None, v))
316
+ if n is None or L is None or not got or None in got:
317
+ rows.append("| d3ca537, unpatched | — | — | — |")
318
+ return "\n".join(rows)
319
+ if len(got) == 1:
320
+ reused, proc = f"**{got[0]:,}** of {L:,} (all {n} pairs)", f"{L - got[0]:,}"
321
+ else:
322
+ reused, proc = f"{got[0]:,}–{got[-1]:,} of {L:,} (varies across {n} pairs)", f"{L - got[-1]:,}–{L - got[0]:,}"
323
+ rows.append(f"| d3ca537, unpatched | {reused} | {proc} | {ident if ident is not None else '—'}/{n} |")
324
+ return "\n".join(rows)
325
+
326
+
327
+ def tools_block():
328
+ t = gate("n-tools-q106")
329
+ fx = [gate(l) for l in ("n-tools-q106-roff", "n-tools-q106-roff-r2", "n-tools-q106-roff-r3")]
330
+ if not t and not any(fx):
331
+ return "_Not measured._"
332
+ names = ["multi-arg", "nested-object", "enum", "correct-decline", "multi-turn", "streaming", "parallel"]
333
+ rows = ["| check | quick start, thinking ON | quick start, thinking OFF | stock template, thinking ON | "
334
+ "stock template, thinking OFF |",
335
+ "| --- | :---: | :---: | :---: | :---: |"]
336
+ detail = (t or {}).get("detail") or {}
337
+ mk = lambda x: "—" if x is None else ("✅" if x else "❌")
338
+
339
+ def count(n, think):
340
+ vals = [((x or {}).get("detail") or {}).get(f"{n}|think={think}") for x in fx]
341
+ if any(v is None for v in vals):
342
+ return "—"
343
+ return f"{sum(bool(v) for v in vals)}/{len(vals)}"
344
+ for n in names:
345
+ rows.append(f"| {n} | {count(n, True)} | {count(n, False)} | {mk(detail.get(f'{n}|think=True'))} | "
346
+ f"{mk(detail.get(f'{n}|think=False'))} |")
347
+ fn = os.path.basename(tier("q106").get("file") or "—")
348
+ tot = (f"**{sum(x['passed'] for x in fx)}/{sum(x['total'] for x in fx)}** over three passes with the quick-start "
349
+ f"configuration, **{t['passed']}/{t['total']}** with the stock template"
350
+ if all(fx) and t and t.get("passed") is not None else "Tool-calling suite")
351
+ return (f"{tot}, run on `{fn}`. Quick start = the included template file + `--reasoning off`, thinking switched "
352
+ f"with `enable_thinking`; stock = the model's own template, thinking switched with `reasoning_effort` "
353
+ f"(`high` / `none`). A check passes only with a native `tool_calls` entry carrying the right arguments "
354
+ f"and no raw XML or think tags left in `content`.\n\n" + "\n".join(rows))
355
+
356
+
357
+ def vision_block():
358
+ on, off = gate("n-vision-q106-faon"), gate("n-vision-q106-faoff")
359
+ if not on and not off:
360
+ return "_Not measured._"
361
+ vp = S.get("vision_probe") or {}
362
+ exp_row = next((x for x in (on, off) if x and x.get("expected")), None)
363
+ exp_txt = ", ".join(f"`{e.strip()}`" for e in exp_row["expected"].split(",")) if exp_row else "—"
364
+ def cell(x):
365
+ if not x:
366
+ return "—"
367
+ exp = x.get("expected") or ""
368
+ nexp = len(exp.split(",")) if exp else None
369
+ hits = x.get("hits") or []
370
+ n = f"{len(hits)}/{nexp} terms" if nexp is not None else "—"
371
+ if x.get("result") == "PASS":
372
+ return f"✅ {n}"
373
+ return "❌ " + ("server stopped" if x.get("server_died") else ("request failed" if x.get("error") else n))
374
+ rows = ["| | `-fa on` | `-fa off` |", "| --- | :---: | :---: |",
375
+ f"| STRIX_LEAN + projector | {cell(on)} | {cell(off)} |"]
376
+ txt = (f"Probe: a synthetic {vp.get('width', '—')}×{vp.get('height', '—')} image with a red circle and a blue square "
377
+ f"(a model that ignores the image cannot name both), sent to `{tier('q106').get('file') or '—'}` with "
378
+ f"`--mmproj`, temperature 0. Pass = the reply names every expected term ({exp_txt}).\n\n"
379
+ + "\n".join(rows) + "\n\n" + J("vision_note"))
380
+ ans = next((x for x in (on, off) if x and x.get("result") == "PASS" and x.get("answer")), None)
381
+ if ans:
382
+ a_ = (ans.get("answer") or "").strip()
383
+ which = "`-fa on`" if ans is on else "`-fa off`"
384
+ cut = a_[:300]
385
+ txt += f"\n\nReply ({which}):\n\n> {cut}" + (" …" if len(a_) >= 300 else "")
386
+ return txt
387
+
388
+
389
+ def files_table(names):
390
+ rows = ["| File | Size | sha256 |", "| --- | ---: | --- |"]
391
+ for fn, size in names:
392
+ size = SIZES.get(fn, size)
393
+ sz = ("—" if size is None else gib(size) if size >= GiB // 10 else
394
+ f"{size / MiB:.1f} MiB" if size >= MiB else f"{size / 1024:.1f} KiB")
395
+ rows.append(f"| `{fn}` | {sz} | `{SUMS.get(fn, '—')}` |")
396
+ return "\n".join(rows)
397
+
398
+
399
+ def receipts_table(tags, imat=False):
400
+ head = ("| File | `output.weight` | `token_embd.weight` | tensors |"
401
+ + (" imatrix entries | bytes differ from standard |" if imat else ""))
402
+ sep = "| --- | --- | --- | ---: |" + (" ---: | :---: |" if imat else "")
403
+ rows = [head, sep]
404
+ for k in tags:
405
+ t = tier(k)
406
+ r = (f"| `{t.get('file') or '—'}` | {t.get('output_weight') or '—'} | {t.get('token_embd') or '—'} | "
407
+ f"{g(t.get('tensors'), '{}')} |")
408
+ if imat:
409
+ dfs = t.get("differs_from_standard")
410
+ r += f" {t.get('imatrix_entries') if t.get('imatrix_entries') is not None else '—'} | "
411
+ r += f"{'yes' if dfs else ('no' if dfs is False else '—')} |"
412
+ rows.append(r)
413
+ return "\n".join(rows)
414
+
415
+
416
+ def repro(model_file, label):
417
+ b = bench(label)
418
+ sha = B.get("sha256") or {}
419
+ cmd = (b.get("cmd") if b else None) or "—"
420
+ return f"""```
421
+ server : {B.get('repo') or '—'} @ {B.get('commit') or '—'}
422
+ unpatched; build dir {os.path.dirname(B['dir']) if B.get('dir') else '—'}, Release, Unix Makefiles, GGML_HIP=ON GGML_VULKAN=ON
423
+ GGML_HIP_GRAPHS=ON GGML_HIP_NO_VMM=ON GGML_NATIVE=ON AMDGPU_TARGETS=gfx1151 LLAMA_CURL=OFF
424
+ CMAKE_HIP_COMPILER=/opt/rocm-7.2.4/lib/llvm/bin/clang
425
+ sha256 llama-quantize {sha.get('llama-quantize') or '—'}
426
+ sha256 llama-imatrix {sha.get('llama-imatrix') or '—'}
427
+ sha256 llama-perplexity {sha.get('llama-perplexity') or '—'}
428
+ sha256 llama-server {sha.get('llama-server') or '—'}
429
+ source : {SRC.get('repo') or '—'} revision {SRC.get('revision') or '—'}
430
+ model : {model_file} (the argv below; every file was measured the same way)
431
+ argv : {cmd}
432
+ template : the quick-start tool-suite and image rows add --chat-template-file chat_template_enable_thinking.jinja
433
+ --reasoning off to this argv (recipe/pipeline/run_tools_roff.sh -> nex_tools_tpl.py; their server logs
434
+ read "chat template, thinking = 0"); the speed rows use the stock template
435
+ env : LD_LIBRARY_PATH=<build>/bin:/opt/rocm-7.2.4/lib
436
+ HSA_OVERRIDE_GFX_VERSION=11.5.1 GGML_HIP_ENABLE_UNIFIED_MEMORY=1
437
+ box : aimax — AMD Ryzen AI Max+ 395 / Radeon 8060S (gfx1151), 124 GiB, GTT 131072 MiB,
438
+ kernel 6.17.6-061706-generic, ROCm 7.2.4
439
+ protocol : {PN_TXT}-token code prompt, {GEN} generated tokens, temp 0 / top_k 1, ignore_eos, cache_prompt false,
440
+ 1 warm-up + median of {REPS}, no co-resident models (box iced)
441
+ measured : {' to '.join(S.get('measured_range') or []) or S.get('measured') or '—'}, by the pipeline in recipe/ (every raw number in recipe/results_summary.json and recipe/raw/)
442
+ ```"""
443
+
444
+
445
+ def methodology_std():
446
+ return f"""```bash
447
+ # 1. convert: text model and the vision projector (the checkpoint has no mtp.* tensors)
448
+ python convert_hf_to_gguf.py hf --outtype bf16 --model-name {N} --outfile {N}-BF16.gguf
449
+ python convert_hf_to_gguf.py hf --outtype bf16 --mmproj --model-name {N} --outfile mmproj-{N}-BF16.gguf
450
+
451
+ # 2. quantize from BF16 only; the LM head is forced up on every tier and read back by exact tensor name
452
+ llama-quantize --output-tensor-type q6_K {N}-BF16.gguf OUT Q4_0_ROCMFP4_STRIX_LEAN 16
453
+ llama-quantize --output-tensor-type q6_K --token-embedding-type q6_K {N}-BF16.gguf OUT Q4_0_ROCMFP4_COHERENT 16
454
+ llama-quantize --output-tensor-type q6_K {N}-BF16.gguf OUT Q4_0_ROCMFP4_FAST 16
455
+
456
+ # 3. BF16 reference logits on the CPU only (this build's ROCm0 path computes the BF16 MoE wrong — Known issues)
457
+ llama-perplexity -m {N}-BF16.gguf -f wikitext-2-raw/wiki.test.raw -c 2048 -b 2048 --chunks 40 --kl-divergence-base bf16.kld \\
458
+ -dev none -ngl 0 --no-op-offload -t 16
459
+ # 4. grade each shipped file against those logits, on each GPU backend
460
+ llama-perplexity -m OUT --kl-divergence-base bf16.kld --kl-divergence -c 2048 -b 2048 -ngl 999 -fa on -dio -dev ROCm0
461
+ llama-perplexity -m OUT --kl-divergence-base bf16.kld --kl-divergence -c 2048 -b 2048 -ngl 999 -fa on -dio -dev Vulkan0
462
+ ```
463
+
464
+ Receipts (the built file is the receipt — exact tensor names, never a substring match; `recipe/logs/`):
465
+
466
+ {receipts_table(STD_TAGS)}"""
467
+
468
+
469
+ def first_rocm_bullet():
470
+ hc = S.get("hub_check")
471
+ others = [h for h in (hc or {}).get("header_checks") or [] if h.get("output_weight_type")]
472
+ if others:
473
+ return "".join(
474
+ f"- Another public ROCmFP4 build of this model exists — [{h['repo']}](https://huggingface.co/{h['repo']}): "
475
+ f"its `{h['file']}` stores `output.weight` as `{h['output_weight_type']}`"
476
+ f"{' and carries no imatrix metadata' if h.get('imatrix_keys') == [] else ''}. Every tier here keeps "
477
+ f"`output.weight` at `Q6_K`, and the imatrix builds are a separate repo.\n" for h in others)
478
+ if isinstance(hc, dict) and hc.get("rocm_builds_found") == 0:
479
+ return ("- **First ROCmFP4 build of this model** — no ROCm or Strix Halo build of Nex-N2.5-mini was on the Hub "
480
+ "at publication.\n")
481
+ return ""
482
+
483
+
484
+ def intro_arch():
485
+ p = SRC.get("params")
486
+ ptxt = f"{p:,} parameters (BF16)" if p is not None else "— parameters"
487
+ return (f"{AR.get('layers', '—')}-layer Qwen3.5 MoE ({AR.get('linear_attn_layers', '—')} Gated DeltaNet linear-attention + "
488
+ f"{AR.get('full_attn_layers', '—')} full-attention layers), {AR.get('num_experts', '—')} routed experts / "
489
+ f"{AR.get('num_experts_per_tok', '—')} active, {AR.get('max_position_embeddings', '—'):,}-token context"
490
+ if AR.get("max_position_embeddings") is not None else
491
+ f"{AR.get('layers', '—')}-layer Qwen3.5 MoE, {ptxt}")
492
+
493
+
494
+ def std_card():
495
+ L = tier("q106")
496
+ bf = S.get("bf16") or {}
497
+ nextn = bf.get("nextn_tensors")
498
+ no_mtp = ("the checkpoint ships no `mtp.*` weights" +
499
+ (f" (the converted BF16 GGUF reads back {nextn} `nextn` tensors)" if nextn is not None else ""))
500
+ return YAML.format(extra="") + f"""
501
+ # Nex-N2.5-mini — ROCmFP4 for AMD Strix Halo (gfx1151)
502
+
503
+ ROCmFP4 / ROCmFPX quantizations of **[nex-agi/Nex-N2.5-mini](https://huggingface.co/nex-agi/Nex-N2.5-mini)** —
504
+ {g(SRC.get('params'), '{:,}')} parameters (BF16), {intro_arch()}, text + image — built and measured on an AMD Ryzen AI
505
+ Max+ 395 (Radeon 8060S, `gfx1151`). Upstream publishes no GGUF.
506
+
507
+ {first_rocm_bullet()}- **Vision projector included.**
508
+ - **No MTP head.** `mtp_num_hidden_layers: 1` is declared in `config.json`, but {no_mtp}. There is no speculative
509
+ decoding on these files.
510
+ - Importance-matrix builds of the same three 4-bit tiers: **[{IMAT}](https://huggingface.co/{IMAT})**.
511
+
512
+ ## Which file should I use?
513
+
514
+ {PROTOCOL}
515
+
516
+ {TABLE_HEAD}
517
+ {chr(10).join(tier_row(k) for k in STD_TAGS)}
518
+ {bf16_row()}
519
+
520
+ {footnotes()}
521
+
522
+ {J('std_recommendation')}
523
+
524
+ {quality_blurb()}
525
+
526
+ **Where the quality numbers come from.** {J('quality_provenance')}
527
+
528
+ {J('backend_quality_note')}
529
+
530
+ ## Quick start
531
+
532
+ {quick_start(JUDGE.get('std_default') or L.get('file') or '—', STD)}
533
+
534
+ {reasoning_block()}
535
+
536
+ ## Speed
537
+
538
+ {speed_table()}
539
+
540
+ {J('speed_note')}
541
+
542
+ ## Prompt caching
543
+
544
+ Measured: pairs of requests that share a long code prefix and differ only in the closing instruction. The second
545
+ request of each pair runs warm (`cache_prompt: true`, resuming from what the first one left) and then cold
546
+ (`cache_prompt: false`), and the two replies are compared byte for byte. Every prompt is padded to one token length so
547
+ warm and cold see identical chunking.
548
+
549
+ {cache_table()}
550
+
551
+ {J('cache_note')}
552
+
553
+ ## Tool calling
554
+
555
+ The template emits the XML-style `<tool_call><function=…><parameter=…>` format, which llama.cpp parses natively
556
+ through the Jinja chat template (on by default). Suite run through `llama-server`, at the checkpoint's recommended
557
+ sampling (temperature 0.7, top-p 0.95, top-k 40):
558
+
559
+ {tools_block()}
560
+
561
+ {J('tools_note')}
562
+
563
+ ## Vision
564
+
565
+ `mmproj-{N}-BF16.gguf` is the {AR.get('vision_layers', '—')}-layer vision tower (width {AR.get('vision_width', '—')}),
566
+ loaded with `--mmproj`. Its attention follows the server's `-fa` setting, so both settings were checked.
567
+
568
+ {vision_block()}
569
+
570
+ ## Memory
571
+
572
+ {J('memory_note')}
573
+
574
+ ## Quantization methodology
575
+
576
+ {methodology_std()}
577
+
578
+ `tie_word_embeddings` is false, so the output head is a real tensor and `--output-tensor-type q6_K` does real work.
579
+ All three tiers pin `output.weight` to `q6_K`; COHERENT also pins `token_embd.weight` to `q6_K`, while STRIX_LEAN and
580
+ FAST keep their tier's own embedding type (shown in the receipts).
581
+
582
+ ## Reproduction
583
+
584
+ {repro(L.get('file') or '—', 'n-q106-rocm')}
585
+
586
+ ## Files
587
+
588
+ {files_table([(tier(k).get('file'), tier(k).get('size_bytes')) for k in STD_TAGS] + list((S.get('aux') or {}).items()))}
589
+
590
+ `SHA256SUMS` covers every model file and the chat template file. `recipe/` holds the measurement pipeline (`recipe/pipeline/`), raw per-run
591
+ results (`recipe/raw/`), build and receipt logs (`recipe/logs/`), and `results_summary.json` with every measured value
592
+ on this card. Architecture facts (layer counts, vocabulary, vision depth) come from the checkpoint's `config.json` at
593
+ revision `{SRC.get('revision') or '—'}`.
594
+
595
+ ## Known issues and limits
596
+
597
+ {J('std_known_issues')}
598
+
599
+ ## License and attribution
600
+
601
+ Apache-2.0, inherited from the base model. Weights and architecture: **Nex-AGI**
602
+ ([nex-agi/Nex-N2.5-mini](https://huggingface.co/nex-agi/Nex-N2.5-mini)). ROCmFP4 / ROCmFPX quantization format and
603
+ runtime: the ROCmFPX project. Quantization and measurements: kingjones777.
604
+ """
605
+
606
+
607
+ def imat_effect_table():
608
+ rows = ["| Tier | Build | Size | KLD vs BF16 ↓ | Same top-1 ↑ | PPL (× BF16) | 99th-pct KLD |",
609
+ "| --- | --- | ---: | ---: | ---: | ---: | ---: |"]
610
+ def d(a, b, k, ek):
611
+ x, y = tier(a).get(k), tier(b).get(k)
612
+ ex, ey = (tier(a).get(ek), tier(b).get(ek)) if ek else (None, None)
613
+ if None in (x, y):
614
+ return "—"
615
+ s = f"{(y - x) / x * 100:+.1f} %"
616
+ if ex is not None and ey is not None:
617
+ s += f" ({abs(y - x) / math.sqrt(ex * ex + ey * ey):.1f}σ)"
618
+ return s
619
+ for base, imat in (("q106", "q106i"), ("q102", "q102i"), ("q103", "q103i")):
620
+ for tag, lab in ((base, "standard"), (imat, "**imatrix**")):
621
+ x = tier(tag)
622
+ ratio = x.get("ppl_ratio")
623
+ rows.append(f"| {NAMES[tag]} | {lab} | {gib(x.get('size_bytes'))} | {pm(x.get('kld_mean'), x.get('kld_err'))} | "
624
+ f"{g(x.get('same_top_p'), '{:.2f} %')} | {pm(x.get('ppl'), x.get('ppl_err'))} "
625
+ f"({'—' if ratio is None else '×%.4f' % ratio}) | {g(x.get('kld_p99'), '{:.4f}')} |")
626
+ dpp = ("—" if None in (tier(base).get("same_top_p"), tier(imat).get("same_top_p"))
627
+ else f"{tier(imat)['same_top_p'] - tier(base)['same_top_p']:+.2f} pp")
628
+ rows.append(f"| | *Δ imatrix* | | {d(base, imat, 'kld_mean', 'kld_err')} | {dpp} | "
629
+ f"{d(base, imat, 'ppl', 'ppl_err')} | {d(base, imat, 'kld_p99', None)} |")
630
+ return "\n".join(rows)
631
+
632
+
633
+ def imat_card():
634
+ im = S.get("imatrix") or {}
635
+ Li = tier("q106i")
636
+ entries = [tier(k).get("imatrix_entries") for k in IMAT_TAGS]
637
+ ent = next((e for e in entries if e is not None), None)
638
+ ent_txt = g(ent, "{:,}") if (ent is None or len(set(e for e in entries if e is not None)) <= 1) else \
639
+ " / ".join(g(e, "{:,}") for e in entries)
640
+ return YAML.format(extra="\n - imatrix") + f"""
641
+ # Nex-N2.5-mini — ROCmFP4 **imatrix** for AMD Strix Halo (gfx1151)
642
+
643
+ Importance-matrix-calibrated ROCmFP4 quantizations of
644
+ **[nex-agi/Nex-N2.5-mini](https://huggingface.co/nex-agi/Nex-N2.5-mini)** ({g(SRC.get('params'), '{:,}')} parameters,
645
+ {intro_arch()}, text + image). Companion to the standard build **[{STD}](https://huggingface.co/{STD})** — the same
646
+ three 4-bit tiers, same vision projector, same unpatched `d3ca537` server; the only difference is how each 4-bit
647
+ block's scale was chosen. There is no MTP head on either repo.
648
+
649
+ ## What the imatrix changes
650
+
651
+ ROCmFP4 has an importance-weighted quantizer path: with `--imatrix`, each block's scale is chosen by an exhaustive
652
+ search that minimises error **weighted by how strongly the calibration activations use each weight**, instead of the
653
+ unweighted default. It changes **which** scales are picked at the **same** bit width and tensor types — so it moves
654
+ quality, not size, and per-token compute is identical.
655
+
656
+ | | |
657
+ | --- | --- |
658
+ | calibration text | {im.get('calibration') or '—'} (the widely used community calibration set) |
659
+ | computed on | BF16 GGUF, {g(im.get('chunks'), '{}')} chunks × {g(im.get('n_ctx'), '{}')} tokens, {im.get('device') or '—'} |
660
+ | entries loaded | {ent_txt} (from the N3 quantize logs) |
661
+ | file | `{im.get('file') or '—'}` (GGUF format), sha256 `{im.get('sha256') or '—'}` |
662
+
663
+ ## Measured effect
664
+
665
+ {quality_blurb()} The calibration text and the grading text are different corpora.
666
+
667
+ {imat_effect_table()}
668
+
669
+ σ = difference divided by the two runs' combined standard error. The two runs score the **same** tokens, so this is
670
+ conservative (paired noise is smaller).
671
+
672
+ {J('imat_verdict')}
673
+
674
+ **Where the quality numbers come from.** {J('quality_provenance')}
675
+
676
+ {J('backend_quality_note')}
677
+
678
+ ## Which file should I use?
679
+
680
+ {J('imat_recommendation')}
681
+
682
+ {TABLE_HEAD}
683
+ {chr(10).join(tier_row(k) for k in IMAT_TAGS)}
684
+ {bf16_row()}
685
+
686
+ {footnotes("above")}
687
+
688
+ {J('imat_speed_note')}
689
+
690
+ Full speed tables (both backends, prose vs code), prompt-cache, tool-calling and vision results are on
691
+ the [standard card](https://huggingface.co/{STD}).
692
+
693
+ ## Quick start
694
+
695
+ {quick_start(JUDGE.get('imat_default') or Li.get('file') or '—', IMAT)}
696
+
697
+ {reasoning_block()}
698
+
699
+ ## Quantization methodology
700
+
701
+ ```bash
702
+ llama-imatrix -m {N}-BF16.gguf -f calibration_datav3.txt -o {N}.imatrix \\
703
+ -c 512 -b 512 -dev none -ngl 0 --no-op-offload -t 16
704
+ llama-quantize --imatrix {N}.imatrix --output-tensor-type q6_K \\
705
+ {N}-BF16.gguf {N}-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf Q4_0_ROCMFP4_STRIX_LEAN 16
706
+ llama-quantize --imatrix {N}.imatrix --output-tensor-type q6_K --token-embedding-type q6_K \\
707
+ {N}-BF16.gguf {N}-imatrix-Q4_0_ROCMFP4_COHERENT.gguf Q4_0_ROCMFP4_COHERENT 16
708
+ llama-quantize --imatrix {N}.imatrix --output-tensor-type q6_K \\
709
+ {N}-BF16.gguf {N}-imatrix-Q4_0_ROCMFP4_FAST.gguf Q4_0_ROCMFP4_FAST 16
710
+ ```
711
+
712
+ Receipts that the weighted path was actually taken, and that each shipped file differs from its standard twin:
713
+
714
+ {receipts_table(IMAT_TAGS, imat=True)}
715
+
716
+ ## Reproduction
717
+
718
+ {repro(Li.get('file') or '—', 'n-q106i-rocm')}
719
+
720
+ ## Files
721
+
722
+ {files_table([(tier(k).get('file'), tier(k).get('size_bytes')) for k in IMAT_TAGS] + [(im.get('file'), im.get('size_bytes'))] + list((S.get('aux') or {}).items()))}
723
+
724
+ ## Known issues and limits
725
+
726
+ {J('imat_known_issues')}
727
+
728
+ ## License and attribution
729
+
730
+ Apache-2.0, inherited from the base model. Weights and architecture: **Nex-AGI**
731
+ ([nex-agi/Nex-N2.5-mini](https://huggingface.co/nex-agi/Nex-N2.5-mini)). Calibration text: bartowski's
732
+ `calibration_datav3`. ROCmFP4 / ROCmFPX: the ROCmFPX project. Imatrix, quantization and measurements: kingjones777.
733
+ """
734
+
735
+
736
+ open(os.path.join(OUT, "README_std.md"), "w").write(std_card())
737
+ def fix_anchors(md, other_repo):
738
+ """Links to sections that exist only on the other card point there instead of to a missing anchor."""
739
+ import re
740
+ slugs = {re.sub(r"[^a-z0-9 -]", "", h.strip().lower()).replace(" ", "-")
741
+ for h in re.findall(r"^#{1,6} (.+)$", md, flags=re.M)}
742
+ return re.sub(r"\]\(#([a-z0-9-]+)\)",
743
+ lambda m: m.group(0) if m.group(1) in slugs else "](https://huggingface.co/%s#%s)" % (
744
+ other_repo, m.group(1)), md)
745
+
746
+
747
+ open(os.path.join(OUT, "README_imat.md"), "w").write(fix_anchors(imat_card(), STD))
748
+ cards = open(os.path.join(OUT, "README_std.md")).read() + open(os.path.join(OUT, "README_imat.md")).read()
749
+ pend = sorted(set(x.split("JUDGMENT PENDING: ")[1].split("]")[0] for x in cards.split("**[")[1:] if "JUDGMENT PENDING" in x))
750
+ dash_cells = cards.count("| — |")
751
+ print("rendered | bench rows =", len(S.get("bench") or []), "| gates =", len(S.get("gates") or []),
752
+ "| pending judgments:", pend, "| '—' cells:", dash_cells)
recipe/pipeline/nex_seat_default_probe.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Which server-side default makes Nex behave well for clients that pass no chat_template_kwargs (the gateway case)?
3
+ Follow-up to nex_tools_tpl.py: with the `high` shim, a no-kwargs one-word request came back entirely in
4
+ reasoning_content (the model never closed its forced-open think block). Two candidate defaults, greedy probes:
5
+ C1 high shim + `--chat-template-kwargs {"enable_thinking": false}` (thinking off unless a client asks)
6
+ C2 v2 shim (explicit enable_thinking=false wins; otherwise enable_thinking maps to high unless reasoning_effort is
7
+ set) + `--chat-template-kwargs {"reasoning_effort": "medium"}` (upstream's adaptive default)
8
+ Diagnostic only -> results/nex_seat_default_probe.json."""
9
+ import json, os, subprocess, sys, time
10
+ from types import SimpleNamespace
11
+
12
+ os.environ["AGNES_BIN"] = "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin"
13
+ sys.path.insert(0, "/mnt/models/nex-n2.5-mini")
14
+ import nex_harness as H # noqa: E402
15
+
16
+ W = H.W
17
+ SRC = open(f"{W}/hf/chat_template.jinja", "rb").read()
18
+ SHIM_V2 = ("{%- if enable_thinking is defined and not enable_thinking %}{%- set reasoning_effort = 'none' %}"
19
+ "{%- elif reasoning_effort is not defined and enable_thinking is defined %}"
20
+ "{%- set reasoning_effort = 'high' %}{%- endif %}\n")
21
+ TPL_V2 = f"{W}/tpl/chat_template_enable_thinking_v2.jinja"
22
+ open(TPL_V2, "wb").write(SHIM_V2.encode() + SRC)
23
+ CONFIGS = [
24
+ ("C1", [f"--chat-template-file", f"{W}/tpl/chat_template_enable_thinking.jinja",
25
+ "--chat-template-kwargs", json.dumps({"enable_thinking": False})]),
26
+ ("C2", ["--chat-template-file", TPL_V2, "--chat-template-kwargs", json.dumps({"reasoning_effort": "medium"})]),
27
+ ]
28
+ PROMPTS = [("correct-decline", "What is 17 times 23? Answer directly."),
29
+ ("single-word", "Reply with the single word: ready"),
30
+ ("multi-arg", "What's the weather in Paris in celsius?")]
31
+ KW = [("no-kwargs", None), ("enable_thinking=true", {"enable_thinking": True}),
32
+ ("enable_thinking=false", {"enable_thinking": False})]
33
+ _orig = subprocess.Popen
34
+ report = {"shim_v2": SHIM_V2, "configs": {}}
35
+ for name, extra in CONFIGS:
36
+ def _popen(cmd, *a, _extra=extra, **k):
37
+ if cmd and str(cmd[0]).endswith("llama-server"):
38
+ cmd = list(cmd) + list(_extra)
39
+ return _orig(cmd, *a, **k)
40
+ subprocess.Popen = _popen
41
+ a = SimpleNamespace(model=f"{W}/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf", dev="ROCm0", ctx=16384,
42
+ draft=None, mtp_infile=False, nmax=4, pmin=0.0, strict=False,
43
+ serverlog=f"{W}/logs/probe_seat_default_{name}.log")
44
+ try:
45
+ s = H.Server(a, 18653)
46
+ finally:
47
+ subprocess.Popen = _orig
48
+ rec = {"extra": extra, "results": {}}
49
+ try:
50
+ for kn, kw in KW:
51
+ for pn, prompt in PROMPTS:
52
+ body = {"messages": [{"role": "user", "content": prompt}], "tools": H.TOOLS, "tool_choice": "auto",
53
+ "temperature": 0, "top_k": 1, "max_tokens": 2048}
54
+ if kw is not None:
55
+ body["chat_template_kwargs"] = kw
56
+ try:
57
+ m = H.post(18653, "/v1/chat/completions", body)["choices"][0]["message"]
58
+ c = m.get("content") or ""
59
+ r = {"content": c[:120], "reasoning_len": len(m.get("reasoning_content") or ""),
60
+ "tool_calls": [(t.get("function") or {}).get("name") for t in m.get("tool_calls") or []],
61
+ "leaks": [x for x in H.LEAK if x in c]}
62
+ except Exception as e: # noqa: BLE001
63
+ r = {"error": repr(e)[:300]}
64
+ rec["results"][f"{kn}|{pn}"] = r
65
+ print(name, kn, pn, json.dumps(r)[:220], flush=True)
66
+ finally:
67
+ s.stop()
68
+ report["configs"][name] = rec
69
+ time.sleep(3)
70
+ json.dump(report, open(f"{W}/results/nex_seat_default_probe.json", "w"), indent=1)
71
+ print("NEX_SEAT_DEFAULT_PROBE_DONE")
recipe/pipeline/nex_seats.sh ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # King 2026-09-16: "leave the fast of the models on this machine for swap i want to test them" -> the two Nex-N2.5-mini
3
+ # FAST files (standard + imatrix) become ON-DEMAND seats: DISABLED systemd units King starts by hand (llama-swap is
4
+ # masked on MAX-1). Every setting comes from this build's measurements (backend, -fa, context, memory cap); a missing
5
+ # measurement stops the script instead of guessing. Each seat is smoke-tested once (start -> /health -> one real
6
+ # completion -> stop) while the box is still iced, and through the gateway when a route already exists.
7
+ set -uo pipefail
8
+ W=/mnt/models/nex-n2.5-mini; B=/opt/llama-rocm/rocmfpx-724/build-hipvk/bin; N=Nex-N2.5-mini
9
+ # the stock template switches thinking only via reasoning_effort, which llama-server's parser analysis cannot see
10
+ # (reasoning leaks into content); this copy maps enable_thinking onto it, and --reasoning off makes thinking opt-in
11
+ # per request (enable_thinking: true). Measured: tool suite 40/42 over 3 passes vs 6/14 stock (nex_tools_tpl.py).
12
+ TPL=$W/tpl/chat_template_enable_thinking.jinja
13
+ GW=http://192.168.0.87:4000; GWKEY=sk-homecloud-master
14
+ cd $W
15
+ prlimit --pid $$ --core=1:1 # 1 BYTE (bash `ulimit -c 1` is 1 KiB and does not stop apport)
16
+ log(){ echo "[$(date -u +%FT%TZ)] $*"; }
17
+
18
+ python3 - > results/nex_seats_plan.json <<'PY' || { log "PLAN FAILED -> no seats"; exit 2; }
19
+ import json, math, sys
20
+ W = "/mnt/models/nex-n2.5-mini"; N = "Nex-N2.5-mini"
21
+ rows = [json.loads(l) for l in open(f"{W}/results/nex_bench.jsonl") if l.strip()]
22
+ bench = {r["label"]: r for r in rows if "tg_median" in r}
23
+ gate = {r["label"]: r for r in rows if "tg_median" not in r}
24
+ siz = [json.loads(l) for l in open(f"{W}/results/nex_sizing.jsonl") if l.strip()]
25
+ EQ = 0.03 # a backend must win decode by more than this AND not lose prefill by more than this to replace ROCm0
26
+
27
+ def backend(tag):
28
+ r, v = bench.get(f"n-{tag}-rocm"), bench.get(f"n-{tag}-vk")
29
+ if not (r and v) or None in (r.get("tg_median"), v.get("tg_median"), r.get("pp_median"), v.get("pp_median")):
30
+ sys.exit(f"missing bench rows for {tag}")
31
+ vk = v["tg_median"] > r["tg_median"] * (1 + EQ) and v["pp_median"] >= r["pp_median"] * (1 - EQ)
32
+ return ("Vulkan0" if vk else "ROCm0"), {"rocm": [r["tg_median"], r["pp_median"]], "vk": [v["tg_median"], v["pp_median"]]}
33
+
34
+ on, off = gate.get("n-vision-q106-faon"), gate.get("n-vision-q106-faoff")
35
+ if not (on and off):
36
+ sys.exit("missing vision gates")
37
+ fa, mmproj = ("on", True) if on.get("result") == "PASS" else (("off", True) if off.get("result") == "PASS" else ("on", False))
38
+
39
+ ok = [s for s in siz if s.get("label") == "strix-lean" and s.get("footprint_after_8k_gib") is not None]
40
+ if not ok:
41
+ sys.exit("missing sizing rows")
42
+ best = max(ok, key=lambda s: s["ctx"]) # largest context that loaded and served a request
43
+ cap = int(math.ceil((best["footprint_after_8k_gib"] * 1.15 + 2) * 1024 / 1000.0) * 1000)
44
+
45
+ seats = []
46
+ for unit, port, tag, path, label in (
47
+ ("max1-nex-fast", 8097, "q103", f"{W}/out/{N}-Q4_0_ROCMFP4_FAST.gguf", "FAST"),
48
+ ("max1-nex-fast-imat", 8098, "q103i", f"{W}/out-imat/{N}-imatrix-Q4_0_ROCMFP4_FAST.gguf", "FAST imatrix")):
49
+ dev, speeds = backend(tag)
50
+ seats.append({"unit": unit, "port": port, "tag": tag, "model": path, "label": label, "dev": dev, "speeds": speeds,
51
+ "fa": fa, "mmproj": f"{W}/out/mmproj-{N}-BF16.gguf" if mmproj else None, "ctx": best["ctx"],
52
+ "memory_max_mib": cap, "sized_from": best,
53
+ "gateway_model": "nex-n2.5-mini-fast@max1" if tag == "q103" else "nex-n2.5-mini-fast-imatrix@max1"})
54
+ print(json.dumps({"seats": seats, "vision": {"faon": on.get("result"), "faoff": off.get("result")}}, indent=1))
55
+ PY
56
+ log "plan: $(python3 -c "import json; d=json.load(open('results/nex_seats_plan.json')); print([(s['unit'], s['dev'], 'fa '+s['fa'], s['ctx'], str(s['memory_max_mib'])+'M', bool(s['mmproj'])) for s in d['seats']])")"
57
+
58
+ n=$(python3 -c "import json; print(len(json.load(open('results/nex_seats_plan.json'))['seats']))")
59
+ fail=0
60
+ for i in $(seq 0 $((n - 1))); do
61
+ eval "$(python3 - $i <<'PY'
62
+ import json, shlex, sys
63
+ s = json.load(open("/mnt/models/nex-n2.5-mini/results/nex_seats_plan.json"))["seats"][int(sys.argv[1])]
64
+ for k in ("unit", "port", "model", "label", "dev", "fa", "ctx", "memory_max_mib", "gateway_model"):
65
+ print(f"{k.upper()}={shlex.quote(str(s[k]))}")
66
+ print(f"MMPROJ={shlex.quote(s['mmproj'] or '')}")
67
+ PY
68
+ )"
69
+ [ -s "$MODEL" ] || { log "$UNIT: model file missing ($MODEL)"; fail=1; continue; }
70
+ [ -s "$TPL" ] || { log "$UNIT: template file missing ($TPL)"; fail=1; continue; }
71
+ if ss -tln | grep -q ":$PORT "; then log "$UNIT: port $PORT already in use -> skip"; fail=1; continue; fi
72
+ MM=""; [ -n "$MMPROJ" ] && MM="--mmproj $MMPROJ"
73
+ tmp=$(mktemp /tmp/$UNIT.XXXX.service)
74
+ cat > $tmp <<EOF
75
+ [Unit]
76
+ Description=MAX-1 on-demand test seat: $N $LABEL (:$PORT) - disabled; start by hand, stop another seat first if memory is tight
77
+ After=network.target
78
+
79
+ [Service]
80
+ User=root
81
+ SupplementaryGroups=render video
82
+ Environment=HSA_OVERRIDE_GFX_VERSION=11.5.1
83
+ Environment=GGML_HIP_ENABLE_UNIFIED_MEMORY=1
84
+ Environment=LD_LIBRARY_PATH=$B:/opt/rocm-7.2.4/lib
85
+ ExecStart=$B/llama-server -m $MODEL $MM -dev $DEV -ngl 999 -fa $FA --no-mmap -fit off -c $CTX -ctk q8_0 -ctv q8_0 -np 1 -b 2048 -ub 1024 -t 16 --poll 100 --jinja --chat-template-file $TPL --reasoning off -cram 512 --host 0.0.0.0 --port $PORT
86
+ Restart=on-failure
87
+ RestartSec=15
88
+ MemoryMax=${MEMORY_MAX_MIB}M
89
+ LimitMEMLOCK=infinity
90
+ # RLIMIT_CORE of exactly 1 byte: a crashing test seat must not pipe a 12 GiB core into apport on the 98 %-full root disk
91
+ LimitCORE=1
92
+
93
+ [Install]
94
+ WantedBy=multi-user.target
95
+ EOF
96
+ cp $tmp /tmp/$UNIT.service
97
+ systemd-analyze verify /tmp/$UNIT.service > /tmp/$UNIT.verify 2>&1; vrc=$?
98
+ if [ $vrc -ne 0 ] || grep -qiE "error|invalid|unknown|ignoring" /tmp/$UNIT.verify; then
99
+ log "$UNIT: unit did not verify (rc=$vrc):"; cat /tmp/$UNIT.verify; rm -f $tmp; fail=1; continue
100
+ fi
101
+ [ -f /etc/systemd/system/$UNIT.service ] && cp /etc/systemd/system/$UNIT.service /etc/systemd/system/.$UNIT.service.bak-$(date +%s)
102
+ install -m 0644 $tmp /etc/systemd/system/$UNIT.service; rm -f $tmp /tmp/$UNIT.service /tmp/$UNIT.verify
103
+ systemctl daemon-reload
104
+ systemctl disable $UNIT.service >/dev/null 2>&1 # on-demand: never part of boot
105
+ log "$UNIT written ($DEV, -fa $FA, ctx $CTX, MemoryMax ${MEMORY_MAX_MIB}M) -> smoke test"
106
+ t0=$(date +%s); systemctl start $UNIT.service
107
+ ok=0
108
+ for k in $(seq 1 180); do
109
+ curl -s -m 3 http://127.0.0.1:$PORT/health | grep -q '"ok"' && { ok=1; break; }
110
+ systemctl is-active --quiet $UNIT.service || { log " $UNIT not active"; break; }
111
+ sleep 5
112
+ done
113
+ load_s=$(( $(date +%s) - t0 ))
114
+ if [ $ok -ne 1 ]; then
115
+ log " FAIL $UNIT never healthy"; journalctl -u $UNIT.service -n 20 --no-pager | tail -20
116
+ systemctl stop $UNIT.service; fail=1; continue
117
+ fi
118
+ python3 - "$UNIT" "$PORT" "$GATEWAY_MODEL" "$load_s" "$GW" "$GWKEY" <<'PY' | tee -a results/nex_seats.jsonl
119
+ import json, sys, time, urllib.request
120
+ unit, port, gwm, load_s, gw, key = sys.argv[1], int(sys.argv[2]), sys.argv[3], int(sys.argv[4]), sys.argv[5], sys.argv[6]
121
+ body = {"messages": [{"role": "user", "content": "Reply with the single word: ready"}], "max_tokens": 64,
122
+ "temperature": 0, "chat_template_kwargs": {"enable_thinking": False}}
123
+ def call(url, b, hdr):
124
+ req = urllib.request.Request(url, data=json.dumps(b).encode(), headers={"Content-Type": "application/json", **hdr})
125
+ return json.load(urllib.request.urlopen(req, timeout=600))
126
+ row = {"unit": unit, "port": port, "load_s": load_s, "time": time.strftime("%FT%TZ", time.gmtime())}
127
+ try:
128
+ r = call(f"http://127.0.0.1:{port}/v1/chat/completions", body, {})
129
+ row["direct_reply"] = (r["choices"][0]["message"].get("content") or "")[:60]
130
+ row["direct_tg"] = r.get("timings", {}).get("predicted_per_second")
131
+ except Exception as e:
132
+ row["direct_error"] = str(e)[:200]
133
+ try: # default request (no kwargs): thinking off by default; nothing of a think block may reach content
134
+ r = call(f"http://127.0.0.1:{port}/v1/chat/completions",
135
+ {"messages": body["messages"], "max_tokens": 1024, "temperature": 0}, {})
136
+ m = r["choices"][0]["message"]
137
+ row["default_reply"] = (m.get("content") or "")[:60]
138
+ row["default_reasoning_len"] = len(m.get("reasoning_content") or "")
139
+ row["default_leak"] = any(x in (m.get("content") or "") for x in ("<think>", "</think>"))
140
+ except Exception as e:
141
+ row["default_error"] = str(e)[:200]
142
+ try: # thinking requested: nothing of the think block may reach content. With thinking forced on and no tools, a
143
+ # one-word answer can stay inside the think block (answer in reasoning_content, content empty) - model behaviour
144
+ r = call(f"http://127.0.0.1:{port}/v1/chat/completions",
145
+ {"messages": body["messages"], "max_tokens": 1024, "temperature": 0,
146
+ "chat_template_kwargs": {"enable_thinking": True}}, {})
147
+ m = r["choices"][0]["message"]
148
+ row["thinking_reply"] = (m.get("content") or "")[:60]
149
+ row["thinking_reasoning_len"] = len(m.get("reasoning_content") or "")
150
+ row["thinking_leak"] = any(x in (m.get("content") or "") for x in ("<think>", "</think>"))
151
+ except Exception as e:
152
+ row["thinking_error"] = str(e)[:200]
153
+ try:
154
+ names = [m["id"] for m in json.load(urllib.request.urlopen(urllib.request.Request(
155
+ f"{gw}/v1/models", headers={"Authorization": f"Bearer {key}"}), timeout=30))["data"]]
156
+ if gwm in names:
157
+ r = call(f"{gw}/v1/chat/completions", {**body, "model": gwm}, {"Authorization": f"Bearer {key}"})
158
+ row["gateway_model"] = gwm
159
+ row["gateway_reply"] = (r["choices"][0]["message"].get("content") or "")[:60]
160
+ else:
161
+ row["gateway_model"] = None # route not added yet
162
+ except Exception as e:
163
+ row["gateway_error"] = str(e)[:200]
164
+ row["result"] = "PASS" if row.get("direct_reply") and not row.get("gateway_error") and \
165
+ row.get("default_reply") and row.get("default_leak") is False and \
166
+ (row.get("thinking_reply") or row.get("thinking_reasoning_len")) and row.get("thinking_leak") is False and \
167
+ (row.get("gateway_model") is None or row.get("gateway_reply")) else "FAIL"
168
+ print(json.dumps(row))
169
+ PY
170
+ grep -q "\"unit\": \"$UNIT\".*\"result\": \"PASS\"" <(tail -1 results/nex_seats.jsonl) || fail=1
171
+ systemctl stop $UNIT.service
172
+ for k in $(seq 1 30); do systemctl is-active --quiet $UNIT.service || break; sleep 2; done
173
+ log " $UNIT stopped (enabled: $(systemctl is-enabled $UNIT.service 2>&1))"
174
+ sleep 5
175
+ done
176
+ log "NEX_SEATS_DONE fail=$fail"
177
+ exit $fail
recipe/pipeline/nex_sizing.sh ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Nex-N2.5-mini memory footprint (drop in MemAvailable): STRIX_LEAN + vision projector, q8_0 KV, one slot, no draft head.
3
+ set -uo pipefail
4
+ W=/mnt/models/nex-n2.5-mini; B=/opt/llama-rocm/rocmfpx-724/build-hipvk/bin; N=Nex-N2.5-mini; cd $W
5
+ export LD_LIBRARY_PATH=$B:/opt/rocm-7.2.4/lib HSA_OVERRIDE_GFX_VERSION=11.5.1 GGML_HIP_ENABLE_UNIFIED_MEMORY=1
6
+ prlimit --pid $$ --core=1:1 # 1 BYTE (bash `ulimit -c 1` is 1 KiB and does not stop apport)
7
+ # One quiet box: publish_v2.sh upload takes the same lock, so an HF upload never skews MemAvailable here.
8
+ exec 9>/mnt/models/.quiet-box.lock
9
+ echo "[$(date -u +%FT%TZ)] waiting for the quiet-box lock"; flock 9; echo "[$(date -u +%FT%TZ)] quiet-box lock held"
10
+ avail(){ awk '/MemAvailable/{printf "%.2f", $2/1048576}' /proc/meminfo; }
11
+ sync; sleep 5
12
+ measure(){ # $1 label $2 ctx $3 model
13
+ local a0=$(avail)
14
+ $B/llama-server -m "$3" -dev ROCm0 -ngl 999 -fa on --no-mmap -fit off -c $2 -ctk q8_0 -ctv q8_0 -np 1 -b 2048 -ub 1024 -t 16 \
15
+ --jinja --mmproj out/mmproj-$N-BF16.gguf -cram 512 --host 127.0.0.1 --port 18720 9>&- > logs/N7_sizing_$1_c$2.log 2>&1 &
16
+ local pid=$! ok=0
17
+ for i in $(seq 1 120); do curl -s -m 2 http://127.0.0.1:18720/health | grep -q ok && { ok=1; break; }; kill -0 $pid 2>/dev/null || break; sleep 3; done
18
+ if [ $ok -ne 1 ]; then echo "{\"label\":\"$1\",\"ctx\":$2,\"result\":\"LOAD_FAIL\"}" | tee -a results/nex_sizing.jsonl; kill $pid 2>/dev/null; sleep 5; return; fi
19
+ local a1=$(avail)
20
+ python3 - <<EOF
21
+ import json, urllib.request
22
+ txt = open("/opt/llama-rocm/rocmfpx-724/convert_hf_to_gguf.py").read()[:30000]
23
+ b = {"messages": [{"role": "user", "content": txt + "\n\nSummarise this file in one sentence."}], "max_tokens": 64,
24
+ "temperature": 0, "chat_template_kwargs": {"reasoning_effort": "none"}}
25
+ urllib.request.urlopen(urllib.request.Request("http://127.0.0.1:18720/v1/chat/completions", data=json.dumps(b).encode(),
26
+ headers={"Content-Type": "application/json"}), timeout=600).read()
27
+ EOF
28
+ local a2=$(avail)
29
+ echo "{\"label\":\"$1\",\"ctx\":$2,\"avail_before\":$a0,\"footprint_loaded_gib\":$(python3 -c "print(round($a0-$a1,2))"),\"footprint_after_8k_gib\":$(python3 -c "print(round($a0-$a2,2))")}" | tee -a results/nex_sizing.jsonl
30
+ kill $pid; wait $pid 2>/dev/null; sleep 8
31
+ }
32
+ for C in 65536 262144; do measure strix-lean $C out/$N-Q4_0_ROCMFP4_STRIX_LEAN.gguf; done
33
+ echo NEX_SIZING_DONE
recipe/pipeline/nex_tools_diag.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Diagnose the Nex tool-call gate (n-tools-q106: 6/14 - every thinking-on check failed, and nested-object failed
3
+ with thinking off on an HTTP 500 "does not match the expected peg-native format"). nex_bench.py keeps only the last
4
+ 800 characters of the harness output, so the per-check reasons were lost.
5
+
6
+ Same binary, file, server flags and tool schema as the gate, but every raw reply is kept (content, reasoning_content,
7
+ tool_calls, HTTP error body). Variants, one server session:
8
+ gate_on reasoning_effort=high, gate sampling (temp 0.7, top_p 0.95, top_k 40) - the failing half
9
+ gate_off reasoning_effort=none, gate sampling - the passing half
10
+ on_greedy reasoning_effort=high, temp 0 / top_k 1 - is it sampling?
11
+ adaptive no reasoning_effort (the template's adaptive mode), gate sampling
12
+ nested_off_x3 the nested-object request three more times with thinking off - is the 500 repeatable?
13
+ Diagnostic only (not a card measurement) -> results/nex_tools_diag.json."""
14
+ import json, os, sys, time, urllib.error, urllib.request
15
+ from types import SimpleNamespace
16
+
17
+ os.environ["AGNES_BIN"] = "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin" # the gate ran on the unpatched server
18
+ sys.path.insert(0, "/mnt/models/nex-n2.5-mini")
19
+ import nex_harness as H # noqa: E402
20
+
21
+ W = H.W
22
+ PORT = 18650
23
+ OUT = f"{W}/results/nex_tools_diag.json"
24
+ a = SimpleNamespace(model=f"{W}/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf", dev="ROCm0", ctx=65536,
25
+ draft=None, mtp_infile=False, nmax=4, pmin=0.0, strict=False,
26
+ serverlog=f"{W}/logs/diag_tools_server.log")
27
+ PROMPTS = {
28
+ "multi-arg": "What's the weather in Paris in celsius?",
29
+ "nested-object": "Book 'Design review' on 2026-10-02 at 14:00 with ana@x.io and bo@x.io.",
30
+ "enum": "Weather in Denver, and give it to me in fahrenheit.",
31
+ "correct-decline": "What is 17 times 23? Answer directly.",
32
+ "multi-turn": "What's the weather in Tokyo in celsius?",
33
+ "streaming": "What's the weather in Rome in celsius?",
34
+ "parallel": "Get the weather in Oslo AND in Lima, both in celsius. Call the tool for each city.",
35
+ }
36
+ GATE = dict(temperature=0.7, top_p=0.95, top_k=40)
37
+ GREEDY = dict(temperature=0, top_k=1)
38
+
39
+
40
+ def call(msgs, kwargs, sampling, stream=False):
41
+ body = {"messages": msgs, "tools": H.TOOLS, "tool_choice": "auto", "max_tokens": 8192, **sampling}
42
+ if kwargs is not None:
43
+ body["chat_template_kwargs"] = kwargs
44
+ t0 = time.time()
45
+ try:
46
+ if not stream:
47
+ r = H.post(PORT, "/v1/chat/completions", body)
48
+ ch = r["choices"][0]
49
+ return {"message": ch["message"], "finish": ch.get("finish_reason"), "s": round(time.time() - t0, 2)}
50
+ body["stream"] = True
51
+ req = urllib.request.Request(f"http://127.0.0.1:{PORT}/v1/chat/completions", data=json.dumps(body).encode(),
52
+ headers={"Content-Type": "application/json"})
53
+ calls, content, reasoning, finish = {}, "", "", None
54
+ for line in urllib.request.urlopen(req, timeout=1800):
55
+ line = line.decode().strip()
56
+ if not line.startswith("data:") or line.endswith("[DONE]"):
57
+ continue
58
+ ch = json.loads(line[5:])["choices"][0]
59
+ d = ch.get("delta") or {}
60
+ finish = ch.get("finish_reason") or finish
61
+ content += d.get("content") or ""
62
+ reasoning += d.get("reasoning_content") or ""
63
+ for tc in d.get("tool_calls") or []:
64
+ c = calls.setdefault(tc["index"], {"name": "", "arguments": ""})
65
+ c["name"] += (tc.get("function") or {}).get("name") or ""
66
+ c["arguments"] += (tc.get("function") or {}).get("arguments") or ""
67
+ msg = {"content": content, "reasoning_content": reasoning,
68
+ "tool_calls": [{"function": v} for _, v in sorted(calls.items())]}
69
+ return {"message": msg, "finish": finish, "s": round(time.time() - t0, 2)}
70
+ except urllib.error.HTTPError as e:
71
+ return {"http_error": e.code, "body": e.read().decode(errors="replace")[:600], "s": round(time.time() - t0, 2)}
72
+ except Exception as e: # noqa: BLE001 - a diagnostic records every failure mode
73
+ return {"exception": repr(e)[:300], "s": round(time.time() - t0, 2)}
74
+
75
+
76
+ def summarize(res):
77
+ if "message" not in res:
78
+ return res
79
+ m = res["message"]
80
+ c = m.get("content") or ""
81
+ return {"finish": res.get("finish"), "s": res["s"],
82
+ "tool_calls": [(t.get("function") or {}).get("name") for t in (m.get("tool_calls") or [])],
83
+ "args": [(t.get("function") or {}).get("arguments") for t in (m.get("tool_calls") or [])],
84
+ "leaks_in_content": [x for x in H.LEAK if x in c],
85
+ "content": c[:600], "reasoning_len": len(m.get("reasoning_content") or ""),
86
+ "reasoning_head": (m.get("reasoning_content") or "")[:300]}
87
+
88
+
89
+ def run_variant(name, kwargs, sampling, stream_ok=True):
90
+ out = {}
91
+ for k, p in PROMPTS.items():
92
+ msgs = [{"role": "user", "content": p}]
93
+ r = call(msgs, kwargs, sampling, stream=(k == "streaming" and stream_ok))
94
+ rec = {"first": summarize(r)}
95
+ if k == "multi-turn" and "message" in r and r["message"].get("tool_calls"):
96
+ tc = r["message"]["tool_calls"][0]
97
+ msgs += [{"role": "assistant", "content": r["message"].get("content") or "",
98
+ "tool_calls": [{"id": "call_1", "type": "function", "function": tc["function"]}]},
99
+ {"role": "tool", "tool_call_id": "call_1", "content": json.dumps({"temp_c": 21, "sky": "clear"})}]
100
+ rec["second"] = summarize(call(msgs, kwargs, sampling))
101
+ out[k] = rec
102
+ print(name, k, json.dumps(rec)[:400], flush=True)
103
+ return out
104
+
105
+
106
+ s = H.Server(a, PORT)
107
+ report = {"model": os.path.basename(a.model), "bin": H.BIN, "cmd": " ".join(s.cmd), "variants": {}}
108
+ try:
109
+ report["variants"]["gate_on"] = run_variant("gate_on", H.THINK_ON, GATE)
110
+ report["variants"]["gate_off"] = run_variant("gate_off", H.THINK_OFF, GATE)
111
+ report["variants"]["on_greedy"] = run_variant("on_greedy", H.THINK_ON, GREEDY, stream_ok=False)
112
+ report["variants"]["adaptive"] = run_variant("adaptive", None, GATE, stream_ok=False)
113
+ report["variants"]["nested_off_x3"] = [
114
+ summarize(call([{"role": "user", "content": PROMPTS["nested-object"]}], H.THINK_OFF, GATE)) for _ in range(3)]
115
+ print("nested_off_x3", json.dumps(report["variants"]["nested_off_x3"])[:600], flush=True)
116
+ finally:
117
+ s.stop()
118
+ json.dump(report, open(OUT, "w"), indent=1)
119
+ print("NEX_TOOLS_DIAG_DONE", OUT)
recipe/pipeline/nex_tools_tpl.py ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Tool-call gate on the Nex STRIX_LEAN file with a one-line template shim.
3
+
4
+ Why: the stock template switches thinking with `reasoning_effort` only. llama-server's template analysis probes
5
+ `enable_thinking`, finds no difference, and builds a parser that never extracts reasoning: with thinking on,
6
+ `reasoning_content` stays empty and the reasoning plus `</think>` land in `content` (n-tools-q106: 0/7 with thinking
7
+ on; results/nex_tools_diag.json, results/nex_reasoning_probe.json). `--reasoning-format deepseek`, server-level
8
+ `--chat-template-kwargs` and `--reasoning on` do not change that. Prepending one line that maps `enable_thinking`
9
+ onto `reasoning_effort` does.
10
+
11
+ This run: the same suite, sampling, file and server as n-tools-q106, plus `--chat-template-file` with the shim, and
12
+ thinking switched with `enable_thinking` true / false -> label n-tools-q106-tpl in results/nex_bench.jsonl (full
13
+ per-check output in logs/N6t_tools_tpl.log). Then probes of the shim's other paths (no kwargs; an explicit
14
+ reasoning_effort) -> results/nex_template_shim.json."""
15
+ import argparse, hashlib, json, os, subprocess, sys
16
+ from types import SimpleNamespace
17
+
18
+ os.environ["AGNES_BIN"] = "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin" # same unpatched server as n-tools-q106
19
+ sys.path.insert(0, "/mnt/models/nex-n2.5-mini")
20
+ import nex_harness as H # noqa: E402
21
+
22
+ ap = argparse.ArgumentParser()
23
+ ap.add_argument("--on", default="high", choices=["high", "medium"], help="reasoning_effort that enable_thinking=true maps to")
24
+ ap.add_argument("--label", default="n-tools-q106-tpl")
25
+ ap.add_argument("--tpl", default="chat_template_enable_thinking.jinja")
26
+ ap.add_argument("--out", default="nex_template_shim.json")
27
+ ap.add_argument("--extra", default="[]", help="JSON list of extra llama-server flags")
28
+ ap.add_argument("--vision", action="store_true", help="also run the -fa on image gate in this configuration")
29
+ ap.add_argument("--repeats", type=int, default=1, help="tool-suite passes (labels <label>, <label>-r2, ...)")
30
+ args = ap.parse_args()
31
+ W = H.W
32
+ TPL = f"{W}/tpl/{args.tpl}"
33
+ SHIM = ("{%- if reasoning_effort is not defined and enable_thinking is defined %}"
34
+ "{%- set reasoning_effort = '" + args.on + "' if enable_thinking else 'none' %}{%- endif %}\n")
35
+ os.makedirs(os.path.dirname(TPL), exist_ok=True)
36
+ src = open(f"{W}/hf/chat_template.jinja", "rb").read()
37
+ open(TPL, "wb").write(SHIM.encode() + src)
38
+
39
+ H.THINK_ON, H.THINK_OFF = {"enable_thinking": True}, {"enable_thinking": False}
40
+ _orig_popen = subprocess.Popen
41
+
42
+
43
+ def _popen(cmd, *pargs, **kw):
44
+ if cmd and str(cmd[0]).endswith("llama-server"):
45
+ cmd = list(cmd) + ["--chat-template-file", TPL] + json.loads(args.extra)
46
+ return _orig_popen(cmd, *pargs, **kw)
47
+
48
+
49
+ subprocess.Popen = _popen
50
+ MODEL = f"{W}/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf"
51
+ a = SimpleNamespace(model=MODEL, dev="ROCm0", ctx=65536, draft=None, mtp_infile=False, nmax=4, pmin=0.0, strict=False,
52
+ port=18600, label=args.label, jsonl=f"{W}/results/nex_bench.jsonl",
53
+ serverlog=f"{W}/logs/b_{args.label}.log")
54
+ H.cmd_tools(a)
55
+ for r in range(2, args.repeats + 1):
56
+ H.cmd_tools(SimpleNamespace(**{**vars(a), "label": f"{args.label}-r{r}",
57
+ "serverlog": f"{W}/logs/b_{args.label}-r{r}.log"}))
58
+ if args.vision:
59
+ A = "/mnt/models/agnes-3.0-flash"
60
+ v = SimpleNamespace(**{**vars(a), "label": args.label.replace("tools", "vision") + "-faon",
61
+ "serverlog": f"{W}/logs/b_{args.label.replace('tools', 'vision')}-faon.log",
62
+ "fa": "on", "mmproj": f"{W}/out/mmproj-Nex-N2.5-mini-BF16.gguf",
63
+ "image": f"{A}/calib/vision_probe.png",
64
+ "question": "Describe the two shapes in this image and their colors.",
65
+ "expect": "red,blue,circle,square"})
66
+ try:
67
+ H.cmd_vision(v)
68
+ except SystemExit:
69
+ pass # cmd_vision exits 1 on FAIL after writing its row; the probes below still run
70
+
71
+ # the shim's other paths, greedy: no kwargs at all, and an explicit reasoning_effort (the shim then steps aside)
72
+ p = SimpleNamespace(**{**vars(a), "label": "", "serverlog": f"{W}/logs/b_{args.label}-probe.log"})
73
+ s = H.Server(p, 18652)
74
+ probes = {}
75
+ try:
76
+ for name, kw in (("no-kwargs", None), ("enable_thinking=false", {"enable_thinking": False}),
77
+ ("reasoning_effort=high", {"reasoning_effort": "high"}),
78
+ ("reasoning_effort=medium", {"reasoning_effort": "medium"}),
79
+ ("reasoning_effort=none", {"reasoning_effort": "none"})):
80
+ for rn, prompt in (("correct-decline", "What is 17 times 23? Answer directly."),
81
+ ("single-word", "Reply with the single word: ready"),
82
+ ("multi-arg", "What's the weather in Paris in celsius?")):
83
+ body = {"messages": [{"role": "user", "content": prompt}], "tools": H.TOOLS, "tool_choice": "auto",
84
+ "temperature": 0, "top_k": 1, "max_tokens": 2048}
85
+ if kw is not None:
86
+ body["chat_template_kwargs"] = kw
87
+ try:
88
+ m = H.post(18652, "/v1/chat/completions", body)["choices"][0]["message"]
89
+ c = m.get("content") or ""
90
+ probes[f"{name}|{rn}"] = {
91
+ "content": c[:200], "reasoning_len": len(m.get("reasoning_content") or ""),
92
+ "tool_calls": [(t.get("function") or {}).get("name") for t in m.get("tool_calls") or []],
93
+ "leaks": [x for x in H.LEAK if x in c]}
94
+ except Exception as e: # noqa: BLE001 - a probe records every failure mode
95
+ probes[f"{name}|{rn}"] = {"error": repr(e)[:300]}
96
+ print("probe", name, rn, json.dumps(probes[f"{name}|{rn}"])[:260], flush=True)
97
+ finally:
98
+ s.stop()
99
+ json.dump({"label": args.label, "enable_thinking_true_maps_to": args.on,
100
+ "template_file": os.path.basename(TPL), "template_path": TPL,
101
+ "sha256": hashlib.sha256(open(TPL, "rb").read()).hexdigest(),
102
+ "source_sha256": hashlib.sha256(src).hexdigest(), "shim": SHIM, "probes": probes},
103
+ open(f"{W}/results/{args.out}", "w"), indent=1)
104
+ print("NEX_TOOLS_TPL_DONE")
recipe/pipeline/readback.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Exact-name read-back gate: the built file is the receipt, not the ftype name.
3
+ usage: readback.py <expect_output> <expect_embd> <file.gguf> (use '-' to skip a check)"""
4
+ import sys
5
+ sys.path.insert(0, "/opt/llama-rocm/rocmfpx-724/gguf-py")
6
+ import gguf
7
+ exp_out, exp_emb, path = sys.argv[1:4]
8
+ r = gguf.GGUFReader(path)
9
+ def tname(t):
10
+ try: return t.tensor_type.name
11
+ except Exception: return f"TYPE_{int(t.tensor_type)}"
12
+ ty = {t.name: tname(t) for t in r.tensors}
13
+ f = r.fields.get("general.file_type")
14
+ ftype = int(f.parts[f.data[0]][0]) if f else None
15
+ arch = bytes(r.fields["general.architecture"].parts[-1]).decode()
16
+ nextn = sum(".nextn." in k for k in ty)
17
+ out, emb = ty.get("output.weight"), ty.get("token_embd.weight")
18
+ ok = (exp_out == "-" or out == exp_out) and (exp_emb == "-" or emb == exp_emb)
19
+ print(f"{'PASS' if ok else 'FAIL'} {path.split('/')[-1]} arch={arch} ftype={ftype} tensors={len(ty)} nextn={nextn} "
20
+ f"output.weight={out} token_embd.weight={emb}")
21
+ sys.exit(0 if ok else 1)
recipe/pipeline/run_tools_c1.sh ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # C1 = high shim template + server default enable_thinking=false: full tool suite + -fa on image gate + probes
3
+ cd /mnt/models/nex-n2.5-mini
4
+ systemd-run --scope --quiet --unit=nex-tools-c1-$(date +%s) -p MemoryMax=32G -p MemorySwapMax=0 \
5
+ python3 nex_tools_tpl.py --on high --label n-tools-q106-c1 --tpl chat_template_enable_thinking.jinja \
6
+ --extra '["--chat-template-kwargs", "{\"enable_thinking\": false}"]' --vision --out nex_template_shim_c1.json
7
+ echo "rc=$?"
recipe/pipeline/run_tools_roff.sh ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Recommended Nex serving: high shim template + --reasoning off (default thinking off; enable_thinking=true per request
3
+ # turns it on). Three tool-suite passes + -fa on image gate + probes.
4
+ cd /mnt/models/nex-n2.5-mini
5
+ systemd-run --scope --quiet --unit=nex-tools-roff-$(date +%s) -p MemoryMax=32G -p MemorySwapMax=0 \
6
+ python3 nex_tools_tpl.py --on high --label n-tools-q106-roff --tpl chat_template_enable_thinking.jinja \
7
+ --extra '["--reasoning", "off"]' --repeats 3 --vision --out nex_template_shim_roff.json
8
+ echo "rc=$?"
recipe/pipeline/upload_watchdog.sh ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # upload_watchdog.sh <name> <workdir> <command...>
3
+ # Runs a Hugging Face upload command in a 40G memory scope (niced) and kills + retries it (3 attempts) when its progress
4
+ # output — upload_large_folder's minute-by-minute "Files:" status and the xet progress bars — has not changed for
5
+ # 20 minutes. Reason: on 2026-09-16 the Agnes imatrix upload hung silently for 51 min (both HTTPS sockets in
6
+ # CLOSE-WAIT, 0 B/s, no error line) while holding the quiet-box lock. upload_large_folder resumes from the folder's
7
+ # .cache, so a retry only sends what is missing. Exit 0 once an attempt prints UPLOAD_DONE.
8
+ # The caller holds the quiet-box lock on fd 9; the upload process itself does not inherit it.
9
+ set -uo pipefail
10
+ name=$1; dir=$2; shift 2
11
+ cd "$dir" || exit 2
12
+ mkdir -p logs
13
+ log(){ echo "[$(date -u +%FT%TZ)] $*"; }
14
+ for try in 1 2 3; do
15
+ L=logs/upload_$name.r$try.log; U=$name-r$try-$(date +%s)
16
+ log "$name attempt $try -> $dir/$L (scope $U, MemoryMax=40G)"
17
+ systemd-run --scope --quiet --unit="$U" -p MemoryMax=40G -p MemorySwapMax=0 nice -n 10 "$@" > "$L" 2>&1 9>&- &
18
+ pid=$!; last=""; same=0
19
+ while kill -0 $pid 2>/dev/null; do
20
+ sleep 60
21
+ cur=$(tr '\r' '\n' < "$L" | grep -E '^Files:|B / ' | tail -3 | md5sum)
22
+ if [ "$cur" = "$last" ]; then same=$((same + 1)); else same=0; last=$cur; fi
23
+ if [ $same -ge 20 ]; then
24
+ log " $name attempt $try: no progress for 20 min -> kill ($(tr '\r' '\n' < "$L" | grep -E '^Files:' | tail -1))"
25
+ systemctl kill --signal=KILL "$U"; same=0
26
+ fi
27
+ done
28
+ wait $pid; rc=$?
29
+ if [ $rc -eq 0 ] && grep -q UPLOAD_DONE "$L"; then log " $name attempt $try done"; exit 0; fi
30
+ log " $name attempt $try failed rc=$rc: $(tr '\r' '\n' < "$L" | grep -v '^\s*$' | tail -1 | cut -c1-200)"
31
+ sleep 30
32
+ done
33
+ exit 1
recipe/pipeline/verify_download.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte + sha256 gate for a pinned HF snapshot. Compares against the tree API's lfs.oid
3
+ (the real content sha256) -- never the plain etag, which is a Xet/CAS id.
4
+ usage: verify_download.py <repo> <revision> <local_dir>"""
5
+ import hashlib, json, os, sys, urllib.request
6
+ from concurrent.futures import ThreadPoolExecutor
7
+ repo, rev, d = sys.argv[1:4]
8
+ tree = json.load(urllib.request.urlopen(
9
+ f"https://huggingface.co/api/models/{repo}/tree/{rev}?recursive=true", timeout=60))
10
+ files = [t for t in tree if t.get("type") == "file"]
11
+ def sha(p):
12
+ h = hashlib.sha256()
13
+ with open(p, "rb") as f:
14
+ for b in iter(lambda: f.read(64 << 20), b""): h.update(b)
15
+ return h.hexdigest()
16
+ def one(t):
17
+ p = os.path.join(d, t["path"])
18
+ if not os.path.exists(p): return (t["path"], "MISSING")
19
+ if os.path.getsize(p) != t["size"]: return (t["path"], f"SIZE {os.path.getsize(p)} != {t['size']}")
20
+ lfs = t.get("lfs")
21
+ if lfs:
22
+ got = sha(p)
23
+ return (t["path"], "ok-sha" if got == lfs["oid"] else f"SHA {got[:12]} != {lfs['oid'][:12]}")
24
+ return (t["path"], "ok-size")
25
+ with ThreadPoolExecutor(6) as ex: res = list(ex.map(one, files))
26
+ bad = [r for r in res if not r[1].startswith("ok")]
27
+ print(f"files={len(res)} sha-verified={sum(r[1]=='ok-sha' for r in res)} size-only={sum(r[1]=='ok-size' for r in res)} bad={len(bad)}")
28
+ for r in bad: print(" BAD", r)
29
+ print("RESULT:", "PASS" if not bad else "FAIL")
30
+ sys.exit(0 if not bad else 1)
recipe/results_summary.json ADDED
@@ -0,0 +1,1721 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "layout": "no MTP (checkpoint declares mtp_num_hidden_layers=1 but ships no mtp.* tensors)",
3
+ "model": "Nex-N2.5-mini",
4
+ "model_repo_std": "kingjones777/Nex-N2.5-mini-ROCmFP4-GGUF",
5
+ "model_repo_imat": "kingjones777/Nex-N2.5-mini-ROCmFP4-imatrix-GGUF",
6
+ "source": {
7
+ "repo": "nex-agi/Nex-N2.5-mini",
8
+ "revision": "87420286149d9cce9bd46cd335ef9bda33c37c1b",
9
+ "license": "apache-2.0",
10
+ "gated": false,
11
+ "params": 35107181936
12
+ },
13
+ "arch": {
14
+ "name": "qwen3_5_moe",
15
+ "llama_cpp": "qwen35moe",
16
+ "layers": 40,
17
+ "linear_attn_layers": 30,
18
+ "full_attn_layers": 10,
19
+ "full_attention_interval": 4,
20
+ "hidden": 2048,
21
+ "num_experts": 256,
22
+ "num_experts_per_tok": 8,
23
+ "expert_width": 512,
24
+ "shared_expert_width": 512,
25
+ "attn_heads": 16,
26
+ "kv_heads": 2,
27
+ "head_dim": 256,
28
+ "linear_key_heads": 16,
29
+ "linear_value_heads": 32,
30
+ "linear_head_dim": 128,
31
+ "vocab": 248320,
32
+ "max_position_embeddings": 262144,
33
+ "tie_word_embeddings": false,
34
+ "vision_layers": 27,
35
+ "vision_width": 1152,
36
+ "hf_tensors": 1026,
37
+ "mtp_num_hidden_layers_declared": 1
38
+ },
39
+ "bf16": {
40
+ "ppl": 6.2303,
41
+ "ppl_err": 0.07538,
42
+ "ppl_paired": 6.228979,
43
+ "ppl_paired_err": 0.075322,
44
+ "chunks": 40,
45
+ "n_ctx": 2048,
46
+ "scored_tokens": 40920,
47
+ "size_bytes": 69376636928,
48
+ "file": "Nex-N2.5-mini-BF16.gguf",
49
+ "readback": "PASS",
50
+ "arch": "qwen35moe",
51
+ "ftype": 32,
52
+ "tensors": 733,
53
+ "nextn_tensors": 0,
54
+ "output_weight": "BF16",
55
+ "token_embd": "BF16",
56
+ "mtp_named_tensors": 0,
57
+ "nextn_named_tensors": 0
58
+ },
59
+ "binary": {
60
+ "repo": "https://github.com/charlie12345/ROCmFPX",
61
+ "commit": "d3ca537",
62
+ "dir": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
63
+ "sha256": {
64
+ "llama-server": "d077b98f3f04df4b482a5826c8922e39cda3aa8d2e2b2fbe1870f36d245cebe7",
65
+ "llama-quantize": "1559189968a30781f837e4d25ca3cdf26c8eb0351023675406535eddcbe0db13",
66
+ "llama-imatrix": "bfdce5c21a01bdc8043d69335b74a7b68b8335ae989991a1e10e21d5faeaeb8e",
67
+ "llama-perplexity": "c2175925bb0c61df89ff787845d8e03a35403f684be52719ac2987b8ca636a53"
68
+ }
69
+ },
70
+ "vision_probe": {
71
+ "width": 448,
72
+ "height": 448,
73
+ "bytes": 1945,
74
+ "sha256": "53924b4715db9757d5b70614dd0e560b8f7de686ff3df9792721d157e2594f5e"
75
+ },
76
+ "imatrix": {
77
+ "chunks": 129,
78
+ "n_ctx": 512,
79
+ "calibration": "bartowski calibration_datav3.txt",
80
+ "file": "Nex-N2.5-mini.imatrix",
81
+ "sha256": "7e5afffc822c64a7b43a1223d0094fb60895a521f6c89b912409d25091bd17f8",
82
+ "size_bytes": 192223936,
83
+ "device": "CPU"
84
+ },
85
+ "hub_check": {
86
+ "checked_at_utc": "2026-09-16T21:27:05Z",
87
+ "queries": [
88
+ "Nex-N2.5-mini",
89
+ "Nex-N2.5",
90
+ "nex-n2.5-mini gguf",
91
+ "Nex N2.5 mini"
92
+ ],
93
+ "repos": [
94
+ {
95
+ "repo": "6block/Nex-N2.5-Pro-GGUF",
96
+ "gguf_files": 58,
97
+ "rocm_like_files": [],
98
+ "gguf_sample": [
99
+ "Nex-N2.5-Pro-IQ2_XS-00001-of-00019.gguf",
100
+ "Nex-N2.5-Pro-IQ2_XS-00002-of-00019.gguf",
101
+ "Nex-N2.5-Pro-IQ2_XS-00003-of-00019.gguf"
102
+ ]
103
+ },
104
+ {
105
+ "repo": "Arahide/Nex-N2.5-mini-INT4-W4A16",
106
+ "gguf_files": 0,
107
+ "rocm_like_files": [],
108
+ "gguf_sample": []
109
+ },
110
+ {
111
+ "repo": "DevQuasar/nex-agi.Nex-N2.5-Max-GGUF",
112
+ "gguf_files": 0,
113
+ "rocm_like_files": [],
114
+ "gguf_sample": []
115
+ },
116
+ {
117
+ "repo": "DevQuasar/nex-agi.Nex-N2.5-Pro-GGUF",
118
+ "gguf_files": 66,
119
+ "rocm_like_files": [],
120
+ "gguf_sample": [
121
+ "Q2_K/nex-agi.Nex-N2.5-Pro.f16.gguf.Q2_K.gguf-00001-of-00011.gguf",
122
+ "Q2_K/nex-agi.Nex-N2.5-Pro.f16.gguf.Q2_K.gguf-00002-of-00011.gguf",
123
+ "Q2_K/nex-agi.Nex-N2.5-Pro.f16.gguf.Q2_K.gguf-00003-of-00011.gguf"
124
+ ]
125
+ },
126
+ {
127
+ "repo": "DevQuasar/nex-agi.Nex-N2.5-mini-GGUF",
128
+ "gguf_files": 7,
129
+ "rocm_like_files": [],
130
+ "gguf_sample": [
131
+ "Q2_K/nex-agi.Nex-N2.5-mini.f16.gguf.Q2_K.gguf",
132
+ "Q3_K_M/nex-agi.Nex-N2.5-mini.f16.gguf.Q3_K_M.gguf",
133
+ "Q4_K_M/nex-agi.Nex-N2.5-mini.f16.gguf.Q4_K_M.gguf"
134
+ ]
135
+ },
136
+ {
137
+ "repo": "IsValorum/Nex-N2.5-mini-APEX-I-MiniPlus-GGUF",
138
+ "gguf_files": 2,
139
+ "rocm_like_files": [],
140
+ "gguf_sample": [
141
+ "Nex-N2.5-mini.APEX-I-MiniPlus.gguf",
142
+ "mmproj-nex-agi_Nex-N2.5-mini-Q8_0.gguf"
143
+ ]
144
+ },
145
+ {
146
+ "repo": "Kagandi/Nex-N2.5-mini-mlx-4Bit",
147
+ "gguf_files": 0,
148
+ "rocm_like_files": [],
149
+ "gguf_sample": []
150
+ },
151
+ {
152
+ "repo": "MrFuzzihead/Nex-N2.5-mini-APEX-GGUF",
153
+ "gguf_files": 12,
154
+ "rocm_like_files": [],
155
+ "gguf_sample": [
156
+ "Nex-N2.5-mini-APEX-Balanced.gguf",
157
+ "Nex-N2.5-mini-APEX-Compact.gguf",
158
+ "Nex-N2.5-mini-APEX-I-Balanced.gguf"
159
+ ]
160
+ },
161
+ {
162
+ "repo": "NandoG-AI/Nex-N2.5-mini-GGUF",
163
+ "gguf_files": 1,
164
+ "rocm_like_files": [],
165
+ "gguf_sample": [
166
+ "Nex-N2.5-mini-Q4_K_M.gguf"
167
+ ]
168
+ },
169
+ {
170
+ "repo": "ProCreations/Nex-N2.5-mini-NVFP4",
171
+ "gguf_files": 0,
172
+ "rocm_like_files": [],
173
+ "gguf_sample": []
174
+ },
175
+ {
176
+ "repo": "SAIFIINDUSTRIES/Nex-N2.5-mini",
177
+ "gguf_files": 0,
178
+ "rocm_like_files": [],
179
+ "gguf_sample": []
180
+ },
181
+ {
182
+ "repo": "Tech2wild/Nex-N2.5-mini-Int4-Int8Mix",
183
+ "gguf_files": 0,
184
+ "rocm_like_files": [],
185
+ "gguf_sample": []
186
+ },
187
+ {
188
+ "repo": "Vontra/Nex-N2.5-mini-MLX-4bit",
189
+ "gguf_files": 0,
190
+ "rocm_like_files": [],
191
+ "gguf_sample": []
192
+ },
193
+ {
194
+ "repo": "Vontra/Nex-N2.5-mini-MLX-6bit",
195
+ "gguf_files": 0,
196
+ "rocm_like_files": [],
197
+ "gguf_sample": []
198
+ },
199
+ {
200
+ "repo": "Vontra/Nex-N2.5-mini-MLX-8bit",
201
+ "gguf_files": 0,
202
+ "rocm_like_files": [],
203
+ "gguf_sample": []
204
+ },
205
+ {
206
+ "repo": "Vontra/Nex-N2.5-mini-MLX-oQ2",
207
+ "gguf_files": 0,
208
+ "rocm_like_files": [],
209
+ "gguf_sample": []
210
+ },
211
+ {
212
+ "repo": "Vontra/Nex-N2.5-mini-MLX-oQ3",
213
+ "gguf_files": 0,
214
+ "rocm_like_files": [],
215
+ "gguf_sample": []
216
+ },
217
+ {
218
+ "repo": "Vontra/Nex-N2.5-mini-MLX-oQ4",
219
+ "gguf_files": 0,
220
+ "rocm_like_files": [],
221
+ "gguf_sample": []
222
+ },
223
+ {
224
+ "repo": "Vontra/Nex-N2.5-mini-MLX-oQ6",
225
+ "gguf_files": 0,
226
+ "rocm_like_files": [],
227
+ "gguf_sample": []
228
+ },
229
+ {
230
+ "repo": "Vontra/Nex-N2.5-mini-MLX-oQ8",
231
+ "gguf_files": 0,
232
+ "rocm_like_files": [],
233
+ "gguf_sample": []
234
+ },
235
+ {
236
+ "repo": "abenzerps/Nex-N2.5-mini-GGUF",
237
+ "gguf_files": 18,
238
+ "rocm_like_files": [],
239
+ "gguf_sample": [
240
+ "Nex-N2.5-mini-IQ1_M.gguf",
241
+ "Nex-N2.5-mini-IQ1_S.gguf",
242
+ "Nex-N2.5-mini-IQ2_M.gguf"
243
+ ]
244
+ },
245
+ {
246
+ "repo": "abenzerps/Nex-N2.5-mini-MLX-4bit",
247
+ "gguf_files": 0,
248
+ "rocm_like_files": [],
249
+ "gguf_sample": []
250
+ },
251
+ {
252
+ "repo": "abenzerps/Nex-N2.5-mini-MLX-6bit",
253
+ "gguf_files": 0,
254
+ "rocm_like_files": [],
255
+ "gguf_sample": []
256
+ },
257
+ {
258
+ "repo": "abenzerps/Nex-N2.5-mini-MLX-8bit",
259
+ "gguf_files": 0,
260
+ "rocm_like_files": [],
261
+ "gguf_sample": []
262
+ },
263
+ {
264
+ "repo": "auryn-macmillan/Nex-N2.5-mini-exl3-5bpw",
265
+ "gguf_files": 0,
266
+ "rocm_like_files": [],
267
+ "gguf_sample": []
268
+ },
269
+ {
270
+ "repo": "bartowski/Nex-N2.5-Pro-GGUF",
271
+ "gguf_files": 144,
272
+ "rocm_like_files": [],
273
+ "gguf_sample": [
274
+ "Nex-N2.5-Pro-IQ1_M/Nex-N2.5-Pro-IQ1_M-00001-of-00003.gguf",
275
+ "Nex-N2.5-Pro-IQ1_M/Nex-N2.5-Pro-IQ1_M-00002-of-00003.gguf",
276
+ "Nex-N2.5-Pro-IQ1_M/Nex-N2.5-Pro-IQ1_M-00003-of-00003.gguf"
277
+ ]
278
+ },
279
+ {
280
+ "repo": "bartowski/nex-agi_Nex-N2.5-mini-GGUF",
281
+ "gguf_files": 28,
282
+ "rocm_like_files": [],
283
+ "gguf_sample": [
284
+ "mmproj-nex-agi_Nex-N2.5-mini-bf16.gguf",
285
+ "mmproj-nex-agi_Nex-N2.5-mini-f16.gguf",
286
+ "nex-agi_Nex-N2.5-mini-IQ2_M.gguf"
287
+ ]
288
+ },
289
+ {
290
+ "repo": "cbert33/Nex-N2.5-mini-FP8-Calibrated",
291
+ "gguf_files": 0,
292
+ "rocm_like_files": [],
293
+ "gguf_sample": []
294
+ },
295
+ {
296
+ "repo": "ghazni101/Nex-N2.5-mini-MQ4R",
297
+ "gguf_files": 0,
298
+ "rocm_like_files": [],
299
+ "gguf_sample": []
300
+ },
301
+ {
302
+ "repo": "julianmb/Nex-N2.5-mini-ROCmFP4-GGUF",
303
+ "gguf_files": 2,
304
+ "rocm_like_files": [
305
+ "Nex-N2.5-mini-ROCmFP4-STRIX_LEAN.gguf"
306
+ ],
307
+ "gguf_sample": [
308
+ "Nex-N2.5-mini-ROCmFP4-STRIX_LEAN.gguf",
309
+ "mmproj-Nex-N2.5-mini.gguf"
310
+ ]
311
+ },
312
+ {
313
+ "repo": "karmx/Nex-N2.5-mini-Mixed-Q2Q3-128K-GGUF",
314
+ "gguf_files": 2,
315
+ "rocm_like_files": [],
316
+ "gguf_sample": [
317
+ "Nex-N2.5-mini-mixed-Q2Q3-vision-trial.gguf",
318
+ "mmproj-Nex-N2.5-mini-f16.gguf"
319
+ ]
320
+ },
321
+ {
322
+ "repo": "liskasYR/Nex-N2.5-Max",
323
+ "gguf_files": 0,
324
+ "rocm_like_files": [],
325
+ "gguf_sample": []
326
+ },
327
+ {
328
+ "repo": "mlx-community/Nex-N2.5-mini-OptiQ-4bit",
329
+ "gguf_files": 0,
330
+ "rocm_like_files": [],
331
+ "gguf_sample": []
332
+ },
333
+ {
334
+ "repo": "mlx-community/Nex-N2.5-mini-oQ4",
335
+ "gguf_files": 0,
336
+ "rocm_like_files": [],
337
+ "gguf_sample": []
338
+ },
339
+ {
340
+ "repo": "mradermacher/Nex-N2.5-mini-GGUF",
341
+ "gguf_files": 13,
342
+ "rocm_like_files": [],
343
+ "gguf_sample": [
344
+ "Nex-N2.5-mini.IQ4_XS.gguf",
345
+ "Nex-N2.5-mini.Q2_K.gguf",
346
+ "Nex-N2.5-mini.Q3_K_L.gguf"
347
+ ]
348
+ },
349
+ {
350
+ "repo": "mradermacher/Nex-N2.5-mini-i1-GGUF",
351
+ "gguf_files": 24,
352
+ "rocm_like_files": [],
353
+ "gguf_sample": [
354
+ "Nex-N2.5-mini.i1-IQ1_M.gguf",
355
+ "Nex-N2.5-mini.i1-IQ1_S.gguf",
356
+ "Nex-N2.5-mini.i1-IQ2_M.gguf"
357
+ ]
358
+ },
359
+ {
360
+ "repo": "nex-agi/Nex-N2.5-Max",
361
+ "gguf_files": 0,
362
+ "rocm_like_files": [],
363
+ "gguf_sample": []
364
+ },
365
+ {
366
+ "repo": "nex-agi/Nex-N2.5-mini",
367
+ "gguf_files": 0,
368
+ "rocm_like_files": [],
369
+ "gguf_sample": []
370
+ },
371
+ {
372
+ "repo": "ngquocvinh/Nex-N2.5-mini-GGUF",
373
+ "gguf_files": 16,
374
+ "rocm_like_files": [],
375
+ "gguf_sample": [
376
+ "Nex-N2.5-mini-IQ1_M.gguf",
377
+ "Nex-N2.5-mini-IQ2_XS.gguf",
378
+ "Nex-N2.5-mini-IQ3_M.gguf"
379
+ ]
380
+ },
381
+ {
382
+ "repo": "orcarouter/Nex-N2.5-mini-Uncensored",
383
+ "gguf_files": 0,
384
+ "rocm_like_files": [],
385
+ "gguf_sample": []
386
+ },
387
+ {
388
+ "repo": "orcarouter/Nex-N2.5-mini-Uncensored-FP8",
389
+ "gguf_files": 0,
390
+ "rocm_like_files": [],
391
+ "gguf_sample": []
392
+ },
393
+ {
394
+ "repo": "orcarouter/Nex-N2.5-mini-Uncensored-GGUF",
395
+ "gguf_files": 6,
396
+ "rocm_like_files": [],
397
+ "gguf_sample": [
398
+ "Nex-N2.5-mini-Uncensored-IQ4_XS.gguf",
399
+ "Nex-N2.5-mini-Uncensored-Q2_K.gguf",
400
+ "Nex-N2.5-mini-Uncensored-Q3_K_M.gguf"
401
+ ]
402
+ },
403
+ {
404
+ "repo": "orcarouter/Nex-N2.5-mini-Uncensored-MLX",
405
+ "gguf_files": 0,
406
+ "rocm_like_files": [],
407
+ "gguf_sample": []
408
+ },
409
+ {
410
+ "repo": "orcarouter/Nex-N2.5-mini-Uncensored-NVFP4",
411
+ "gguf_files": 0,
412
+ "rocm_like_files": [],
413
+ "gguf_sample": []
414
+ },
415
+ {
416
+ "repo": "primitive-ai/Nex-N2.5-mini-FP8",
417
+ "gguf_files": 0,
418
+ "rocm_like_files": [],
419
+ "gguf_sample": []
420
+ },
421
+ {
422
+ "repo": "primitive-ai/Nex-N2.5-mini-NVFP4",
423
+ "gguf_files": 0,
424
+ "rocm_like_files": [],
425
+ "gguf_sample": []
426
+ },
427
+ {
428
+ "repo": "primitive-ai/Nex-N2.5-mini-mixed-NVFP4-FP8",
429
+ "gguf_files": 0,
430
+ "rocm_like_files": [],
431
+ "gguf_sample": []
432
+ },
433
+ {
434
+ "repo": "qtum/Nex-N2.5-Pro-GGUF",
435
+ "gguf_files": 58,
436
+ "rocm_like_files": [],
437
+ "gguf_sample": [
438
+ "Nex-N2.5-Pro-IQ2_XS-00001-of-00019.gguf",
439
+ "Nex-N2.5-Pro-IQ2_XS-00002-of-00019.gguf",
440
+ "Nex-N2.5-Pro-IQ2_XS-00003-of-00019.gguf"
441
+ ]
442
+ },
443
+ {
444
+ "repo": "quant-mind/Nex-N2.5-mini-W4A16-AutoRound",
445
+ "gguf_files": 0,
446
+ "rocm_like_files": [],
447
+ "gguf_sample": []
448
+ },
449
+ {
450
+ "repo": "sakamakismile/Nex-N2.5-Max-GGUF",
451
+ "gguf_files": 39,
452
+ "rocm_like_files": [],
453
+ "gguf_sample": [
454
+ "Q3_K_M/Nex-N2.5-Max-Q3_K_M-00001-of-00018.gguf",
455
+ "Q3_K_M/Nex-N2.5-Max-Q3_K_M-00002-of-00018.gguf",
456
+ "Q3_K_M/Nex-N2.5-Max-Q3_K_M-00003-of-00018.gguf"
457
+ ]
458
+ },
459
+ {
460
+ "repo": "sigmanih/nex-agi-Nex-N2.5-mini-GGUF-Q4_K_S",
461
+ "gguf_files": 1,
462
+ "rocm_like_files": [],
463
+ "gguf_sample": [
464
+ "nex-agi--Nex-N2.5-mini.Q4_K_S.gguf"
465
+ ]
466
+ },
467
+ {
468
+ "repo": "sojufx/Nex-N2.5-mini-NVFP4",
469
+ "gguf_files": 0,
470
+ "rocm_like_files": [],
471
+ "gguf_sample": []
472
+ },
473
+ {
474
+ "repo": "suzu89/Nex-N2.5-mini-oQ5",
475
+ "gguf_files": 0,
476
+ "rocm_like_files": [],
477
+ "gguf_sample": []
478
+ },
479
+ {
480
+ "repo": "vikrant1123/Nex-N2.5-mini-Uncensored-APEX-GGUF",
481
+ "gguf_files": 5,
482
+ "rocm_like_files": [],
483
+ "gguf_sample": [
484
+ "Nex-N2.5-mini-Uncensored-APEX-I-Balanced.gguf",
485
+ "Nex-N2.5-mini-Uncensored-APEX-I-Compact.gguf",
486
+ "Nex-N2.5-mini-Uncensored-APEX-I-Quality.gguf"
487
+ ]
488
+ }
489
+ ],
490
+ "gguf_repos": 19,
491
+ "rocm_builds_found": 1,
492
+ "header_checks": [
493
+ {
494
+ "repo": "julianmb/Nex-N2.5-mini-ROCmFP4-GGUF",
495
+ "file": "Nex-N2.5-mini-ROCmFP4-STRIX_LEAN.gguf",
496
+ "file_type": 106,
497
+ "tensors": 733,
498
+ "block_count": 40,
499
+ "output_weight_type_id": 101,
500
+ "token_embd_type_id": 13,
501
+ "imatrix_keys": [],
502
+ "read_via": "HTTP range read of the GGUF header",
503
+ "output_weight_type": "Q4_0_ROCMFP4_FAST",
504
+ "token_embd_type": "Q5_K"
505
+ }
506
+ ]
507
+ },
508
+ "repeat": {
509
+ "step": "N5",
510
+ "device": "ROCm0",
511
+ "rows": 40,
512
+ "result": "MATCH"
513
+ },
514
+ "repeat_vk": {
515
+ "step": "N5v",
516
+ "device": "Vulkan0",
517
+ "rows": 40,
518
+ "result": "MATCH"
519
+ },
520
+ "reference": {
521
+ "step": "N1c",
522
+ "cpu_chunk1": 5.6964,
523
+ "vulkan0_chunk1": 5.6953,
524
+ "hip_rocm0_chunk1": 139.1466,
525
+ "hip_rocm0_faoff_chunk1": 136.6879,
526
+ "hip_rocm0_final": 105.9103,
527
+ "result": "PASS"
528
+ },
529
+ "reference_device": "CPU",
530
+ "tiers": {
531
+ "q106": {
532
+ "file": "Nex-N2.5-mini-Q4_0-ROCmFP4-STRIX_LEAN.gguf",
533
+ "local_file": "Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf",
534
+ "dir": "out",
535
+ "ftype": 106,
536
+ "size_bytes": 18744342208,
537
+ "quant_mib": 17865.52,
538
+ "bpw": 4.32,
539
+ "quant_seconds": 394.87116,
540
+ "imatrix_entries": null,
541
+ "readback": "PASS",
542
+ "arch": "qwen35moe",
543
+ "tensors": 733,
544
+ "nextn_tensors": 0,
545
+ "output_weight": "Q6_K",
546
+ "token_embd": "Q5_K",
547
+ "quality_measured": true,
548
+ "ppl": 6.473964,
549
+ "ppl_err": 0.079799,
550
+ "ppl_ratio": 1.03933,
551
+ "kld_mean": 0.104436,
552
+ "kld_err": 0.001413,
553
+ "kld_p99": 0.926687,
554
+ "kld_median": 0.047702,
555
+ "same_top_p": 86.659,
556
+ "rms_dp": 9.028,
557
+ "vk": {
558
+ "ppl": 6.474466,
559
+ "ppl_err": 0.079947,
560
+ "ppl_ratio": 1.03941,
561
+ "kld_mean": 0.104408,
562
+ "kld_err": 0.001395,
563
+ "kld_p99": 0.899358,
564
+ "kld_median": 0.048009,
565
+ "same_top_p": 86.794,
566
+ "rms_dp": 9.03
567
+ }
568
+ },
569
+ "q102": {
570
+ "file": "Nex-N2.5-mini-Q4_0-ROCmFP4-COHERENT.gguf",
571
+ "local_file": "Nex-N2.5-mini-Q4_0_ROCMFP4_COHERENT.gguf",
572
+ "dir": "out",
573
+ "ftype": 102,
574
+ "size_bytes": 19846166208,
575
+ "quant_mib": 18916.3,
576
+ "bpw": 4.58,
577
+ "quant_seconds": 443.71327,
578
+ "imatrix_entries": null,
579
+ "readback": "PASS",
580
+ "arch": "qwen35moe",
581
+ "tensors": 733,
582
+ "nextn_tensors": 0,
583
+ "output_weight": "Q6_K",
584
+ "token_embd": "Q6_K",
585
+ "quality_measured": true,
586
+ "ppl": 6.561727,
587
+ "ppl_err": 0.08124,
588
+ "ppl_ratio": 1.053419,
589
+ "kld_mean": 0.097071,
590
+ "kld_err": 0.001342,
591
+ "kld_p99": 0.874485,
592
+ "kld_median": 0.043524,
593
+ "same_top_p": 87.287,
594
+ "rms_dp": 8.8,
595
+ "vk": {
596
+ "ppl": 6.592123,
597
+ "ppl_err": 0.081874,
598
+ "ppl_ratio": 1.058299,
599
+ "kld_mean": 0.097165,
600
+ "kld_err": 0.001337,
601
+ "kld_p99": 0.858566,
602
+ "kld_median": 0.043968,
603
+ "same_top_p": 87.265,
604
+ "rms_dp": 8.853
605
+ }
606
+ },
607
+ "q103": {
608
+ "file": "Nex-N2.5-mini-Q4_0-ROCmFP4-FAST.gguf",
609
+ "local_file": "Nex-N2.5-mini-Q4_0_ROCMFP4_FAST.gguf",
610
+ "dir": "out",
611
+ "ftype": 103,
612
+ "size_bytes": 18648495808,
613
+ "quant_mib": 17774.11,
614
+ "bpw": 4.3,
615
+ "quant_seconds": 392.98796999999996,
616
+ "imatrix_entries": null,
617
+ "readback": "PASS",
618
+ "arch": "qwen35moe",
619
+ "tensors": 733,
620
+ "nextn_tensors": 0,
621
+ "output_weight": "Q6_K",
622
+ "token_embd": "Q4_0_ROCMFP4_FAST",
623
+ "quality_measured": true,
624
+ "ppl": 6.549829,
625
+ "ppl_err": 0.080919,
626
+ "ppl_ratio": 1.051509,
627
+ "kld_mean": 0.108779,
628
+ "kld_err": 0.00142,
629
+ "kld_p99": 0.956811,
630
+ "kld_median": 0.04973,
631
+ "same_top_p": 86.405,
632
+ "rms_dp": 9.108,
633
+ "vk": {
634
+ "ppl": 6.551305,
635
+ "ppl_err": 0.081055,
636
+ "ppl_ratio": 1.051746,
637
+ "kld_mean": 0.108756,
638
+ "kld_err": 0.001422,
639
+ "kld_p99": 0.930024,
640
+ "kld_median": 0.050197,
641
+ "same_top_p": 86.356,
642
+ "rms_dp": 9.101
643
+ }
644
+ },
645
+ "q106i": {
646
+ "file": "Nex-N2.5-mini-imatrix-Q4_0-ROCmFP4-STRIX_LEAN.gguf",
647
+ "local_file": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf",
648
+ "dir": "out-imat",
649
+ "ftype": 106,
650
+ "size_bytes": 18744342464,
651
+ "quant_mib": 17865.52,
652
+ "bpw": 4.32,
653
+ "quant_seconds": 306.08412,
654
+ "imatrix_entries": 510,
655
+ "readback": "PASS",
656
+ "arch": "qwen35moe",
657
+ "tensors": 733,
658
+ "nextn_tensors": 0,
659
+ "output_weight": "Q6_K",
660
+ "token_embd": "Q5_K",
661
+ "quality_measured": true,
662
+ "ppl": 6.353616,
663
+ "ppl_err": 0.077001,
664
+ "ppl_ratio": 1.020009,
665
+ "kld_mean": 0.085158,
666
+ "kld_err": 0.001309,
667
+ "kld_p99": 0.737186,
668
+ "kld_median": 0.038436,
669
+ "same_top_p": 87.849,
670
+ "rms_dp": 8.281,
671
+ "vk": {
672
+ "ppl": 6.364168,
673
+ "ppl_err": 0.077334,
674
+ "ppl_ratio": 1.021703,
675
+ "kld_mean": 0.083563,
676
+ "kld_err": 0.001206,
677
+ "kld_p99": 0.713036,
678
+ "kld_median": 0.038,
679
+ "same_top_p": 87.903,
680
+ "rms_dp": 8.201
681
+ },
682
+ "same_tensor_types_as_standard": true,
683
+ "file_size_delta_bytes": 256,
684
+ "differs_from_standard": true,
685
+ "header_keys_only_in_imatrix": [
686
+ "quantize.imatrix.chunks_count",
687
+ "quantize.imatrix.dataset",
688
+ "quantize.imatrix.entries_count",
689
+ "quantize.imatrix.file"
690
+ ],
691
+ "header_keys_only_in_standard": []
692
+ },
693
+ "q102i": {
694
+ "file": "Nex-N2.5-mini-imatrix-Q4_0-ROCmFP4-COHERENT.gguf",
695
+ "local_file": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_COHERENT.gguf",
696
+ "dir": "out-imat",
697
+ "ftype": 102,
698
+ "size_bytes": 19846166464,
699
+ "quant_mib": 18916.3,
700
+ "bpw": 4.58,
701
+ "quant_seconds": 409.08034000000004,
702
+ "imatrix_entries": 510,
703
+ "readback": "PASS",
704
+ "arch": "qwen35moe",
705
+ "tensors": 733,
706
+ "nextn_tensors": 0,
707
+ "output_weight": "Q6_K",
708
+ "token_embd": "Q6_K",
709
+ "quality_measured": true,
710
+ "ppl": 6.36005,
711
+ "ppl_err": 0.077045,
712
+ "ppl_ratio": 1.021042,
713
+ "kld_mean": 0.076947,
714
+ "kld_err": 0.001181,
715
+ "kld_p99": 0.685225,
716
+ "kld_median": 0.034241,
717
+ "same_top_p": 88.463,
718
+ "rms_dp": 7.909,
719
+ "vk": {
720
+ "ppl": 6.36321,
721
+ "ppl_err": 0.077202,
722
+ "ppl_ratio": 1.021549,
723
+ "kld_mean": 0.076844,
724
+ "kld_err": 0.001332,
725
+ "kld_p99": 0.669352,
726
+ "kld_median": 0.033844,
727
+ "same_top_p": 88.556,
728
+ "rms_dp": 7.783
729
+ },
730
+ "same_tensor_types_as_standard": true,
731
+ "file_size_delta_bytes": 256,
732
+ "differs_from_standard": true,
733
+ "header_keys_only_in_imatrix": [
734
+ "quantize.imatrix.chunks_count",
735
+ "quantize.imatrix.dataset",
736
+ "quantize.imatrix.entries_count",
737
+ "quantize.imatrix.file"
738
+ ],
739
+ "header_keys_only_in_standard": []
740
+ },
741
+ "q103i": {
742
+ "file": "Nex-N2.5-mini-imatrix-Q4_0-ROCmFP4-FAST.gguf",
743
+ "local_file": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_FAST.gguf",
744
+ "dir": "out-imat",
745
+ "ftype": 103,
746
+ "size_bytes": 18648496064,
747
+ "quant_mib": 17774.11,
748
+ "bpw": 4.3,
749
+ "quant_seconds": 328.50694,
750
+ "imatrix_entries": 510,
751
+ "readback": "PASS",
752
+ "arch": "qwen35moe",
753
+ "tensors": 733,
754
+ "nextn_tensors": 0,
755
+ "output_weight": "Q6_K",
756
+ "token_embd": "Q4_0_ROCMFP4_FAST",
757
+ "quality_measured": true,
758
+ "ppl": 6.368075,
759
+ "ppl_err": 0.077317,
760
+ "ppl_ratio": 1.02233,
761
+ "kld_mean": 0.088974,
762
+ "kld_err": 0.001318,
763
+ "kld_p99": 0.784672,
764
+ "kld_median": 0.039738,
765
+ "same_top_p": 87.454,
766
+ "rms_dp": 8.37,
767
+ "vk": {
768
+ "ppl": 6.392929,
769
+ "ppl_err": 0.077851,
770
+ "ppl_ratio": 1.026321,
771
+ "kld_mean": 0.08915,
772
+ "kld_err": 0.001266,
773
+ "kld_p99": 0.784911,
774
+ "kld_median": 0.039583,
775
+ "same_top_p": 87.424,
776
+ "rms_dp": 8.509
777
+ },
778
+ "same_tensor_types_as_standard": true,
779
+ "file_size_delta_bytes": 256,
780
+ "differs_from_standard": true,
781
+ "header_keys_only_in_imatrix": [
782
+ "quantize.imatrix.chunks_count",
783
+ "quantize.imatrix.dataset",
784
+ "quantize.imatrix.entries_count",
785
+ "quantize.imatrix.file"
786
+ ],
787
+ "header_keys_only_in_standard": []
788
+ }
789
+ },
790
+ "aux": {
791
+ "mmproj-Nex-N2.5-mini-BF16.gguf": 902821920,
792
+ "chat_template_enable_thinking.jinja": 7895
793
+ },
794
+ "mmproj": {
795
+ "file": "mmproj-Nex-N2.5-mini-BF16.gguf",
796
+ "size_bytes": 902821920,
797
+ "readback": "PASS",
798
+ "arch": "clip",
799
+ "ftype": 32,
800
+ "tensors": 334
801
+ },
802
+ "bench": [
803
+ {
804
+ "label": "n-q106-rocm",
805
+ "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf",
806
+ "draft": null,
807
+ "nmax": null,
808
+ "strict": false,
809
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
810
+ "dev": "ROCm0",
811
+ "ctx": 65536,
812
+ "workload": "code",
813
+ "load_s": 22.0,
814
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
815
+ "tg_median": 63.94,
816
+ "tg_min": 63.56,
817
+ "tg_max": 63.96,
818
+ "pp_median": 1158.2,
819
+ "prompt_n": 7098,
820
+ "accept": null,
821
+ "prompt_n_min": 7098,
822
+ "prompt_n_max": 7100
823
+ },
824
+ {
825
+ "label": "n-q106-vk",
826
+ "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf",
827
+ "draft": null,
828
+ "nmax": null,
829
+ "strict": false,
830
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
831
+ "dev": "Vulkan0",
832
+ "ctx": 65536,
833
+ "workload": "code",
834
+ "load_s": 4.0,
835
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
836
+ "tg_median": 68.16,
837
+ "tg_min": 68.1,
838
+ "tg_max": 68.21,
839
+ "pp_median": 1006.0,
840
+ "prompt_n": 7096,
841
+ "accept": null,
842
+ "prompt_n_min": 7096,
843
+ "prompt_n_max": 7098
844
+ },
845
+ {
846
+ "label": "n-q102-rocm",
847
+ "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_COHERENT.gguf",
848
+ "draft": null,
849
+ "nmax": null,
850
+ "strict": false,
851
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
852
+ "dev": "ROCm0",
853
+ "ctx": 65536,
854
+ "workload": "code",
855
+ "load_s": 24.0,
856
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_COHERENT.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
857
+ "tg_median": 61.74,
858
+ "tg_min": 61.74,
859
+ "tg_max": 61.8,
860
+ "pp_median": 1186.7,
861
+ "prompt_n": 7100,
862
+ "accept": null,
863
+ "prompt_n_min": 7096,
864
+ "prompt_n_max": 7100
865
+ },
866
+ {
867
+ "label": "n-q102-vk",
868
+ "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_COHERENT.gguf",
869
+ "draft": null,
870
+ "nmax": null,
871
+ "strict": false,
872
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
873
+ "dev": "Vulkan0",
874
+ "ctx": 65536,
875
+ "workload": "code",
876
+ "load_s": 22.0,
877
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_COHERENT.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
878
+ "tg_median": 68.0,
879
+ "tg_min": 67.88,
880
+ "tg_max": 68.09,
881
+ "pp_median": 1001.4,
882
+ "prompt_n": 7098,
883
+ "accept": null,
884
+ "prompt_n_min": 7098,
885
+ "prompt_n_max": 7101
886
+ },
887
+ {
888
+ "label": "n-q103-rocm",
889
+ "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_FAST.gguf",
890
+ "draft": null,
891
+ "nmax": null,
892
+ "strict": false,
893
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
894
+ "dev": "ROCm0",
895
+ "ctx": 65536,
896
+ "workload": "code",
897
+ "load_s": 22.0,
898
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_FAST.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
899
+ "tg_median": 63.31,
900
+ "tg_min": 63.14,
901
+ "tg_max": 63.38,
902
+ "pp_median": 1156.6,
903
+ "prompt_n": 7100,
904
+ "accept": null,
905
+ "prompt_n_min": 7094,
906
+ "prompt_n_max": 7100
907
+ },
908
+ {
909
+ "label": "n-q103-vk",
910
+ "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_FAST.gguf",
911
+ "draft": null,
912
+ "nmax": null,
913
+ "strict": false,
914
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
915
+ "dev": "Vulkan0",
916
+ "ctx": 65536,
917
+ "workload": "code",
918
+ "load_s": 20.0,
919
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_FAST.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
920
+ "tg_median": 68.62,
921
+ "tg_min": 68.6,
922
+ "tg_max": 68.67,
923
+ "pp_median": 998.9,
924
+ "prompt_n": 7098,
925
+ "accept": null,
926
+ "prompt_n_min": 7098,
927
+ "prompt_n_max": 7101
928
+ },
929
+ {
930
+ "label": "n-q106i-rocm",
931
+ "model": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf",
932
+ "draft": null,
933
+ "nmax": null,
934
+ "strict": false,
935
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
936
+ "dev": "ROCm0",
937
+ "ctx": 65536,
938
+ "workload": "code",
939
+ "load_s": 22.0,
940
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out-imat/Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
941
+ "tg_median": 63.29,
942
+ "tg_min": 63.19,
943
+ "tg_max": 63.41,
944
+ "pp_median": 1145.3,
945
+ "prompt_n": 7100,
946
+ "accept": null,
947
+ "prompt_n_min": 7097,
948
+ "prompt_n_max": 7100
949
+ },
950
+ {
951
+ "label": "n-q106i-vk",
952
+ "model": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf",
953
+ "draft": null,
954
+ "nmax": null,
955
+ "strict": false,
956
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
957
+ "dev": "Vulkan0",
958
+ "ctx": 65536,
959
+ "workload": "code",
960
+ "load_s": 20.0,
961
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out-imat/Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_STRIX_LEAN.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
962
+ "tg_median": 67.77,
963
+ "tg_min": 67.74,
964
+ "tg_max": 67.86,
965
+ "pp_median": 995.0,
966
+ "prompt_n": 7098,
967
+ "accept": null,
968
+ "prompt_n_min": 7098,
969
+ "prompt_n_max": 7100
970
+ },
971
+ {
972
+ "label": "n-q102i-rocm",
973
+ "model": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_COHERENT.gguf",
974
+ "draft": null,
975
+ "nmax": null,
976
+ "strict": false,
977
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
978
+ "dev": "ROCm0",
979
+ "ctx": 65536,
980
+ "workload": "code",
981
+ "load_s": 24.0,
982
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out-imat/Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_COHERENT.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
983
+ "tg_median": 61.56,
984
+ "tg_min": 61.53,
985
+ "tg_max": 61.63,
986
+ "pp_median": 1183.6,
987
+ "prompt_n": 7098,
988
+ "accept": null,
989
+ "prompt_n_min": 7096,
990
+ "prompt_n_max": 7100
991
+ },
992
+ {
993
+ "label": "n-q102i-vk",
994
+ "model": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_COHERENT.gguf",
995
+ "draft": null,
996
+ "nmax": null,
997
+ "strict": false,
998
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
999
+ "dev": "Vulkan0",
1000
+ "ctx": 65536,
1001
+ "workload": "code",
1002
+ "load_s": 22.0,
1003
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out-imat/Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_COHERENT.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
1004
+ "tg_median": 67.81,
1005
+ "tg_min": 67.77,
1006
+ "tg_max": 67.85,
1007
+ "pp_median": 998.7,
1008
+ "prompt_n": 7097,
1009
+ "accept": null,
1010
+ "prompt_n_min": 7096,
1011
+ "prompt_n_max": 7097
1012
+ },
1013
+ {
1014
+ "label": "n-q103i-rocm",
1015
+ "model": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_FAST.gguf",
1016
+ "draft": null,
1017
+ "nmax": null,
1018
+ "strict": false,
1019
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
1020
+ "dev": "ROCm0",
1021
+ "ctx": 65536,
1022
+ "workload": "code",
1023
+ "load_s": 22.0,
1024
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out-imat/Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_FAST.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
1025
+ "tg_median": 63.03,
1026
+ "tg_min": 62.55,
1027
+ "tg_max": 63.11,
1028
+ "pp_median": 1154.4,
1029
+ "prompt_n": 7101,
1030
+ "accept": null,
1031
+ "prompt_n_min": 7099,
1032
+ "prompt_n_max": 7101
1033
+ },
1034
+ {
1035
+ "label": "n-q103i-vk",
1036
+ "model": "Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_FAST.gguf",
1037
+ "draft": null,
1038
+ "nmax": null,
1039
+ "strict": false,
1040
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
1041
+ "dev": "Vulkan0",
1042
+ "ctx": 65536,
1043
+ "workload": "code",
1044
+ "load_s": 20.0,
1045
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out-imat/Nex-N2.5-mini-imatrix-Q4_0_ROCMFP4_FAST.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
1046
+ "tg_median": 68.44,
1047
+ "tg_min": 68.42,
1048
+ "tg_max": 68.56,
1049
+ "pp_median": 993.9,
1050
+ "prompt_n": 7098,
1051
+ "accept": null,
1052
+ "prompt_n_min": 7098,
1053
+ "prompt_n_max": 7102
1054
+ },
1055
+ {
1056
+ "label": "n-q106-rocm-prose",
1057
+ "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf",
1058
+ "draft": null,
1059
+ "nmax": null,
1060
+ "strict": false,
1061
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
1062
+ "dev": "ROCm0",
1063
+ "ctx": 65536,
1064
+ "workload": "prose",
1065
+ "load_s": 22.0,
1066
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf -dev ROCm0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
1067
+ "tg_median": 63.06,
1068
+ "tg_min": 62.94,
1069
+ "tg_max": 63.09,
1070
+ "pp_median": 1139.1,
1071
+ "prompt_n": 7454,
1072
+ "accept": null,
1073
+ "prompt_n_min": 7453,
1074
+ "prompt_n_max": 7455
1075
+ },
1076
+ {
1077
+ "label": "n-q106-vk-prose",
1078
+ "model": "Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf",
1079
+ "draft": null,
1080
+ "nmax": null,
1081
+ "strict": false,
1082
+ "bin": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin",
1083
+ "dev": "Vulkan0",
1084
+ "ctx": 65536,
1085
+ "workload": "prose",
1086
+ "load_s": 22.0,
1087
+ "cmd": "/opt/llama-rocm/rocmfpx-724/build-hipvk/bin/llama-server -m /mnt/models/nex-n2.5-mini/out/Nex-N2.5-mini-Q4_0_ROCMFP4_STRIX_LEAN.gguf -dev Vulkan0 -ngl 999 -fa on -dio --jinja -fit off --parallel 1 -c 65536 -b 2048 -ub 1024 --host 127.0.0.1 --port 18600 --no-webui",
1088
+ "tg_median": 67.34,
1089
+ "tg_min": 67.31,
1090
+ "tg_max": 67.35,
1091
+ "pp_median": 977.7,
1092
+ "prompt_n": 7454,
1093
+ "accept": null,
1094
+ "prompt_n_min": 7454,
1095
+ "prompt_n_max": 7457
1096
+ }
1097
+ ],
1098
+ "gates": [
1099
+ {
1100
+ "label": "n-c3-q106",
1101
+ "gate": "cachegate3-aligned",
1102
+ "n": 5,
1103
+ "L": 7039,
1104
+ "expect_cache_n": 6011,
1105
+ "all_reused": true,
1106
+ "all_aligned": true,
1107
+ "identical": 5,
1108
+ "rows": [
1109
+ {
1110
+ "variant": 0,
1111
+ "L": 7039,
1112
+ "warm_prompt_n": 1028,
1113
+ "warm_cache_n": 6011,
1114
+ "cold_prompt_n": 7039,
1115
+ "cold_cache_n": 0,
1116
+ "aligned": true,
1117
+ "warm_draft": [
1118
+ null,
1119
+ null
1120
+ ],
1121
+ "cold_draft": [
1122
+ null,
1123
+ null
1124
+ ],
1125
+ "identical": true,
1126
+ "first_diff_char": null,
1127
+ "warm_sha": "013b7b4662ba",
1128
+ "cold_sha": "013b7b4662ba",
1129
+ "instr": "Write a function that lists every tensor name in this file. ok ok ok ok",
1130
+ "warm_instr": "Summarise this file. (warm-up 0) ok ok ok ok",
1131
+ "warm_text": "```python\ndef list_tensor_names(model: ModelBase) -> list[str]:\n \"\"\"Return every tensor name indexed by the model, in model-tensor order.\"\"\"\n return list(model.model_tensors.keys())\n```\n\nExample usage:\n\n```python\nmodel = SomeModelClass(\n dir_model=Path(\"...\"),\n ftype=gguf.LlamaFileType.GUESSED,\n fname_out=Path(\"model.gguf\"),\n)\n\nfor name in list_tensor_names(model):\n print(name)\n```\n\nIf you want to include tensors that are only produced later by `modify_tensors()` or quantization dequantization, use this version instead:\n\n```python\ndef list_all_tensor_names(model: ModelBase) -> list[str]:\n \"\"\"Return tensor names from indexing plus tensors produced by tensor transforms.\"\"\"\n names = set(model.model_tensors.keys())\n\n for name, gen in model.model",
1132
+ "cold_text": "```python\ndef list_tensor_names(model: ModelBase) -> list[str]:\n \"\"\"Return every tensor name indexed by the model, in model-tensor order.\"\"\"\n return list(model.model_tensors.keys())\n```\n\nExample usage:\n\n```python\nmodel = SomeModelClass(\n dir_model=Path(\"...\"),\n ftype=gguf.LlamaFileType.GUESSED,\n fname_out=Path(\"model.gguf\"),\n)\n\nfor name in list_tensor_names(model):\n print(name)\n```\n\nIf you want to include tensors that are only produced later by `modify_tensors()` or quantization dequantization, use this version instead:\n\n```python\ndef list_all_tensor_names(model: ModelBase) -> list[str]:\n \"\"\"Return tensor names from indexing plus tensors produced by tensor transforms.\"\"\"\n names = set(model.model_tensors.keys())\n\n for name, gen in model.model",
1133
+ "warm_prompt_ms": 999.89,
1134
+ "cold_prompt_ms": 6158.66
1135
+ },
1136
+ {
1137
+ "variant": 1,
1138
+ "L": 7039,
1139
+ "warm_prompt_n": 1028,
1140
+ "warm_cache_n": 6011,
1141
+ "cold_prompt_n": 7039,
1142
+ "cold_cache_n": 0,
1143
+ "aligned": true,
1144
+ "warm_draft": [
1145
+ null,
1146
+ null
1147
+ ],
1148
+ "cold_draft": [
1149
+ null,
1150
+ null
1151
+ ],
1152
+ "identical": true,
1153
+ "first_diff_char": null,
1154
+ "warm_sha": "76498f09c9c8",
1155
+ "cold_sha": "76498f09c9c8",
1156
+ "instr": "Write a function that counts the model classes registered in this file. ok ok ok",
1157
+ "warm_instr": "Summarise this file. (warm-up 1) ok ok ok ok",
1158
+ "warm_text": "```python\ndef count_model_classes(path: str | os.PathLike[str]) -> int:\n \"\"\"Count classes that inherit from ModelBase in the given Python file.\"\"\"\n with open(path, \"r\", encoding=\"utf-8\") as f:\n tree = ast.parse(f.read(), filename=path)\n\n count = 0\n\n for node in tree.body:\n if not isinstance(node, ast.ClassDef):\n continue\n\n for base in node.bases:\n if isinstance(base, ast.Name) and base.id == \"ModelBase\":\n count += 1\n break\n\n return count\n```\n\nExample usage:\n\n```python\nif __name__ == \"__main__\":\n print(count_model_classes(\"your_file.py\"))\n```\n\nThis counts only direct subclasses of `ModelBase`, not indirect subclasses. If you want to count indirect subclasses too, use this version:",
1159
+ "cold_text": "```python\ndef count_model_classes(path: str | os.PathLike[str]) -> int:\n \"\"\"Count classes that inherit from ModelBase in the given Python file.\"\"\"\n with open(path, \"r\", encoding=\"utf-8\") as f:\n tree = ast.parse(f.read(), filename=path)\n\n count = 0\n\n for node in tree.body:\n if not isinstance(node, ast.ClassDef):\n continue\n\n for base in node.bases:\n if isinstance(base, ast.Name) and base.id == \"ModelBase\":\n count += 1\n break\n\n return count\n```\n\nExample usage:\n\n```python\nif __name__ == \"__main__\":\n print(count_model_classes(\"your_file.py\"))\n```\n\nThis counts only direct subclasses of `ModelBase`, not indirect subclasses. If you want to count indirect subclasses too, use this version:",
1160
+ "warm_prompt_ms": 1002.97,
1161
+ "cold_prompt_ms": 6165.72
1162
+ },
1163
+ {
1164
+ "variant": 2,
1165
+ "L": 7039,
1166
+ "warm_prompt_n": 1028,
1167
+ "warm_cache_n": 6011,
1168
+ "cold_prompt_n": 7039,
1169
+ "cold_cache_n": 0,
1170
+ "aligned": true,
1171
+ "warm_draft": [
1172
+ null,
1173
+ null
1174
+ ],
1175
+ "cold_draft": [
1176
+ null,
1177
+ null
1178
+ ],
1179
+ "identical": true,
1180
+ "first_diff_char": null,
1181
+ "warm_sha": "16577469a2ea",
1182
+ "cold_sha": "16577469a2ea",
1183
+ "instr": "Write a function that finds the longest method in this file. ok ok ok ok",
1184
+ "warm_instr": "Summarise this file. (warm-up 2) ok ok ok ok",
1185
+ "warm_text": "```python\nimport ast\nfrom pathlib import Path\n\n\ndef find_longest_method(path: str | Path) -> tuple[str, int, ast.FunctionDef | ast.AsyncFunctionDef]:\n \"\"\"\n Return the longest method in a Python file.\n\n Length is measured by the number of AST nodes in the method body.\n \"\"\"\n source_path = Path(path)\n tree = ast.parse(source_path.read_text(encoding=\"utf-8\"), filename=str(source_path))\n\n methods = [\n node\n for node in ast.walk(tree)\n if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))\n ]\n\n if not methods:\n raise ValueError(f\"No methods found in {source_path}\")\n\n longest = max(\n methods,\n key=lambda node: sum(1 for _ in ast.walk(node.body)),\n )\n\n return (\n longest.name",
1186
+ "cold_text": "```python\nimport ast\nfrom pathlib import Path\n\n\ndef find_longest_method(path: str | Path) -> tuple[str, int, ast.FunctionDef | ast.AsyncFunctionDef]:\n \"\"\"\n Return the longest method in a Python file.\n\n Length is measured by the number of AST nodes in the method body.\n \"\"\"\n source_path = Path(path)\n tree = ast.parse(source_path.read_text(encoding=\"utf-8\"), filename=str(source_path))\n\n methods = [\n node\n for node in ast.walk(tree)\n if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))\n ]\n\n if not methods:\n raise ValueError(f\"No methods found in {source_path}\")\n\n longest = max(\n methods,\n key=lambda node: sum(1 for _ in ast.walk(node.body)),\n )\n\n return (\n longest.name",
1187
+ "warm_prompt_ms": 1003.48,
1188
+ "cold_prompt_ms": 6169.04
1189
+ },
1190
+ {
1191
+ "variant": 3,
1192
+ "L": 7039,
1193
+ "warm_prompt_n": 1028,
1194
+ "warm_cache_n": 6011,
1195
+ "cold_prompt_n": 7039,
1196
+ "cold_cache_n": 0,
1197
+ "aligned": true,
1198
+ "warm_draft": [
1199
+ null,
1200
+ null
1201
+ ],
1202
+ "cold_draft": [
1203
+ null,
1204
+ null
1205
+ ],
1206
+ "identical": true,
1207
+ "first_diff_char": null,
1208
+ "warm_sha": "a8545d39788d",
1209
+ "cold_sha": "a8545d39788d",
1210
+ "instr": "Write a function that returns every regular expression used in this file. ok ok ok",
1211
+ "warm_instr": "Summarise this file. (warm-up 3) ok ok ok ok",
1212
+ "warm_text": "```python\nimport re\n\ndef extract_regular_expressions(source: str) -> list[str]:\n \"\"\"\n Return every regular expression string literal used in the given Python source.\n\n This is a lexical scanner, not a full AST parser, so it handles normal string\n literals but does not evaluate them.\n \"\"\"\n expressions: list[str] = []\n i = 0\n n = len(source)\n\n while i < n:\n if source[i] not in \"'\\\"\":\n i += 1\n continue\n\n quote = source[i]\n i += 1\n chars: list[str] = []\n\n while i < n:\n ch = source[i]\n\n if ch == \"\\\\\":\n if i + 1 >= n:\n break\n chars.append(ch)\n chars.append(source[i + 1])\n i",
1213
+ "cold_text": "```python\nimport re\n\ndef extract_regular_expressions(source: str) -> list[str]:\n \"\"\"\n Return every regular expression string literal used in the given Python source.\n\n This is a lexical scanner, not a full AST parser, so it handles normal string\n literals but does not evaluate them.\n \"\"\"\n expressions: list[str] = []\n i = 0\n n = len(source)\n\n while i < n:\n if source[i] not in \"'\\\"\":\n i += 1\n continue\n\n quote = source[i]\n i += 1\n chars: list[str] = []\n\n while i < n:\n ch = source[i]\n\n if ch == \"\\\\\":\n if i + 1 >= n:\n break\n chars.append(ch)\n chars.append(source[i + 1])\n i",
1214
+ "warm_prompt_ms": 1003.44,
1215
+ "cold_prompt_ms": 6170.8
1216
+ },
1217
+ {
1218
+ "variant": 4,
1219
+ "L": 7039,
1220
+ "warm_prompt_n": 1028,
1221
+ "warm_cache_n": 6011,
1222
+ "cold_prompt_n": 7039,
1223
+ "cold_cache_n": 0,
1224
+ "aligned": true,
1225
+ "warm_draft": [
1226
+ null,
1227
+ null
1228
+ ],
1229
+ "cold_draft": [
1230
+ null,
1231
+ null
1232
+ ],
1233
+ "identical": true,
1234
+ "first_diff_char": null,
1235
+ "warm_sha": "af97b2dde4e2",
1236
+ "cold_sha": "af97b2dde4e2",
1237
+ "instr": "Write a function that maps each class in this file to its base classes. ok",
1238
+ "warm_instr": "Summarise this file. (warm-up 4) ok ok ok ok",
1239
+ "warm_text": "```python\ndef map_classes_to_base_classes(source: str) -> dict[str, list[str]]:\n \"\"\"\n Return a mapping of class names to their direct base class names.\n\n Example:\n class A(B): pass\n class C(A): pass\n returns:\n {\"A\": [\"B\"], \"C\": [\"A\"]}\n \"\"\"\n import ast\n\n tree = ast.parse(source)\n result: dict[str, list[str]] = {}\n\n for node in tree.body:\n if isinstance(node, ast.ClassDef):\n bases = [ast.unparse(base) for base in node.bases]\n result[node.name] = bases\n\n return result\n```\n\nUsage:\n\n```python\nsource = open(\"file.py\", \"r\", encoding=\"utf-8\").read()\nprint(map_classes_to_base_classes(source))\n```\n\nFor the provided file",
1240
+ "cold_text": "```python\ndef map_classes_to_base_classes(source: str) -> dict[str, list[str]]:\n \"\"\"\n Return a mapping of class names to their direct base class names.\n\n Example:\n class A(B): pass\n class C(A): pass\n returns:\n {\"A\": [\"B\"], \"C\": [\"A\"]}\n \"\"\"\n import ast\n\n tree = ast.parse(source)\n result: dict[str, list[str]] = {}\n\n for node in tree.body:\n if isinstance(node, ast.ClassDef):\n bases = [ast.unparse(base) for base in node.bases]\n result[node.name] = bases\n\n return result\n```\n\nUsage:\n\n```python\nsource = open(\"file.py\", \"r\", encoding=\"utf-8\").read()\nprint(map_classes_to_base_classes(source))\n```\n\nFor the provided file",
1241
+ "warm_prompt_ms": 1005.61,
1242
+ "cold_prompt_ms": 6177.63
1243
+ }
1244
+ ],
1245
+ "result": "PASS"
1246
+ },
1247
+ {
1248
+ "label": "n-tools-q106",
1249
+ "passed": 6,
1250
+ "total": 14,
1251
+ "detail": {
1252
+ "multi-arg|think=True": false,
1253
+ "nested-object|think=True": false,
1254
+ "enum|think=True": false,
1255
+ "correct-decline|think=True": false,
1256
+ "multi-turn|think=True": false,
1257
+ "streaming|think=True": false,
1258
+ "parallel|think=True": false,
1259
+ "multi-arg|think=False": true,
1260
+ "nested-object|think=False": false,
1261
+ "enum|think=False": true,
1262
+ "correct-decline|think=False": true,
1263
+ "multi-turn|think=False": true,
1264
+ "streaming|think=False": true,
1265
+ "parallel|think=False": true
1266
+ }
1267
+ },
1268
+ {
1269
+ "label": "n-vision-q106-faon",
1270
+ "fa": "on",
1271
+ "mtp": false,
1272
+ "expected": "red,blue,circle,square",
1273
+ "answer": "The image shows two shapes: a red circle on the left and a blue square on the right.",
1274
+ "hits": [
1275
+ "red",
1276
+ "blue",
1277
+ "circle",
1278
+ "square"
1279
+ ],
1280
+ "error": null,
1281
+ "server_died": false,
1282
+ "server_log_errors": [],
1283
+ "result": "PASS"
1284
+ },
1285
+ {
1286
+ "label": "n-vision-q106-faoff",
1287
+ "fa": "off",
1288
+ "mtp": false,
1289
+ "expected": "red,blue,circle,square",
1290
+ "answer": "The image shows two simple shapes:\n\n- A **red circle** on the left.\n- A **blue square** on the right.",
1291
+ "hits": [
1292
+ "red",
1293
+ "blue",
1294
+ "circle",
1295
+ "square"
1296
+ ],
1297
+ "error": null,
1298
+ "server_died": false,
1299
+ "server_log_errors": [],
1300
+ "result": "PASS"
1301
+ },
1302
+ {
1303
+ "label": "n-tools-q106-tpl",
1304
+ "passed": 14,
1305
+ "total": 14,
1306
+ "detail": {
1307
+ "multi-arg|think=True": true,
1308
+ "nested-object|think=True": true,
1309
+ "enum|think=True": true,
1310
+ "correct-decline|think=True": true,
1311
+ "multi-turn|think=True": true,
1312
+ "streaming|think=True": true,
1313
+ "parallel|think=True": true,
1314
+ "multi-arg|think=False": true,
1315
+ "nested-object|think=False": true,
1316
+ "enum|think=False": true,
1317
+ "correct-decline|think=False": true,
1318
+ "multi-turn|think=False": true,
1319
+ "streaming|think=False": true,
1320
+ "parallel|think=False": true
1321
+ }
1322
+ },
1323
+ {
1324
+ "label": "n-tools-q106-tpl-medium",
1325
+ "passed": 7,
1326
+ "total": 14,
1327
+ "detail": {
1328
+ "multi-arg|think=True": false,
1329
+ "nested-object|think=True": false,
1330
+ "enum|think=True": false,
1331
+ "correct-decline|think=True": false,
1332
+ "multi-turn|think=True": false,
1333
+ "streaming|think=True": false,
1334
+ "parallel|think=True": false,
1335
+ "multi-arg|think=False": true,
1336
+ "nested-object|think=False": true,
1337
+ "enum|think=False": true,
1338
+ "correct-decline|think=False": true,
1339
+ "multi-turn|think=False": true,
1340
+ "streaming|think=False": true,
1341
+ "parallel|think=False": true
1342
+ }
1343
+ },
1344
+ {
1345
+ "label": "n-tools-q106-c1",
1346
+ "passed": 13,
1347
+ "total": 14,
1348
+ "detail": {
1349
+ "multi-arg|think=True": true,
1350
+ "nested-object|think=True": false,
1351
+ "enum|think=True": true,
1352
+ "correct-decline|think=True": true,
1353
+ "multi-turn|think=True": true,
1354
+ "streaming|think=True": true,
1355
+ "parallel|think=True": true,
1356
+ "multi-arg|think=False": true,
1357
+ "nested-object|think=False": true,
1358
+ "enum|think=False": true,
1359
+ "correct-decline|think=False": true,
1360
+ "multi-turn|think=False": true,
1361
+ "streaming|think=False": true,
1362
+ "parallel|think=False": true
1363
+ }
1364
+ },
1365
+ {
1366
+ "label": "n-vision-q106-c1-faon",
1367
+ "fa": "on",
1368
+ "mtp": false,
1369
+ "expected": "red,blue,circle,square",
1370
+ "answer": "The image shows two shapes: a red circle on the left and a blue square on the right.",
1371
+ "hits": [
1372
+ "red",
1373
+ "blue",
1374
+ "circle",
1375
+ "square"
1376
+ ],
1377
+ "error": null,
1378
+ "server_died": false,
1379
+ "server_log_errors": [],
1380
+ "result": "PASS"
1381
+ },
1382
+ {
1383
+ "label": "n-tools-q106-roff",
1384
+ "passed": 13,
1385
+ "total": 14,
1386
+ "detail": {
1387
+ "multi-arg|think=True": true,
1388
+ "nested-object|think=True": false,
1389
+ "enum|think=True": true,
1390
+ "correct-decline|think=True": true,
1391
+ "multi-turn|think=True": true,
1392
+ "streaming|think=True": true,
1393
+ "parallel|think=True": true,
1394
+ "multi-arg|think=False": true,
1395
+ "nested-object|think=False": true,
1396
+ "enum|think=False": true,
1397
+ "correct-decline|think=False": true,
1398
+ "multi-turn|think=False": true,
1399
+ "streaming|think=False": true,
1400
+ "parallel|think=False": true
1401
+ }
1402
+ },
1403
+ {
1404
+ "label": "n-tools-q106-roff-r2",
1405
+ "passed": 13,
1406
+ "total": 14,
1407
+ "detail": {
1408
+ "multi-arg|think=True": true,
1409
+ "nested-object|think=True": true,
1410
+ "enum|think=True": true,
1411
+ "correct-decline|think=True": true,
1412
+ "multi-turn|think=True": true,
1413
+ "streaming|think=True": true,
1414
+ "parallel|think=True": false,
1415
+ "multi-arg|think=False": true,
1416
+ "nested-object|think=False": true,
1417
+ "enum|think=False": true,
1418
+ "correct-decline|think=False": true,
1419
+ "multi-turn|think=False": true,
1420
+ "streaming|think=False": true,
1421
+ "parallel|think=False": true
1422
+ }
1423
+ },
1424
+ {
1425
+ "label": "n-tools-q106-roff-r3",
1426
+ "passed": 14,
1427
+ "total": 14,
1428
+ "detail": {
1429
+ "multi-arg|think=True": true,
1430
+ "nested-object|think=True": true,
1431
+ "enum|think=True": true,
1432
+ "correct-decline|think=True": true,
1433
+ "multi-turn|think=True": true,
1434
+ "streaming|think=True": true,
1435
+ "parallel|think=True": true,
1436
+ "multi-arg|think=False": true,
1437
+ "nested-object|think=False": true,
1438
+ "enum|think=False": true,
1439
+ "correct-decline|think=False": true,
1440
+ "multi-turn|think=False": true,
1441
+ "streaming|think=False": true,
1442
+ "parallel|think=False": true
1443
+ }
1444
+ },
1445
+ {
1446
+ "label": "n-vision-q106-roff-faon",
1447
+ "fa": "on",
1448
+ "mtp": false,
1449
+ "expected": "red,blue,circle,square",
1450
+ "answer": "The image shows two shapes: a red circle on the left and a blue square on the right.",
1451
+ "hits": [
1452
+ "red",
1453
+ "blue",
1454
+ "circle",
1455
+ "square"
1456
+ ],
1457
+ "error": null,
1458
+ "server_died": false,
1459
+ "server_log_errors": [],
1460
+ "result": "PASS"
1461
+ }
1462
+ ],
1463
+ "sizing": [
1464
+ {
1465
+ "label": "strix-lean",
1466
+ "ctx": 65536,
1467
+ "avail_before": 122.34,
1468
+ "footprint_loaded_gib": 21.11,
1469
+ "footprint_after_8k_gib": 21.29
1470
+ },
1471
+ {
1472
+ "label": "strix-lean",
1473
+ "ctx": 262144,
1474
+ "avail_before": 122.15,
1475
+ "footprint_loaded_gib": 24.36,
1476
+ "footprint_after_8k_gib": 24.52
1477
+ }
1478
+ ],
1479
+ "n_ubatch": 1024,
1480
+ "template_fix": {
1481
+ "file": "chat_template_enable_thinking.jinja",
1482
+ "size_bytes": 7895,
1483
+ "sha256": "9183c7ba8510fb9628edd2265a4cad8c02b3aecec3cbdf65620f47494e75836d",
1484
+ "source_sha256": "f1753536417ee87cded4bc5017354eb2123c079d20c634403a3d808b2ba3cc5b",
1485
+ "shim": "{%- if reasoning_effort is not defined and enable_thinking is defined %}{%- set reasoning_effort = 'high' if enable_thinking else 'none' %}{%- endif %}\n",
1486
+ "server_flags": [
1487
+ "--chat-template-file",
1488
+ "chat_template_enable_thinking.jinja",
1489
+ "--reasoning",
1490
+ "off"
1491
+ ],
1492
+ "probes_roff": {
1493
+ "no-kwargs|correct-decline": {
1494
+ "content": "391",
1495
+ "reasoning_len": 0,
1496
+ "tool_calls": [],
1497
+ "leaks": []
1498
+ },
1499
+ "no-kwargs|single-word": {
1500
+ "content": "ready",
1501
+ "reasoning_len": 0,
1502
+ "tool_calls": [],
1503
+ "leaks": []
1504
+ },
1505
+ "no-kwargs|multi-arg": {
1506
+ "content": "",
1507
+ "reasoning_len": 0,
1508
+ "tool_calls": [
1509
+ "get_weather"
1510
+ ],
1511
+ "leaks": []
1512
+ },
1513
+ "enable_thinking=false|correct-decline": {
1514
+ "content": "391",
1515
+ "reasoning_len": 0,
1516
+ "tool_calls": [],
1517
+ "leaks": []
1518
+ },
1519
+ "enable_thinking=false|single-word": {
1520
+ "content": "ready",
1521
+ "reasoning_len": 0,
1522
+ "tool_calls": [],
1523
+ "leaks": []
1524
+ },
1525
+ "enable_thinking=false|multi-arg": {
1526
+ "content": "",
1527
+ "reasoning_len": 0,
1528
+ "tool_calls": [
1529
+ "get_weather"
1530
+ ],
1531
+ "leaks": []
1532
+ },
1533
+ "reasoning_effort=high|correct-decline": {
1534
+ "content": "We need answer directly. 391.\n</think>\n\n391",
1535
+ "reasoning_len": 0,
1536
+ "tool_calls": [],
1537
+ "leaks": [
1538
+ "</think>"
1539
+ ]
1540
+ },
1541
+ "reasoning_effort=high|single-word": {
1542
+ "content": "We need need output exactly ready.\n</think>\n\nready",
1543
+ "reasoning_len": 0,
1544
+ "tool_calls": [],
1545
+ "leaks": [
1546
+ "</think>"
1547
+ ]
1548
+ },
1549
+ "reasoning_effort=high|multi-arg": {
1550
+ "content": "We need need tool. Current weather Paris celsius.\n</think>\n\n",
1551
+ "reasoning_len": 0,
1552
+ "tool_calls": [
1553
+ "get_weather"
1554
+ ],
1555
+ "leaks": [
1556
+ "</think>"
1557
+ ]
1558
+ },
1559
+ "reasoning_effort=medium|correct-decline": {
1560
+ "content": "\n\n</think>\n\n391",
1561
+ "reasoning_len": 0,
1562
+ "tool_calls": [],
1563
+ "leaks": [
1564
+ "</think>"
1565
+ ]
1566
+ },
1567
+ "reasoning_effort=medium|single-word": {
1568
+ "content": "\n\n</think>\n\nready",
1569
+ "reasoning_len": 0,
1570
+ "tool_calls": [],
1571
+ "leaks": [
1572
+ "</think>"
1573
+ ]
1574
+ },
1575
+ "reasoning_effort=medium|multi-arg": {
1576
+ "content": "\n\n</think>\n\n",
1577
+ "reasoning_len": 0,
1578
+ "tool_calls": [
1579
+ "get_weather"
1580
+ ],
1581
+ "leaks": [
1582
+ "</think>"
1583
+ ]
1584
+ },
1585
+ "reasoning_effort=none|correct-decline": {
1586
+ "content": "391",
1587
+ "reasoning_len": 0,
1588
+ "tool_calls": [],
1589
+ "leaks": []
1590
+ },
1591
+ "reasoning_effort=none|single-word": {
1592
+ "content": "ready",
1593
+ "reasoning_len": 0,
1594
+ "tool_calls": [],
1595
+ "leaks": []
1596
+ },
1597
+ "reasoning_effort=none|multi-arg": {
1598
+ "content": "",
1599
+ "reasoning_len": 0,
1600
+ "tool_calls": [
1601
+ "get_weather"
1602
+ ],
1603
+ "leaks": []
1604
+ }
1605
+ },
1606
+ "probes_high_default_on": {
1607
+ "no-kwargs|correct-decline": {
1608
+ "content": "391",
1609
+ "reasoning_len": 30,
1610
+ "tool_calls": [],
1611
+ "leaks": []
1612
+ },
1613
+ "no-kwargs|multi-arg": {
1614
+ "content": "",
1615
+ "reasoning_len": 50,
1616
+ "tool_calls": [
1617
+ "get_weather"
1618
+ ],
1619
+ "leaks": []
1620
+ },
1621
+ "reasoning_effort=medium|correct-decline": {
1622
+ "content": "391",
1623
+ "reasoning_len": 0,
1624
+ "tool_calls": [],
1625
+ "leaks": []
1626
+ },
1627
+ "reasoning_effort=medium|multi-arg": {
1628
+ "content": "",
1629
+ "reasoning_len": 0,
1630
+ "tool_calls": [
1631
+ "get_weather"
1632
+ ],
1633
+ "leaks": []
1634
+ },
1635
+ "reasoning_effort=none|correct-decline": {
1636
+ "content": "",
1637
+ "reasoning_len": 3,
1638
+ "tool_calls": [],
1639
+ "leaks": []
1640
+ },
1641
+ "reasoning_effort=none|multi-arg": {
1642
+ "content": "",
1643
+ "reasoning_len": 133,
1644
+ "tool_calls": [],
1645
+ "leaks": []
1646
+ }
1647
+ },
1648
+ "medium_mapping_label": "n-tools-q106-tpl-medium"
1649
+ },
1650
+ "tools_diag": {
1651
+ "stock_on_replies": 7,
1652
+ "stock_on_leaks": 7,
1653
+ "stock_on_reasoning_extracted": 0,
1654
+ "nested_off_attempts": 4,
1655
+ "nested_off_http500": 2,
1656
+ "gate_http500_logged": true,
1657
+ "flag_probes": {
1658
+ "default": {
1659
+ "leaks": 3,
1660
+ "n": 3
1661
+ },
1662
+ "fmt-deepseek": {
1663
+ "leaks": 3,
1664
+ "n": 3
1665
+ },
1666
+ "srv-kwargs-high": {
1667
+ "leaks": 3,
1668
+ "n": 3
1669
+ },
1670
+ "reasoning-on": {
1671
+ "leaks": 3,
1672
+ "n": 3
1673
+ },
1674
+ "tpl-enable-thinking": {
1675
+ "leaks": 0,
1676
+ "n": 3
1677
+ }
1678
+ }
1679
+ },
1680
+ "seats": {
1681
+ "max1-nex-fast": {
1682
+ "unit": "max1-nex-fast",
1683
+ "port": 8097,
1684
+ "load_s": 25,
1685
+ "time": "2026-09-17T01:21:10Z",
1686
+ "direct_reply": "ready",
1687
+ "direct_tg": 41.41386950489719,
1688
+ "default_reply": "ready",
1689
+ "default_reasoning_len": 0,
1690
+ "default_leak": false,
1691
+ "thinking_reply": "",
1692
+ "thinking_reasoning_len": 5,
1693
+ "thinking_leak": false,
1694
+ "gateway_model": "nex-n2.5-mini-fast@max1",
1695
+ "gateway_reply": "ready",
1696
+ "result": "PASS"
1697
+ },
1698
+ "max1-nex-fast-imat": {
1699
+ "unit": "max1-nex-fast-imat",
1700
+ "port": 8098,
1701
+ "load_s": 25,
1702
+ "time": "2026-09-17T01:21:43Z",
1703
+ "direct_reply": "ready",
1704
+ "direct_tg": 41.54290343352097,
1705
+ "default_reply": "ready",
1706
+ "default_reasoning_len": 0,
1707
+ "default_leak": false,
1708
+ "thinking_reply": "",
1709
+ "thinking_reasoning_len": 5,
1710
+ "thinking_leak": false,
1711
+ "gateway_model": "nex-n2.5-mini-fast-imatrix@max1",
1712
+ "gateway_reply": "ready",
1713
+ "result": "PASS"
1714
+ }
1715
+ },
1716
+ "measured": "2026-09-16",
1717
+ "measured_range": [
1718
+ "2026-09-16",
1719
+ "2026-09-17"
1720
+ ]
1721
+ }
recipe/templates/chat_template_enable_thinking_medium.jinja ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if reasoning_effort is not defined and enable_thinking is defined %}{%- set reasoning_effort = 'medium' if enable_thinking else 'none' %}{%- endif %}
2
+ {%- set image_count = namespace(value=0) %}
3
+ {%- set video_count = namespace(value=0) %}
4
+ {%- macro render_content(content, do_vision_count, is_system_content=false) %}
5
+ {%- if content is string %}
6
+ {{- content }}
7
+ {%- elif content is iterable and content is not mapping %}
8
+ {%- for item in content %}
9
+ {%- if 'image' in item or 'image_url' in item or item.type == 'image' %}
10
+ {%- if is_system_content %}
11
+ {{- raise_exception('System message cannot contain images.') }}
12
+ {%- endif %}
13
+ {%- if do_vision_count %}
14
+ {%- set image_count.value = image_count.value + 1 %}
15
+ {%- endif %}
16
+ {%- if add_vision_id %}
17
+ {{- 'Picture ' ~ image_count.value ~ ': ' }}
18
+ {%- endif %}
19
+ {{- '<|vision_start|><|image_pad|><|vision_end|>' }}
20
+ {%- elif 'video' in item or item.type == 'video' %}
21
+ {%- if is_system_content %}
22
+ {{- raise_exception('System message cannot contain videos.') }}
23
+ {%- endif %}
24
+ {%- if do_vision_count %}
25
+ {%- set video_count.value = video_count.value + 1 %}
26
+ {%- endif %}
27
+ {%- if add_vision_id %}
28
+ {{- 'Video ' ~ video_count.value ~ ': ' }}
29
+ {%- endif %}
30
+ {{- '<|vision_start|><|video_pad|><|vision_end|>' }}
31
+ {%- elif 'text' in item %}
32
+ {{- item.text }}
33
+ {%- else %}
34
+ {{- raise_exception('Unexpected item type in content.') }}
35
+ {%- endif %}
36
+ {%- endfor %}
37
+ {%- elif content is none or content is undefined %}
38
+ {{- '' }}
39
+ {%- else %}
40
+ {{- raise_exception('Unexpected content type.') }}
41
+ {%- endif %}
42
+ {%- endmacro %}
43
+ {%- if not messages %}
44
+ {{- raise_exception('No messages provided.') }}
45
+ {%- endif %}
46
+ {%- if tools and tools is iterable and tools is not mapping %}
47
+ {{- '<|im_start|>system\n' }}
48
+ {{- "# Tools\n\nYou have access to the following functions:\n\n<tools>" }}
49
+ {%- for tool in tools %}
50
+ {{- "\n" }}
51
+ {{- tool | tojson }}
52
+ {%- endfor %}
53
+ {{- "\n</tools>" }}
54
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
55
+ {%- if messages[0].role == 'system' %}
56
+ {%- set content = render_content(messages[0].content, false, true)|trim %}
57
+ {%- if content %}
58
+ {{- '\n\n' + content }}
59
+ {%- endif %}
60
+ {%- endif %}
61
+ {{- '<|im_end|>\n' }}
62
+ {%- else %}
63
+ {%- if messages[0].role == 'system' %}
64
+ {%- set content = render_content(messages[0].content, false, true)|trim %}
65
+ {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
66
+ {%- endif %}
67
+ {%- endif %}
68
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
69
+ {%- for message in messages[::-1] %}
70
+ {%- set index = (messages|length - 1) - loop.index0 %}
71
+ {%- if ns.multi_step_tool and message.role == "user" %}
72
+ {%- set content = render_content(message.content, false)|trim %}
73
+ {%- if not(content.startswith('<tool_response>') and content.endswith('</tool_response>')) %}
74
+ {%- set ns.multi_step_tool = false %}
75
+ {%- set ns.last_query_index = index %}
76
+ {%- endif %}
77
+ {%- endif %}
78
+ {%- endfor %}
79
+ {%- if ns.multi_step_tool %}
80
+ {{- raise_exception('No user query found in messages.') }}
81
+ {%- endif %}
82
+ {%- for message in messages %}
83
+ {%- set content = render_content(message.content, true)|trim %}
84
+ {%- if message.role == "system" %}
85
+ {%- if not loop.first %}
86
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
87
+ {%- endif %}
88
+ {%- elif message.role == "user" %}
89
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
90
+ {%- elif message.role == "assistant" %}
91
+ {%- set reasoning_content = '' %}
92
+ {%- if message.reasoning_content is string %}
93
+ {%- set reasoning_content = message.reasoning_content %}
94
+ {%- else %}
95
+ {%- if '</think>' in content %}
96
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
97
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
98
+ {%- endif %}
99
+ {%- endif %}
100
+ {%- set reasoning_content = reasoning_content|trim %}
101
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}
102
+ {%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}
103
+ {%- for tool_call in message.tool_calls %}
104
+ {%- if tool_call.function is defined %}
105
+ {%- set tool_call = tool_call.function %}
106
+ {%- endif %}
107
+ {%- if loop.first %}
108
+ {%- if content|trim %}
109
+ {{- '\n\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
110
+ {%- else %}
111
+ {{- '<tool_call>\n<function=' + tool_call.name + '>\n' }}
112
+ {%- endif %}
113
+ {%- else %}
114
+ {{- '\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
115
+ {%- endif %}
116
+ {%- if tool_call.arguments is defined %}
117
+ {%- for args_name, args_value in tool_call.arguments|items %}
118
+ {{- '<parameter=' + args_name + '>\n' }}
119
+ {%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}
120
+ {{- args_value }}
121
+ {{- '\n</parameter>\n' }}
122
+ {%- endfor %}
123
+ {%- endif %}
124
+ {{- '</function>\n</tool_call>' }}
125
+ {%- endfor %}
126
+ {%- endif %}
127
+ {{- '<|im_end|>\n' }}
128
+ {%- elif message.role == "tool" %}
129
+ {%- if loop.previtem and loop.previtem.role != "tool" %}
130
+ {{- '<|im_start|>user' }}
131
+ {%- endif %}
132
+ {{- '\n<tool_response>\n' }}
133
+ {{- content }}
134
+ {{- '\n</tool_response>' }}
135
+ {%- if not loop.last and loop.nextitem.role != "tool" %}
136
+ {{- '<|im_end|>\n' }}
137
+ {%- elif loop.last %}
138
+ {{- '<|im_end|>\n' }}
139
+ {%- endif %}
140
+ {%- else %}
141
+ {{- raise_exception('Unexpected message role.') }}
142
+ {%- endif %}
143
+ {%- endfor %}
144
+ {%- if add_generation_prompt %}
145
+ {{- '<|im_start|>assistant\n' }}
146
+ {%- if reasoning_effort is not defined or reasoning_effort is none %}
147
+ {{- '<think>' }}
148
+ {%- elif reasoning_effort == 'none' %}
149
+ {{- '<think>\n\n</think>\n\n' }}
150
+ {%- elif reasoning_effort == 'high' %}
151
+ {{- '<think>\n' }}
152
+ {%- else %}
153
+ {{- '<think>' }}
154
+ {%- endif %}
155
+ {%- endif %}
recipe/templates/chat_template_enable_thinking_v2.jinja ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if enable_thinking is defined and not enable_thinking %}{%- set reasoning_effort = 'none' %}{%- elif reasoning_effort is not defined and enable_thinking is defined %}{%- set reasoning_effort = 'high' %}{%- endif %}
2
+ {%- set image_count = namespace(value=0) %}
3
+ {%- set video_count = namespace(value=0) %}
4
+ {%- macro render_content(content, do_vision_count, is_system_content=false) %}
5
+ {%- if content is string %}
6
+ {{- content }}
7
+ {%- elif content is iterable and content is not mapping %}
8
+ {%- for item in content %}
9
+ {%- if 'image' in item or 'image_url' in item or item.type == 'image' %}
10
+ {%- if is_system_content %}
11
+ {{- raise_exception('System message cannot contain images.') }}
12
+ {%- endif %}
13
+ {%- if do_vision_count %}
14
+ {%- set image_count.value = image_count.value + 1 %}
15
+ {%- endif %}
16
+ {%- if add_vision_id %}
17
+ {{- 'Picture ' ~ image_count.value ~ ': ' }}
18
+ {%- endif %}
19
+ {{- '<|vision_start|><|image_pad|><|vision_end|>' }}
20
+ {%- elif 'video' in item or item.type == 'video' %}
21
+ {%- if is_system_content %}
22
+ {{- raise_exception('System message cannot contain videos.') }}
23
+ {%- endif %}
24
+ {%- if do_vision_count %}
25
+ {%- set video_count.value = video_count.value + 1 %}
26
+ {%- endif %}
27
+ {%- if add_vision_id %}
28
+ {{- 'Video ' ~ video_count.value ~ ': ' }}
29
+ {%- endif %}
30
+ {{- '<|vision_start|><|video_pad|><|vision_end|>' }}
31
+ {%- elif 'text' in item %}
32
+ {{- item.text }}
33
+ {%- else %}
34
+ {{- raise_exception('Unexpected item type in content.') }}
35
+ {%- endif %}
36
+ {%- endfor %}
37
+ {%- elif content is none or content is undefined %}
38
+ {{- '' }}
39
+ {%- else %}
40
+ {{- raise_exception('Unexpected content type.') }}
41
+ {%- endif %}
42
+ {%- endmacro %}
43
+ {%- if not messages %}
44
+ {{- raise_exception('No messages provided.') }}
45
+ {%- endif %}
46
+ {%- if tools and tools is iterable and tools is not mapping %}
47
+ {{- '<|im_start|>system\n' }}
48
+ {{- "# Tools\n\nYou have access to the following functions:\n\n<tools>" }}
49
+ {%- for tool in tools %}
50
+ {{- "\n" }}
51
+ {{- tool | tojson }}
52
+ {%- endfor %}
53
+ {{- "\n</tools>" }}
54
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
55
+ {%- if messages[0].role == 'system' %}
56
+ {%- set content = render_content(messages[0].content, false, true)|trim %}
57
+ {%- if content %}
58
+ {{- '\n\n' + content }}
59
+ {%- endif %}
60
+ {%- endif %}
61
+ {{- '<|im_end|>\n' }}
62
+ {%- else %}
63
+ {%- if messages[0].role == 'system' %}
64
+ {%- set content = render_content(messages[0].content, false, true)|trim %}
65
+ {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
66
+ {%- endif %}
67
+ {%- endif %}
68
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
69
+ {%- for message in messages[::-1] %}
70
+ {%- set index = (messages|length - 1) - loop.index0 %}
71
+ {%- if ns.multi_step_tool and message.role == "user" %}
72
+ {%- set content = render_content(message.content, false)|trim %}
73
+ {%- if not(content.startswith('<tool_response>') and content.endswith('</tool_response>')) %}
74
+ {%- set ns.multi_step_tool = false %}
75
+ {%- set ns.last_query_index = index %}
76
+ {%- endif %}
77
+ {%- endif %}
78
+ {%- endfor %}
79
+ {%- if ns.multi_step_tool %}
80
+ {{- raise_exception('No user query found in messages.') }}
81
+ {%- endif %}
82
+ {%- for message in messages %}
83
+ {%- set content = render_content(message.content, true)|trim %}
84
+ {%- if message.role == "system" %}
85
+ {%- if not loop.first %}
86
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
87
+ {%- endif %}
88
+ {%- elif message.role == "user" %}
89
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
90
+ {%- elif message.role == "assistant" %}
91
+ {%- set reasoning_content = '' %}
92
+ {%- if message.reasoning_content is string %}
93
+ {%- set reasoning_content = message.reasoning_content %}
94
+ {%- else %}
95
+ {%- if '</think>' in content %}
96
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
97
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
98
+ {%- endif %}
99
+ {%- endif %}
100
+ {%- set reasoning_content = reasoning_content|trim %}
101
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}
102
+ {%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}
103
+ {%- for tool_call in message.tool_calls %}
104
+ {%- if tool_call.function is defined %}
105
+ {%- set tool_call = tool_call.function %}
106
+ {%- endif %}
107
+ {%- if loop.first %}
108
+ {%- if content|trim %}
109
+ {{- '\n\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
110
+ {%- else %}
111
+ {{- '<tool_call>\n<function=' + tool_call.name + '>\n' }}
112
+ {%- endif %}
113
+ {%- else %}
114
+ {{- '\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
115
+ {%- endif %}
116
+ {%- if tool_call.arguments is defined %}
117
+ {%- for args_name, args_value in tool_call.arguments|items %}
118
+ {{- '<parameter=' + args_name + '>\n' }}
119
+ {%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}
120
+ {{- args_value }}
121
+ {{- '\n</parameter>\n' }}
122
+ {%- endfor %}
123
+ {%- endif %}
124
+ {{- '</function>\n</tool_call>' }}
125
+ {%- endfor %}
126
+ {%- endif %}
127
+ {{- '<|im_end|>\n' }}
128
+ {%- elif message.role == "tool" %}
129
+ {%- if loop.previtem and loop.previtem.role != "tool" %}
130
+ {{- '<|im_start|>user' }}
131
+ {%- endif %}
132
+ {{- '\n<tool_response>\n' }}
133
+ {{- content }}
134
+ {{- '\n</tool_response>' }}
135
+ {%- if not loop.last and loop.nextitem.role != "tool" %}
136
+ {{- '<|im_end|>\n' }}
137
+ {%- elif loop.last %}
138
+ {{- '<|im_end|>\n' }}
139
+ {%- endif %}
140
+ {%- else %}
141
+ {{- raise_exception('Unexpected message role.') }}
142
+ {%- endif %}
143
+ {%- endfor %}
144
+ {%- if add_generation_prompt %}
145
+ {{- '<|im_start|>assistant\n' }}
146
+ {%- if reasoning_effort is not defined or reasoning_effort is none %}
147
+ {{- '<think>' }}
148
+ {%- elif reasoning_effort == 'none' %}
149
+ {{- '<think>\n\n</think>\n\n' }}
150
+ {%- elif reasoning_effort == 'high' %}
151
+ {{- '<think>\n' }}
152
+ {%- else %}
153
+ {{- '<think>' }}
154
+ {%- endif %}
155
+ {%- endif %}