HelloSun commited on
Commit
b497cd9
·
verified ·
1 Parent(s): b0a3013

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +87 -34
README.md CHANGED
@@ -57,7 +57,8 @@ cmake --build build -j --target llama-diffusion-cli llama-cli llama-quantize
57
 
58
  ### 2. Diffusion decoding (recommended)
59
 
60
- The chat format is
 
61
 
62
  ```
63
  [unused9]系统:<system>[unused10][unused9]用户:<user>[unused10][unused9]助手:
@@ -66,7 +67,7 @@ The chat format is
66
  ```bash
67
  ./build/bin/llama-diffusion-cli \
68
  -m pangu-diffusion-Q4_K_M.gguf \
69
- -p "[unused9]系统:[unused10][unused9]用户:Which is bigger, 9.11 or 9.9?[unused10][unused9]助手:" \
70
  -ub 256 \
71
  --diffusion-block-length 32 \
72
  --diffusion-small-block 4 \
@@ -85,12 +86,15 @@ threshold in a single denoising step, with one small block per block:
85
  ```bash
86
  ./build/bin/llama-diffusion-cli \
87
  -m pangu-diffusion-Q4_K_M.gguf \
88
- -p "[unused9]系统:[unused10][unused9]用户:<question>[unused10][unused9]助手:" \
89
  -ub 256 --diffusion-block-length 32 --diffusion-small-block 32 \
90
  --diffusion-confidence-threshold 0.9 --diffusion-algorithm 4 \
91
  --temp 0 -t 16 --seed 42
92
  ```
93
 
 
 
 
94
  `--diffusion-algorithm` values: `0` origin, `1` entropy, `2` margin, `3` random, `4` confidence.
95
  `-ub N` is the maximum sequence length; the tail that does not fill a whole block is dropped.
96
 
@@ -103,34 +107,31 @@ threshold in a single denoising step, with one small block per block:
103
 
104
  ## Example
105
 
106
- Prompt (translated): *“Which is bigger, 9.11 or 9.9?”* — command as in §2:
 
107
 
108
  ```
109
- # Which is bigger, 9.11 or 9.9?
110
-
111
- I need to compare 9.11 and 9.9 to see which one is bigger. Both numbers are
112
- between 9 and 10, so they're both greater than 9 but less than 10.
113
 
114
- Let me think about this carefully. 9.11 means 9 and 11 hundredths, which is
115
- 9 + 11/100. Similarly, 9.9 means 9 and 9 tenths, which is 9 + 9/10.
116
 
117
- To compare them, I should convert them to the same format. Let me convert both
118
- to hundredths.
119
 
120
- 9.9 = 9.90 (adding a zero to make it 9.90)
121
 
122
- Now I have:
123
- - 9.11
124
- - 9.90
125
 
126
- Since both have the same number of decimal places, I can compare them directly.
127
 
128
- The first digit after the decimal is 1 for 9.11 and 9 for 9.90. Since 9 > 1,
129
- 9.90 is larger than 9.11.
130
-
131
- So, 9.9 is bigger than 9.11.
132
  ```
133
 
 
 
 
 
 
134
  ## Speed when you actually use it (measured)
135
 
136
  Test environment — the resources **actually usable inside the container (docker)**:
@@ -164,7 +165,7 @@ Notes:
164
  token whose confidence exceeds `T` is revealed in the same step (`transfer = argmax(conf)
165
  | (conf > T)`), which raises throughput — the same mechanism the authors report as giving
166
  up to 2.5× over autoregressive decoding on Ascend NPUs. A lower `T` is faster but less
167
- accurate; measured on this CPU (224 tokens, block 32 / small-block 32, `alg=confidence`,
168
  `temp=0`):
169
 
170
  | `--diffusion-confidence-threshold` | speed |
@@ -188,12 +189,16 @@ Notes:
188
  - re-decode the block each step, dropping its stale keys (`llama_memory_seq_rm`),
189
  reveal the most-confident masked token of the current small block, left to right;
190
  - commit the block with a causal forward so the KV cache holds correct causal
191
- context, then sample the first token of the next block from the last position.
192
- 3. **`examples/diffusion/diffusion-cli.cpp`** — read `diffusion.block_attention`,
193
- add `--diffusion-small-block`, use greedy sampling when `temperature == 0`.
 
 
 
194
  4. **`gguf-py` + `conversion/pangu.py`** — write the new `diffusion.block_attention`
195
  metadata key for diffusion checkpoints (alongside `diffusion.shift_logits` and
196
- `tokenizer.ggml.mask_token_id`).
 
197
 
198
  ### Model metadata in the GGUF
199
 
@@ -202,18 +207,66 @@ general.architecture = pangu-embedded
202
  diffusion.shift_logits = true
203
  diffusion.block_attention = true
204
  tokenizer.ggml.mask_token_id = 45830
 
205
  ```
206
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
  ## Notes / limitations
208
 
209
- - CPU-only, `-t 16`, ≈ 4.6 GB file: a 256-token block-diffusion run takes a few minutes
210
- (`block_length` forwards per block). Throughput can be improved with
211
  `alg = confidence_threshold, num_small_blocks = 1` (see the official README).
212
- - The committed-block KV-cache path was numerically cross-checked against the
213
- Hugging Face reference (`cos ≈ 0.996`, f16 vs bf16), and the same binaries reproduce
214
- the model's reference-quality output above.
215
- - Quantization may slightly affect the tricky reasoning cases; use `alg = entropy`,
216
- `temp = 0` for the most stable results.
 
 
 
217
 
218
  ## Supported features
219
 
@@ -231,10 +284,10 @@ Implemented (matching the reference `inference/generation_utils.py`):
231
  | Reveal order: `confidence`, `entropy`, `topk_margin` | ✓ `--diffusion-algorithm 4/1/2` |
232
  | `confidence_threshold` fast mode (multi-token reveal per step) | ✓ `--diffusion-confidence-threshold` |
233
  | EOS early stop | ✓ |
 
234
  | Autoregressive decoding | ✓ `llama-cli` |
235
 
236
  Not implemented:
237
- - Batched (multi-sequence) block diffusion — the example CLI runs a single sequence.
238
  - Vendor NPU kernels — this uses whatever backend llama.cpp was built with (CPU here).
239
 
240
  ## Original model
 
57
 
58
  ### 2. Diffusion decoding (recommended)
59
 
60
+ `llama-diffusion-cli` applies the model's chat template automatically: pass the **raw
61
+ user message**, not a pre-formatted prompt. The rendered prompt is
62
 
63
  ```
64
  [unused9]系统:<system>[unused10][unused9]用户:<user>[unused10][unused9]助手:
 
67
  ```bash
68
  ./build/bin/llama-diffusion-cli \
69
  -m pangu-diffusion-Q4_K_M.gguf \
70
+ -p "Which is bigger, 9.11 or 9.9?" \
71
  -ub 256 \
72
  --diffusion-block-length 32 \
73
  --diffusion-small-block 4 \
 
86
  ```bash
87
  ./build/bin/llama-diffusion-cli \
88
  -m pangu-diffusion-Q4_K_M.gguf \
89
+ -p "<question>" \
90
  -ub 256 --diffusion-block-length 32 --diffusion-small-block 32 \
91
  --diffusion-confidence-threshold 0.9 --diffusion-algorithm 4 \
92
  --temp 0 -t 16 --seed 42
93
  ```
94
 
95
+ `--diffusion-n-seq N` runs N sequences through the block decoder in a single
96
+ (micro-)batch (the prompt is replicated; see *Batched decoding* below).
97
+
98
  `--diffusion-algorithm` values: `0` origin, `1` entropy, `2` margin, `3` random, `4` confidence.
99
  `-ub N` is the maximum sequence length; the tail that does not fill a whole block is dropped.
100
 
 
107
 
108
  ## Example
109
 
110
+ Prompt (translated): *“Which is bigger, 9.11 or 9.9?”* — command as in §2, fast mode
111
+ (`-ub 256`, `--diffusion-confidence-threshold 0.9`, Q4_K_M):
112
 
113
  ```
114
+ I need to figure out which is bigger between 9.11 and 9.9. Both are decimals, so I should compare them directly.
 
 
 
115
 
116
+ First, let's write them with the same number of decimal places to make it easier. 9.11 has two decimal places, and 9.9 has one. So, I can write 9.9 as 9.90 to make it two decimal places.
 
117
 
118
+ So, 9.11 vs 9.90.
 
119
 
120
+ Now, comparing the tenths place: both have 9 in the tenths place. So, that's the same.
121
 
122
+ Next, the hundredths place: 9.11 has 1 in the hundredths place, and 9.90 has 0 in the hundredths place. Since 1 is greater than 0, ...
 
 
123
 
124
+ I can think of them as fractions. 9.11 is 911/100, and 9.9 is 990/100.
125
 
126
+ Since the denominator is the same, I can compare the numerators: 911 vs 990.
127
+ 911 is less than 990, so 911/100 is less than 990/100, which ...
 
 
128
  ```
129
 
130
+ For a short prompt the output is reproduced **token-for-token identically to the Hugging
131
+ Face reference** (see *Numerical parity* below), e.g. `-p "hello"` (f16 GGUF):
132
+ `[unused16]Okay, the user just said "hello". That's a simple greeting. I should respond
133
+ politely and warmly. Maybe they're just starting a conversation`.
134
+
135
  ## Speed when you actually use it (measured)
136
 
137
  Test environment — the resources **actually usable inside the container (docker)**:
 
165
  token whose confidence exceeds `T` is revealed in the same step (`transfer = argmax(conf)
166
  | (conf > T)`), which raises throughput — the same mechanism the authors report as giving
167
  up to 2.5× over autoregressive decoding on Ascend NPUs. A lower `T` is faster but less
168
+ accurate; measured on this CPU (235 tokens, block 32 / small-block 32, `alg=confidence`,
169
  `temp=0`):
170
 
171
  | `--diffusion-confidence-threshold` | speed |
 
189
  - re-decode the block each step, dropping its stale keys (`llama_memory_seq_rm`),
190
  reveal the most-confident masked token of the current small block, left to right;
191
  - commit the block with a causal forward so the KV cache holds correct causal
192
+ context, then sample the first token of the next block from the last position;
193
+ - `diffusion_generate_nseq()` generalises this to `n_seq` sequences sharing one
194
+ micro-batch (see `--diffusion-n-seq`).
195
+ 3. **`examples/diffusion/diffusion-cli.cpp`** — read `diffusion.block_attention`, add
196
+ `--diffusion-small-block/-confidence-threshold/-n-seq`, size the context for the
197
+ batched prefill, and use greedy sampling when `temperature == 0`.
198
  4. **`gguf-py` + `conversion/pangu.py`** — write the new `diffusion.block_attention`
199
  metadata key for diffusion checkpoints (alongside `diffusion.shift_logits` and
200
+ `tokenizer.ggml.mask_token_id`), and set `tokenizer.ggml.add_space_prefix = false`
201
+ (see *Tokenizer fix* below).
202
 
203
  ### Model metadata in the GGUF
204
 
 
207
  diffusion.shift_logits = true
208
  diffusion.block_attention = true
209
  tokenizer.ggml.mask_token_id = 45830
210
+ tokenizer.ggml.add_space_prefix = false
211
  ```
212
 
213
+ ### Tokenizer fix
214
+
215
+ The upstream conversion honours `add_prefix_space` from `tokenizer_config.json`, but the
216
+ slow `PanguTokenizer` (sentencepiece, `legacy: true`) does **not** actually prepend a space.
217
+ With the flag left on, llama.cpp inserted spurious space tokens after every special token
218
+ (`[unused9]系统:…` became `[unused9]␠系统:…`), which changed the input and the generation.
219
+ The patch forces `tokenizer.ggml.add_space_prefix = false`; the tokenizer output then
220
+ matches the reference exactly (a 22-token prompt becomes 22 tokens, was 37).
221
+
222
+ ### Numerical parity
223
+
224
+ Validated against the Hugging Face reference (`inference/generation_utils.py`,
225
+ `alg=confidence`, `num_small_blocks=1`, `threshold=0.9`, `temperature=0`) on the **f16**
226
+ GGUF: for `-p "hello"` the generated token IDs are **identical, token for token**, to the
227
+ reference. (The earlier mismatch was entirely the tokenizer issue above, not the
228
+ decoder.)
229
+
230
+ ## Batched decoding (`--diffusion-n-seq`)
231
+
232
+ `--diffusion-n-seq N` runs N independent sequences through the block decoder inside a
233
+ single (micro-)batch. The example CLI replicates the prompt, so this is mainly a way to
234
+ measure batching; a real deployment would fill the rows with different prompts.
235
+
236
+ All sequences produce **byte-identical output** to the single-sequence run (verified for
237
+ N = 4 and N = 8), i.e. the batching is correct.
238
+
239
+ Measured on the CPU above (Q4_K_M, block 32 / small-block 32, `threshold 0.9`, greedy,
240
+ 235 generated tokens):
241
+
242
+ | `--diffusion-n-seq` | wall time | aggregate | per sequence |
243
+ |---|---|---|---|
244
+ | 1 | 44.5 s | 5.28 t/s | 5.28 t/s |
245
+ | 4 | 162.4 s | 5.79 t/s | 1.45 t/s |
246
+ | 8 | 321.2 s | 5.85 t/s | 0.73 t/s |
247
+
248
+ **Review / honest verdict:** on this **CPU** batching gives essentially *no* throughput
249
+ gain — aggregate speed stays flat (≈5.3–5.9 t/s) and the time grows ~linearly with `N`,
250
+ so per-sequence speed drops 1/N. That is expected: a CPU decode step is compute-bound and
251
+ widens ~linearly with `n_seq` (there are no tensor cores to fill and no memory-bandwidth
252
+ headroom to exploit), so the fixed per-step work simply multiplies. Batching is where the
253
+ official 2.5× over autoregressive decoding comes from **on Ascend NPUs/GPUs**, not here.
254
+ We kept it because it is correct, cheap to carry, and a prerequisite for any GPU
255
+ deployment — but do not expect a CPU speed-up from it.
256
+
257
  ## Notes / limitations
258
 
259
+ - CPU-only, `-t 16`, ≈ 4.6 GB file: a 256-token block-diffusion run takes tens of seconds
260
+ to a few minutes (`block_length` forwards per block). Throughput can be improved with
261
  `alg = confidence_threshold, num_small_blocks = 1` (see the official README).
262
+ - The decoder reproduces the Hugging Face reference **token-for-token** on the f16 GGUF
263
+ (see *Numerical parity*), and the block-diffusion path was cross-checked against the
264
+ reference logits (`cos ≈ 0.996`, f16 vs bf16).
265
+ - **Quantization + the greedy fast mode can change the reasoning**: on the adversarial
266
+ `9.11 vs 9.9` prompt the Q4_K_M fast mode first states the wrong intermediate answer and
267
+ only corrects itself from the fraction comparison above, whereas the f16 model matches
268
+ the reference. Use the f16 GGUF, or `alg = entropy`, `temp = 0`, when a case must be
269
+ exactly reproduced.
270
 
271
  ## Supported features
272
 
 
284
  | Reveal order: `confidence`, `entropy`, `topk_margin` | ✓ `--diffusion-algorithm 4/1/2` |
285
  | `confidence_threshold` fast mode (multi-token reveal per step) | ✓ `--diffusion-confidence-threshold` |
286
  | EOS early stop | ✓ |
287
+ | Batched (multi-sequence) block diffusion | ✓ `--diffusion-n-seq` |
288
  | Autoregressive decoding | ✓ `llama-cli` |
289
 
290
  Not implemented:
 
291
  - Vendor NPU kernels — this uses whatever backend llama.cpp was built with (CPU here).
292
 
293
  ## Original model