| --- |
| 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+). |
|
|