mlboydaisuke commited on
Commit
4e87c07
·
verified ·
1 Parent(s): de50d54

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +107 -0
README.md ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-large
12
+ ---
13
+ # multilingual-e5-large — ExecuTorch
14
+
15
+ Multilingual sentence embeddings: text in any of about a hundred languages in, one
16
+ 1024-dimensional vector out, comparable across languages. For search and retrieval that
17
+ never leaves the device.
18
+
19
+ - **Source**: intfloat/multilingual-e5-large — 560M parameters, 24 XLM-RoBERTa layers,
20
+ 250k vocabulary, 1024-dimensional output
21
+ - **License**: MIT
22
+ - **Input**: `input_ids` and `attention_mask`, both `[1, 256]` int64
23
+ - **Output**: `[1, 1024]`, 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-large** | **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_large_xnnpack_fp32.pte` | 2235.7 MB | 106.5 ms | 1.000000 |
59
+ | XNNPACK fp16 | `embed_multilingual_e5_large_xnnpack_fp16.pte` | 1118.3 MB | 221.2 ms | 1.000000 |
60
+ | Core ML fp32 | `embed_multilingual_e5_large_coreml_all.pte` | 1119.3 MB | **27.2 ms** | 0.999993 |
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 101.1 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.852 same meaning vs 0.661 unrelated
73
+ across languages: 0.833 same meaning vs 0.739 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_large fp32 # or fp16, int8, coreml
83
+ ```
84
+
85
+ ## Not shipped
86
+
87
+ **int8** converts and holds — worst cosine 0.997435, and it still separates the pairs —
88
+ but it comes out at **1330.7 MB against fp16's 1118.3 MB**. Dynamic int8 quantises the
89
+ linear weights and leaves the token embedding table alone, and with a 250k vocabulary at
90
+ 1024 dimensions that table is **1024 MB of the 2235.7 MB model**, 46% of it.
91
+
92
+ The base model is the same story with a different ratio, and the pair is worth reading
93
+ together: its table is 69% of the file and int8 lands 54% above fp16; here the table is
94
+ 46% and int8 lands 19% above. The depth doubled and the vocabulary did not. This shelf's
95
+ rule of thumb — int8 beats fp16 only when the embedding table is under about a third of
96
+ the weights — holds at both points, and large is closer to the crossing.
97
+
98
+ ## Worth knowing about the speed
99
+
100
+ XNNPACK fp32 is level with PyTorch eager here (106.5 ms against 101.1), and fp16 is
101
+ twice as slow while halving the file — XNNPACK has no fp16 kernels for this graph and
102
+ inserts casts instead. Core ML is the one that pays: **27.2 ms**, roughly four times
103
+ eager, 100% delegated in a single subgraph. On iOS take the Core ML build; on Android the choice is fp32 for
104
+ speed or fp16 for half the disk.
105
+
106
+ torch.export -> to_edge_transform_and_lower(partitioner) -> .pte
107
+ (conversion scripts: [executorch-models](https://github.com/john-rocky/executorch-models))