Back to guides
3
4 min

Embed & Store

Vectors That Capture Meaning

What Are Embeddings?

An embedding is a list of numbers (a vector) that represents the meaning of a piece of text. Similar meanings produce similar vectors. This is the magic that makes semantic search work.

"What is the PTO policy?"     → [0.12, -0.34, 0.78, 0.45, ...]
"How many vacation days?"     → [0.11, -0.31, 0.76, 0.43, ...]  ← very similar!
"Expense reimbursement rules" → [0.89, 0.22, -0.15, 0.67, ...]  ← very different

The first two questions are about the same topic — their vectors are close together in high-dimensional space. The third is about a different topic — its vector points in a different direction.

Why Not Just Use Keywords?

Keyword search for "vacation days" won't find a document that says "paid time off." Embedding search will, because both phrases have similar meaning-vectors. This is semantic search — matching by meaning, not by exact words.

Embedding Models

You send text to an embedding model API, and it returns a vector. Common choices:

ModelDimensionsSpeedQuality
OpenAI text-embedding-3-small1536FastGood for most use cases
OpenAI text-embedding-3-large3072SlowerBetter for nuanced content
Cohere embed-v31024FastStrong multilingual support

For this course, we'll use 1536-dimensional vectors (the most common). The actual model choice matters less than getting the pipeline right.

async function embed(text: string): Promise<number[]> {
  // In production: call OpenAI/Cohere API
  // For learning: we'll use mock embeddings first,
  // then swap in a real model
  const response = await openai.embeddings.create({
    model: "text-embedding-3-small",
    input: text,
  });
  return response.data[0].embedding; // number[1536]
}

Storing in pgvector

pgvector is a PostgreSQL extension that stores vectors alongside your regular data. Supabase includes it out of the box — no separate vector database needed.

-- Enable the extension
create extension if not exists vector;

-- Create chunks table with a vector column
create table chunks (
  id         text primary key,
  content    text not null,
  embedding  vector(1536),
  metadata   jsonb default '{}',
  created_at timestamptz default now()
);

The vector(1536) column stores your embeddings right next to the text content and metadata. One table, one query — no need to join across systems.

HNSW Indexing

Without an index, searching vectors requires comparing your query against every single stored vector. With 10,000 chunks, that's fine. With 1,000,000 chunks, it's too slow.

HNSW (Hierarchical Navigable Small World) is an approximate nearest-neighbor index. It trades a tiny bit of accuracy for massive speed improvements:

create index on chunks
  using hnsw (embedding vector_cosine_ops)
  with (m = 16, ef_construction = 64);
Without IndexWith HNSW
Scans every vectorNavigates a graph structure
O(n) — linearO(log n) — logarithmic
100% accurate~99% accurate (close enough)
Fine for < 10K rowsScales to millions

For this course, our dataset is small enough that brute-force search works fine. But we'll add the HNSW index anyway — it's a one-line addition that makes the system production-ready.

Similarity Metrics

How do you measure "similar"? Two common approaches:

Cosine Similarity

Measures the angle between two vectors. Ranges from -1 (opposite) to 1 (identical). Ignores magnitude — two vectors pointing the same direction score 1.0 regardless of length.

Dot Product

Multiplies corresponding elements and sums them. Faster to compute, but sensitive to vector magnitude. Works well when vectors are normalized (length = 1).

For text search, use cosine similarity. It's the standard, and pgvector supports it natively with the <=> operator:

select id, content, 1 - (embedding <=> query_embedding) as similarity
from chunks
order by embedding <=> query_embedding
limit 5;

The <=> operator returns cosine distance (0 = identical). We subtract from 1 to get similarity (1 = identical).

This is chapter 3 of RAG in 60 Minutes.

Get the full hands-on course — free during early access. Build the complete system. Your projects become your portfolio.

View course details