Embeddings Cheat Sheet

Quick reference for the rag-blog stack. Pair with lessons/0001-embeddings-vector-of-meaning.html.

Core facts

PropertyValue
Modelall-MiniLM-L6-v2
Architecture6-layer transformer encoder, mean-pooled
Output dimension384
Size on disk~80 MB
Similarity functionCosine (vectors are pre-normalized, so it's a dot product)
HardwareCPU (no GPU needed for our scale)
LicenseApache 2.0

The mental model in one line

Text in → list of 384 numbers out, where similar meaning → nearby direction.

Three similarity functions

FunctionFormulaRangeWhen to use
Cosine similarity (A · B) / (‖A‖ · ‖B‖) [-1, 1] Default for normalized text embeddings. Insensitive to magnitude.
Dot product A · B (-∞, ∞) Equivalent to cosine only if vectors are unit-length (our case).
Euclidean distance ‖A - B‖ [0, ∞) Useful when you care about magnitude. LanceDB uses this by default.

The four key lines of code

Load the model

self.model = SentenceTransformer(model_name)   # rag_pipeline.py
dim = self.model.get_embedding_dimension()     # → 384

Encode a batch (used at ingest time)

embeddings = self.model.encode(
    texts,                       # list[str]
    show_progress_bar=True,
    normalize_embeddings=True    # ← important
)

Encode a single string (used at query time)

vec = self.model.encode([text], normalize_embeddings=True)[0].tolist()

Find the closest chunks

results = lancedb_table.search(query_vec).metric("cosine").limit(top_k).to_list()

Common gotchas

Forgetting normalize_embeddings=True
If you toggle it off, cosine similarity and dot product no longer agree. Pick one and stay consistent.
Comparing across models
Vectors from MiniLM and vectors from mpnet are not in the same space. Never mix them.
Dimensionality mismatch
If you swap models and the dimension changes (e.g. MiniLM 384 → mpnet 768), you must re-ingest the whole index.
"Top-K doesn't include what I want"
Almost always a chunking problem, not an embedding problem. Re-check chunking.py.

Where to look in the codebase

ConceptFile · Symbol
Model choiceconfig.py · MODEL_NAME
Loading + dimensionrag_pipeline.py · Embedder.__init__
Batch encoding (ingest)rag_pipeline.py · Embedder.embed
Single encoding (query)rag_pipeline.py · Embedder.embed_one
Vector storagerag_pipeline.py · VectorStore · _create_table
Vector searchrag_pipeline.py · VectorStore.vector_search
Hybrid fusionrag_pipeline.py · HybridSearch.search

Useful one-liners

# Embed a single string
vec = embedder.embed_one("neovim folding")

# Embed many
vecs = embedder.embed(["neovim folding", "vim folding", "folding laundry"])

# Inspect a vector
print(vecs[0].shape)              # (384,)
print(np.linalg.norm(vecs[0]))    # ~1.0 if normalized
print(vecs[0][:5])                # first 5 floats

# Cosine similarity (our convention)
def cos(a, b): return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

Glossary

TermMeaning
EmbeddingA list of floats representing a piece of text. "Vector" and "embedding" are used interchangeably in this codebase.
EncoderThe neural network that produces embeddings. Ours is transformer-based.
TokenSub-word unit the encoder reads. ~1 token ≈ 4 characters of English.
Mean poolingHow we collapse a sequence of token vectors into one vector (averaging).
Cosine similarityThe angle between two vectors. We use it as our "how similar" score.
Cosine distance1 - cosine_similarity. This is what LanceDB returns by default. We convert back via vector_score = 1 - score.
Unit vector / normalizedA vector of length 1. With these, cosine = dot product.
DimensionHow many floats are in the vector. 384 for our model.