Embeddings & Vector Search
SQL LIKE matches characters. Vector search matches meaning. You'll learn how embeddings turn text into numbers, build similarity search from scratch, and understand when to use Pinecone, pgvector, or Chroma. You'll ship a search engine that finds 'cozy sneakers' when users type 'comfortable shoes'.
Use this at work tomorrow
Replace a keyword-based search in your app with semantic search — users will find what they mean, not just what they type.
Learning Objectives
- 1Understand embeddings as feature vectors (1536 dimensions → meaning)
- 2Implement cosine similarity from scratch — then use it at scale
- 3Generate embeddings with OpenAI's embedding API
- 4Know when to pick Pinecone vs pgvector vs Chroma vs in-memory
- 5Build a semantic search engine with 100+ real documents
Ship It: Semantic search engine
By the end of this day, you'll build and deploy a semantic search engine. This isn't a toy — it's a real project for your portfolio.
I can explain what embeddings are, compute cosine similarity, and build a semantic search system that matches meaning instead of keywords.
How does semantic search find 'cozy sneakers' when you search 'comfortable shoes'?
From Text Search to Semantic Search
SQL LIKE queries match exact strings — 'comfortable shoes' will never match 'cozy sneakers'. Semantic search matches meaning. The magic is embeddings — turning text into vectors (arrays of 1536 numbers) where similar meanings are close together in vector space. It's like GPS coordinates for meaning.
What does an embedding convert text into?
What do the 1536 numbers in an embedding vector represent?
Embeddings Are Feature Vectors You Already Understand
You've worked with feature flags, analytics dimensions, or coordinate systems. Embeddings are the same concept at scale — each of the 1536 dimensions captures a semantic feature learned by the model. 'King' and 'Queen' are close in the royalty dimension but differ on the gender dimension. You don't pick the features — the model learns them.
Who decides what each dimension in an embedding means?
When should you use a dedicated vector database like Pinecone instead of in-memory arrays?
Real Vector Databases: When to Use What
For prototyping: in-memory arrays with cosine similarity (what we do today). For production with <100K docs: pgvector (add vectors to your existing Postgres). For production at scale: Pinecone (managed, fast), Weaviate (open-source, hybrid search), or Chroma (lightweight, Python-first). The interface is always the same: store vectors, query by similarity, get top-K results.
You have a Postgres database and 50K product descriptions. What's the EASIEST way to add semantic search?
The Full Evolution
Watch one function evolve through every concept you just learned.
Production Gotchas
Embedding costs are cheap (~$0.02 per 1M tokens) but re-embedding your entire dataset on model change is expensive. Always store raw text alongside vectors — you'll need to re-embed when better models drop. Dimensionality matters: text-embedding-3-small (1536d) vs text-embedding-3-large (3072d) — more dimensions = better quality but more storage/compute. Normalize your vectors for cosine similarity.
Code Comparison
Search: SQL LIKE vs Semantic
Traditional text search vs AI-powered semantic search
// Traditional search — matches characters
const results = await db.query(
`SELECT * FROM products
WHERE name ILIKE $1
OR description ILIKE $1
ORDER BY relevance
LIMIT 10`,
[`%${searchQuery}%`]
);
// "comfortable shoes"
// won't match "cozy sneakers" ✗
// won't match "comfy footwear" ✗
// won't match "easy-to-wear kicks" ✗// Semantic search — matches meaning
import { embed } from "ai";
import { openai } from "@ai-sdk/openai";
// 1. Embed the query (~2ms)
const { embedding } = await embed({
model: openai.embedding(
"text-embedding-3-small"
),
value: searchQuery,
});
// 2. Find similar vectors (top-K)
const results = await vectorDB.query({
vector: embedding,
topK: 10,
});
// "comfortable shoes" MATCHES:
// "cozy sneakers" ✓ (0.91 similarity)
// "comfy footwear" ✓ (0.89 similarity)
// "easy-to-wear kicks" ✓ (0.84 similarity)KEY DIFFERENCES
- SQL LIKE matches characters — embeddings match meaning
- Embeddings turn text into vectors (arrays of 1536 numbers)
- Similar meanings = close vectors (cosine similarity → 0 to 1)
- No need to predict all synonyms — the model handles it
Bridge Map: SQL LIKE / full-text search → Vector similarity search
Click any bridge to see the translation
Hands-On Challenges
Build, experiment, and get AI-powered feedback on your code.
Semantic Product Search Engine
Build and deploy a semantic search engine that lets users search a product catalog by meaning, not keywords. When someone searches 'comfortable shoes', they should find 'cozy sneakers'. This is the same search technology powering modern e-commerce.
Acceptance Criteria
- Index 50+ products with text descriptions and metadata (price, category, etc.)
- Generate embeddings using the OpenAI embedding API (text-embedding-3-small)
- Implement cosine similarity search that returns top-K results ranked by relevance
- Show similarity scores visually (progress bars or percentage badges)
- Filter out low-quality matches below a threshold (e.g., score < 0.5)
- Handle edge cases: empty queries, no results found, API failures
- Deploy to a public URL (Vercel, Netlify, etc.)
Build Roadmap
0/6Create a new Next.js app with TypeScript and Tailwind CSS. Set up your project structure with a products data file and a search API route.
npx create-next-app@latest semantic-search --typescript --tailwind --appCreate a /data/products.ts file for your product catalogDeploy Tip
Push to GitHub and import into Vercel. Pre-compute your embeddings at build time or on first request, then cache them. Set your OPENAI_API_KEY in Vercel environment variables.
Sign in to submit your deployed project.
I can explain what embeddings are, compute cosine similarity, and build a semantic search system that matches meaning instead of keywords.