Your Truncated Embedding Vector Is Silently the Wrong Length — Here's the One-Line Fix
Most major embedding APIs — OpenAI's text-embedding-3 family, Gemini's gemini-embedding models, Cohere embed-v4, Nomic Embed v1.5 — are now trained with Matryoshka Representation Learning, which means you can safely shorten an embedding after the fact to save storage and search cost, with only a small, predictable accuracy hit. That's a genuinely useful trick. It's also got a one-line gotcha that's easy to miss the first time, so I added an Embedding Vector Truncator & Renormalizer to Bracketly, my free client-side dev tools site.
Here's the gotcha: embeddings from these APIs are L2-normalized to unit length by default — that's what makes cosine similarity and dot-product search interchangeable, and it's part of why the math downstream (nearest-neighbor search, reranking, thresholding) behaves predictably. Slice off the last N dimensions of a unit vector and the result is not unit length anymore — you've changed its magnitude without touching its direction. If you then compare that truncated vector against others with cosine similarity or dot product without renormalizing first, you get numbers that are subtly, silently wrong. Nothing throws an error. Your search results just get quietly worse, and it's the kind of bug that's genuinely hard to notice unless you're specifically looking for it, because the vectors still look like embeddings — same shape, plausible-looking floats.
Providers that expose a native truncation parameter (OpenAI's dimensions argument, for instance) handle this for you automatically. The gap is when you're truncating a vector yourself — a value you already stored at full size and want to shrink for a cheaper index, or a self-hosted Matryoshka-trained model where you're slicing the array by hand. In that case the fix really is one line: take the L2 norm of the truncated slice (square root of the sum of its squared values) and divide every value by it. The tool does exactly that — paste a vector, pick a target dimension, get back the renormalized result plus its norm before and after, so you can confirm it's actually unit length again.
I also added an optional second-vector field so you can paste a comparison vector and see cosine similarity computed two ways: on the original full-length vectors, and on both truncated-and-renormalized. The two numbers won't be identical — you did genuinely discard information, so a small shift is the expected accuracy/size tradeoff Matryoshka truncation is built around — but seeing the actual delta for your own real vectors is a lot more convincing than trusting a blog post's abstract claim that "it should still work reasonably well." Everything runs as plain array arithmetic in your browser tab; nothing you paste is sent anywhere.
Top comments (0)