Downloads · 30 days
110
14% of all-time downloads
Uncino/bge-m3-multivector-gguf
bge-m3-multivector-gguf is a machine learning model from Uncino. Use it for the machine learning task on the model card, and read the license before you ship it in a product. It is set up for sentence-transformers. The card lists the license as mit.
This repository provides pre-converted GGUF files for the BAAI BGE-M3 embedding model, enhanced to output all three embedding types from a single inference call:
Downloads · 30 days
110
14% of all-time downloads
All-time downloads
774
Public
Repo size
1.8 GB
Likes
1
Public
Click a slice to open those files.
.gguf1.8 GB · 100%
From the Hugging Face model README
This repository provides pre-converted GGUF files for the BAAI BGE-M3 embedding model, enhanced to output all three embedding types from a single inference call:
| Head | Output | Shape | Use Case |
|---|---|---|---|
| Dense | CLS pooling → L2 normalization | float[1024] | Semantic similarity (cosine) |
| Sparse | linear → ReLU → log(1+x) per token | [token_id, weight] pairs | Lexical / hybrid search |
| ColBERT | linear → L2 norm per token | n_tokens × float[1024] | Token-level late interaction |
A single llama_decode() computes all three. No separate models, no external BM25.
Unlike the standard BGE-M3 GGUF (which only preserves the dense head), these files
contain the full cls.sparse and cls.colbert weights extracted from the original
sentence-transformers checkpoint.
| File | Quantization | Size | Heads |
|---|---|---|---|
bge-m3-multivector-q8.gguf | Q8_0 | ~600 MB | Dense + Sparse + ColBERT |
bge-m3-multivector-f16.gguf | F16 | ~1.1 GB | Dense + Sparse + ColBERT |
Q8_0 is recommended for production — identical quality, half the size.
Use the companion llama.cpp-mv fork, which supports all three heads natively. Start the server:
llama-server --model bge-m3-multivector-q8.gguf \
--pooling cls --no-mmap --embedding \
--host 0.0.0.0 --port 8080 \
-c 8192 -b 8192 -ub 8192 -np 1 --fit off \
-ngl 99
Companion fork with inference code: [llama.cpp-mv](https://github.com/iz0eyj/llama.cpp-mv)
Default call returns dense + sparse:
curl -X POST http://127.0.0.1:8080/v1/embeddings \
-H "Content-Type: application/json" \
-d '{"input": "Samarcanda è una città meravigliosa"}'
Add ?colbert=true (or "colbert": true in the JSON body) for all three:
curl -X POST "http://127.0.0.1:8080/v1/embeddings?colbert=true" \
-H "Content-Type: application/json" \
-d '{"input": "Samarcanda è una città meravigliosa"}'
{
"data": [{
"embedding": [0.001, -0.023, ...], // dense: 1024 floats
"sparse_embedding": [ // sparse: [token_id, weight] pairs
[0, 0.116],
[121283, 0.154],
[2, 0.095]
],
"colbert_embedding": [ // colbert: n_tokens × 1024
[-0.768, -0.048, ...],
[ 0.312, 1.205, ...],
[-0.015, -0.823, ...]
],
"index": 0,
"object": "embedding"
}],
"model": "bge-m3-multivector-q8.gguf",
"usage": {"prompt_tokens": 5, "total_tokens": 5}
}
colbert_embedding is only present when ?colbert=true is setimport numpy as np
def colbert_score(vecs_a, vecs_b):
"""MaxSim per token, then average."""
sim = np.dot(vecs_a, vecs_b.T) # [n_a, n_b]
return np.mean(np.max(sim, axis=1))
# Example: "Samarcanda è bella" vs "Samarcanda è meravigliosa"
# score ≈ 1010 (similar) vs ≈ 330 (different topic)
The standard llama.cpp converter strips tensors it doesn't recognize. BGE-M3's
sparse and colbert heads (sparse_linear.pt, colbert_linear.pt) are stored
separately from the main model checkpoint and were silently skipped.
Our converter patches (in llama.cpp-mv):
gguf-py/gguf/constants.py — Added CLS_SPARSE and CLS_COLBERT tensor typesgguf-py/gguf/tensor_mapping.py — Mapped sparse_linear → cls.sparse, colbert_linear → cls.colbertconversion/bert.py — Load .pt files from model directory via generate_extra_tensors()Command:
python convert_hf_to_gguf.py BAAI/bge-m3 --outtype q8_0 --outfile bge-m3-multivector-q8.gguf
The companion C++ fork adds three separate output paths from the same hidden states:
Transformer (24 layers XLM-RoBERTa)
│
▼ hidden_states [1024, n_tokens]
│
├── [CLS] ──► L2 normalize ──► dense [1024]
├── sparse_linear → ReLU → log1p ──► sparse [n_tokens] scalars
└── colbert_linear → L2 norm ──► colbert [n_tokens × 1024]
Key design decisions:
log1p for sparse is applied on CPU after GPU transfer (avoids new GGML op)ggml_norm for per-token L2 normalizationCompanion fork with inference code: llama.cpp-mv `) or CUDA.
MIT — matches both BAAI/bge-m3 and llama.cpp.