tooape commited on
Commit
cd292c5
·
verified ·
1 Parent(s): d2350cc

Initial upload: QAT-derived int8 ONNX export of EmbeddingGemma-300M

Browse files
.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
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: gemma
3
+ base_model: google/embeddinggemma-300m-qat-q8_0-unquantized
4
+ tags:
5
+ - sentence-transformers
6
+ - sentence-similarity
7
+ - feature-extraction
8
+ - onnx
9
+ - quantized
10
+ - int8
11
+ - transformers.js
12
+ library_name: transformers.js
13
+ pipeline_tag: feature-extraction
14
+ ---
15
+
16
+ # EmbeddingGemma-300M QAT → ONNX (int8)
17
+
18
+ ONNX export of [`google/embeddinggemma-300m-qat-q8_0-unquantized`](https://huggingface.co/google/embeddinggemma-300m-qat-q8_0-unquantized), quantized to int8 via ONNX Runtime dynamic quantization. Designed as a drop-in replacement for [`onnx-community/embeddinggemma-300m-ONNX`](https://huggingface.co/onnx-community/embeddinggemma-300m-ONNX) (which is PTQ-derived).
19
+
20
+ The headline difference: this export starts from Google's **QAT-trained** checkpoint, where weights were trained to tolerate int8 quantization noise during training. PTQ-derived exports apply quantization to a model that was never trained for it. The expected quality recovery is ~1.36 MTEB points.
21
+
22
+ ## Provenance
23
+
24
+ | | |
25
+ |---|---|
26
+ | Source checkpoint | `google/embeddinggemma-300m-qat-q8_0-unquantized` (safetensors fp32) |
27
+ | Export route | `optimum-cli export onnx --library-name sentence_transformers --opset 18` |
28
+ | Quantization | `onnxruntime.quantization.quantize_dynamic`, `QInt8`, `per_channel=True`, `reduce_range=False` |
29
+ | Toolchain | optimum-onnx 2.1.0, sentence-transformers 4.1.0, onnxruntime 1.26.0, torch 2.12.0, Python 3.14 |
30
+
31
+ The `per_channel=True` flag is load-bearing: QAT weights were trained with per-channel scales, and collapsing them to per-tensor would discard exactly the calibration QAT performed.
32
+
33
+ ## Files
34
+
35
+ ```
36
+ onnx/
37
+ ├── model.onnx # fp32 (~1.2 GB) — fallback / reference
38
+ ├── model_q8.onnx # int8 (~310 MB) — transformers.js v3 dtype="q8"
39
+ └── model_quantized.onnx # int8 (~310 MB) — identical to model_q8.onnx, transformers.js v2 alias
40
+ config.json
41
+ tokenizer.json
42
+ tokenizer_config.json
43
+ tokenizer.model
44
+ special_tokens_map.json
45
+ added_tokens.json
46
+ ```
47
+
48
+ ## Graph signature
49
+
50
+ ```
51
+ Inputs:
52
+ input_ids: [batch_size, sequence_length] int64
53
+ attention_mask: [batch_size, sequence_length] int64
54
+
55
+ Outputs:
56
+ token_embeddings: [batch_size, sequence_length, 768] float32
57
+ sentence_embedding: [batch_size, 768] float32 ← unit-normalized
58
+ ```
59
+
60
+ The `sentence_embedding` output is the full pipeline: mean-pool over tokens → Dense projection → LayerNorm → L2-normalize. MRL truncation (768 → 512 / 256 / 128) is the consumer's choice and should be applied after fetching this output.
61
+
62
+ ## Validation
63
+
64
+ Numerical agreement between fp32-QAT and int8-QAT on 5 diverse queries (cosine similarity, higher = more agreement; 1.0 = identical vector):
65
+
66
+ | Query | Cosine |
67
+ |---|---:|
68
+ | "how do I quantize an ONNX model" | 0.997491 |
69
+ | "difference between QAT and PTQ" | 0.997789 |
70
+ | "sentence embedding similarity" | 0.997953 |
71
+ | "WebGPU on iOS" | 0.997189 |
72
+ | "Adobe Photoshop tutorial" | 0.997584 |
73
+ | **Mean** | **0.9976** |
74
+
75
+ For comparison, PTQ-int8 against the same fp32 reference typically lands in the 0.985–0.995 range — meaning PTQ produces ~2–4× more drift than what QAT produces here.
76
+
77
+ ## Usage (transformers.js)
78
+
79
+ ```js
80
+ import { pipeline } from '@huggingface/transformers';
81
+
82
+ const embedder = await pipeline(
83
+ 'feature-extraction',
84
+ 'tooape/embeddinggemma-300m-qat-q8-ONNX',
85
+ { dtype: 'q8' }
86
+ );
87
+
88
+ const out = await embedder('your query text here', {
89
+ pooling: 'none', // sentence_embedding is already pooled+normalized
90
+ normalize: false, // already unit-normalized in the ONNX graph
91
+ });
92
+ ```
93
+
94
+ ## Usage (Python / onnxruntime)
95
+
96
+ ```python
97
+ import numpy as np
98
+ import onnxruntime as ort
99
+ from transformers import AutoTokenizer
100
+
101
+ sess = ort.InferenceSession("onnx/model_q8.onnx")
102
+ tok = AutoTokenizer.from_pretrained("tooape/embeddinggemma-300m-qat-q8-ONNX")
103
+ enc = tok("task: search result | query: your query", return_tensors="np")
104
+ feeds = {i.name: enc[i.name] for i in sess.get_inputs() if i.name in enc}
105
+ sentence_embedding = sess.run(["sentence_embedding"], feeds)[0] # (1, 768) unit-norm
106
+ ```
107
+
108
+ ## License
109
+
110
+ Inherits the [Gemma Terms of Use](https://ai.google.dev/gemma/terms) from the source checkpoint. Same access conditions apply.
added_tokens.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "<image_soft_token>": 262144
3
+ }
config.json ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_sliding_window_pattern": 6,
3
+ "architectures": [
4
+ "Gemma3TextModel"
5
+ ],
6
+ "attention_bias": false,
7
+ "attention_dropout": 0.0,
8
+ "attn_logit_softcapping": null,
9
+ "bos_token_id": 2,
10
+ "dtype": "float32",
11
+ "eos_token_id": 1,
12
+ "export_model_type": "transformer",
13
+ "final_logit_softcapping": null,
14
+ "head_dim": 256,
15
+ "hidden_activation": "gelu_pytorch_tanh",
16
+ "hidden_size": 768,
17
+ "initializer_range": 0.02,
18
+ "intermediate_size": 1152,
19
+ "layer_types": [
20
+ "sliding_attention",
21
+ "sliding_attention",
22
+ "sliding_attention",
23
+ "sliding_attention",
24
+ "sliding_attention",
25
+ "full_attention",
26
+ "sliding_attention",
27
+ "sliding_attention",
28
+ "sliding_attention",
29
+ "sliding_attention",
30
+ "sliding_attention",
31
+ "full_attention",
32
+ "sliding_attention",
33
+ "sliding_attention",
34
+ "sliding_attention",
35
+ "sliding_attention",
36
+ "sliding_attention",
37
+ "full_attention",
38
+ "sliding_attention",
39
+ "sliding_attention",
40
+ "sliding_attention",
41
+ "sliding_attention",
42
+ "sliding_attention",
43
+ "full_attention"
44
+ ],
45
+ "max_position_embeddings": 2048,
46
+ "model_type": "gemma3_text",
47
+ "num_attention_heads": 3,
48
+ "num_hidden_layers": 24,
49
+ "num_key_value_heads": 1,
50
+ "pad_token_id": 0,
51
+ "query_pre_attn_scalar": 256,
52
+ "rms_norm_eps": 1e-06,
53
+ "rope_local_base_freq": 10000.0,
54
+ "rope_scaling": null,
55
+ "rope_theta": 1000000.0,
56
+ "sliding_window": 257,
57
+ "transformers_version": "4.57.6",
58
+ "use_bidirectional_attention": true,
59
+ "use_cache": true,
60
+ "vocab_size": 262144
61
+ }
onnx/model.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:985793983822dc05d7eeba8d7bd13e88980d4ee9bed18a0694ef0ce7de363375
3
+ size 1231716334
onnx/model_q8.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:483fd617174767efc1083950a98a0a0cba2b131920a303811c6882a5591a7dea
3
+ size 310651109
onnx/model_quantized.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:483fd617174767efc1083950a98a0a0cba2b131920a303811c6882a5591a7dea
3
+ size 310651109
special_tokens_map.json ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "boi_token": "<start_of_image>",
3
+ "bos_token": {
4
+ "content": "<bos>",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false
9
+ },
10
+ "eoi_token": "<end_of_image>",
11
+ "eos_token": {
12
+ "content": "<eos>",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false
17
+ },
18
+ "image_token": "<image_soft_token>",
19
+ "pad_token": {
20
+ "content": "<pad>",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false
25
+ },
26
+ "unk_token": {
27
+ "content": "<unk>",
28
+ "lstrip": false,
29
+ "normalized": false,
30
+ "rstrip": false,
31
+ "single_word": false
32
+ }
33
+ }
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6852f8d561078cc0cebe70ca03c5bfdd0d60a45f9d2e0e1e4cc05b68e9ec329e
3
+ size 33385008
tokenizer.model ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1299c11d7cf632ef3b4e11937501358ada021bbdf7c47638d13c0ee982f2e79c
3
+ size 4689074
tokenizer_config.json ADDED
The diff for this file is too large to render. See raw diff