cdelconde commited on
Commit
44ed717
·
verified ·
1 Parent(s): eb38c71

Initial public release 1.0

Browse files
Files changed (10) hide show
  1. .gitattributes +1 -0
  2. LICENSE +21 -0
  3. README.md +79 -0
  4. keep_ids.npy +3 -0
  5. manifest.json +33 -0
  6. model.onnx +3 -0
  7. prune_meta.json +6 -0
  8. remap.py +41 -0
  9. tokenizer.json +3 -0
  10. tokenizer_config.json +21 -0
.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
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AtomicoLabs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ language:
4
+ - en
5
+ - es
6
+ library_name: onnxruntime
7
+ pipeline_tag: sentence-similarity
8
+ tags:
9
+ - embeddings
10
+ - onnx
11
+ - retrieval
12
+ - sts
13
+ - on-device
14
+ base_model: intfloat/multilingual-e5-large-instruct
15
+ ---
16
+
17
+ # ALF-emb-micro 1.0
18
+
19
+ Bilingual EN+ES embeddings. ALF is the AtomicoLabs model family. **Micro** = under 1B parameters.
20
+
21
+ Vocab-pruned finetune of multilingual-e5-large-instruct. Shipping format is per-channel int8 ONNX (mean-pool, L2-normalized, 1024-d).
22
+
23
+ Weights: GitHub Release [`v1.0`](https://github.com/AtomicoLabs/ALF-emb-micro/releases/tag/v1.0) and this Hugging Face revision `v1.0`.
24
+
25
+ | | Composite | EN retrieval | ES retrieval | STS | Domain |
26
+ |---|---|---|---|---|---|
27
+ | ALF-emb-micro 1.0 (int8) | 79.99 | 57.25 | 77.80 | 89.07 | 95.85 |
28
+ | OpenAI text-embedding-3-small | 80.08 | 59.74 | 79.52 | 88.66 | 92.39 |
29
+
30
+ 370M params · vocab 64.5k · cosine parity vs fp32 0.984.
31
+
32
+ This tokenizer is **not** drop-in e5. You must remap ids with `keep_ids.npy` / `remap.py`.
33
+
34
+ ## Use
35
+
36
+ ```python
37
+ from pathlib import Path
38
+ import sys
39
+ import numpy as np
40
+ import onnxruntime as ort
41
+ from huggingface_hub import snapshot_download
42
+
43
+ repo = Path(snapshot_download("AtomicoLabs/ALF-emb-micro", revision="v1.0"))
44
+ sys.path.insert(0, str(repo))
45
+ from remap import RemapTokenizer
46
+
47
+ QUERY = (
48
+ "Instruct: Given a web search query, retrieve relevant passages that answer the query\n"
49
+ "Query: "
50
+ )
51
+
52
+ tok = RemapTokenizer(repo, np.load(repo / "keep_ids.npy").tolist())
53
+ sess = ort.InferenceSession(str(repo / "model.onnx"), providers=["CPUExecutionProvider"])
54
+
55
+ def embed(texts, *, is_query=False):
56
+ batch = [(QUERY + t if is_query else t) for t in texts]
57
+ enc = tok(batch, padding=True, truncation=True, max_length=512, return_tensors="np")
58
+ vec = sess.run(None, {
59
+ "input_ids": enc["input_ids"].astype(np.int64),
60
+ "attention_mask": enc["attention_mask"].astype(np.int64),
61
+ })[0]
62
+ return vec.astype(np.float32)
63
+ ```
64
+
65
+ Documents take an empty prefix. Queries need the instruct prefix above.
66
+
67
+ ## Limits
68
+
69
+ - English retrieval is a bit under the OpenAI small bar; Spanish and domain are close or ahead.
70
+ - Max 512 tokens. int8, not fp16/fp32.
71
+ - Not a general instruction model.
72
+
73
+ ## Training
74
+
75
+ Finetune of [`intfloat/multilingual-e5-large-instruct`](https://huggingface.co/intfloat/multilingual-e5-large-instruct) (MIT), then vocab prune 560M → 370M, then dynamic per-channel int8 ONNX.
76
+
77
+ ## License
78
+
79
+ MIT. Include this notice and the e5-large-instruct MIT notice when you redistribute.
keep_ids.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7fda54c0a5cd1da4326af3614982a3edbc4b19e708e46244cac83314a25b5a4a
3
+ size 258376
manifest.json ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "id": "ALF-emb-micro-1.0",
3
+ "family": "ALF",
4
+ "track": "emb",
5
+ "tier": "micro",
6
+ "version": "1.0",
7
+ "description": "AtomicoLabs model family EN+ES embeddings. Vocab-pruned e5-large-instruct finetune, per-channel int8 ONNX.",
8
+ "files": {
9
+ "model": "model.onnx",
10
+ "tokenizer": "tokenizer.json",
11
+ "keep_ids": "keep_ids.npy",
12
+ "remap": "remap.py"
13
+ },
14
+ "format": "onnx-int8-dynamic-per-channel",
15
+ "size_bytes": 371768932,
16
+ "params": 369999872,
17
+ "vocab_size": 64562,
18
+ "dim": 1024,
19
+ "max_length": 512,
20
+ "pooling": "mean",
21
+ "normalize": true,
22
+ "query_prefix": "Instruct: Given a web search query, retrieve relevant passages that answer the query\nQuery: ",
23
+ "doc_prefix": "",
24
+ "inputs": ["input_ids", "attention_mask"],
25
+ "output": "embedding",
26
+ "base": "intfloat/multilingual-e5-large-instruct",
27
+ "finetune": "e5l-560",
28
+ "scores": {
29
+ "bar": {"name": "openai-text-embedding-3-small", "composite": 80.08, "en": 59.74, "es": 79.52, "sts": 88.66, "domain": 92.39},
30
+ "fp32": {"composite": 80.65, "en": 58.56, "es": 78.63, "sts": 88.97, "domain": 96.45},
31
+ "int8": {"composite": 79.99, "en": 57.25, "es": 77.80, "sts": 89.07, "domain": 95.85, "cosine_parity": 0.984}
32
+ }
33
+ }
model.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:82028ab4f0b13aa76a0837e3b15898fbd6061023348a9b0f89b3cc18e77cfa0e
3
+ size 371768932
prune_meta.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "vocab_size": 64562,
3
+ "coverage": 1.0,
4
+ "n_params": 369999872,
5
+ "base": "embeddings/checkpoints/e5l-560/model"
6
+ }
remap.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Pruned-vocab id remap for ALF-emb-micro."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+
8
+ class RemapTokenizer:
9
+ def __init__(self, tok_dir: str | Path, keep_ids: list[int], unk_new: int | None = None):
10
+ from transformers import AutoTokenizer
11
+ import numpy as np
12
+ import torch
13
+
14
+ self.base = AutoTokenizer.from_pretrained(str(tok_dir))
15
+ self.map = {old: new for new, old in enumerate(keep_ids)}
16
+ unk_old = self.base.unk_token_id
17
+ self.unk_new = unk_new if unk_new is not None else self.map.get(unk_old, 0)
18
+ vocab = int(getattr(self.base, "vocab_size", 0) or 0)
19
+ size = max(vocab, max(keep_ids) + 1 if keep_ids else 1)
20
+ lut = np.full(size, self.unk_new, dtype=np.int64)
21
+ for old, new in self.map.items():
22
+ if 0 <= old < size:
23
+ lut[old] = new
24
+ self._lut_np = lut
25
+ self._lut = torch.from_numpy(lut)
26
+
27
+ def __call__(self, texts, **kwargs):
28
+ enc = self.base(texts, **kwargs)
29
+ ids = enc["input_ids"]
30
+ if hasattr(ids, "clamp"):
31
+ lut = self._lut.to(device=ids.device)
32
+ safe = ids.clamp(0, lut.numel() - 1).long()
33
+ enc["input_ids"] = lut[safe].to(dtype=ids.dtype)
34
+ else:
35
+ import numpy as np
36
+
37
+ arr = np.asarray(ids, dtype=np.int64)
38
+ mapped = self._lut_np[np.clip(arr, 0, len(self._lut_np) - 1)]
39
+ tensors = kwargs.get("return_tensors")
40
+ enc["input_ids"] = mapped if tensors in ("np", "pt") or hasattr(ids, "shape") else mapped.tolist()
41
+ return enc
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:57bd17004cf7bbc354c19884c97c0e8a0503d2dcf10dde17d6890fc90adc8cb6
3
+ size 17082833
tokenizer_config.json ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": true,
3
+ "backend": "tokenizers",
4
+ "bos_token": "<s>",
5
+ "clean_up_tokenization_spaces": true,
6
+ "cls_token": "<s>",
7
+ "eos_token": "</s>",
8
+ "is_local": true,
9
+ "local_files_only": false,
10
+ "mask_token": "<mask>",
11
+ "max_length": 512,
12
+ "model_max_length": 512,
13
+ "pad_token": "<pad>",
14
+ "sep_token": "</s>",
15
+ "sp_model_kwargs": {},
16
+ "stride": 0,
17
+ "tokenizer_class": "XLMRobertaTokenizer",
18
+ "truncation_side": "right",
19
+ "truncation_strategy": "longest_first",
20
+ "unk_token": "<unk>"
21
+ }