Building a Movie Recommendation Engine with Hugging Face and Voyage AI
This guest blog post is from Arek Borucki, Machine Learning Platform & Data Engineer for Hugging Face - a collaboration platform for the machine learning community. The Hugging Face Hub works as a central place where anyone can share, explore, discover, and experiment with open-source ML. HF empowers the next generation of machine learning engineers, scientists, and end users to learn, collaborate and share their work to build an open and ethical AI future together. With the fast-growing community, some of the most used open-source ML libraries and tools, and a talented science team exploring the edge of tech, Hugging Face is at the heart of the AI revolution. Traditional movie search relies on filtering by genre, actor, or title. But what if you could search by how you feel? Imagine typin
This guest blog post is from Arek Borucki, Machine Learning Platform & Data Engineer for Hugging Face - a collaboration platform for the machine learning community. The Hugging Face Hub works as a central place where anyone can share, explore, discover, and experiment with open-source ML. HF empowers the next generation of machine learning engineers, scientists, and end users to learn, collaborate and share their work to build an open and ethical AI future together. With the fast-growing community, some of the most used open-source ML libraries and tools, and a talented science team exploring the edge of tech, Hugging Face is at the heart of the AI revolution.
Traditional movie search relies on filtering by genre, actor, or title. But what if you could search by how you feel? Imagine typing:
"something uplifting after a rough day at work"
"a movie that will make me cry"
"I need adrenaline, can't sleep anyway"
"something to watch with grandma who hates violence"
This is mood-based semantic search: matching your emotional state to movie plot descriptions using AI embeddings.
In this tutorial, you will build a mood-based movie recommendation engine using three powerful technologies: voyage-4-nano (a state-of-the-art open-source embedding model), Hugging Face (for model and dataset hosting), and MongoDB Atlas Vector Search (for storing and querying embeddings at scale).
Why mood-based search?
Genre tags are coarse. A "drama" can be heartwarming or devastating. A "comedy" can be light escapism or dark satire. Traditional filters cannot capture these nuances.
Semantic search solves this by understanding meaning. When you search for "feel-good movie for a rainy Sunday", the system doesn't look for those exact words. It understands the intent and matches it against plot descriptions that evoke similar feelings.
Architecture overview
The system combines three components from the Hugging Face ecosystem with MongoDB:
voyage-4-nano (Hugging Face Hub): Converts text to embeddings (up to 2048 dimensions, we use 1024)
MongoDB/embedded_movies(Hugging Face Datasets): 1500+ movies with plot summaries, genres, cast
MongoDB Atlas Vector Search: Stores embeddings and performs similarity search
Understanding voyage-4-nano
voyage-4-nano is the smallest model in Voyage AI's latest embedding series, released with open-weights under the Apache 2.0 license. Voyage AI was acquired by MongoDB, and the Voyage 4 series models are now available through MongoDB Atlas. All models in the series (voyage-4-large, voyage-4, voyage-4-lite, and voyage-4-nano) produce compatible embeddings in a shared embedding space, allowing you to mix and match models within a single use case.
Although voyage-4-nano natively supports embeddings up to 2048 dimensions, we deliberately truncate them to 1024 dimensions using its Matryoshka embedding property. In practice, this provides a strong balance between semantic quality, storage efficiency, and vector search latency, while preserving stable ranking behavior.
Sentence Transformers
This tutorial uses Sentence Transformers, a Python library built on top of Hugging Face Transformers. It is specifically designed for working with embedding models and provides a simple API for generating text embeddings.
Why Sentence Transformers instead of raw Transformers? When working with embedding models, you need to handle tokenization, pooling, normalization, and prompt formatting. Sentence Transformers does all of this automatically in a single method call. The code is cleaner, there are fewer potential errors, and you get built-in features like batch processing with progress bars.
Under the hood, Sentence Transformers still uses Hugging Face Transformers to load and run the model.
Configure the development environment
Let's get started!
Create the Project Structure
Code Snippet
Install dependencies
Create the requirements.txt file:
Code Snippet
Create a Python virtual environment and install dependencies:
Code Snippet
Run MongoDB Atlas locally
Use Atlas CLI to create a local deployment with Vector Search support:
Code Snippet
Choose local when prompted. Once ready, you'll receive a connection string like:
Code Snippet
Configure environment variables
Create the .env file:
Code Snippet
I use 1024 dimensions as a balance between retrieval quality and storage efficiency. You can experiment with 2048 (max retrieval quality) or 512 (faster queries).
Implement system components
Database module
The database module manages MongoDB connections and creates the vector search index. The index must match the embedding dimensions specified in our configuration.
Code Snippet
AI module with voyage-4-nano
The AI module loads voyage-4-nano from Hugging Face Hub and provides methods for generating embeddings. We use the sentence-transformers library for a clean API.
Code Snippet
voyage-4-nano uses different prompts for queries and documents:
encode_query() prepends: "Represent the query for retrieving supporting documents:"
encode_document() prepends: "Represent the document for retrieval: "
This asymmetric encoding improves retrieval quality.
Data indexing module
The indexer downloads the movie dataset from Hugging Face, generates fresh embeddings with voyage-4-nano, and stores everything in MongoDB.
Code Snippet
Search API
The FastAPI application exposes the mood-based search endpoint. Users describe their mood, and the system returns semantically matching movies.
Code Snippet
Package initialization
Code Snippet
Project structure
Your final project structure should look like this:
Code Snippet
Run and test
Index the data
First, run the indexer to download movies from Hugging Face and generate embeddings:
Code Snippet
Expected output:
Code Snippet
Start the API server
Code Snippet
Test mood-based queries
Query 1: Feel-good movie after a tough day
Code Snippet
Response:
Code Snippet
The system returned action films with themes of personal transformation and helping others. Scores around 0.65 show moderate similarity because "uplifting" is an abstract concept that does not appear directly in plot text.
Query 2: Emotional catharsis
Code Snippet
Response:
Code Snippet
The system found films with emotionally heavy themes. "Tae Guk Gi" is a war drama about brothers forced to fight against each other. "Split Decisions" deals with loss and revenge after a boxer's death. The word "tears" in "The Wedding Party" plot directly matched the query's emotional intent.
Query 3: With filters
Code Snippet
Response:
Code Snippet
With strict filters (rating >= 7.5, genre = Action), only one movie matched. Notice the significantly higher score of 0.761 compared to previous queries. The phrase "exciting adventure" directly aligns with "over-the-top action" in the plot description. This demonstrates that concrete, descriptive mood queries produce stronger semantic matches than abstract emotional ones.
Key observations
Abstract mood queries ("uplifting", "emotionally moved") score 0.62 to 0.67
Concrete descriptions ("exciting adventure") score 0.75+
Filters help find better matches even with fewer results
The system understands themes even without exact word matches
Comparing embedding dimensions
One unique advantage of voyage-4-nano's Matryoshka embeddings is the ability to experiment with different dimensions. Let's compare how dimension choice affects results.
Create a test script:
Code Snippet
Run the script:
Code Snippet
Result:
Code Snippet
In this example, all three dimension settings correctly rank the plots in the same order: the friendship story scores highest, the robot companion story is second (thematically related through companionship), and the violent thriller scores lowest.
The key differences:
Discrimination gap: With 2048 dimensions, the gap between the best match (0.4496) and worst match (0.1472) is 0.302. With 256 dimensions, the gap is larger at 0.397 (0.4139 minus 0.0168). Interestingly, lower dimensions can produce wider gaps due to more aggressive compression of the embedding space, but this doesn't necessarily mean better quality. The absolute similarity scores are lower and less reliable.
Ranking stability: In many cases, the top-ranked results will remain consistent across dimensions. However, lower dimensions will see a slight decrease in retrieval quality compared to the full 2048-dimensional vector.
When dimensions matter: If your application requires maximum accuracy and the ability to distinguish between very fine semantic nuances, higher dimensions are the best choice. However, if you have constraints around storage costs and query latency, lower dimensions may be a better fit, as they offer significant efficiency gains with only a marginal trade-off in retrieval precision.
Practical recommendation: Start with 1024 dimensions as a balanced default. Drop to 512 if storage is a concern. Use 2048 only when you need maximum precision for nuanced queries.
megaphone
Next Steps
Sign in to highlight and annotate this article

Conversation starters
Daily AI Digest
Get the top 5 AI stories delivered to your inbox every morning.
More about
modeltransformerreleaseAnthropic Leak Exposes Claude Mythos Model and Security Concerns - Startup Fortune
<a href="https://news.google.com/rss/articles/CBMilwFBVV95cUxOajhiTVRfRjczdXlXemZWRk1EX1B5ZXlQOXA4Zk5YckMza043SGxKM0pUMUstRlZtN3UtUGRJTmk3aUV4ZzFOTGdQZWN0QURWU1ZRS0QtMS1RZzNkcUZuTVItd0lvUVJ3TGVHdnZZcUx1ZGxGdlIyek04MmduYlhqMjBWR0RfbEliSFFIblpMZGNSaFJBbkVr?oc=5" target="_blank">Anthropic Leak Exposes Claude Mythos Model and Security Concerns</a> <font color="#6f6f6f">Startup Fortune</font>
MLCommons Releases New MLPerf Inference v6.0 Benchmark Results - GlobeNewswire
<a href="https://news.google.com/rss/articles/CBMizwFBVV95cUxQR1BTNkQxc01RMy1hUExQbU5jdFZDWWRsMEx2LVI1eGpnMDZFMVp2Wno2VFVhTlJieDhkQUVhMEc5Q25xVGpCRmJVeC1pcW1oaDh4Wl9JeHpNbmtTY25hVjdIMUFmaklBanh1VFVNRmtBUTN5TmpPVjlBbklONzc2LWpGT0l1aGZSNHhnZDluZ19JV1BCeHJ4cXAzWXFGYXEzbllUNm9TQ1NLM04yMVhSTjduN0ItUXR1Zl9yYmd1WjNJVDhETHI0VHBjUmV2dWc?oc=5" target="_blank">MLCommons Releases New MLPerf Inference v6.0 Benchmark Results</a> <font color="#6f6f6f">GlobeNewswire</font>
Anthropic Faces Second AI-Related Exposure Incident as Claude Code Files Are Accidentally Released - AI Insider
<a href="https://news.google.com/rss/articles/CBMi0gFBVV95cUxNS1dkSFNkTVFoU0NHRXdQQ0lZUFhUd0RrOEJqYVZMRTZMQWlJV1R2Z0piSHVMRmh4dGpvcmotTXMxMy1YX1Flb2R4Nm16NTYxb3ktdWVHU183cjNLbWxEYTZIakZzOUZ4blhxRkhSUjEyYXVMcTAxQTNBM3dhYnFlSXctUk9HMktqa0YxVzB6MnhES2tpdWVXZXR5UUplTERUQXg2ZGo3TVVuX19ETHNGSU1kc1VWcGlyUmV4azRtYkNJTlhiLVE1WElVcDIyWlNkTGc?oc=5" target="_blank">Anthropic Faces Second AI-Related Exposure Incident as Claude Code Files Are Accidentally Released</a> <font color="#6f6f6f">AI Insider</font>
Knowledge Map
Connected Articles — Knowledge Graph
This article is connected to other articles through shared AI topics and tags.
More in Releases
Penguin Ai Launches Gwen, a Build-Your-Own AI Platform for Healthcare Operations - aithority.com
<a href="https://news.google.com/rss/articles/CBMiuwFBVV95cUxNdEt4ZHQ5a0FrUVRwQ2hKblgtbmVyNnVib3RPTXBubnotWkkyVVRjOF85YVNHV1ZVTzJ2eXNCdk9iVmk2ZWFHRGgxb0pVeFlDcGJZdW9MNHBDOEJueGVjcUZUTU5MX2R6bzJsemdVRExCWlp5UW5haHE3bzVCZ1Q5NVJTTWZSeXBsVl9MRDRLRk9jSVhGc0ljTG1CbzRNN1VtZXA1OTYxeThQUUxzckZuZE5qWERQR0k5SS13?oc=5" target="_blank">Penguin Ai Launches Gwen, a Build-Your-Own AI Platform for Healthcare Operations</a> <font color="#6f6f6f">aithority.com</font>
SEAS Researchers Expose Hidden “Alignment Discretion” Shaping AI Behavior - Harvard School of Engineering and Applied Sciences
<a href="https://news.google.com/rss/articles/CBMiowFBVV95cUxONEZoeldndUE2ZUZsSkloQmZVMk1jZUhncUY0V3c5NDQ0TlNLVTluWkppejlpOVdpemxqNEVvaDAwbG43VWpxOFpuakFtRDNLUlVTbEwzR25kYnJieVdkSEs0MVRESHpPSHN6dEhXUk9qVGRlVjFhT2ZqVjlJV056MG94MDN3dWVCSUtoRWVDODF5bVVET2gxQW5DSk1oT1pUNlVB?oc=5" target="_blank">SEAS Researchers Expose Hidden “Alignment Discretion” Shaping AI Behavior</a> <font color="#6f6f6f">Harvard School of Engineering and Applied Sciences</font>
How Artificial Intelligence Is Reshaping Canadian Real Estate Development Decisions - newswire.com
<a href="https://news.google.com/rss/articles/CBMipgFBVV95cUxNQUhzdXV2RDgtLWZ2MF9IU3VwWV9yOW9OSzE5aXZBS0ctZzRWaVJ2Vm9DUEJxcksyVFRjM2JpZVliendKZ0RsZ3E0Z3JqX3VYUnoxNXZjNnVOdUpRUUR0YUVKWW51V19jS3h1QlNzZTBtNzk5NXVmbDhIbWpjUzMxQlMwM2VxYlR0VjVjaHVfMFRNbXdlalE3b2Nad2lxeTRZLXc5WWVB?oc=5" target="_blank">How Artificial Intelligence Is Reshaping Canadian Real Estate Development Decisions</a> <font color="#6f6f6f">newswire.com</font>
AI Guardrails by Zapier Gives Teams Inline Safety Checks for Every AI-Powered Workflow - citybiz
<a href="https://news.google.com/rss/articles/CBMiwwFBVV95cUxQYnF4UHY5NkdscDd5b1VsOUhCLXpOd2Zjdy16YW93NkxRVXdRV1FiazdEaDFwMXVXSnRLYWltSGpoNkZQRHpyRGpUZGo2UVdaQXJPeVptWU9HTFd6Y203dmNhX3dvcGF5cnppQ2M4T1M0VWtPZnlUYThCUXh2cHVQUDNBX0wwbkRwR0c2YkZhTWhHSHY2b1hQS1ZDdXdRbm9adGdHYTZuQjNDN255Z2s4ZHdwRkRJUmpNRENzd29aM3NjSEE?oc=5" target="_blank">AI Guardrails by Zapier Gives Teams Inline Safety Checks for Every AI-Powered Workflow</a> <font color="#6f6f6f">citybiz</font>
Discussion
Sign in to join the discussion
No comments yet — be the first to share your thoughts!