Quick answer: An embedding model is a trained neural network that turns text (or images, or audio) into a list of numbers called a vector, where similar meanings land close together in that number space. The model is the machine; the vectors are what it makes. You pick one model, run all your content through it, and use the resulting vectors for search, clustering, and retrieval.
People mix up two things constantly: the embedding model and the embeddings. The embeddings are the output. The embedding model is the thing that produces them. If you have read our piece on what vector embeddings are, this post is the other half of the story: how to pick and run the model that generates them.
The Model Versus the Vectors
Think of an embedding model as a very specific kind of function. You feed it a chunk of text, it returns a fixed-length array of floating point numbers, and that array is the same length for every input you give it. A sentence, a paragraph, and a single word all come out as, say, a 1024-number vector.
The magic is in the training. The model has seen enormous amounts of text and learned to place related ideas near each other. "How do I reset my password" and "I forgot my login credentials" end up as nearby vectors even though they share almost no words. That property is what makes embeddings useful for search and retrieval.
One rule matters above all others: you must embed your queries and your documents with the same model. Vectors from two different models are not comparable. They live in different coordinate systems, and the distances between them mean nothing.
Popular Families, Conceptually
You do not need to memorize a catalog, but it helps to know the rough landscape. Embedding models come in a few broad groups.
| Family | Where it runs | Typical use |
|---|---|---|
| Hosted API models | A provider's servers, called over HTTP | Fast to start, no infra, per-token billing |
| Open-source sentence models | Your own machine or GPU | Full control, no per-call cost, you host it |
| Multilingual models | Either | Content in many languages sharing one space |
| Domain-tuned models | Either | Code, legal, biomedical, or other niche text |
Hosted options are the quickest way to get moving: you send text, you get vectors. Open-source models that you run locally trade setup effort for control and remove per-call costs. Multilingual variants matter if your corpus spans languages, because a good multilingual model puts "dog" and "perro" near each other. Domain-tuned models are worth it when general models keep missing the distinctions your field cares about.
I am deliberately not quoting benchmark numbers here. Public leaderboards shift monthly, and a model that tops a general leaderboard can still lose on your specific data. Treat family names as starting points, not verdicts.
Dimensions and Context Length
Two numbers describe most embedding models: the dimension count and the context length.
Dimensions are how many numbers are in each vector. Common sizes run from a few hundred to a few thousand. More dimensions can capture more nuance, but they cost more storage and make similarity search slower. A 3072-dimension vector is four times the storage of a 768-dimension one. For many applications, a mid-size model is the sweet spot, and the accuracy gain from the largest models is small.
Some newer models support shortening the vector after the fact, letting you keep the first N numbers and drop the rest with only a modest accuracy loss. That is handy when storage or speed becomes the bottleneck.
Context length is how much text the model reads at once. If a model has a 512-token window and you feed it a 2000-word document, it silently ignores most of the page. This is why chunking matters. You split long documents into passages that fit the window, embed each passage, and store them separately. Get the chunk size wrong and your retrieval quality drops no matter how good the model is.
How to Choose One
Here is the order I actually work in when picking an embedding model.
- Match the language and domain. If your content is multilingual or highly technical, filter to models built for that first. This eliminates most of the field immediately.
- Decide hosted or self-hosted. Do you want zero infrastructure and a per-call bill, or do you want to run the model yourself for control and no marginal cost? This is often a policy or budget decision more than a technical one.
- Check the context length against your chunks. Pick a model whose window comfortably fits your typical passage. Do not force a mismatch.
- Pick a dimension size you can afford at scale. Multiply your document count by the vector size and be honest about storage and query speed. A vector database will hold these; see our guide on what a vector database is for how that side works.
- Test on your data. This is the step everyone skips and the only one that actually decides the winner.
Evaluating on Your Own Data
A leaderboard tells you how a model does on someone else's benchmark. Your users do not send someone else's queries. Build a small evaluation set from your real world.
Collect 30 to 50 real queries and, for each, mark which documents in your corpus should come back. Then run each candidate model, retrieve the top results, and measure how often the right document lands in the top 5. This is called recall at 5, and it is blunt but honest.
from sentence_transformers import SentenceTransformer
import numpy as np
# A candidate embedding model, run locally
model = SentenceTransformer("BAAI/bge-small-en-v1.5")
documents = [
"Reset your password from the account settings page.",
"Our refund window is 30 days from purchase.",
"Enable two-factor authentication under security.",
]
doc_vectors = model.encode(documents, normalize_embeddings=True)
def search(query, k=3):
q = model.encode(query, normalize_embeddings=True)
scores = doc_vectors @ q # cosine similarity, vectors normalized
ranked = np.argsort(scores)[::-1][:k]
return [(documents[i], float(scores[i])) for i in ranked]
for text, score in search("I forgot my login"):
print(round(score, 3), text)
Swap in a second model, rerun, and compare the recall numbers. Whichever model finds the right documents most often on your queries wins. Cost, speed, and dimension size break the tie when two models score close.
Where Web Content Fits In
Embeddings are only as good as the text you feed them. If you are building a retrieval system over web pages, the raw HTML is full of navigation, ads, and script tags that pollute your vectors. Clean text in, useful vectors out.
That is the practical reason to fetch pages as clean markdown before embedding. With link.sc, you pull a page into structured text in one call, then embed the result:
import requests
from sentence_transformers import SentenceTransformer
resp = requests.post(
"https://api.link.sc/v1/fetch",
headers={"x-api-key": "lsc_..."},
json={"url": "https://example.com/docs/pricing", "format": "markdown"},
)
clean_text = resp.json()["content"]
model = SentenceTransformer("BAAI/bge-small-en-v1.5")
vector = model.encode(clean_text, normalize_embeddings=True)
print(len(vector), "dimensions")
Feed the model a clean page and its vector actually reflects the content. Feed it raw HTML and half the signal is boilerplate.
The Short Version
An embedding model is the trained function; embeddings are its output. Match the model to your language and domain, mind the dimensions and context window, and never trust a leaderboard over a test on your own queries. Get those right and the rest of your retrieval stack has a solid foundation to build on.
Building retrieval over live web content? link.sc turns any URL into clean markdown ready to embed. Start free.