File size: 2,557 Bytes
e9f4f65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
---
license: apache-2.0
base_model: tiiuae/Falcon-Perception
tags: [webgpu, wgsl, int8, browser, object-detection, open-vocabulary, quantized]
---

# falcon-perception-webgpu β€” FPQ4 (q8 + q4-lm) weights

Custom mixed-precision quants of
[tiiuae/Falcon-Perception](https://huggingface.co/tiiuae/Falcon-Perception)
(0.6B open-vocabulary detection VLM) in the FPQ4 wire format of the
[falcon-perception-webgpu-demo](https://huggingface.co/spaces/borkiss/falcon-perception-webgpu-demo)
browser runtime β€” hand-written WGSL kernels, no ONNX Runtime for the language
stack, GPU-resident decode loop with speculative decoding for video.

**`falcon-q8-lm4.bin`** (724 MB, single file, everything the engine needs):

- all 113 layer matrices **int8** (group 128) β€” box quality demands it: any
  single q4 group's noise flips coordinate bins (q4 box-set IoU vs fp32 is
  only 0.43; q8 reaches hidden cosine 0.9993);
- `lm_head` **int4** β€” bit-exact argmax vs q8, βˆ’34 MB and βˆ’half the lm-read
  traffic per decode token;
- coord/size decode heads **f16**, Fourier coord/size encoders f32 β€”
  0/14 bin mismatches vs the ONNX reference;
- embeddings f16.

Numbers on an Apple M4 (10-core GPU, ~120 GB/s) in Chrome:

| | this runtime | original Space (fp32 ONNX/WASM) |
|---|---|---|
| full detection query | **1.2 s** | 7.8–8.7 s |
| decode | 91–95 tok/s | ~8.7 tok/s |
| download | 724 MB | 2.4 GB |
| video keyframes | 2.2–2.5 Hz (≀3 objects) + 30 FPS correlation tracker | β€” |

Quality vs the fp32 original on identical pixels: 8/8 boxes matched,
mean IoU 0.957. The runtime itself is verified bit-exact per layer (75/75)
against a numpy dequantized-weights reference, decode token-for-token.

## FPQ4 container

`'FPQ4'` magic + u32 manifest length + JSON manifest + 256-byte-aligned blobs,
absolute offsets β€” one `fetch`, sliced straight into GPU buffers:

```js
const head = new DataView(await file.slice(0, 8).arrayBuffer());
const mlen = head.getUint32(4, true);
const manifest = JSON.parse(new TextDecoder().decode(
    await file.slice(8, 8 + mlen).arrayBuffer()));
// per tensor t: file.slice(t.packed.offset, t.packed.offset + t.packed.length) β†’ writeBuffer
```

q8 matrix β‰ˆ 1.02 bytes/param (packed + f16 scales + i8 zeros, group 128);
q4 β‰ˆ 0.52 bytes/param. Only the mask heads (`anyup`/`segm_head`) stay in ONNX
on the demo's segmentation path; detection runs 100% on WGSL.

Try it: **https://huggingface.co/spaces/borkiss/falcon-perception-webgpu-demo**
(needs WebGPU with `shader-f16` + `subgroups` β€” Chrome/Edge 125+).