llm-cachecheck 0.2.3__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {llm_cachecheck-0.2.3 → llm_cachecheck-0.3.0}/PKG-INFO +95 -12
- {llm_cachecheck-0.2.3 → llm_cachecheck-0.3.0}/README.md +94 -11
- {llm_cachecheck-0.2.3 → llm_cachecheck-0.3.0}/cachecheck.py +213 -24
- llm_cachecheck-0.3.0/examples/conversations_example.jsonl +2 -0
- llm_cachecheck-0.3.0/test_cachecheck.py +657 -0
- llm_cachecheck-0.2.3/test_cachecheck.py +0 -365
- {llm_cachecheck-0.2.3 → llm_cachecheck-0.3.0}/.gitignore +0 -0
- {llm_cachecheck-0.2.3 → llm_cachecheck-0.3.0}/LICENSE +0 -0
- {llm_cachecheck-0.2.3 → llm_cachecheck-0.3.0}/examples/qwen2.5-3b-q4km_metal_b12138.json +0 -0
- {llm_cachecheck-0.2.3 → llm_cachecheck-0.3.0}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: llm-cachecheck
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Measure how often the prompt cache changes greedy answers on your LLM server (llama.cpp, vLLM and SGLang)
|
|
5
5
|
Project-URL: Homepage, https://github.com/aditi-p31/cache-divergence-study/tree/main/cachecheck
|
|
6
6
|
Project-URL: Source, https://github.com/aditi-p31/cache-divergence-study
|
|
@@ -46,7 +46,8 @@ second answer on two paths:
|
|
|
46
46
|
Each path runs twice. A probe counts as valid only when all of these hold:
|
|
47
47
|
|
|
48
48
|
- both paths repeat on their own
|
|
49
|
-
- the server's own counts show that the cache hit covered the turn-1 answer
|
|
49
|
+
- the server's own counts show that the cache hit covered the turn-1 answer,
|
|
50
|
+
to within `--hit-tolerance` tokens and at least past the turn-1 prompt
|
|
50
51
|
- the server's own counts show that the recompute path reused nothing
|
|
51
52
|
|
|
52
53
|
## Run it
|
|
@@ -61,8 +62,8 @@ llm-cachecheck --help
|
|
|
61
62
|
Or download the single file
|
|
62
63
|
[`cachecheck.py`](https://github.com/aditi-p31/cache-divergence-study/blob/main/cachecheck/cachecheck.py)
|
|
63
64
|
and run `python cachecheck.py` in place of `llm-cachecheck`. Both take the
|
|
64
|
-
same options.
|
|
65
|
-
sends 120
|
|
65
|
+
same options. Each conversation takes six requests, so a run of the 20
|
|
66
|
+
built-in conversations sends 120.
|
|
66
67
|
|
|
67
68
|
**llama.cpp.** The cache is switched per request. Start the server with one
|
|
68
69
|
slot, because the default is several slots that share a cache. Turn the
|
|
@@ -73,10 +74,44 @@ llama-server -m model.gguf -np 1 --cache-ram 0 --port 8080
|
|
|
73
74
|
llm-cachecheck --base-url http://127.0.0.1:8080
|
|
74
75
|
```
|
|
75
76
|
|
|
76
|
-
**vLLM
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
**vLLM or SGLang, one server.** Start the server with prefix caching on (the
|
|
78
|
+
default) and with cached-token reporting on. The tool sends every request with
|
|
79
|
+
a `cache_salt`. The two turns of the cache path share one salt, so turn 2
|
|
80
|
+
reuses the state of turn 1. Each recompute request gets a salt that no other
|
|
81
|
+
request has used, so it cannot reuse any cached state.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
vllm serve Qwen/Qwen2.5-3B-Instruct --port 8000 \
|
|
85
|
+
--generation-config vllm --enable-prompt-tokens-details
|
|
86
|
+
llm-cachecheck --mode one-server --base-url http://127.0.0.1:8000 \
|
|
87
|
+
--model Qwen/Qwen2.5-3B-Instruct
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
For SGLang, add `--enable-cache-report` and `--sampling-defaults openai`.
|
|
91
|
+
On real vLLM 0.33.0 and SGLang 0.5.23 servers (SGLang with CUDA graphs disabled), the recompute answers in this mode had the same text as those of a second server with prefix caching off, on all 20 conversations in every run ([details](https://github.com/aditi-p31/cache-divergence-study/blob/main/cachecheck-0.3-validation/README.md)).
|
|
92
|
+
|
|
93
|
+
The server must honour `cache_salt`. If it does not, the recompute requests
|
|
94
|
+
reuse cached state, the tool marks those probes as inconclusive and says so,
|
|
95
|
+
and the two-server setup below still works. The server must also report cached
|
|
96
|
+
tokens, so `--skip-hit-check` is not available in this mode.
|
|
97
|
+
|
|
98
|
+
This mode compares a cache hit with a cache miss on one server. From reading
|
|
99
|
+
the vLLM 0.33.0 and SGLang 0.5.23 source, a miss on a standard attention model,
|
|
100
|
+
served without a KV connector such as LMCache, takes the same code path as on a
|
|
101
|
+
server with prefix caching off. For some setups, for example models with Mamba
|
|
102
|
+
or sliding-window layers, or speculative decoding, turning prefix caching on
|
|
103
|
+
also changes how the server handles requests that miss. To compare with
|
|
104
|
+
caching off there, use two servers.
|
|
105
|
+
|
|
106
|
+
Run it on a server that gets no other traffic, such as a staging copy. On a
|
|
107
|
+
busy server, batching with other requests can change answers by itself. The
|
|
108
|
+
tool's repeat checks mark many such probes as inconclusive, but they cannot
|
|
109
|
+
rule out a difference caused by other traffic.
|
|
110
|
+
|
|
111
|
+
**vLLM, SGLang or another OpenAI-compatible server, two servers.** The cache
|
|
112
|
+
is a server setting, so serve the same model twice, once with prefix caching
|
|
113
|
+
on and once with it off. Both servers must report cached tokens. For vLLM on
|
|
114
|
+
one 24 GB GPU (a 3B model, so two copies fit):
|
|
80
115
|
|
|
81
116
|
```bash
|
|
82
117
|
vllm serve Qwen/Qwen2.5-3B-Instruct --port 8000 --gpu-memory-utilization 0.45 \
|
|
@@ -97,14 +132,16 @@ URLs would reach the same server.
|
|
|
97
132
|
The tool then reports the recompute path reusing cached tokens and marks every
|
|
98
133
|
probe invalid, so check the server logs if that happens.
|
|
99
134
|
|
|
100
|
-
Tested on real servers
|
|
101
|
-
conversations; details in the [currency note](https://github.com/aditi-p31/cache-divergence-study/blob/main/CURRENCY_CHECK_2026-11.md)):
|
|
135
|
+
Tested on real servers (one RTX 4090; the tool's 20 conversations). The two-server and llama.cpp rows are from 2026-11-11 and 11-12 UTC ([currency note](https://github.com/aditi-p31/cache-divergence-study/blob/main/CURRENCY_CHECK_2026-11.md)); the one-server rows are from 2026-11-14 UTC ([details](https://github.com/aditi-p31/cache-divergence-study/blob/main/cachecheck-0.3-validation/README.md)):
|
|
102
136
|
|
|
103
137
|
| Server | Model | Conversations with a different turn-2 answer | Both caches off |
|
|
104
138
|
|---|---|---|---|
|
|
105
139
|
| vLLM 0.33.0, two servers | Qwen2.5-3B-Instruct, BF16 | 14 of 20, in each of 5 runs | 0 of 20 |
|
|
106
140
|
| SGLang 0.5.23, two servers (CUDA graphs disabled) | Qwen2.5-3B-Instruct, BF16 | 12 of 20, in each of 2 runs | 0 of 20 |
|
|
107
141
|
| llama.cpp v0.9.0 | Qwen2.5-7B-Instruct, Q4_K_M | 11 of 20, in each of 2 runs | |
|
|
142
|
+
| vLLM 0.33.0, one server | Qwen2.5-3B-Instruct, BF16 | 14 of 20, in each of 2 runs | |
|
|
143
|
+
| SGLang 0.5.23, one server (CUDA graphs disabled) | Qwen2.5-3B-Instruct, BF16 | 12 of 20, in each of 2 runs | |
|
|
144
|
+
| SGLang 0.5.23, one server, default settings | Qwen2.5-3B-Instruct, BF16 | 12 of 20, in each of 2 runs | |
|
|
108
145
|
|
|
109
146
|
If you run it, an [issue](https://github.com/aditi-p31/cache-divergence-study/issues) with what you saw is welcome.
|
|
110
147
|
|
|
@@ -112,13 +149,56 @@ Two server processes can also differ for other reasons. To check that, start
|
|
|
112
149
|
both with prefix caching off and run with `--skip-hit-check`. Every probe
|
|
113
150
|
should come out the same.
|
|
114
151
|
|
|
115
|
-
Options: `--
|
|
116
|
-
|
|
152
|
+
Options: `--probes` reads your own conversations (next section), `--n` sets
|
|
153
|
+
the number of probes (default: all), `--max-tokens` the answer length
|
|
154
|
+
(default 256), `--out` the JSON report path. If your server caches in blocks or
|
|
155
|
+
pages larger than 32 tokens, set `--hit-tolerance` to that size, or cache hits
|
|
156
|
+
can look too short. With large pages, also ask for longer turn-1 answers, so
|
|
157
|
+
the hit can reach past the prompt.
|
|
117
158
|
|
|
118
159
|
Models that think before answering need thinking turned off for this check.
|
|
119
160
|
Their templates often drop past thinking from the history, which shortens the
|
|
120
161
|
cache hit, and the tool marks those probes as inconclusive.
|
|
121
162
|
|
|
163
|
+
## Run it on your own conversations
|
|
164
|
+
|
|
165
|
+
The built-in conversations are short and generic. To check the kind of
|
|
166
|
+
prompts your application sends, put your own in a JSON Lines file, one
|
|
167
|
+
conversation per line, and pass it with `--probes`:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
llm-cachecheck --base-url http://127.0.0.1:8080 --probes my_conversations.jsonl
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Each line has one of two forms
|
|
174
|
+
([example file](https://github.com/aditi-p31/cache-divergence-study/blob/main/cachecheck/examples/conversations_example.jsonl)):
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
{"id": "returns-1", "turn1": "A customer wants to return shoes bought 40 days ago. ...", "turn2": "Rewrite the reply so it offers store credit instead."}
|
|
178
|
+
{"id": "sql-1", "messages": [{"role": "system", "content": "You are a careful SQL assistant."}, {"role": "user", "content": "Write a query for the ten largest orders."}], "followup": "Change it so it only counts orders created in 2025."}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
- `turn1` is the first user message and `turn2` the follow-up.
|
|
182
|
+
- In the longer form, `messages` is the conversation up to and including the
|
|
183
|
+
turn-1 user message, so it can carry your system prompt and earlier turns.
|
|
184
|
+
`followup` is the turn-2 user message.
|
|
185
|
+
- `id` is optional and is copied into the report.
|
|
186
|
+
- Text messages only, with the roles system, developer, user and assistant.
|
|
187
|
+
Tool calls and images are not supported.
|
|
188
|
+
|
|
189
|
+
The tool generates the turn-1 answer itself and builds turn 2 on it, as with
|
|
190
|
+
the built-in conversations, and it always decodes greedily. A file that holds
|
|
191
|
+
one JSON array of these objects also works.
|
|
192
|
+
|
|
193
|
+
Let turn 1 ask for an answer of a few sentences. The tool counts a cache hit
|
|
194
|
+
only when it reaches past the turn-1 prompt into the answer. A server that
|
|
195
|
+
caches in blocks (vLLM uses 16 tokens by default) can stop the hit at the
|
|
196
|
+
prompt when the answer is short, and the probe is then inconclusive.
|
|
197
|
+
|
|
198
|
+
The JSON report saves every answer, so keep it private if your conversations
|
|
199
|
+
are. The printed result block holds no conversation text: only the counts
|
|
200
|
+
and the run settings, including the model name.
|
|
201
|
+
|
|
122
202
|
## Reading the result
|
|
123
203
|
|
|
124
204
|
A real run on Apple Silicon (Metal) with Qwen2.5-3B-Instruct at Q4_K_M,
|
|
@@ -148,6 +228,9 @@ It took about 15 minutes on a laptop.
|
|
|
148
228
|
| 1 | At least one valid probe differed |
|
|
149
229
|
| 2 | Inconclusive: too few valid probes, or a request failed |
|
|
150
230
|
|
|
231
|
+
A usage error (a bad or conflicting option) also exits with status 2, before
|
|
232
|
+
any request is sent and without writing a report.
|
|
233
|
+
|
|
151
234
|
The JSON report keeps every answer, the finish reasons, token counts, cached
|
|
152
235
|
token counts and the server build.
|
|
153
236
|
|
|
@@ -22,7 +22,8 @@ second answer on two paths:
|
|
|
22
22
|
Each path runs twice. A probe counts as valid only when all of these hold:
|
|
23
23
|
|
|
24
24
|
- both paths repeat on their own
|
|
25
|
-
- the server's own counts show that the cache hit covered the turn-1 answer
|
|
25
|
+
- the server's own counts show that the cache hit covered the turn-1 answer,
|
|
26
|
+
to within `--hit-tolerance` tokens and at least past the turn-1 prompt
|
|
26
27
|
- the server's own counts show that the recompute path reused nothing
|
|
27
28
|
|
|
28
29
|
## Run it
|
|
@@ -37,8 +38,8 @@ llm-cachecheck --help
|
|
|
37
38
|
Or download the single file
|
|
38
39
|
[`cachecheck.py`](https://github.com/aditi-p31/cache-divergence-study/blob/main/cachecheck/cachecheck.py)
|
|
39
40
|
and run `python cachecheck.py` in place of `llm-cachecheck`. Both take the
|
|
40
|
-
same options.
|
|
41
|
-
sends 120
|
|
41
|
+
same options. Each conversation takes six requests, so a run of the 20
|
|
42
|
+
built-in conversations sends 120.
|
|
42
43
|
|
|
43
44
|
**llama.cpp.** The cache is switched per request. Start the server with one
|
|
44
45
|
slot, because the default is several slots that share a cache. Turn the
|
|
@@ -49,10 +50,44 @@ llama-server -m model.gguf -np 1 --cache-ram 0 --port 8080
|
|
|
49
50
|
llm-cachecheck --base-url http://127.0.0.1:8080
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
**vLLM
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
**vLLM or SGLang, one server.** Start the server with prefix caching on (the
|
|
54
|
+
default) and with cached-token reporting on. The tool sends every request with
|
|
55
|
+
a `cache_salt`. The two turns of the cache path share one salt, so turn 2
|
|
56
|
+
reuses the state of turn 1. Each recompute request gets a salt that no other
|
|
57
|
+
request has used, so it cannot reuse any cached state.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
vllm serve Qwen/Qwen2.5-3B-Instruct --port 8000 \
|
|
61
|
+
--generation-config vllm --enable-prompt-tokens-details
|
|
62
|
+
llm-cachecheck --mode one-server --base-url http://127.0.0.1:8000 \
|
|
63
|
+
--model Qwen/Qwen2.5-3B-Instruct
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
For SGLang, add `--enable-cache-report` and `--sampling-defaults openai`.
|
|
67
|
+
On real vLLM 0.33.0 and SGLang 0.5.23 servers (SGLang with CUDA graphs disabled), the recompute answers in this mode had the same text as those of a second server with prefix caching off, on all 20 conversations in every run ([details](https://github.com/aditi-p31/cache-divergence-study/blob/main/cachecheck-0.3-validation/README.md)).
|
|
68
|
+
|
|
69
|
+
The server must honour `cache_salt`. If it does not, the recompute requests
|
|
70
|
+
reuse cached state, the tool marks those probes as inconclusive and says so,
|
|
71
|
+
and the two-server setup below still works. The server must also report cached
|
|
72
|
+
tokens, so `--skip-hit-check` is not available in this mode.
|
|
73
|
+
|
|
74
|
+
This mode compares a cache hit with a cache miss on one server. From reading
|
|
75
|
+
the vLLM 0.33.0 and SGLang 0.5.23 source, a miss on a standard attention model,
|
|
76
|
+
served without a KV connector such as LMCache, takes the same code path as on a
|
|
77
|
+
server with prefix caching off. For some setups, for example models with Mamba
|
|
78
|
+
or sliding-window layers, or speculative decoding, turning prefix caching on
|
|
79
|
+
also changes how the server handles requests that miss. To compare with
|
|
80
|
+
caching off there, use two servers.
|
|
81
|
+
|
|
82
|
+
Run it on a server that gets no other traffic, such as a staging copy. On a
|
|
83
|
+
busy server, batching with other requests can change answers by itself. The
|
|
84
|
+
tool's repeat checks mark many such probes as inconclusive, but they cannot
|
|
85
|
+
rule out a difference caused by other traffic.
|
|
86
|
+
|
|
87
|
+
**vLLM, SGLang or another OpenAI-compatible server, two servers.** The cache
|
|
88
|
+
is a server setting, so serve the same model twice, once with prefix caching
|
|
89
|
+
on and once with it off. Both servers must report cached tokens. For vLLM on
|
|
90
|
+
one 24 GB GPU (a 3B model, so two copies fit):
|
|
56
91
|
|
|
57
92
|
```bash
|
|
58
93
|
vllm serve Qwen/Qwen2.5-3B-Instruct --port 8000 --gpu-memory-utilization 0.45 \
|
|
@@ -73,14 +108,16 @@ URLs would reach the same server.
|
|
|
73
108
|
The tool then reports the recompute path reusing cached tokens and marks every
|
|
74
109
|
probe invalid, so check the server logs if that happens.
|
|
75
110
|
|
|
76
|
-
Tested on real servers
|
|
77
|
-
conversations; details in the [currency note](https://github.com/aditi-p31/cache-divergence-study/blob/main/CURRENCY_CHECK_2026-11.md)):
|
|
111
|
+
Tested on real servers (one RTX 4090; the tool's 20 conversations). The two-server and llama.cpp rows are from 2026-11-11 and 11-12 UTC ([currency note](https://github.com/aditi-p31/cache-divergence-study/blob/main/CURRENCY_CHECK_2026-11.md)); the one-server rows are from 2026-11-14 UTC ([details](https://github.com/aditi-p31/cache-divergence-study/blob/main/cachecheck-0.3-validation/README.md)):
|
|
78
112
|
|
|
79
113
|
| Server | Model | Conversations with a different turn-2 answer | Both caches off |
|
|
80
114
|
|---|---|---|---|
|
|
81
115
|
| vLLM 0.33.0, two servers | Qwen2.5-3B-Instruct, BF16 | 14 of 20, in each of 5 runs | 0 of 20 |
|
|
82
116
|
| SGLang 0.5.23, two servers (CUDA graphs disabled) | Qwen2.5-3B-Instruct, BF16 | 12 of 20, in each of 2 runs | 0 of 20 |
|
|
83
117
|
| llama.cpp v0.9.0 | Qwen2.5-7B-Instruct, Q4_K_M | 11 of 20, in each of 2 runs | |
|
|
118
|
+
| vLLM 0.33.0, one server | Qwen2.5-3B-Instruct, BF16 | 14 of 20, in each of 2 runs | |
|
|
119
|
+
| SGLang 0.5.23, one server (CUDA graphs disabled) | Qwen2.5-3B-Instruct, BF16 | 12 of 20, in each of 2 runs | |
|
|
120
|
+
| SGLang 0.5.23, one server, default settings | Qwen2.5-3B-Instruct, BF16 | 12 of 20, in each of 2 runs | |
|
|
84
121
|
|
|
85
122
|
If you run it, an [issue](https://github.com/aditi-p31/cache-divergence-study/issues) with what you saw is welcome.
|
|
86
123
|
|
|
@@ -88,13 +125,56 @@ Two server processes can also differ for other reasons. To check that, start
|
|
|
88
125
|
both with prefix caching off and run with `--skip-hit-check`. Every probe
|
|
89
126
|
should come out the same.
|
|
90
127
|
|
|
91
|
-
Options: `--
|
|
92
|
-
|
|
128
|
+
Options: `--probes` reads your own conversations (next section), `--n` sets
|
|
129
|
+
the number of probes (default: all), `--max-tokens` the answer length
|
|
130
|
+
(default 256), `--out` the JSON report path. If your server caches in blocks or
|
|
131
|
+
pages larger than 32 tokens, set `--hit-tolerance` to that size, or cache hits
|
|
132
|
+
can look too short. With large pages, also ask for longer turn-1 answers, so
|
|
133
|
+
the hit can reach past the prompt.
|
|
93
134
|
|
|
94
135
|
Models that think before answering need thinking turned off for this check.
|
|
95
136
|
Their templates often drop past thinking from the history, which shortens the
|
|
96
137
|
cache hit, and the tool marks those probes as inconclusive.
|
|
97
138
|
|
|
139
|
+
## Run it on your own conversations
|
|
140
|
+
|
|
141
|
+
The built-in conversations are short and generic. To check the kind of
|
|
142
|
+
prompts your application sends, put your own in a JSON Lines file, one
|
|
143
|
+
conversation per line, and pass it with `--probes`:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
llm-cachecheck --base-url http://127.0.0.1:8080 --probes my_conversations.jsonl
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Each line has one of two forms
|
|
150
|
+
([example file](https://github.com/aditi-p31/cache-divergence-study/blob/main/cachecheck/examples/conversations_example.jsonl)):
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{"id": "returns-1", "turn1": "A customer wants to return shoes bought 40 days ago. ...", "turn2": "Rewrite the reply so it offers store credit instead."}
|
|
154
|
+
{"id": "sql-1", "messages": [{"role": "system", "content": "You are a careful SQL assistant."}, {"role": "user", "content": "Write a query for the ten largest orders."}], "followup": "Change it so it only counts orders created in 2025."}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
- `turn1` is the first user message and `turn2` the follow-up.
|
|
158
|
+
- In the longer form, `messages` is the conversation up to and including the
|
|
159
|
+
turn-1 user message, so it can carry your system prompt and earlier turns.
|
|
160
|
+
`followup` is the turn-2 user message.
|
|
161
|
+
- `id` is optional and is copied into the report.
|
|
162
|
+
- Text messages only, with the roles system, developer, user and assistant.
|
|
163
|
+
Tool calls and images are not supported.
|
|
164
|
+
|
|
165
|
+
The tool generates the turn-1 answer itself and builds turn 2 on it, as with
|
|
166
|
+
the built-in conversations, and it always decodes greedily. A file that holds
|
|
167
|
+
one JSON array of these objects also works.
|
|
168
|
+
|
|
169
|
+
Let turn 1 ask for an answer of a few sentences. The tool counts a cache hit
|
|
170
|
+
only when it reaches past the turn-1 prompt into the answer. A server that
|
|
171
|
+
caches in blocks (vLLM uses 16 tokens by default) can stop the hit at the
|
|
172
|
+
prompt when the answer is short, and the probe is then inconclusive.
|
|
173
|
+
|
|
174
|
+
The JSON report saves every answer, so keep it private if your conversations
|
|
175
|
+
are. The printed result block holds no conversation text: only the counts
|
|
176
|
+
and the run settings, including the model name.
|
|
177
|
+
|
|
98
178
|
## Reading the result
|
|
99
179
|
|
|
100
180
|
A real run on Apple Silicon (Metal) with Qwen2.5-3B-Instruct at Q4_K_M,
|
|
@@ -124,6 +204,9 @@ It took about 15 minutes on a laptop.
|
|
|
124
204
|
| 1 | At least one valid probe differed |
|
|
125
205
|
| 2 | Inconclusive: too few valid probes, or a request failed |
|
|
126
206
|
|
|
207
|
+
A usage error (a bad or conflicting option) also exits with status 2, before
|
|
208
|
+
any request is sent and without writing a report.
|
|
209
|
+
|
|
127
210
|
The JSON report keeps every answer, the finish reasons, token counts, cached
|
|
128
211
|
token counts and the server build.
|
|
129
212
|
|