Skip to main content
LLM Engineering intermediate Lesson 6 of 12

LLM Embeddings and Vector Databases

Generate text embeddings, understand semantic similarity, and build search and recommendation systems with vector databases.

Real-World Scenario

A legal-tech company has 100,000 past case documents. A lawyer types a description of a new case and needs to find the 10 most similar past cases — not by keyword matching, but by semantic meaning. Traditional search fails because the terminology varies across decades of legal writing. Embeddings capture semantic meaning, so “vehicular negligence resulting in bodily harm” and “car accident causing personal injury” are recognized as similar.

Generating Embeddings

# pip install voyageai numpy scikit-learn
# Voyage AI is Anthropic's recommended embedding provider
import voyageai
import numpy as np

vo = voyageai.Client()   # reads VOYAGE_API_KEY from environment

# Single text embedding
text = "Machine learning models learn from data to make predictions."
result = vo.embed([text], model="voyage-3")
embedding = result.embeddings[0]

print(f"Embedding dimensions: {len(embedding)}")  # 1024
print(f"First 5 values: {embedding[:5]}")

# Batch embedding — more efficient than one-at-a-time
documents = [
    "Python is a high-level programming language.",
    "The stock market closed higher today.",
    "Neural networks are inspired by the brain.",
    "Interest rates affect bond prices inversely.",
    "Backpropagation computes gradients efficiently.",
]
result = vo.embed(documents, model="voyage-3", input_type="document")
doc_embeddings = np.array(result.embeddings)   # (5, 1024)
print(f"Batch embedding shape: {doc_embeddings.shape}")

Semantic Similarity

import voyageai
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

vo = voyageai.Client()

def embed(texts: list[str], input_type: str = "document") -> np.ndarray:
    result = vo.embed(texts, model="voyage-3", input_type=input_type)
    return np.array(result.embeddings)

# Pairs of texts with varying similarity
pairs = [
    ("The dog chased the cat", "A puppy ran after a kitten"),       # Very similar
    ("I love programming in Python", "Python is great for coding"), # Similar
    ("The sun rises in the east", "Quantum entanglement is weird"), # Very different
    ("Stock prices fell today", "Markets declined sharply"),        # Similar
    ("I enjoy cooking pasta", "The Eiffel Tower is in Paris"),      # Different
]

texts_a = [p[0] for p in pairs]
texts_b = [p[1] for p in pairs]

embeddings_a = embed(texts_a)
embeddings_b = embed(texts_b)

print("Semantic similarity scores:")
for (a, b), emb_a, emb_b in zip(pairs, embeddings_a, embeddings_b):
    sim = cosine_similarity([emb_a], [emb_b])[0][0]
    bar = "█" * int(sim * 20)
    print(f"  {sim:.3f} {bar}")
    print(f"    A: {a}")
    print(f"    B: {b}")
import voyageai
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

vo = voyageai.Client()

# Knowledge base
documents = [
    {"id": 1, "title": "Python Basics",     "text": "Python is interpreted, dynamically typed, and uses indentation."},
    {"id": 2, "title": "Machine Learning",   "text": "ML algorithms learn patterns from data without explicit programming."},
    {"id": 3, "title": "Docker Containers",  "text": "Docker packages applications with their dependencies into containers."},
    {"id": 4, "title": "Neural Networks",    "text": "Neural networks learn hierarchical representations through layers."},
    {"id": 5, "title": "SQL Databases",      "text": "SQL databases store structured data in tables with relationships."},
    {"id": 6, "title": "REST APIs",          "text": "REST APIs use HTTP methods to expose resources as endpoints."},
    {"id": 7, "title": "Git Version Control","text": "Git tracks file changes and enables collaboration through branches."},
    {"id": 8, "title": "Deep Learning",      "text": "Deep learning uses many-layered neural networks for complex tasks."},
]

# Pre-compute document embeddings (do this once, cache the result)
doc_texts = [d["text"] for d in documents]
doc_embeddings = np.array(
    vo.embed(doc_texts, model="voyage-3", input_type="document").embeddings
)

def semantic_search(query: str, top_k: int = 3) -> list[dict]:
    """Find the most semantically similar documents to a query."""
    # Embed the query with input_type="query" for better performance
    query_embedding = np.array(
        vo.embed([query], model="voyage-3", input_type="query").embeddings
    )
    
    similarities = cosine_similarity(query_embedding, doc_embeddings)[0]
    top_indices  = np.argsort(similarities)[::-1][:top_k]
    
    return [
        {**documents[i], "similarity": float(similarities[i])}
        for i in top_indices
    ]

# Test queries
queries = [
    "How do I containerize my application?",
    "What is the difference between ML and deep learning?",
    "How to collaborate with teammates on code?",
]

for query in queries:
    print(f"\nQuery: {query}")
    results = semantic_search(query, top_k=2)
    for r in results:
        print(f"  [{r['similarity']:.3f}] {r['title']}: {r['text'][:60]}...")

Production Vector Database with ChromaDB

# pip install chromadb
import chromadb
import voyageai
import numpy as np
from typing import Optional

vo = voyageai.Client()

# Persistent ChromaDB client — stores data on disk
chroma_client = chromadb.PersistentClient(path="./vector_db")

# Create or get a collection
collection = chroma_client.get_or_create_collection(
    name="knowledge_base",
    metadata={"hnsw:space": "cosine"},  # use cosine distance
)

def embed_batch(texts: list[str], input_type: str = "document") -> list[list[float]]:
    result = vo.embed(texts, model="voyage-3", input_type=input_type)
    return result.embeddings

def index_documents(documents: list[dict]) -> None:
    """Add documents to the vector database."""
    texts  = [d["text"]  for d in documents]
    ids    = [str(d["id"]) for d in documents]
    metas  = [{"title": d["title"]} for d in documents]

    embeddings = embed_batch(texts, input_type="document")

    collection.add(
        ids=ids,
        documents=texts,
        embeddings=embeddings,
        metadatas=metas,
    )
    print(f"Indexed {len(documents)} documents. Total: {collection.count()}")


def search(query: str, n_results: int = 5, filter_meta: Optional[dict] = None) -> list[dict]:
    """Search the vector database."""
    query_embedding = embed_batch([query], input_type="query")[0]

    results = collection.query(
        query_embeddings=[query_embedding],
        n_results=n_results,
        where=filter_meta,   # optional metadata filter
        include=["documents", "metadatas", "distances"],
    )

    output = []
    for doc, meta, dist in zip(
        results["documents"][0],
        results["metadatas"][0],
        results["distances"][0],
    ):
        output.append({
            "text":       doc,
            "title":      meta["title"],
            "similarity": 1 - dist,  # ChromaDB returns distance, convert to similarity
        })
    return output


# Index and search
documents = [
    {"id": 1, "title": "Python", "text": "Python is a versatile high-level programming language."},
    {"id": 2, "title": "ML",     "text": "Machine learning enables computers to learn from data."},
    {"id": 3, "title": "Docker", "text": "Docker containerizes applications for consistent deployment."},
]

index_documents(documents)

results = search("how to deploy apps consistently")
for r in results:
    print(f"[{r['similarity']:.3f}] {r['title']}: {r['text'][:60]}...")

Building a Recommendation System

import voyageai
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

vo = voyageai.Client()

# Product catalog
products = [
    {"id": 1,  "name": "Python Crash Course",         "category": "books",    "desc": "Beginner Python programming book"},
    {"id": 2,  "name": "Automate the Boring Stuff",   "category": "books",    "desc": "Python automation for everyday tasks"},
    {"id": 3,  "name": "MacBook Pro 14",               "category": "hardware", "desc": "Apple laptop for professional developers"},
    {"id": 4,  "name": "Mechanical Keyboard",          "category": "hardware", "desc": "Tactile keyboard for programmers"},
    {"id": 5,  "name": "Machine Learning Yearning",    "category": "books",    "desc": "Deep learning project strategy by Andrew Ng"},
    {"id": 6,  "name": "Hands-On Machine Learning",   "category": "books",    "desc": "Scikit-learn and TensorFlow practical guide"},
    {"id": 7,  "name": "GPU Cloud Credits",            "category": "cloud",    "desc": "GPU compute for ML training workloads"},
    {"id": 8,  "name": "Standing Desk",                "category": "hardware", "desc": "Ergonomic adjustable height desk"},
]

# Pre-compute product embeddings
product_texts = [f"{p['name']}: {p['desc']}" for p in products]
product_embeddings = np.array(
    vo.embed(product_texts, model="voyage-3", input_type="document").embeddings
)

def get_recommendations(purchased_product_id: int, top_k: int = 3) -> list[dict]:
    """Return top_k most similar products to the one purchased."""
    idx = next(i for i, p in enumerate(products) if p["id"] == purchased_product_id)
    query_emb = product_embeddings[idx:idx+1]

    similarities = cosine_similarity(query_emb, product_embeddings)[0]
    # Exclude the product itself
    similarities[idx] = -1

    top_indices = np.argsort(similarities)[::-1][:top_k]
    return [
        {**products[i], "similarity": float(similarities[i])}
        for i in top_indices
    ]

# "Customers who bought this also bought..."
print("Bought: Python Crash Course")
print("Recommendations:")
for rec in get_recommendations(purchased_product_id=1):
    print(f"  [{rec['similarity']:.3f}] {rec['name']} ({rec['category']})")

Frequently Asked Questions

What is an embedding?
An embedding is a dense vector of floating-point numbers that represents the meaning of text. Similar texts have vectors that are close together in high-dimensional space. A 1536-dimensional embedding captures semantic meaning so that 'dog' and 'puppy' are close, while 'dog' and 'quantum mechanics' are far apart.
What is cosine similarity and why use it for embeddings?
Cosine similarity measures the angle between two vectors, ranging from -1 (opposite) to 1 (identical). Unlike Euclidean distance, it's invariant to the magnitude (length) of the vectors — only direction matters. This is ideal for embeddings because two texts can vary in length but still have similar meaning.