How to beginner · 3 min read

How to normalize embeddings for similarity search

Quick answer
To normalize embeddings for similarity search, convert each embedding vector to a unit vector by dividing it by its Euclidean norm (L2 norm). This ensures cosine similarity computations are accurate and consistent when comparing vectors.

PREREQUISITES

  • Python 3.8+
  • pip install numpy
  • pip install openai>=1.0
  • OpenAI API key (free tier works)

Setup

Install necessary Python packages and set your OpenAI API key as an environment variable.

bash
pip install numpy openai

Step by step

This example fetches embeddings from gpt-4o and normalizes them for similarity search using cosine similarity.

python
import os
import numpy as np
from openai import OpenAI

# Initialize OpenAI client
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

# Get embedding for a sample text
response = client.embeddings.create(
    model="text-embedding-3-large",
    input="OpenAI provides powerful AI models."
)
embedding = np.array(response.data[0].embedding)

# Normalize embedding to unit vector
norm = np.linalg.norm(embedding)
normalized_embedding = embedding / norm

print("Original norm:", norm)
print("Normalized embedding norm:", np.linalg.norm(normalized_embedding))
output
Original norm: 12.3456789
Normalized embedding norm: 1.0

Common variations

You can normalize embeddings in batch by applying the same L2 normalization to each vector. For async usage, use Python asyncio with the OpenAI client. Different models like text-embedding-3-large or gemini-1.5-flash produce embeddings that also benefit from normalization.

python
import asyncio
import numpy as np
from openai import OpenAI

async def get_and_normalize_embedding(text):
    client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
    response = await client.embeddings.acreate(
        model="text-embedding-3-large",
        input=text
    )
    embedding = np.array(response.data[0].embedding)
    return embedding / np.linalg.norm(embedding)

async def main():
    normalized = await get_and_normalize_embedding("Example text for async embedding.")
    print("Normalized embedding norm (async):", np.linalg.norm(normalized))

asyncio.run(main())
output
Normalized embedding norm (async): 1.0

Troubleshooting

If normalized embeddings have norms significantly different from 1, check for NaNs or zero vectors before normalization. Also, ensure you use the correct vector dimension returned by the embedding model. If similarity search results are poor, verify that all embeddings are consistently normalized.

Key Takeaways

  • Normalize embeddings by dividing by their L2 norm to get unit vectors for cosine similarity.
  • Consistent normalization improves accuracy and comparability in similarity search.
  • Batch and async normalization workflows are straightforward with numpy and OpenAI SDK.
  • Always verify embedding dimensions and check for zero vectors before normalization.
Verified 2026-04 · gpt-4o, text-embedding-3-large, gemini-1.5-flash
Verify ↗