🐦 Colibri — Brazilian-Portuguese Embeddings
A tiny embedding model that punches far above its weight.
Named after the colibri (hummingbird) — the smallest bird, yet it out-flies much larger ones.
~157M params · 768-dim · plain SentenceTransformer (no adapters) · runs on a cheap CPU VPS
Colibri is a compact Brazilian-Portuguese text-embedding model derived from
google/embeddinggemma-300m. Despite being half the size,
it matches or beats much larger multilingual embedders on MTEB-BR — including 7B and 27B models — and is
designed small on purpose so it runs comfortably on a simple CPU VPS, with no GPU required.
Use cases: Portuguese semantic search, retrieval-augmented generation (RAG), retrieval, reranking, clustering, semantic textual similarity (STS) and classification — for Brazilian-Portuguese text across legal, tax, financial, medical, academic and general domains.
✨ Highlights
- 🏆 Beats bigger models on MTEB-BR — including
embeddinggemma-300m, and 7B / 27B multilingual embedders. - 🪶 Half the footprint of
embeddinggemma-300m: ~607 MB vs ~1.2 GB; 229 MB of RAM as GGUF Q8_0. - 💻 Runs on a $-few/month CPU VPS — benchmarked on 4 vCPU / 16 GB (no GPU).
- 🔌 Plain
SentenceTransformer— no adapters, no LoRA at inference. Drop-in. - 📐 Matryoshka dimensions (768 / 512 / 256 / 128) + an fp16 branch + a fast ONNX path + GGUF for llama.cpp.
🥇 Quality — MTEB-BR
Evaluated on MTEB-BR (22 native Brazilian-Portuguese tasks: retrieval, reranking, STS, classification, clustering, pair-classification). Score = mean over the 22 tasks.
| Model | Params | MTEB-BR |
|---|---|---|
| 🐦 Colibri (this model) | ~157M | 0.6501 |
| google/embeddinggemma-300m | 300M | 0.6490 |
| Linq-AI-Research/Linq-Embed-Mistral | 7B | 0.6473 |
| openai/text-embedding-3-large | – | 0.6449 |
| intfloat/multilingual-e5-large-instruct | 560M | 0.6409 |
| Salesforce/SFR-Embedding-2_R | 7B | 0.6397 |
| Alibaba-NLP/gte-Qwen2-7B-instruct | 7B | 0.6392 |
| microsoft/harrier-oss-v1-27b | 27B | 0.6390 |
| BAAI/bge-m3 | 568M | 0.6157 |
| intfloat/multilingual-e5-large | 560M | 0.5909 |
A ~157M-parameter model outperforming 7B–27B multilingual embedders on Brazilian Portuguese.
Size ↔ quality frontier. Colibri sits on the open-model Pareto frontier for MTEB-BR — it dominates its own
base embeddinggemma-300m (half the size, higher score) and matches models up to ~10× larger:
💻 Built for a simple CPU VPS
Colibri was designed to be small enough for cheap, GPU-less hosting. Measured on a
Verda CPU.4V.16G (4 vCPU, 16 GB RAM), a typical small VPS, encoding
Brazilian-Portuguese sentences with 4 threads:
| Runtime | Model size | Peak RAM | Latency (p50) | Throughput | Cosine vs fp32 |
|---|---|---|---|---|---|
PyTorch fp32 (SentenceTransformer) |
607 MB | 1,035 MB | 77 ms | 33 sent/s | 1 (reference) |
ONNX (backend="onnx") |
604 MB | 1,438 MB | 32 ms | 44 sent/s | 1.0000 |
| ONNX int8 (dynamic quantization) | 153 MB | 888 MB | 22 ms | 71 sent/s | 0.971 |
| GGUF Q8_0 (llama.cpp, GGUF repo) | 169 MB | 229 MB | 35 ms | 31 sent/s | 0.9996 |
| GGUF Q4_K_M | 111 MB | 217 MB | 31 ms | 38 sent/s | 0.986 |
Takeaways
- Least RAM: GGUF Q8_0 in llama.cpp, at 229 MB, a quarter of PyTorch, with the same embeddings (cosine 0.9996). This is the one to run next to a local LLM.
- Fastest: ONNX. It takes 32 ms against 77 ms for PyTorch, but uses more RAM: the ONNX Runtime session holds
its own fp32 weights (about 885 MB on its own), and
sentence-transformersstill loads PyTorch (about 480 MB). - ONNX int8 is faster and lighter still, but its embeddings drift (cosine 0.97), so GGUF Q8_0 is the better small option.
- Earlier versions of this card listed 2.9 GB for ONNX. That peak came from exporting the model to ONNX at load
time, since the repo had no ONNX file then.
onnx/model.onnxnow ships with the model, so nothing is exported.
Benchmark hardware: Verda CPU.4V.16G. Latency is one sentence;
throughput is 512 sentences in batches of 32. Cosine is against PyTorch fp32 on 30 sentences. Numbers are
indicative single-node CPU measurements.
🚀 Usage
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("tardellirs/colibri-embed-ptbr")
query = "Como declarar imposto de renda de aluguel?"
docs = [
"Rendimentos de aluguel devem ser informados na ficha de Rendimentos Tributáveis...",
"O Pix é um meio de pagamento instantâneo criado pelo Banco Central...",
]
q = model.encode(query, prompt_name="query") # "task: search result | query: "
d = model.encode(docs, prompt_name="document") # "title: none | text: "
print(model.similarity(q, d))
Faster on CPU — ONNX backend (about 2× faster, no other code changes):
model = SentenceTransformer("tardellirs/colibri-embed-ptbr", backend="onnx")
Least RAM — GGUF for llama.cpp (229 MB): see
tardellirs/colibri-embed-ptbr-GGUF.
Prompts follow EmbeddingGemma conventions (query / document / classification / clustering / similarity).
🎛️ Variants: precision & dimension
Precision — a half-precision branch (same quality, half the size; best for GPU/storage — on CPU it's not faster):
| Variant | Load | Size |
|---|---|---|
| fp32 (default) | SentenceTransformer("tardellirs/colibri-embed-ptbr") |
~607 MB |
| fp16 | SentenceTransformer("tardellirs/colibri-embed-ptbr", revision="fp16") |
~304 MB |
Matryoshka dimensions — truncate the 768-dim output to 512 / 256 / 128 for smaller vectors (cheaper index, faster search) with a graceful quality trade-off:
model = SentenceTransformer("tardellirs/colibri-embed-ptbr", truncate_dim=256)
(The MTEB-BR score above is for the full 768-dim embeddings.)
🔧 How it was built
A three-stage pipeline: vocabulary trimming → knowledge distillation → model soup.
1. Vocabulary trimming. tardellirs/embeddinggemma-pt-br
trims embeddinggemma-300m's 262k multilingual vocabulary down to a ~64k Brazilian-Portuguese vocabulary,
cutting the model from ~300M to ~157M effective parameters with negligible quality loss.
Code: github.com/tardellirs/embedding-vocab-trimmer.
2. Knowledge distillation. Relational (similarity-preserving) KD from two complementary teachers —
Qwen/Qwen3-Embedding-4B (strong at clustering) and
Qwen/Qwen3-Embedding-8B (strong at retrieval / reranking). The
student learns to reproduce the average of the two teachers' pairwise-similarity matrices (dimension-agnostic;
preserves STS). Trained on a diverse ~100k-passage corpus of native Brazilian Portuguese spanning legal, tax,
financial, medical, academic, technical, encyclopedic and general-web domains:
| Domain | Sources |
|---|---|
| General web | HuggingFaceFW/fineweb-2 (pt) |
| Legal | jurisprudencias_stj, leis_ordinarias_1988_2024 |
| Tax | codigo_tributario |
| Financial regulation | bbrc, bacen2024 |
| Academic | Brazilian scientific abstracts, corpus-carolina |
| Medical | Brazilian clinical / health texts |
| Technical | Stack Overflow em Português |
| Encyclopedic | Wikipedia-PT |
Evaluation integrity: the model is trained only on training / non-evaluation splits — every MTEB-BR evaluation example is held out, so the scores reflect generalization, not memorization.
3. Model soup + merge. Distillation checkpoints were combined (model soup / weight averaging) and linearly merged with the trimmed base, with the mixing weight chosen on held-out validation. Both operations yield ordinary weights, so the published model is a single standalone encoder.
📝 Updates
- 2026-11-09: with
transformers4.x the tokenizer left out the final<eos>thattransformers5.x (which the model was saved with) adds, and the embeddings came out different (cosine ~0.87 to the intended ones).tokenizer_config.jsonnow setsadd_bos_token/add_eos_token, so both give the same tokens. The tokenizer also dropped 6,246 unused added tokens with ids past the embedding matrix; no text tokenizes differently. Addedonnx/model.onnxand a GGUF build.
🔗 Links
- Base: google/embeddinggemma-300m · Trimmed base: tardellirs/embeddinggemma-pt-br
- Trimming code: github.com/tardellirs/embedding-vocab-trimmer
- Distillation teachers: Qwen/Qwen3-Embedding-4B · Qwen/Qwen3-Embedding-8B
- Benchmark: MTEB-BR · CPU benchmark hardware: Verda
📚 Citation
If you use Colibri, please cite:
@software{colibri_embed_ptbr,
title = {Colibri: a compact Brazilian-Portuguese text-embedding model},
author = {Stekel, Tardelli R. C.},
year = {2026},
url = {https://huggingface.co/tardellirs/colibri-embed-ptbr},
doi = {10.57967/hf/11507},
publisher = {Hugging Face}
}
🙏 Acknowledgments
We gratefully acknowledge Verda for the GPU compute credits that supported this work.
Built with vocabulary trimming · relational knowledge distillation · model soup.