RAG

Vector Embeddings👨‍💻

Vector embeddings are the foundation of modern semantic search and RAG systems. An embedding model takes a piece of text -- a sentence, a paragraph, a document chunk -- and compresses its meaning into a fixed-length array of floating-point numbers. Two texts with similar meanings produce vectors that are close together in this high-dimensional space, even if they share no words in common.

This is what makes embeddings transformative: they capture semantic similarity, not just lexical overlap. The query 'how to fix a broken pipe' and the document 'repairing plumbing leaks' have zero words in common, but their embeddings will be near each other because the meaning overlaps. Traditional keyword search would miss this match entirely.

Choosing the right embedding model, understanding similarity metrics, and knowing how dimensionality affects performance are the decisions that determine whether your retrieval pipeline returns relevant results or noise. This guide covers the mechanics, the models, and the practical code to embed text and measure similarity.

Key Takeaways

  • 1An embedding is a dense vector (array of floats) that encodes the semantic meaning of text. Similar texts produce vectors that are geometrically close in the embedding space, enabling similarity search.
  • 2Embedding models are trained on massive datasets of text pairs (queries and relevant passages) so they learn that semantically equivalent phrases should map to nearby points, regardless of surface-level wording.
  • 3Cosine similarity is the standard metric for comparing embeddings. It measures the angle between two vectors and ranges from -1 (opposite) to 1 (identical). Dot product and Euclidean distance are alternatives with different trade-offs.
  • 4Embedding dimensions (128 to 3072) trade off between information capacity and computational cost. Higher dimensions capture more nuance but require more storage, memory, and slower similarity search.
  • 5Open-source models like sentence-transformers (all-MiniLM-L6-v2, nomic-embed-text) run locally without API costs. API-based models (OpenAI text-embedding-3-small, Cohere embed-v4) offer higher quality at the cost of latency and per-token pricing.
  • 6Embeddings are static once computed -- if your embedding model changes, you must re-embed your entire corpus. This makes model selection a decision you should get right early.

Examples

Generate embeddings with sentence-transformers (local, free)

python

sentence-transformers is the go-to open-source library for text embeddings. The normalize_embeddings=True flag unit-normalizes each vector, which means dot product equals cosine similarity -- this avoids a separate normalization step during search. The similarity scores confirm that semantically related texts cluster together.

Cosine similarity, dot product, and Euclidean distance compared

python

Cosine similarity is direction-only and ignores magnitude, making it robust for texts of different lengths. Dot product is faster but sensitive to vector magnitude -- normalize first. Euclidean distance is intuitive but inverted (lower = more similar). Most vector databases use cosine or dot product because they are faster to compute and work well with HNSW indexes.

Comparing embedding models: quality vs speed vs cost

python

Not all embedding models are equal. all-MiniLM-L6-v2 is the standard starting point -- fast and good enough for most use cases. nomic-embed-text-v1.5 offers better retrieval quality at the cost of speed and memory. Run this benchmark on your own hardware to make an informed trade-off between quality and throughput.

Store and search embeddings with pgvector

python

pgvector lets you use PostgreSQL as your vector database -- no separate service to manage. The HNSW index makes similarity search fast even at millions of vectors. The <=> operator computes cosine distance (1 - cosine_similarity), so we subtract from 1 to get similarity. This pattern is ideal when your application already uses PostgreSQL.

Batch embedding with batching and progress tracking

python

When embedding large corpora, batch processing prevents memory issues and gives you progress visibility. The npz format compresses the numpy array for efficient storage. normalize_embeddings=True ensures all vectors are unit-length, which makes dot product equivalent to cosine similarity during search.

Common Mistakes

Mistake:

Using different embedding models for indexing documents and querying. The vectors live in incompatible spaces, so similarity scores are meaningless.

Fix:

Always use the exact same model and version for both document embedding and query embedding. Store the model name alongside your vector index so you can verify consistency.

Mistake:

Embedding entire documents as a single vector, which forces the model to compress pages of content into one fixed-size representation, losing most of the detail.

Fix:

Chunk documents into 200-1000 token passages before embedding. Each chunk becomes its own vector, allowing retrieval to pinpoint the relevant section rather than returning a vague document-level match.

Mistake:

Assuming higher-dimensional embeddings are always better. Using 3072-dimensional vectors when 384 would suffice quadruples storage and slows down search with minimal quality gain.

Fix:

Benchmark on your actual retrieval task. For most RAG applications, 384 to 768 dimensions provide the best quality-to-cost ratio. Only move to higher dimensions if your evaluation metrics show a meaningful improvement.

Mistake:

Not normalizing embeddings before using dot product similarity, which causes vectors with larger magnitudes to dominate regardless of semantic relevance.

Fix:

Either normalize all vectors to unit length (L2 norm = 1) and use dot product, or use cosine similarity which normalizes implicitly. Most embedding libraries have a normalize flag -- use it.

Mistake:

Caching embeddings without tracking the model version, then switching to a new embedding model without re-embedding the corpus. Old and new embeddings are incompatible.

Fix:

Treat model changes as a full re-indexing event. Store the model name and version as metadata on your vector index. When you upgrade the model, re-embed all documents before serving queries.

Best Practices

  • Start with sentence-transformers/all-MiniLM-L6-v2 for prototyping -- it runs locally, produces 384-dim vectors, and has strong retrieval quality for its size. Graduate to larger models only if evaluation shows a need.
  • Always normalize embeddings at encoding time (normalize_embeddings=True) so that dot product and cosine similarity produce identical rankings. This lets you use the faster dot product during search.
  • Benchmark embedding models on your own data, not public leaderboards. A model that tops the MTEB benchmark may underperform on your domain-specific queries. Build an evaluation set of 50-100 query-document pairs.
  • Use batch encoding for large corpora. Encoding one text at a time wastes GPU throughput. Batch sizes of 32-128 typically maximize hardware utilization without exceeding memory.
  • Store raw text alongside embeddings so you can re-embed when upgrading models. Embeddings are derived artifacts -- the source text is the ground truth.
  • Monitor embedding latency in production. If query embedding adds more than 50ms to your search pipeline, consider using a smaller model, quantized embeddings, or GPU acceleration.

Summary

Vector embeddings transform text into dense numerical representations that capture semantic meaning. Similar texts produce similar vectors, enabling search by meaning rather than keyword matching. Choose an embedding model based on your quality, speed, and cost requirements -- sentence-transformers models run locally for free while API-based models offer higher quality at a price. Normalize your vectors, use cosine similarity or dot product for comparison, and always embed documents and queries with the same model. The embedding step is the first and most critical stage of any RAG pipeline.

Practice RAG with hands-on challenges

Learn vector embeddings hands-on in your IDE

Interactive lessons and challenges on Stanza, practice in VS Code, Cursor, or the web.

Related Concepts

Related Cheatsheets

Master RAG with Stanza

Interactive lessons and challenges, right in your code editor.

Check the free courses. No credit card.