Late interaction normalization produces nonfinite float16 embeddings
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 3/5
- Estimated time
- Half a day
- Newbie friendliness
- 70/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- numpy, python
- Domain
- machine-learning
Research direction
Start with _post_process_onnx_output in the Colbert and LateOn late-interaction postprocessors, which compute L2 norms in float16. Run the reproduction from the issue, which builds an OnnxOutputContext directly, and check that the output has infinities or NaNs. Read the shared normalization helper that the issue says already handles float16 safely, and reuse its approach in both postprocessors. Done when float16 output keeps its dtype, the norms come out near [1, 0, 1], and existing padding, punctuation and query tests still pass.
Written by the indexing model from the issue text.
Description
Colbert._post_process_onnx_output and LateOn._post_process_onnx_output compute L2 norms in float16 when an ONNX model returns float16 embeddings. Small finite embeddings underflow to a zero norm, producing infinities. Zero vectors produce NaNs because the 1e-12 denominator floor also becomes zero in float16. Larger finite values can overflow the norm and become zero vectors.
I reproduced this on main at de502ca8 with NumPy 2.5.3 on Linux. The shared normalization helper already handles float16 safely, but these two postprocessors use their own normalization.
This isolates postprocessing without loading model weights.
import numpy as np
from fastembed.common.onnx_model import OnnxOutputContext
from fastembed.late_interaction.colbert import Colbert
model = object.__new__(Colbert)
model._ensure_tokenizer = lambda: None
model.skip_list = set()
model.pad_token_id = 0
vectors = np.full((1, 3, 128), 1e-5, dtype=np.float16)
vectors[0, 1] = 0
vectors[0, 2] = 100
context = OnnxOutputContext(
model_output=vectors,
attention_mask=np.ones((1, 3), dtype=np.int64),
input_ids=np.array([[1, 2, 3]], dtype=np.int64),
)
result = next(iter(model._post_process_onnx_output(context)))
print(np.isfinite(result).all())
print(np.linalg.norm(result.astype(np.float32), axis=1))
The output contains infinities and NaNs, and the large vector has norm zero. Expected output is finite with norms near [1, 0, 1]. The same reproduction works with LateOn.
Float16 output should retain its dtype and be normalized using enough precision to avoid these errors. Existing padding, punctuation filtering and query behavior should be preserved.
- Dominant language
- Python
- Stars
- 3.2k
- Forks
- 276
- Avg merge
- 13h 15m
- Merged PRs (30d)
- 57
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from qdrant/fastembed
-
Non-positive worker counts wait for results without starting workersPossibly taken @IlyaKhalafi claimed this 3 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
Worker crashes go unnoticed while waiting for a resultPossibly taken @IlyaKhalafi claimed this 2 days ago. Open
Difficulty 3/5 Half a day Newbie friendliness 25/100
Maintainers usually reply within 1 day
-
Failed worker pool construction raises an extra destructor exceptionPossibly taken @IlyaKhalafi claimed this 3 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 25/100
Maintainers usually reply within 1 day
-
[Bug]: rerank_pairs raises TypeError when pairs are passed as a tuple of pairsPossibly taken @michaelkillgta claimed this 8 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 22/100
Maintainers usually reply within 1 day
-
[Feature]: Support huggingface-hub 2.0Possibly taken @joein claimed this 18 days ago. Open
Difficulty 3/5 1-2 days Newbie friendliness 65/100
qdrant/fastembed#742 · 1 assignee ·
Maintainers usually reply within 1 day
All issues in qdrant/fastembed
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
infrastructure qa
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
khuisman/mcp-gee-sweet#1068 ·
Maintainers usually reply within 1 day
-
area:ecosystem documentation
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Chelis-Lang/chelis#3866 ·
Maintainers usually reply within 1 day
-
`lvm_compact` has no self-hosted twin, and `docs/158` §5 says every language-face component mustOpenbug sev-3 vm
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
-
issue: Picking a prompt from the / menu in a channel inserts a command chip instead of the promptOpenbug confirmed issue
Difficulty 2/5 Half a day Newbie friendliness 78/100
open-webui/open-webui#32712 · 2 comments ·
Maintainers usually reply within 1 day