ONNX and QHexRT embedding providers ignore normalize=false

Author: sanchitmonga22Created Sep 11, 2026Updated Sep 11, 2026
LabelsbugP2

Follow-up from #841 by @ayaangazali -- thanks again for that PR!

What

Now that the commons proto adapter forwards EmbeddingsOptions.normalize=false as RAC_EMBEDDINGS_NORMALIZE_NONE, the llamacpp and MLX engines honour it -- but the ONNX and QHexRT embedding providers don't. engines/onnx/onnx_embedding_provider.cpp:626 and :788 call normalize_vector(pooled) unconditionally on both the single and batch paths, and qhexrt_embeddings_ops.cpp:7/:44 return the plan's always-L2-normalized vector regardless of the caller's request.

Why it matters

A caller asking for a raw pooled vector gets one only when the model happens to run on llamacpp or MLX -- the same API call returns different semantics depending on which engine backs the loaded model. The Electron feature test (bindings/electron/test/feature/embeddings.feature.test.ts:141-166) currently asserts unit-length output for normalize=NONE against the ONNX MiniLM model, which is itself evidence of the gap.

Suggested approach

  • In onnx_embedding_provider.cpp, skip normalize_vector(pooled) on both the single and batch paths when options->normalize == RAC_EMBEDDINGS_NORMALIZE_NONE.
  • In QHexRT, either honour the flag the same way or explicitly document/reject normalize=false for that backend.
  • Flip the Electron feature test's assertion once ONNX honours the flag.

Done when

  • ONNX and QHexRT embedding providers return raw pooled vectors when normalize=false is requested.
  • The Electron feature test reflects the corrected behavior.

Not blocking #841. @ayaangazali, you know this code well now -- you're welcome to take this one if you're interested.

Opened with help from Claude Code and Codex.

Reviewed with help from Claude Code and Codex.

Source: RunanywhereAI/runanywhere-sdks