What Are Embeddings? How Text Becomes Numbers
Embeddings are arrays of numbers (vectors) that represent the meaning of a piece of text. Two sentences about the same topic produce vectors that sit close together in mathematical space, while unrelated sentences land far apart. This makes embeddings the foundation of semantic search, recommendation systems, and retrieval-augmented generation (RAG).
What exactly is an embedding?
Think of a library where every book has a GPS coordinate. Cookbooks cluster together on one shelf, programming books on another. If you know the coordinates of "JavaScript: The Good Parts," you can find nearby books that cover similar topics without reading a single page.
Embeddings work the same way, but for text. A model reads a sentence and outputs an array of numbers, typically 384 to 3,072 floats. That array is the sentence's "GPS coordinate" in a high-dimensional space. Sentences with similar meanings get similar coordinates.
For example, the sentences "M-Pesa lets you send money from your phone" and "You can transfer cash using Safaricom's mobile wallet" say roughly the same thing. Their embedding vectors will be close together, even though they share few words. Meanwhile, "The Nairobi Expressway reduced travel time to JKIA" will be far away from both, because its meaning is unrelated.
How does text become a vector?
The pipeline has three steps:
- Tokenisation. The text is broken into tokens, which are word pieces. "Embeddings" might become ["Embed", "dings"]. Each token maps to a number the model understands.
- Model forward pass. The tokens flow through a neural network (a transformer). The network has been trained on enormous amounts of text, learning which words appear in similar contexts. Each layer refines the representation.
- Pooling. The model outputs one vector per token. To get a single vector for the entire sentence, the outputs are combined, usually by averaging. The result is your embedding.
You do not need to understand the internals to use embeddings. Call an API, pass in text, get back an array of numbers. But knowing the pipeline helps you reason about edge cases, like why very short inputs (a single word) sometimes produce weaker embeddings than full sentences.
A worked example: comparing three sentences
This TypeScript snippet embeds three sentences and compares them using cosine similarity. You need an OpenAI API key to run it.
import OpenAI from 'openai';
const openai = new OpenAI();
const sentences = [
'M-Pesa lets you send money from your phone',
'You can transfer cash using Safaricom mobile wallet',
'The Nairobi Expressway reduced travel time to JKIA',
];
async function embed(text: string): Promise<number[]> {
const res = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: text,
});
return res.data[0].embedding;
}
function cosineSimilarity(a: number[], b: number[]): number {
let dot = 0, magA = 0, magB = 0;
for (let i = 0; i < a.length; i++) {
dot += a[i] * b[i];
magA += a[i] * a[i];
magB += b[i] * b[i];
}
return dot / (Math.sqrt(magA) * Math.sqrt(magB));
}
async function main() {
const vectors = await Promise.all(sentences.map(embed));
console.log('M-Pesa vs Safaricom wallet:',
cosineSimilarity(vectors[0], vectors[1]).toFixed(4));
console.log('M-Pesa vs Expressway:',
cosineSimilarity(vectors[0], vectors[2]).toFixed(4));
}
main();When you run this, the first pair (both about mobile money) scores high, around 0.85 to 0.92. The second pair (mobile money vs. a highway) scores much lower, around 0.15 to 0.30. The numbers capture what your intuition already knows: the first two sentences are about the same thing.
Embedding dimensions and model choices
Different models produce different vector sizes:
- text-embedding-3-small (OpenAI): 1,536 dimensions. Good balance of quality and cost.
- text-embedding-3-large (OpenAI): 3,072 dimensions. Higher quality, roughly double the storage.
- all-MiniLM-L6-v2 (open source, sentence-transformers): 384 dimensions. Runs locally on a laptop, no API key needed.
- voyage-3 (Anthropic partner): 1,024 dimensions. Strong on code and technical text.
More dimensions capture more nuance but cost more to store and slower to compare. For most applications, 1,536 dimensions from a mid-range model is a solid default. If you are running on a tight budget or want to avoid external API calls, an open-source model with 384 dimensions works surprisingly well.
The critical rule: use the same model for both indexing and querying. Vectors from different models live in different spaces and cannot be compared.
When do you actually need embeddings?
Embeddings unlock three major capabilities:
- Semantic search. Traditional keyword search fails when users phrase things differently from your documents. A search for "send money on phone" won't match a document titled "Mobile Wallet Transfer Guide" using keyword matching. With embeddings, both phrases map to nearby vectors, and the search succeeds.
- RAG (Retrieval Augmented Generation). When you want an LLM to answer questions from your own documents, you embed and store those documents, then retrieve the relevant chunks at query time. Embeddings are the retrieval engine in RAG.
- Recommendations and clustering. Embed your product descriptions or articles. Products with similar embeddings are similar in meaning. You can recommend "customers who viewed this also liked" without hand-coding rules.
If your use case is pure keyword matching and your users always use the exact terms in your data, you may not need embeddings. But the moment user language diverges from your data's language, embeddings close that gap.
Frequently Asked Questions
- Are embeddings the same as word2vec?
- word2vec was an early embedding method that learned one vector per word. Modern embedding models (like those from OpenAI or sentence-transformers) use transformers and produce vectors for entire sentences or paragraphs. They capture richer meaning, including word order and context, which word2vec could not.
- How large is a typical embedding vector?
- Common dimensions range from 384 to 3,072 floating-point numbers depending on the model. Each float is 4 bytes, so a 1,536-dimension vector takes about 6 KB. For a million documents, that is roughly 6 GB of vector storage, which is manageable for most databases.
- Can I generate embeddings locally without an API?
- Yes. Open-source models like all-MiniLM-L6-v2 from the sentence-transformers library run on a laptop CPU. They are free, private, and fast enough for small to medium datasets. API-based options from OpenAI or Cohere are simpler to start with but cost money and send your data to an external server.
Ready to build real-world apps?
Join the McTaba Labs full-stack marathon. Ship 8 production apps with M-Pesa, USSD, and WhatsApp integrations, and get career support until placement.
See Programs