Welcome back! In the last few lessons, you learned how to turn music tracks and user preferences into vectors, use cosine similarity for recommendations, and group tracks into clusters. Now, you are ready to see how all these pieces come together in a real-world application.
In this lesson, you will learn how to expose your recommendation logic through API endpoints. These endpoints allow your music app to deliver personalized track suggestions, show how tracks are grouped, and let users inspect their own listening profiles.
Before jumping into the code, it’s helpful to understand the purpose of each endpoint:
- A recommendation endpoint helps deliver real-time track suggestions.
- A cluster summary endpoint lets users or developers explore how the music library is organized.
- A user profile endpoint exposes the internal representation (embedding) of a user’s taste — useful for debugging or building transparency features.
These endpoints don’t just return data — they act as bridges between the machine learning logic and a real frontend or client.
Before we dive into the new endpoints, let’s quickly remind ourselves how the app is set up. You have a Flask application that loads track data, computes embeddings, and prepares everything needed for recommendations. Here’s a summary of the setup:
This code ensures that your app is ready to serve recommendations as soon as it starts. If you are using CodeSignal, these libraries and data will already be set up for you.
The main endpoint for delivering personalized track suggestions is:
Let’s break down how this works:
<user_id>: The ID of the user you want recommendations for.top_n(optional): How many recommendations to return (the default is 5).
Here’s the relevant code:
What happens here?
- The endpoint reads the
top_nparameter and checks if it’s a valid positive integer. - It calls
recommend_tracks_by_similarity(user_id, top_n)to get the best track IDs for the user. - If there are no recommendations (for example, if the user is new), it returns an empty list with a helpful message. This case is known as the cold start problem in recommendation systems. Since the system doesn't yet know the user’s preferences, it can't generate a profile vector. In a production app, you'd typically fall back to popular tracks or ask the user to rate a few songs first.
Another useful endpoint is:
n_clusters(optional): How many clusters to group tracks into (the default is 3).
Here’s the code:
What does this do?
- Reads the
n_clustersparameter and checks if it’s valid. - Calls
assign_track_clusters(n_clusters)to group tracks. - For each cluster, collects the track IDs, titles, and genres.
- Returns a summary of all clusters.
The cluster summary endpoint is especially useful for debugging and UI exploration. It lets you answer questions like:
- “Which songs are grouped together?”
- “What type of content does cluster 1 contain?”
- “Are similar genres or moods appearing in the same cluster?”
It’s also useful if you want to build features like “Browse by mood” or “Explore by cluster.”
Example output:
The last endpoint in this lesson is:
<user_id>: The ID of the user whose profile you want to inspect.
Here’s the code:
What does this do?
- Calls
generate_user_profile_vector(user_id)to get the user’s embedding. - If the user has no listening history, it returns an empty vector and a message.
- Otherwise, it returns the user’s profile vector and its dimension.
Example output for a user with a profile:
Example output for a new user:
This endpoint is helpful for debugging and understanding how user preferences are represented in your system. The profile vector is the mean embedding of all tracks a user has listened to. You can think of it as a mathematical summary of their musical taste. While the numbers may not be human-readable, they power the similarity comparisons used for recommendations.
If you want to visualize or analyze a user’s taste shift over time, you could compare their profile vectors before and after a given period.
Let’s quickly recap the flow from data to endpoint:
get_all_tracks()loads your track metadata (genre, mood, tempo, etc.).get_track_embeddings()transforms this metadata into vector format (using one-hot + scaled numerical features).generate_user_profile_vector(user_id)averages the vectors of the user’s listened tracks.recommend_tracks_by_similarity()compares that profile vector to all track vectors using cosine similarity.- The Flask endpoint simply serves the results to external clients (like a web app or mobile frontend).
Each endpoint is therefore just an interface — the heavy lifting is already done in user_model.py and recommend.py.
Security Note: In this simplified environment, all API routes are public for demonstration purposes. In a real-world app, you would need to authenticate users and protect endpoints like
/recommendationsand/profile-vectorto prevent unauthorized access to private user data.
In this lesson, you learned how to expose your recommendation logic through three key API endpoints:
- The embedding-based recommendation endpoint for personalized track suggestions
- The clusters summary endpoint for viewing how tracks are grouped
- The user profile vector endpoint for inspecting user preferences
These endpoints are the foundation for building interactive and personalized music experiences. In the next section, you will get hands-on practice using these endpoints, making requests, and interpreting the results. This will help you solidify your understanding and prepare you to build even more advanced features.
