An embedding isn’t just useful for search — it’s also a powerful way to represent user preferences.
Think about how a feed works, like on YouTube. How do you recommend content to someone who loves funny cat videos versus someone who’s into programming tutorials?
Each video usually has tags, right? We can convert those tags into embeddings — mathematical representations of the video’s content.
Once everything is represented as embeddings, we can calculate similarity scores between the user's interests and available content.
But here’s the catch: if a user interacts with multiple videos, how do we combine those interests into a single preference embedding?
The answer: use a decay technique.
This means that recent interactions weigh more, while older ones slowly lose influence over time.
The code is as simple as it sounds.
First, you’ll need a column to store the user’s preference embedding — basically, a vector that represents their tastes.
👉 If you don’t know how to create one, check my previous tutorial! 😄
Now, let’s talk about the decay factor. I usually keep it between 0.1 and 0.25, meaning that we preserve 90% to 75% of the current preferences and update the rest based on the user’s latest action.
💡 Tip: If it’s the user’s first time, just save the embedding as is — no decay needed.
Here’s the full code:
const decayFactor = 0.1;
const decayEmbedding = preferenceEmbedding.map((value, index) => {
return value * (1 - decayFactor) + actionEmbedding[index] * decayFactor;
});
That’s it. Simple and effective.
Now, every time the user interacts with something — like watching a video or clicking on a product — you update their embedding using this formula.
Then, when they visit the feed, you simply run a similarity search based on their latest preferences.
A pro tip I highly recommend (and personally use) is to cache the user’s preference embedding using Redis, so you don’t need to fetch or compute it from scratch every time.
And guess what? That’ll be the topic of my next post.
See you soon, folks! 🚀
Top comments (0)