Views
No views yet
BAAI/bge-small-en-v1.5 (BERT encoder, 33M params)last_hidden_state), then L2-normalizeBAAI/bge-small-en-v1.5 from Hugging Face — the repo ships an onnx/model.onnx (opset 11) exported from PyTorch.MNNConvert -f ONNX --fp16 against that ONNX, which fused 25 LayerNorms and produced encoder.mnn.tokenizer.json, tokenizer_config.json, special_tokens_map.json, vocab.txt) from the source repo.1MNNConvert -f ONNX \
2 --modelFile BAAI/bge-small-en-v1.5/onnx/model.onnx \
3 --MNNModel encoder.mnn \
4 --fp16 --bizCode bge-smallllama.cpp llama-embedding against the standard BAAI bge-small-en-v1.5.Q*_K_M.gguf. Both models use CLS pooling + L2 normalization and the BGE query prefix "Represent this sentence for searching relevant passages: ".| Metric | GGUF (baseline) | MNN fp16 | Ratio |
|---|---|---|---|
| Recall@1 | 70.0% | 70.0% | 100% |
| Recall@3 | 75.0% | 75.0% | 100% |
| Recall@5 | 85.0% | 85.0% | 100% |
| Recall@10 | 95.0% | 95.0% | 100% |
| MRR | 0.7659 | 0.7653 | 99.9% |
| Mean gold-chunk cos sim | 0.7646 | 0.7654 | — |
sentence-transformers on sanity checks). There is no measurable retrieval regression.input_ids: shape (batch, seq)attention_mask: shape (batch, seq)token_type_ids: shape (batch, seq), all zeros for single-text embeddinglast_hidden_state: shape (batch, seq, 384) — Caffe/NCHW layout (use Tensor_DimensionType_Caffe when copying to host).1import MNN, numpy as np
2from transformers import AutoTokenizer
3
4tok = AutoTokenizer.from_pretrained("darkmaniac7/bge-small-en-MNN")
5interp = MNN.Interpreter("encoder.mnn")
6sess = interp.createSession({"backend": "CPU", "numThread": 4})
7in_ids = interp.getSessionInput(sess, "input_ids")
8in_mask = interp.getSessionInput(sess, "attention_mask")
9in_tok = interp.getSessionInput(sess, "token_type_ids")
10out_t = interp.getSessionOutput(sess, "last_hidden_state")
11
12def embed(text):
13 enc = tok(text, padding=False, truncation=True, max_length=512, return_tensors="np")
14 seq = enc["input_ids"].shape[1]
15 for t, arr in ((in_ids, enc["input_ids"]), (in_mask, enc["attention_mask"]), (in_tok, enc["token_type_ids"])):
16 interp.resizeTensor(t, (1, seq))
17 interp.resizeSession(sess)
18 for t, arr in ((in_ids, enc["input_ids"]), (in_mask, enc["attention_mask"]), (in_tok, enc["token_type_ids"])):
19 tmp = MNN.Tensor((1, seq), MNN.Halide_Type_Int,
20 arr.astype(np.int32), MNN.Tensor_DimensionType_Tensorflow)
21 t.copyFrom(tmp)
22 interp.runSession(sess)
23 shape = out_t.getShape()
24 host = MNN.Tensor(shape, MNN.Halide_Type_Float,
25 np.zeros(tuple(shape), dtype=np.float32),
26 MNN.Tensor_DimensionType_Caffe)
27 out_t.copyToHostTensor(host)
28 arr = np.array(host.getData(), dtype=np.float32).reshape(tuple(shape))
29 cls = arr[0, 0, :]
30 return cls / (np.linalg.norm(cls) + 1e-12)
31
32# For asymmetric retrieval, prefix queries per BGE convention:
33qvec = embed("Represent this sentence for searching relevant passages: " + "your query here")
34pvec = embed("passage text here")
35score = float(np.dot(qvec, pvec)) # cosine (both are unit-norm)