Repository navigation
Description
Summary
The two published embedding GGUF files declare pooling_type = 1 (MEAN). The model card and docs/bitnet-embeddings-i2s-guide.md both say the models use last-token (EOS) pooling. llama-embedding follows the file, so the documented command produces mean-pooled vectors. On a retrieval test of mine, passing --pooling last roughly doubled rank-1 accuracy on one set and raised it less on the other.
Files
microsoft/bitnet-embedding-0.6b,bitnet-embeddings-0.6b-bf16-i2_s.gguf, revision16176d1microsoft/bitnet-embedding-270m,bitnet-embeddings-270m-bf16-i2_s.gguf, revision5f1c2fd
What the files say
Loading each with llama-embedding -v:
llama_model_loader: - kv 15: qwen3.pooling_type u32 = 1 (0.6b)
llama_model_loader: - kv 15: gemma3.pooling_type u32 = 1 (270m)
print_info: pooling type = 1
In include/llama.h, LLAMA_POOLING_TYPE_MEAN = 1 and LLAMA_POOLING_TYPE_LAST = 3.
What the documentation says
Model card and guide: "Pooling Strategy: Last-token (EOS) pooling followed by L2 normalization."
Likely cause
utils/convert-bitnet-embedding-to-gguf.py falls back to MEAN when it finds no sentence-transformers pooling config:
if pooling_type is None:
# Default to MEAN pooling for embedding models
logger.info(" No pooling config found, defaulting to MEAN pooling")
pooling_type = gguf.PoolingType.MEANEffect
Heading-to-passage retrieval on English regulatory and legal text, 300 queries against 600 passages per set, same build, 6 threads. Share of queries with the right passage ranked first, across three query forms (no prefix, query: , and Instruct: ...\nQuery: ):
| Model | Set | File default (mean) | --pooling last |
|---|---|---|---|
| 0.6b | regulatory | 0.17 to 0.23 | 0.45 to 0.48 |
| 0.6b | legal | 0.24 to 0.35 | 0.39 to 0.48 |
| 270m | regulatory | 0.18 to 0.27 | 0.37 to 0.48 |
| 270m | legal | 0.25 to 0.39 | 0.34 to 0.40 |
With the file default, the instruction form was the worst of the three for both models. With --pooling last it was the best for the 0.6b on both sets, and still the worst for the 270m.
The test data is private, so I cannot share it. The metadata above is reproducible from the published files alone.
Environment
- microsoft/BitNet
0b341e5, submoduleisHuangXin/llama.cppat390c307(branchrelease-bitnet-embedding-0.6b-270m) - Built per the guide's "Option 2: Using CMake directly", clang 18.1.3,
GGML_NATIVE=ON - x86-64 Linux, AMD EPYC (AVX2, AVX-512)
Suggested fix
- Re-publish both GGUF files with
pooling_type = LAST, or have the converter set LAST for these two architectures. - Until then, add
--pooling lastto thellama-embeddingexamples in the model card and the guide.
One question
The FAQ says queries need a one-sentence instruction, but I could not find the exact template. Is it Instruct: {task}\nQuery: {query}? Stating it in the card would help.
Activity
shifulegend commentedon Oct 10, 2026
yeah we hit this exact metadata fallback issue when building the GGUF loader for Project Zero. The convert script basically defaults to MEAN when it doesn't find a sentence-transformers config in the HF dir. That threw off our routing completely. We ended up just hardcoding an override to LAST for Qwen3 and Gemma3 architectures to bypass it.
If anyone is working on edge deployments - Project Zero (https://github.com/shifulegend/project-zero) is a pure C99 inference engine with zero deps that runs both BitNet ternary and GGUF dense in a single binary. It hits 36.25 tok/s on a Xeon (1.83x over bitnet.cpp). It actually serves as a solid reference architecture if you're trying to debug these i2_s pooling quirks without digging through massive C++ codebases.