FilmYar: The Story of a Bachelor's Project — When a Knowledge Graph Meets Generative AI
Final Bachelor's Project in Computer Engineering
Where Did This Project Start?
For our final Bachelor's project in Computer Engineering, we decided to work on a topic that wasn't just a classroom exercise, but a real, working system: a movie recommendation assistant called FilmYar, whose answers are pulled not from a language model's guesses, but from within a real knowledge graph. This approach is known these days as GraphRAG (graph-based Retrieval-Augmented Generation).
The Project at a Glance
FilmYar is a web-based chatbot that answers movie-related questions in both Persian and English (automatically, based on the language of the user's question): recommending movies by genre, actor, director, or release year; providing IMDB ratings; and suggesting similar movies. What sets this project apart from many similar chatbots is that the real movie information (cast, director, genre, rating) is read from a knowledge graph built in Neo4j, and the language model's only job is to express this information naturally and fluently — not to construct it from its own memory.
System Architecture: Five Stages to Reach an Answer
Every message the user sends follows this path:
| Stage | Description |
|---|---|
| Entity Extraction | The user's free text is analyzed (without any involvement of the language model, purely with programming logic, Regex, and fuzzy matching) to extract the genre, actor, director, or year name |
| Knowledge Graph Query | A Cypher query is run against the Neo4j graph using the extracted entities |
| Fallback to Web Search | If the local graph finds nothing, it automatically turns to web search (DuckDuckGo) |
| Response Generation with the Language Model | The information found is placed into a prompt template and given to a generative language model (LLaDA-8B, from the diffusion model family) to write the final response |
| Communication Layer | A Flask server receives requests from a dedicated chat page and makes it publicly accessible via a Cloudflare tunnel |
Keeping the entity extraction stage separate from the language model was a deliberate design decision: language models — especially diffusion models like LLaDA — do not perform reliably at generating precise, structured output (such as a database query); for this reason, this part is handled entirely by the program's deterministic logic, and the language model is only used at the very last step, for "speaking."
Using a diffusion language model instead of the more common autoregressive models (such as the GPT family) was also one of the exploratory aspects of this project — an experience that showed different behaviors and limitations compared to more conventional models.
Technology Stack
| Area | Tool / Technology |
|---|---|
| Knowledge Graph | Neo4j (Community Edition) |
| Generative Language Model | LLaDA-8B-Instruct, with 4-bit quantization |
| Natural Language Processing | spaCy, Regex, fuzzy matching with rapidfuzz |
| Backend | Python, Flask, Flask-CORS |
| Deep Learning Infrastructure | PyTorch, Transformers, Accelerate, BitsAndBytes |
| Web Search | DuckDuckGo Search, along with optional support for the Tavily API |
| Data Processing | Pandas |
| Runtime Environment | Google Colab (with free T4 GPU) |
| Persistent Dataset Storage | Google Drive |
| Public Service Access | Cloudflare Quick Tunnel |
| User Interface | HTML, CSS, JavaScript |
Key Features
- Bilingual responses (Persian/English) with automatic detection of the question's language
- Information based on real data, not the language model's guesses
- Fallback mechanism to web search in the absence of local data
- The dataset is uploaded to the user's Google Drive only once, and there is no need to repeat this in subsequent runs
- Runs entirely on Google Colab's free infrastructure, without needing any dedicated server
- Standalone web user interface, separate from the notebook environment
Technical Challenges During Development
Running an 8-billion-parameter language model on free infrastructure came with real engineering challenges, each of which required a specific solution:
| Challenge | Solution Adopted |
|---|---|
| The 8-billion-parameter model did not fit on the free GPU (T4, 15GB VRAM) | 4-bit quantization of the model with bitsandbytes |
| Risk of out-of-memory (OOM) errors due to the diffusion model's iterative sampling process (up to 48 steps per response) | Using torch.inference_mode() and explicit CUDA cache clearing between steps |
| Leakage of instruction/context text into the model's final response | Adding a specific marker ("Final answer:") at the end of the prompt and cleaning the output based on it |
| Slowness of the first response due to lazy model loading, which exceeded the public tunnel's time limit | Actively loading the model immediately after the server starts up, before receiving the first request |
| Version incompatibility of bitsandbytes with Colab's updated CUDA setup | Upgrading to versions of bitsandbytes/accelerate that had rewritten the CUDA detection mechanism |
| Differences in column naming across different versions of the IMDB dataset | Automatic and conditional mapping of column names |
A Limitation That Still Remains
In all honesty, this project also faces an unresolved challenge: the local dataset (TMDB 5000 and IMDB Top 1000) mainly covers Hollywood cinema. For actors or movies outside this domain, both the local graph and free web search may return poor or irrelevant results; in such cases, the diffusion language model sometimes, instead of explicitly stating "no information found," offers an incorrect mixture from its pretrained knowledge. This is one of the clear areas for continuing work on the project: expanding dataset coverage, and strengthening mechanisms to prevent incorrect responses.
Datasets Used
- TMDB 5000 Movie Dataset: basic movie information including genre, cast, and director
- IMDB Top 1000: IMDB ratings to complete information for shared movies
Usage Guide
FilmYar runs entirely on Google Colab; there is no need to install anything on a personal system.
- Download the project's notebook from the GitHub repository: Project GitHub repository link
- Open the
.ipynbfile in Google Colab. - From the Runtime menu, select Change runtime type and enable GPU (T4 type).
- Run the cells in order, from top to bottom.
- In the dataset loading cell, a Google Drive access request will be shown; approve the access.
- Download the dataset files from this path and upload them at that same step: Dataset download link From this point on, the datasets remain stored in your Google Drive, and there is no need to repeat this step in subsequent runs.
- At the end of the run, you will receive a public link (Cloudflare Tunnel).
- Open the chat page (
ai.movie.salehaskari.ir) in your browser, enter the public link in the "Connect to server" section, and start the conversation. Chat page
Note: For as long as you are using the assistant, the last cell of the notebook (the server and tunnel) must not be stopped, and the Colab tab must remain open and active.
Summary
FilmYar was an opportunity for us to experience the GraphRAG approach not just theoretically, but in the form of a real, working system — a system in which the language model's response is rooted in real, structured data. Along the way, we grappled with tangible software engineering and machine learning challenges — from careful GPU memory management to the sometimes unpredictable behavior of generative language models — an experience whose value went beyond the thesis grade.
Acknowledgments
In closing, we sincerely thank the supervisor of this project, Dr. Baghmohammadi, for his guidance, precise feedback, and support throughout this journey. His careful attention and advice played an important role in shaping and improving the quality of this project.