Ben Graville commited on
docs: descriptive model card
Browse files
README.md
CHANGED
|
@@ -2,13 +2,16 @@
|
|
| 2 |
license: gemma
|
| 3 |
base_model: google/embeddinggemma-300m
|
| 4 |
library_name: coreai
|
|
|
|
| 5 |
tags:
|
| 6 |
-
-
|
| 7 |
- aimodel
|
| 8 |
-
- sentence-embedding
|
| 9 |
-
- on-device
|
| 10 |
- apple-silicon
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
extra_gated_heading: Access EmbeddingGemma on Hugging Face
|
| 13 |
extra_gated_description: >-
|
| 14 |
This artifact is a derivative of google/embeddinggemma-300m and is governed by
|
|
@@ -17,52 +20,133 @@ extra_gated_description: >-
|
|
| 17 |
|
| 18 |
# embeddinggemma-300m β Core AI (.aimodel)
|
| 19 |
|
| 20 |
-
`google/embeddinggemma-300m` exported as a single static
|
| 21 |
-
(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
| | |
|
| 24 |
|---|---|
|
| 25 |
-
|
|
| 26 |
-
| Recipe
|
| 27 |
-
|
|
| 28 |
-
|
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
-
##
|
| 36 |
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
|
|
|
| 40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
-
|
|
|
|
| 43 |
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
> this artifact: the conversion box is Linux with no GPU delegate, so nothing here has
|
| 47 |
-
> produced a vector.
|
| 48 |
|
| 49 |
-
|
| 50 |
-
`model/` (this repo @ `2bee70c5bc49cafc3c9e7f88d4d0095508cbfd4b`) put through **`coreai_opt.coreai_utils.quantize_weights`
|
| 51 |
-
with `dtype=INT8`** - a Core AI *graph* compression pass that rewrites the weight
|
| 52 |
-
constants of an existing `.aimodel` in place. There is **no PyTorch round-trip and no
|
| 53 |
-
re-export**: the graph, the input signature (`seq_len 256`, 768-d output) and the
|
| 54 |
-
tokenizer are the fp32 bundle's.
|
| 55 |
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
-
|
| 63 |
-
bundle's, carried so the folder is self-contained.
|
| 64 |
|
| 65 |
-
**
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
license: gemma
|
| 3 |
base_model: google/embeddinggemma-300m
|
| 4 |
library_name: coreai
|
| 5 |
+
pipeline_tag: sentence-similarity
|
| 6 |
tags:
|
| 7 |
+
- core-ai
|
| 8 |
- aimodel
|
|
|
|
|
|
|
| 9 |
- apple-silicon
|
| 10 |
+
- on-device
|
| 11 |
+
- embeddings
|
| 12 |
+
- sentence-embedding
|
| 13 |
+
- quantized
|
| 14 |
+
- int8
|
| 15 |
extra_gated_heading: Access EmbeddingGemma on Hugging Face
|
| 16 |
extra_gated_description: >-
|
| 17 |
This artifact is a derivative of google/embeddinggemma-300m and is governed by
|
|
|
|
| 20 |
|
| 21 |
# embeddinggemma-300m β Core AI (.aimodel)
|
| 22 |
|
| 23 |
+
`google/embeddinggemma-300m` exported as a single static Core AI graph for Apple silicon by
|
| 24 |
+
the [Visible](https://visible.cx) project. The whole embedding pipeline is **in the graph**:
|
| 25 |
+
transformer β mean pooling β dense stack β L2 normalise, one call in, one 768-d unit vector
|
| 26 |
+
out. There is no host-side pooling to get wrong.
|
| 27 |
+
|
| 28 |
+
Two variants ship here: an **fp32** bundle (built from the verified zoo recipe) and an
|
| 29 |
+
**int8** bundle produced by compressing that graph in place. Their qualification status is
|
| 30 |
+
not the same β read the status table before choosing.
|
| 31 |
+
|
| 32 |
+
This repo is the Core AI *leg* of Visible's embedding story, not the production one. Core ML
|
| 33 |
+
is the app's serving embedding path; this bundle is constructed always but only executes in
|
| 34 |
+
`VISIBLE_COREAI_KIT` builds on macOS 27+.
|
| 35 |
+
|
| 36 |
+
## Provenance
|
| 37 |
|
| 38 |
| | |
|
| 39 |
|---|---|
|
| 40 |
+
| Base checkpoint | `google/embeddinggemma-300m` |
|
| 41 |
+
| Recipe (fp32) | `coreai-model-zoo/conversion/export_embeddinggemma.py --dtype float32 --seq-len 256` |
|
| 42 |
+
| Recipe index | `models/qwen3-embedding/recipe.toml` β `["embeddinggemma-300m"]`, `status = "verified"` |
|
| 43 |
+
| Upstream reference bundle | `mlboydaisuke/embeddinggemma-300m-CoreAI` @ `d9a60a18d384484a8dab809b3070b82fb41458ce` |
|
| 44 |
+
| Producer fingerprint | `coreai-core 1.0.0b2` on both inner asset `metadata.json` files |
|
| 45 |
+
| Asset creation dates | `20260817T201458Z` (fp32), `20260817T212021Z` (int8) |
|
| 46 |
+
| Toolchain | `coreai-torch 0.4.1`, `coreai-core 1.0.0b2`, `coreai-opt 0.2.1`, `torch 2.9.0` |
|
| 47 |
+
| Asset metadata | `author: "Google DeepMind"`, `license: "Gemma"` (fp32 bundle) |
|
| 48 |
+
| Conversion host | Linux x86_64 (Debian 13), CPU only |
|
| 49 |
|
| 50 |
+
The `int8/` bundle is **not a second export**. It is the fp32 bundle put through
|
| 51 |
+
`coreai_opt.coreai_utils.quantize_weights(dtype=DType.INT8)` β the Core AI *graph*
|
| 52 |
+
compression path, which rewrites an existing program's weight constants in place. There was
|
| 53 |
+
no PyTorch round-trip and no re-trace: the graph, the input signature and the tokenizer are
|
| 54 |
+
the fp32 bundle's, unchanged. The pass accepted the graph first try, in about a minute of
|
| 55 |
+
box time.
|
| 56 |
|
| 57 |
+
## Contents
|
| 58 |
|
| 59 |
+
| Path | Bytes | Weights | Sequence length |
|
| 60 |
+
|---|---:|---|---|
|
| 61 |
+
| `model/embeddinggemma-300m_float32_static.aimodel` + `model/reference.json` + `model/tokenizer/` | 1,277,545,730 | fp32 | 256 |
|
| 62 |
+
| `int8/embeddinggemma-300m_int8_static.aimodel` + `int8/reference.json` + `int8/tokenizer/` | 356,639,960 | int8 (graph-compressed) | 256 |
|
| 63 |
|
| 64 |
+
| File | fp32 (`model/`) | int8 (`int8/`) |
|
| 65 |
+
|---|---:|---:|
|
| 66 |
+
| `main.mlirb` | 1,244,157,766 | **323,252,231** (0.26Γ) |
|
| 67 |
+
| `main.hash` | 32 | 32 |
|
| 68 |
+
| asset `metadata.json` | 340 | 105 |
|
| 69 |
+
| `reference.json` | 1,615 | 1,615 |
|
| 70 |
+
| `tokenizer/tokenizer.json` | 33,385,272 | 33,385,272 |
|
| 71 |
+
| `tokenizer/tokenizer_config.json` | 705 | 705 |
|
| 72 |
|
| 73 |
+
`reference.json` and `tokenizer/` in `int8/` are byte-identical copies of the fp32
|
| 74 |
+
bundle's, carried so the folder is self-contained.
|
| 75 |
|
| 76 |
+
`reference.json` is the exporter's own torch oracle: four reference texts and their
|
| 77 |
+
pairwise cosines, for checking the source pipeline end to end.
|
|
|
|
|
|
|
| 78 |
|
| 79 |
+
## Requirements
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
|
| 81 |
+
- **Apple silicon Mac**, Core AI runtime, macOS 27+.
|
| 82 |
+
- **Static input signature:** `input_ids [1, 256] int32`, `attention_mask [1, 256] int32`
|
| 83 |
+
β `embedding [1, 768]` fp32, L2-normalised. Sequence length 256 is baked into the graph
|
| 84 |
+
β pad or truncate to it; there is no dynamic-length variant.
|
| 85 |
+
- Weights β 1.24 GB resident (fp32) or β 0.32 GB (int8). No KV cache; this is an encoder,
|
| 86 |
+
so there is no per-token memory growth and no context ladder.
|
| 87 |
+
- Note the sequence-length difference from the Core ML artifact in this org, which is
|
| 88 |
+
**seq 128**. The two are not drop-in substitutes for each other.
|
| 89 |
|
| 90 |
+
## Measured performance
|
|
|
|
| 91 |
|
| 92 |
+
**None, from either bundle.** No embedding vector has been computed from either artifact:
|
| 93 |
+
they were built on a Linux box, where Core AI cannot execute (it needs Apple silicon), and
|
| 94 |
+
no Mac-side run has been recorded. Everything below is a *build and bytes* result, not a
|
| 95 |
+
runtime result.
|
| 96 |
+
|
| 97 |
+
For contrast: the catalog's generation bundles carry throughput measured on a 10-row guided
|
| 98 |
+
enrichment harness on a 16 GB M2 Pro Mac. There is no equivalent measurement here β not a
|
| 99 |
+
slower number, no number.
|
| 100 |
+
|
| 101 |
+
## Qualification status
|
| 102 |
+
|
| 103 |
+
| Artifact | Status |
|
| 104 |
+
|---|---|
|
| 105 |
+
| `model/` (fp32, seq 256) | **BUILT AND FINGERPRINTED, RUNTIME-UNQUALIFIED.** The recipe is the zoo's `status = "verified"` entry, the producer fingerprint passes, and the exporter's own pre-export gate (wrapper vs `sentence_transformers.encode` cosine > 0.999) passed. No vector has been computed from the *exported graph* on a Mac. |
|
| 106 |
+
| `int8/` (graph-compressed) | **EXPERIMENTAL.** Named gate: **cross-runtime vector parity against the fp32 bundle on a Mac** β cosine similarity per vector *and* retrieval-rank agreement, on a fixed corpus, not a spot-check of output shapes. Do not use for production embeddings until that passes. |
|
| 107 |
+
|
| 108 |
+
The int8 caveat is not boilerplate. fp16 embeddinggemma is already **known** to fail
|
| 109 |
+
vector-precision parity β the exporter's own comment records that a full `.to(float16)`
|
| 110 |
+
overflows Gemma3 activations and emits NaN embeddings, which independently matches
|
| 111 |
+
Visible's earlier finding. A 4Γ compression passing parity is therefore a hypothesis, not
|
| 112 |
+
an expectation.
|
| 113 |
+
|
| 114 |
+
## Verification
|
| 115 |
+
|
| 116 |
+
- **Producer fingerprint:** both inner asset `metadata.json` files read
|
| 117 |
+
`producer: "coreai-core 1.0.0b2"`. The pair to reject is `coreai-torch 0.4.0` /
|
| 118 |
+
`coreai-core 1.0.0b1`, whose bundles abort in-process at load and take the host
|
| 119 |
+
application down uncatchably. Read the **inner** asset file β the bundle manifest never
|
| 120 |
+
carries a `producer` field, for good and bad bundles alike.
|
| 121 |
+
- **Determinism β this bundle is NOT reproducible, and the sibling Core ML repo is.**
|
| 122 |
+
Rebuilt from the same recipe, `main.mlirb` differed from the published upstream bundle by
|
| 123 |
+
**+262 bytes**. Two runs on the same box nine minutes apart with an identical command
|
| 124 |
+
differed from *each other* by **+32 bytes**. So the difference is not a
|
| 125 |
+
macOSβLinux or toolchain-version artifact: the exporter is simply not byte-deterministic.
|
| 126 |
+
The tokenizer half is identical in every comparison made. **"Verify by rebuilding" is not
|
| 127 |
+
available for `.aimodel` bundles**; integrity rests on per-file SHA-256 of the exact
|
| 128 |
+
published bytes.
|
| 129 |
+
|
| 130 |
+
For the contrast, see `visible-cx/embeddinggemma-300m-CoreML`, where the same model's
|
| 131 |
+
Core ML `weight.bin` reproduced **bit-exactly** across operating systems β 0 of
|
| 132 |
+
308,616,576 bytes differing. Two artifacts of one model, two different supply-chain
|
| 133 |
+
arguments.
|
| 134 |
+
- **The torch oracle agrees to ~6e-8.** `reference.json`'s pairwise cosines from the box
|
| 135 |
+
rebuild match the published values to roughly seven decimal places (largest deviation
|
| 136 |
+
~6e-8, e.g. `query_bike|query_capital` 0.14591985940933228 vs 0.1459198147058487). That
|
| 137 |
+
is CPU float nondeterminism across machines, not a different model. It validates the
|
| 138 |
+
**source** pipeline β checkpoint β prompts β pooling β dense β L2 β and explicitly does
|
| 139 |
+
**not** validate the exported graph's execution.
|
| 140 |
+
- No ANE-residency measurement exists for either bundle. `export_embeddinggemma.py` exposes
|
| 141 |
+
only `--dtype`, `--seq-len`, `--output-dir`, `--overwrite`; there is no compute-unit flag,
|
| 142 |
+
so an ANE-shaped variant would be model authoring rather than configuration.
|
| 143 |
+
|
| 144 |
+
## License
|
| 145 |
+
|
| 146 |
+
EmbeddingGemma is Gemma-family. These bundles are a derivative of
|
| 147 |
+
`google/embeddinggemma-300m`, and use is subject to the
|
| 148 |
+
[Gemma Terms of Use](https://ai.google.dev/gemma/terms) and the
|
| 149 |
+
[Gemma Prohibited Use Policy](https://ai.google.dev/gemma/prohibited_use_policy). The
|
| 150 |
+
fp32 bundle's own asset metadata carries `license: "Gemma"` and
|
| 151 |
+
`author: "Google DeepMind"`. Those terms travel with the artifact and with any
|
| 152 |
+
redistribution of it; Visible's contribution is the conversion, not the weights.
|