๐Ÿ”ฅ 0
โญ 0
Lesson 2 of 10 22 min +175 XP

Vector Databases for Products

When a customer searches for "something to keep my coffee hot during my commute", traditional keyword search fails. There's no exact match for that query in your product titles.

But if you've embedded your products into vectors, you can find semantically similar items like insulated travel mugs, thermal flasks, and heated car cup holders.

0
Keyword search results
47
Vector search results
~50ms
Query latency

What are Vector Embeddings?

Vector embeddings are numerical representations of data (text, images, etc.) where similar items are close together in vector space.

from openai import OpenAI

client = OpenAI()

# Convert product description to a vector
product = "Yeti Rambler 20oz Tumbler - Stainless steel, vacuum insulated, keeps drinks cold for 24 hours or hot for 12 hours"

response = client.embeddings.create(
    model="text-embedding-3-small",
    input=product
)

# This is a 1536-dimensional vector!
embedding = response.data[0].embedding
print(f"Vector dimensions: {len(embedding)}")  # 1536
print(f"First few values: {embedding[:5]}")    # [-0.023, 0.041, -0.008, ...]
Why 1536 Dimensions?

More dimensions = more nuance. A 1536-dimensional vector can capture subtle differences between "lightweight running shoes" and "breathable jogging sneakers" that would be impossible in just 2 or 3 dimensions.

How Vector Search Works

Query
"cozy blanket for winter"
โ†’
Embed
[0.02, -0.15, ...]
โ†’
Search
Find nearest vectors
โ†’
Results
Similar products

Popular Vector Databases

Pinecone

  • Fully managed cloud service
  • Scales automatically
  • Simple API
  • Best for: Production apps

Weaviate

  • Open source (self-hosted or cloud)
  • Built-in hybrid search
  • GraphQL API
  • Best for: Flexibility & control

Chroma

  • Open source, embeddable
  • Runs in-memory or persistent
  • Great Python integration
  • Best for: Prototyping & dev

Setting Up Pinecone for Products

from pinecone import Pinecone, ServerlessSpec
from openai import OpenAI

# Initialize clients
pc = Pinecone(api_key="your-pinecone-key")
openai_client = OpenAI()

# Create an index for products
pc.create_index(
    name="ecommerce-products",
    dimension=1536,  # OpenAI embedding size
    metric="cosine",
    spec=ServerlessSpec(
        cloud="aws",
        region="us-east-1"
    )
)

index = pc.Index("ecommerce-products")

# Sample products to index
products = [
    {
        "id": "prod_001",
        "name": "Yeti Rambler 20oz",
        "description": "Stainless steel vacuum insulated tumbler, keeps drinks cold 24hrs or hot 12hrs",
        "category": "drinkware",
        "price": 35.00
    },
    {
        "id": "prod_002",
        "name": "Hydro Flask 32oz",
        "description": "Wide mouth water bottle, double-wall vacuum insulation, BPA-free",
        "category": "drinkware",
        "price": 44.95
    },
    {
        "id": "prod_003",
        "name": "Stanley Quencher 40oz",
        "description": "Insulated tumbler with handle and straw, fits in car cup holder",
        "category": "drinkware",
        "price": 45.00
    }
]

# Embed and upsert products
def embed_text(text):
    response = openai_client.embeddings.create(
        model="text-embedding-3-small",
        input=text
    )
    return response.data[0].embedding

vectors_to_upsert = []
for product in products:
    # Combine name and description for embedding
    text = f"{product['name']}: {product['description']}"
    embedding = embed_text(text)

    vectors_to_upsert.append({
        "id": product["id"],
        "values": embedding,
        "metadata": {
            "name": product["name"],
            "description": product["description"],
            "category": product["category"],
            "price": product["price"]
        }
    })

# Upsert to Pinecone
index.upsert(vectors=vectors_to_upsert)
print(f"Indexed {len(vectors_to_upsert)} products")

Querying the Vector Database

def search_products(query: str, top_k: int = 5, category: str = None):
    """Search for products using semantic similarity"""

    # Embed the query
    query_embedding = embed_text(query)

    # Build filter if category specified
    filter_dict = {"category": category} if category else None

    # Search Pinecone
    results = index.query(
        vector=query_embedding,
        top_k=top_k,
        include_metadata=True,
        filter=filter_dict
    )

    return results.matches

# Search for products
results = search_products("something to keep my coffee hot during commute")

for match in results:
    print(f"Score: {match.score:.3f}")
    print(f"  Product: {match.metadata['name']}")
    print(f"  Price: ${match.metadata['price']}")
    print()
Output:
Score: 0.892
  Product: Yeti Rambler 20oz
  Price: $35.00

Score: 0.867
  Product: Stanley Quencher 40oz
  Price: $45.00

Score: 0.854
  Product: Hydro Flask 32oz
  Price: $44.95

Setting Up Chroma (Local Development)

import chromadb
from chromadb.utils import embedding_functions

# Initialize Chroma client
client = chromadb.PersistentClient(path="./chroma_db")

# Use OpenAI embeddings
openai_ef = embedding_functions.OpenAIEmbeddingFunction(
    api_key="your-openai-key",
    model_name="text-embedding-3-small"
)

# Create collection
collection = client.create_collection(
    name="products",
    embedding_function=openai_ef,
    metadata={"hnsw:space": "cosine"}
)

# Add products
collection.add(
    ids=["prod_001", "prod_002", "prod_003"],
    documents=[
        "Yeti Rambler 20oz: Stainless steel vacuum insulated tumbler",
        "Hydro Flask 32oz: Wide mouth water bottle, double-wall insulation",
        "Stanley Quencher 40oz: Insulated tumbler with handle and straw"
    ],
    metadatas=[
        {"category": "drinkware", "price": 35.00},
        {"category": "drinkware", "price": 44.95},
        {"category": "drinkware", "price": 45.00}
    ]
)

# Query
results = collection.query(
    query_texts=["travel coffee mug"],
    n_results=3
)

Setting Up Weaviate

import weaviate
from weaviate.classes.init import Auth

# Connect to Weaviate Cloud
client = weaviate.connect_to_weaviate_cloud(
    cluster_url="your-cluster-url",
    auth_credentials=Auth.api_key("your-api-key"),
    headers={"X-OpenAI-Api-Key": "your-openai-key"}
)

# Define schema for products
client.collections.create(
    name="Product",
    vectorizer_config=weaviate.classes.config.Configure.Vectorizer.text2vec_openai(),
    properties=[
        weaviate.classes.config.Property(
            name="name",
            data_type=weaviate.classes.config.DataType.TEXT
        ),
        weaviate.classes.config.Property(
            name="description",
            data_type=weaviate.classes.config.DataType.TEXT
        ),
        weaviate.classes.config.Property(
            name="category",
            data_type=weaviate.classes.config.DataType.TEXT
        ),
        weaviate.classes.config.Property(
            name="price",
            data_type=weaviate.classes.config.DataType.NUMBER
        )
    ]
)

# Add products
products = client.collections.get("Product")
products.data.insert({
    "name": "Yeti Rambler 20oz",
    "description": "Stainless steel vacuum insulated tumbler",
    "category": "drinkware",
    "price": 35.00
})

# Search with hybrid (vector + keyword)
response = products.query.hybrid(
    query="insulated coffee tumbler",
    limit=5
)

Comparison: Which to Choose?

Feature Pinecone Weaviate Chroma
Hosting Managed only Both Self-hosted
Hybrid Search Limited Built-in Limited
Scale Billions Millions+ Thousands
Free Tier Yes Yes Free (OSS)
Best For Production Hybrid search Development
Recommendation for E-commerce

Start with Chroma for prototyping (it's free and runs locally). Move to Pinecone for production (managed, scales easily). Use Weaviate if you need advanced hybrid search features.

Distance Metrics Explained

Cosine Similarity

Measures angle between vectors. Best for text embeddings where direction matters more than magnitude.

cosine(A, B) = AยทB / (||A|| ร— ||B||)

Euclidean Distance

Straight-line distance. Good when magnitude matters, like comparing product features.

euclidean(A, B) = sqrt(sum((A-B)ยฒ))

Dot Product

Fast and simple. Often used with normalized vectors (same as cosine).

dot(A, B) = sum(A ร— B)

Key Takeaways

  • Vector databases enable semantic search - Find products by meaning, not just keywords
  • Embeddings capture meaning - Similar products have similar vectors
  • Use cosine similarity for text - It's the standard for text embeddings
  • Start with Chroma, scale with Pinecone - Match your database to your stage

Next up: Embedding Product Catalogs - How to structure and embed your product data for optimal search.

๐Ÿง  Quick Quiz

Test your understanding of this lesson.

1

What does a vector database store?

2

What is the main advantage of vector search over keyword search for e-commerce?

3

Which distance metric is most commonly used for text embeddings?

Introduction to RAG and Agents