Netflix knows what you want to watch next. Spotify knows your mood before you do. Amazon surfaces the exact product you were thinking about. These are classic recommendation systems โ€” and they work well. But they have a fundamental limitation: they match patterns from the past. They don’t understand why you want something. Generative AI changes that.

This article explores how generative AI upgrades traditional recommendation systems โ€” and walks through practical implementation patterns you can apply today.

๐Ÿ” What’s Wrong with Traditional Recommendations?

Classic recommendation systems fall into two camps:

  • Collaborative filtering โ€” “People like you also liked X.” It looks at what similar users did and assumes you’ll behave the same way.
  • Content-based filtering โ€” “You liked this, so here’s something similar.” It matches item features to your past preferences.

Both approaches work, but they share a core weakness: they are backward-looking. They rely entirely on historical behaviour. They struggle with:

  • Cold start โ€” new users with no history get generic recommendations
  • Context blindness โ€” they don’t know if you’re shopping for yourself or as a gift
  • Intent gaps โ€” “I want something calming to read on a Sunday afternoon” is not a query a traditional system can handle
  • Explanation โ€” they can tell you what to read, not why it’s right for you

This is exactly where generative AI steps in.

๐Ÿง  What Generative AI Adds

A large language model doesn’t just match patterns โ€” it reasons about meaning. It can:

  • Understand natural language queries (“something like Inception but more grounded”)
  • Explain recommendations in human terms (“Based on your interest in local AI tools, you might enjoy…”)
  • Generate personalised summaries of why an item fits a user
  • Handle zero-shot cases โ€” making reasonable recommendations even with no user history
  • Combine structured data (ratings, categories) with unstructured context (reviews, descriptions, user notes)

The result is a system that feels less like a filter and more like a knowledgeable friend.

๐Ÿ—๏ธ The Architecture: Two Patterns

There are two main ways to integrate generative AI into a recommendation pipeline.

Pattern 1: LLM as the Ranker

The traditional system generates a candidate pool, and the LLM re-ranks them based on deeper context.

User Query
    โ†“
Traditional Retrieval (fast, broad) โ†’ 50 candidates
    โ†“
LLM Re-ranking (slow, precise) โ†’ Top 5 with explanations
    โ†“
User

This is the most practical pattern. The retrieval step handles scale; the LLM handles nuance.

Pattern 2: LLM as the Query Expander

The LLM enriches a vague user query before it hits the retrieval system.

User: "something relaxing for the weekend"
    โ†“
LLM expands โ†’ "calm, low-stakes, light fiction, nature themes, short chapters"
    โ†“
Semantic Search against content corpus
    โ†“
Ranked results

Both patterns can be combined for even better results.

๐Ÿ› ๏ธ Building It: Step by Step

Let’s build a simple generative AI-powered book recommendation system using Python. We’ll use sentence embeddings for retrieval and an LLM for re-ranking and explanation.

Install dependencies:

pip install sentence-transformers openai scikit-learn numpy

Step 1: Set up your content corpus

# A small book corpus โ€” in production this would be thousands of items
books = [
    {"id": 1, "title": "Atomic Habits", "description": "A practical guide to building good habits and breaking bad ones through small, consistent changes."},
    {"id": 2, "title": "The Hitchhiker's Guide to the Galaxy", "description": "A comedic science fiction adventure about the end of the Earth and one man's journey across the universe."},
    {"id": 3, "title": "Deep Work", "description": "How to focus without distraction on cognitively demanding tasks to produce high-quality work."},
    {"id": 4, "title": "Project Hail Mary", "description": "A lone astronaut wakes up with no memory and must save Earth from an extinction-level threat."},
    {"id": 5, "title": "The Pragmatic Programmer", "description": "Timeless advice and best practices for software developers to write better, more maintainable code."},
    {"id": 6, "title": "Sapiens", "description": "A sweeping history of humankind, from early humans to the modern age, examining how Homo sapiens came to dominate the planet."},
    {"id": 7, "title": "Thinking, Fast and Slow", "description": "An exploration of the two systems of thought that drive human decisions โ€” intuition and deliberate reasoning."},
    {"id": 8, "title": "The Martian", "description": "An astronaut stranded on Mars must use his ingenuity and science skills to survive until rescue arrives."},
]

Step 2: Build the semantic retrieval layer

from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

model = SentenceTransformer('all-MiniLM-L6-v2')

# Pre-compute embeddings for all books
corpus_texts = [f"{b['title']}. {b['description']}" for b in books]
corpus_embeddings = model.encode(corpus_texts)

def retrieve_candidates(query, top_n=5):
    """Fast semantic retrieval โ€” returns top N candidates."""
    query_embedding = model.encode([query])
    scores = cosine_similarity(query_embedding, corpus_embeddings)[0]
    top_indices = np.argsort(scores)[::-1][:top_n]
    return [(books[i], float(scores[i])) for i in top_indices]

Step 3: LLM re-ranking and explanation

import openai
import json

client = openai.OpenAI(api_key="your-api-key")

def rerank_and_explain(user_query, candidates, user_context=""):
    """Use an LLM to re-rank candidates and generate personalised explanations."""

    candidate_list = "\n".join([
        f"{i+1}. {c['title']}: {c['description']}"
        for i, (c, _) in enumerate(candidates)
    ])

    prompt = f"""You are a personalised book recommendation assistant.

User request: "{user_query}"
{f'Additional context about the user: {user_context}' if user_context else ''}

Here are candidate books retrieved by a search system:
{candidate_list}

Task:
1. Re-rank these books from most to least relevant for this specific user request.
2. For the top 3, write a one-sentence personalised explanation of why it fits.
3. Return a JSON array with fields: title, rank, explanation.

Return only valid JSON, no other text."""

    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.3
    )

    try:
        return json.loads(response.choices[0].message.content)
    except json.JSONDecodeError:
        return []

Step 4: The LLM query expander

def expand_query(vague_query):
    """Turn a vague user request into a rich search query."""
    prompt = f"""A user is looking for a book recommendation and said: "{vague_query}"

Expand this into a detailed search description (2-3 sentences) that captures the likely intent, mood, themes, and type of content they want. Be specific. Return only the expanded description, no other text."""

    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.5
    )
    return response.choices[0].message.content.strip()

Step 5: Wire it all together

def recommend(user_query, user_context="", expand=True):
    print(f"\n๐Ÿ“š Finding recommendations for: '{user_query}'\n")

    # Optionally expand vague queries
    search_query = expand_query(user_query) if expand else user_query
    if expand:
        print(f"๐Ÿ” Expanded query: {search_query}\n")

    # Retrieve candidates semantically
    candidates = retrieve_candidates(search_query, top_n=5)

    # Re-rank and explain with LLM
    results = rerank_and_explain(user_query, candidates, user_context)

    print("๐ŸŽฏ Top Recommendations:\n")
    for item in results:
        print(f"{item['rank']}. {item['title']}")
        print(f"   โ†’ {item['explanation']}\n")

# Try it out
recommend(
    "something to help me think more clearly and make better decisions",
    user_context="software developer, reads mostly non-fiction"
)

Sample output:

๐Ÿ“š Finding recommendations for: 'something to help me think more clearly...'

๐Ÿ” Expanded query: The user wants a non-fiction book about improving
cognitive clarity, decision-making frameworks, and rational thinking...

๐ŸŽฏ Top Recommendations:

1. Thinking, Fast and Slow
   โ†’ Directly addresses how your two thinking systems influence decisions,
     essential reading for anyone wanting to reason more deliberately.

2. Deep Work
   โ†’ Teaches you to eliminate cognitive noise and focus deeply, a practical
     complement to understanding how good thinking actually happens.

3. Atomic Habits
   โ†’ Building systematic habits around how you think and work compounds
     over time into dramatically better decision-making.

โšก Using a Local LLM Instead

Don’t want to pay for API calls? Swap the OpenAI client for Ollama running Gemma 4 locally. The only change needed:

client = openai.OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama"  # required but unused by Ollama
)
# Then use model="gemma4" in your completions calls

Complete privacy, zero API cost, same results.

๐Ÿ”ฎ Where This Is Already Happening

This isn’t theoretical โ€” generative AI is actively reshaping recommendations in production:

  • Spotify uses LLMs to understand the mood and context behind listening sessions, not just track history
  • Amazon generates personalised product descriptions based on what it knows about your purchase intent
  • Netflix is experimenting with LLM-generated synopses tuned to individual taste profiles
  • GitHub Copilot is essentially a recommendation engine for code โ€” suggesting the most contextually relevant completion based on everything in your file

๐Ÿงฉ Key Takeaways

The shift from traditional to generative AI recommendations isn’t about replacing what works โ€” it’s about adding a layer of understanding on top of retrieval. The practical stack looks like this:

LayerTechnologyRole
RetrievalSentence embeddings + cosine similarityFast, scalable candidate generation
UnderstandingLLM (GPT-4o, Gemma, Llama)Query expansion, re-ranking, explanation
PersonalisationUser context in the promptTailoring results to the individual

Start with the retrieval layer โ€” it’s fast and free. Add the LLM layer when you need nuance. The combination is more powerful than either alone, and as the earlier article on building a question recommendation engine showed, the retrieval foundation is something you can set up in an afternoon.