Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
It's easy to get lost in the theory before you've ever produced a single real recommendation. This task closes module one by building the smallest complete recommender you can defend: load interactions, compute item-item similarity, retrieve candidates from a user's history, and rank them. It won't beat a production system, but every later module is a strictly better version of one of these four steps — better similarity (embeddings instead of co-occurrence counts), better retrieval (ANN indexes instead of a dict scan), better ranking (a learned model instead of a similarity score), better evaluation (proper offline metrics instead of eyeballing the list). Building the whole pipeline once, end to end, however crude, gives you the skeleton every later technique slots into.
The demo builds an item-item collaborative filter from a small synthetic interaction table using cosine similarity over co-occurrence vectors, then produces a top-N recommendation list for one user by aggregating similarity scores from their history — the whole pipeline in under 40 lines.
import numpy as np
from collections import defaultdict
# Interaction table: user -> set of items they've interacted with.
INTERACTIONS = {
"alice": {"item_hiking_boots", "item_tent", "item_compass"},
"bob": {"item_tent", "item_compass", "item_sleeping_bag"},
"carla": {"item_hiking_boots", "item_tent"},
"dev": {"item_novel", "item_cookbook"},
"erin": {"item_novel", "item_cookbook", "item_hiking_boots"},
}
def build_item_vectors(interactions):
# Represent each item as a vector over users who interacted with it.
users = sorted(interactions)
items = sorted({it for s in interactions.values() for it in s})
item_index = {it: idx for idx, it in enumerate(items)}
vecs = defaultdict(lambda: np.zeros(len(users)))
for u_idx, u in enumerate(users):
for it in interactions[u]:
vecs[it][u_idx] = 1.0
return vecs, items
def cosine(a, b):
denom = np.linalg.norm(a) * np.linalg.norm(b)
return float(np.dot(a, b) / denom) if denom else 0.0
def recommend(user, interactions, top_n=3):
vecs, all_items = build_item_vectors(interactions)
seen = interactions[user]
candidates = [it for it in all_items if it not in seen]
scored = []
for cand in candidates:
# score = sum of similarity to every item the user has already seen
sim_sum = sum(cosine(vecs[cand], vecs[seen_item]) for seen_item in seen)
scored.append((cand, sim_sum))
scored.sort(key=lambda x: x[1], reverse=True)
return scored[:top_n]
for user in INTERACTIONS:
recs = recommend(user, INTERACTIONS)
print(f"{user:>6} -> {recs}")python3 main.py