Alvario's picture
int8 quantisation + mmap-able tokenizer artifacts of potion-multilingual-128M
ba8c550 verified
|
Raw
History Blame Contribute Delete
3.33 kB
---
license: mit
base_model: minishlab/potion-multilingual-128M
tags:
- model2vec
- static-embeddings
- embeddings
- multilingual
- quantized
library_name: model2vec
---
# potion-multilingual-128M-i8-tokenade
An int8 quantisation of [`minishlab/potion-multilingual-128M`](https://huggingface.co/minishlab/potion-multilingual-128M),
plus precomputed tokenizer artifacts for low-memory loading.
All credit for the model itself goes to [the Minish Lab](https://huggingface.co/minishlab)
β€” this repo adds no training, no distillation and no new data. It only changes
how the same weights are stored and loaded.
## Why
model2vec inference is `tokenize β†’ look up rows β†’ mean-pool`: no context, no
forward pass. Loading it should not cost like a transformer, but in practice a
stock load decodes the whole weight matrix to `f32` and inflates
`tokenizer.json` into an in-memory trie β€” together about **1 GB of RSS and
~930 ms** before the first vector. That is fine for a long-lived server and
prohibitive for a short-lived CLI process.
These artifacts are the same model arranged so it can be memory-mapped instead:
| | stock load | these artifacts |
|---|---|---|
| RSS | ~1056 MB | **~4.5 MB** |
| first embedding | ~930 ms | **~1 ms** |
| per embedding | ~0.03 ms | ~0.11 ms |
The per-embedding cost regresses (no pre-decoded matrix, no cache); a process
needs roughly 12 700 embeddings in one run before that outweighs the load-time
saving.
## Files
| file | what it is |
|---|---|
| `model.safetensors` | the embedding matrix, `I8`, `[500353, 256]` |
| `vocab.fst` | the Unigram vocab as an FST: token bytes β†’ id |
| `vocab.fst.scores` | `f64` unigram log-probs, one per id, in id order |
| `vocab.fst.norm` | the normalizer / pre-tokenizer spec and decoding metadata |
| `tokenizer.json` | upstream's, unchanged β€” kept so the FST can be re-derived and verified |
| `config.json` | upstream's, unchanged |
## Quantisation
Symmetric, one global scale (`max|W| / 127`). The scale is deliberately **not**
stored: mean-pooling is linear and model2vec L2-normalises its output, so a
single global factor cancels exactly. Rows can therefore be read straight from
disk as raw `i8`.
This is measured, not assumed. Against `model2vec-rs` reading the f32 original,
over 100 133 text segments extracted from real PDF / DOCX / XLSX / EPUB / ODT /
ODS / ODP / PPTX files:
* token ids: **0 divergences**
* embeddings: worst cosine **0.999994**
Retrieval quality on our internal evaluation is unchanged within noise
(0.570/0.413 vs 0.571/0.414 for f32).
## Caveats
* `[UNK]` handling follows `model2vec-rs` exactly, including that it does *not*
drop `[UNK]` rows for a Unigram tokenizer (it looks for a string `unk_token`
field, which Unigram does not emit). If you consume these artifacts with your
own loader and drop `[UNK]` instead, you will get different vectors on
unk-heavy text.
* `vocab.fst` maps duplicate tokens to their **last** id, matching how
`tokenizers` builds its `token_to_ids` map.
* The FST/score/norm layout is ours, not a model2vec standard. Anything reading
only `model.safetensors` + `tokenizer.json` (including model2vec itself) works
with this repo unmodified β€” the i8 tensor is a standard safetensors dtype.
## License
MIT, inherited from the upstream model.