If you ask a database whether two strings are equal, it compares the bytes. If the bytes match, equal. If not, not equal. Synonyms, paraphrases, near-misses, things that are obviously about the same topic but use different words: invisible.

That works for some questions. "Find the row where id = 12345" is a byte-comparison question, and a B-tree finds it in microseconds. But "find documents about renewable energy" is not a byte-comparison question. The word "renewable" might not appear; the document might be about wind farms, solar arrays, or hydroelectric dams. Keyword search misses these unless someone has written down every synonym in advance.

Embeddings exist to make those questions answerable.

Meaning, not byte matches: keyword search for "renewable energy" returns one result that contains the exact phrase and misses related documents about wind farms, solar power, and hydroelectric dams. Embedding search returns all four ranked by relevance, because they're semantically related even when the words don't overlap.

The trick

You take each item, run it through a model, and out comes a list of numbers. Maybe 384 numbers, maybe 1536, maybe 768; the count depends on the model. That list is the item's embedding.

The numbers are coordinates. They place the item somewhere in a high-dimensional space. The geometry of the space is set up so that items with similar meaning land near each other, and items with different meaning land far apart. "Wind farms in Iowa" lands near "Solar power in California" because both are about renewable energy. "Wind farms in Iowa" lands far from "Marble countertops" because those are about different things, even though "in" appears in both.

Searching for documents about renewable energy is now a geometry question: which items are nearest to the embedding of the phrase "renewable energy"? That's something a vector database can do quickly, even with millions of items.

The trick: text becomes coordinates. Three documents (wind farms in Iowa, solar power in California, marble countertops) are fed through an embedding model and placed as points in a 2D projection of a high-dimensional space. The two renewable-energy documents land near each other; the marble countertops document lands far away. Nearby points equal similar meaning.

Where the numbers come from

A neural network. Specifically, one that was trained on a huge corpus of text (or images, or code, or whatever modality you care about) with an objective something like: "given two inputs, produce embeddings that are close together if they're related, and far apart if they're not."

The training data does the work. If you feed a model billions of pages of Wikipedia and StackOverflow and arXiv papers and Reddit threads, it learns that "wind farm" and "solar array" appear in similar contexts and should produce similar embeddings, even though the surface words have nothing in common. The model is just learning patterns of co-occurrence at massive scale, but the result behaves remarkably like a model of meaning.

You don't have to train one yourself. There are good open models you can download and run on a laptop CPU (all-MiniLM-L6-v2 is one); there are paid hosted models from OpenAI and Cohere and others; there are domain-specific models trained on legal documents, biomedical literature, code repositories. They differ in size, speed, cost, dimensionality, and quality on your particular data.

For the longer, no-math story of how a model comes to know what words mean in the first place — the training intuition behind all of this — see How a computer learns what words mean.

What "near" means

Once everything is embedded, "find similar items" becomes "find nearby vectors." But there's more than one way to measure distance.

The most common one for text embeddings is cosine similarity. It looks at the angle between two vectors, ignoring how long either one is. Two vectors pointing in the same direction have cosine similarity 1.0; two perpendicular vectors have 0.0; two pointing in opposite directions have -1.0. (Vector Panda's API normalizes the score to fall in [0, 1] for ease of reading.)

There are other metrics. Euclidean distance treats vectors as points and measures the literal straight-line distance between them. Dot product measures angle and magnitude together; it's similar to cosine but doesn't normalize. Most modern text models produce normalized vectors and assume cosine, so cosine is the default basically everywhere. If you're using a model that recommends a different metric, the model card will tell you.

The important thing is that all three are doing the same kind of work: turning "are these two things meaningfully related" into a single number you can sort by.

What "near" means: three ways to compare embeddings. Cosine similarity measures the angle between vectors and ignores length (range -1 to 1, higher is more similar). Euclidean distance is the literal point-to-point distance (range 0 to infinity, lower is more similar). Dot product uses both direction and magnitude. For most text embeddings, cosine is the usual default.

Why dimensionality matters

A 384-dimensional embedding is a list of 384 floats. A 1536-dimensional embedding is a list of 1536 floats. Both fit in memory; both can be queried quickly; both encode meaning. So why do bigger models produce bigger vectors?

More dimensions give the model more axes along which to express meaning. With 384 numbers, the model has 384 ways to differentiate items. With 1536, four times as many. The result tends to be a more nuanced model: it can distinguish "wind farms in Iowa" from "wind farms in Texas" more reliably than a smaller model can.

It's not free. More dimensions means more bytes per row (a 1536-dim float32 vector is 6 KB; ten million of them is 60 GB). It means more arithmetic per query, so latency goes up. It means more memory pressure on the hot path. The right dimensionality is the smallest one that gives you the result quality you need; bigger isn't automatically better.

Dimensionality and model tradeoffs: a 384-dimensional model gives smaller vectors, lower memory, faster queries, and a good starting point. A 1536-dimensional model gives more nuance and a higher ceiling but needs more bytes per row, more arithmetic per query, and more memory. Quality and nuance go up with dimensions; memory and latency cost go up too. The right dimensionality is the smallest one that gives you the quality you need.

How to pick a model

Start with the question of where it runs. Local models (sentence-transformers and friends) cost nothing per query and don't send your data anywhere; they're typically smaller and a touch lower quality. Hosted models (OpenAI, Cohere, Voyage) have stronger results on most benchmarks but charge per token and require sending text over the wire.

Then think about your domain. General-purpose models work fine for most things. If you're searching legal contracts or medical records or source code, a domain-specific model will usually beat a general one by a noticeable margin. The Massive Text Embedding Benchmark (MTEB) leaderboard at huggingface.co/spaces/mteb/leaderboard ranks dozens of models on standard tasks and is a reasonable starting point.

Then iterate. Pick a model that looks plausible, embed a small slice of your data, run a handful of representative queries, and look at the top-k results yourself. If they're sensible, you're done. If they're not, switch models. The setup cost is low and the quality difference between a well-chosen model and a default one can be large.

Closing

The reason vector search works at all is that someone trained a model that turns the squishy notion of "meaning" into a list of numbers. That's a remarkable thing, and it took a couple of decades of research to get right, but the result is straightforward to use: hand the model your text, get a vector back, store the vector, and compare new vectors against it later.

Vector Panda is the storage and comparison layer. The model is yours to choose. The two pieces are decoupled on purpose: as embedding models get better (and they do, every few months), you can swap to a new one without touching the database, and your existing pipeline keeps working with whatever vectors you point it at.