mlboydaisuke commited on
Commit
1219863
·
verified ·
1 Parent(s): d78cfa2

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +104 -0
README.md ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - executorch
5
+ - xnnpack
6
+ - pte
7
+ - on-device
8
+ - sentence-similarity
9
+ - feature-extraction
10
+ base_model:
11
+ - intfloat/multilingual-e5-base
12
+ ---
13
+ # multilingual-e5-base — ExecuTorch
14
+
15
+ Multilingual sentence embeddings: text in any of about a hundred languages in, one
16
+ 768-dimensional vector out, comparable across languages. For search and retrieval that
17
+ never leaves the device.
18
+
19
+ - **Source**: intfloat/multilingual-e5-base — 278M parameters, 12 XLM-RoBERTa layers,
20
+ 250k vocabulary, 768-dimensional output
21
+ - **License**: MIT
22
+ - **Input**: `input_ids` and `attention_mask`, both `[1, 256]` int64
23
+ - **Output**: `[1, 768]`, mean-pooled over the mask and L2-normalised inside the graph
24
+
25
+ ## Two parts of the recipe, and only one of them is in the graph
26
+
27
+ **The pooling is in.** sentence-transformers keeps it per model, and the four small
28
+ embedding models on this shelf do not agree:
29
+
30
+ | | pooling | normalised |
31
+ |---|---|---|
32
+ | **multilingual-e5-base** | **mean** | **yes** |
33
+ | all-MiniLM-L6-v2 / L12-v2 | mean | yes |
34
+ | bge-small-en-v1.5 | **CLS** | yes |
35
+ | paraphrase-multilingual-L12 | mean | **no** |
36
+
37
+ Read off `modules.json` and `1_Pooling/config.json` rather than assumed from the family
38
+ name — the other multilingual model on this shelf uses the same pooling and does *not*
39
+ normalise.
40
+
41
+ **The prefix is not.** E5 is trained with `"query: "` in front of a search query and
42
+ `"passage: "` in front of a document, and it expects them at inference:
43
+
44
+ ```
45
+ query: query: how do I keep data on the phone?
46
+ passage: passage: On-device inference keeps the data on the phone.
47
+ ```
48
+
49
+ That is text, so it happens before tokenisation and the `.pte` never sees it as anything
50
+ but tokens. Leaving it out does not throw and does not look wrong — it returns a
51
+ plausible vector that retrieves worse. The conversion repo's checker applies it, so the
52
+ numbers below are for the recipe as the model intends it.
53
+
54
+ ## Verification
55
+
56
+ | build | file | size | latency | worst cosine vs eager |
57
+ |---|---|---|---|---|
58
+ | XNNPACK fp32 | `embed_multilingual_e5_base_xnnpack_fp32.pte` | 1110.0 MB | 40.9 ms | 1.000000 |
59
+ | XNNPACK fp16 | `embed_multilingual_e5_base_xnnpack_fp16.pte` | 555.2 MB | 88.6 ms | 0.999999 |
60
+ | Core ML fp32 | `embed_multilingual_e5_base_coreml_all.pte` | 555.4 MB | **6.8 ms** | 0.999988 |
61
+
62
+ Mac arm64, median of 10, one 256-token sequence — a reference point for relative cost,
63
+ not a device number. Eager fp32 on the same input is 32.9 ms. Cosine is measured against
64
+ the model run in eager through its own pooling, over eight sentences.
65
+
66
+ **And that the vectors are useful**, which agreement alone cannot show. A paraphrase
67
+ against an unrelated sentence, and then the same test across languages —
68
+ "機械学習のモデルを端末の上で動かす" against "On-device inference keeps the data on the
69
+ phone":
70
+
71
+ ```
72
+ same language: 0.848 same meaning vs 0.669 unrelated
73
+ across languages: 0.781 same meaning vs 0.701 unrelated
74
+ ```
75
+
76
+ The cross-lingual row is what this model is for, and it is the row the English-only
77
+ models on this shelf fail. Note the scale: E5 puts everything high, so 0.70 for an
78
+ unrelated pair is normal and the **gap** is what carries the signal, not the absolute
79
+ number.
80
+
81
+ ```bash
82
+ python convert/check_embed.py multilingual_e5_base fp32 # or fp16, int8, coreml
83
+ ```
84
+
85
+ ## Not shipped
86
+
87
+ **int8** converts and holds — worst cosine 0.996673, and it still separates the pairs —
88
+ but it comes out at **855.6 MB against fp16's 555.2 MB**. Dynamic int8 quantises the
89
+ linear weights and leaves the token embedding table alone, and with a 250k vocabulary at
90
+ 768 dimensions that table is **768 MB of the 1110 MB model**, 69% of it. Quantising every
91
+ linear saves 254 MB; fp16 halves the table too. This shelf's rule of thumb holds: int8
92
+ beats fp16 only when the embedding table is under a third of the weights, and a
93
+ multilingual vocabulary is never under a third.
94
+
95
+ ## Worth knowing about the speed
96
+
97
+ XNNPACK fp32 is slower than PyTorch eager here (40.9 ms against 32.9), and fp16 is slower
98
+ again while halving the file — XNNPACK has no fp16 kernels for this graph and inserts
99
+ casts instead. Core ML is the one that pays: **6.8 ms**, five times eager, 100% delegated
100
+ in a single subgraph. On iOS take the Core ML build; on Android the choice is fp32 for
101
+ speed or fp16 for half the disk.
102
+
103
+ torch.export -> to_edge_transform_and_lower(partitioner) -> .pte
104
+ (conversion scripts: [executorch-models](https://github.com/john-rocky/executorch-models))