# Moviebox: recommending films by comparing plot summaries with tf-idf

> Moviebox is a small Python recommender that treats a film title as a bag of words: it vectorises the plot summaries of 5000 movies with tf-idf and ranks them by cosine similarity to the one you picked. It is an academic exercise from 2018 with a real command line interface, and it is a useful read precisely because the method is so simple.

**klaudiosinani/moviebox** — Machine learning movie recommending system

- Repository: https://github.com/klaudiosinani/moviebox
- Website: https://klaudiosinani.com/moviebox
- Stars: 537 · Forks: 54
- Language: Python
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/klaudiosinani-moviebox

## A recommender that only ever reads the plot

Moviebox is described in the readme as a content based machine learning recommending system built with tf-idf and cosine similarities. That phrase content based is the whole design in three words, and it excludes everything a modern recommender usually leans on.

There are no ratings here. There is no user profile, no collaborative filtering, no matrix factorisation, no learned embeddings. The only input is a film, and the only signal is the text of its plot summary. The similarity between two films is the similarity between two vectors of plot words.

The readme describes the flow. A natural number corresponding to the ID of a unique movie title is accepted as input from the user. The plot summaries of 5000 different movies in the dataset are analysed and vectorised through tf-idf. A number of movies is then chosen as recommendations based on their cosine similarity with the vectorised input movie. The cosine value of the angle between any two non-zero vectors, resulting from their inner product, is used as the primary measure of similarity, so that only movies whose story and meaning are as close as possible to the initial one are displayed.

That last clause, story and meaning as close as possible, is a claim worth pausing on. What tf-idf and cosine similarity actually measure is vocabulary overlap weighted by term rarity. Two films about pirates score highly together because they share words like ship, captain and sea, not because a reader would consider them similar in any meaningful sense. The readme is describing the intent of the method, and the method delivers something cruder than the intent.

For a teaching project that gap is the interesting part, since you can see exactly where the similarity comes from and where it breaks down.

## A fixed 5000 film dataset, and where it comes from

The dataset is the project's main constraint, and the readme is specific about it.

The file in use is a random subset of the Carnegie Mellon Movie Summary Corpus, and it consists of 5000 movie titles along with their respective categories and plots. The corpus it draws from is a well known research dataset of film plot summaries, and taking a random subset of it is a reasonable way to get a workable size without hand curating anything.

The consequence is that the entire knowledge of the system is 5000 plot summaries, frozen at the time the package was built. It cannot recommend a film released after the corpus was assembled, it cannot recommend anything outside that subset, and there is no update path. A new release means a new dataset file, which means a new version of the package.

The corpus ships with categories as well as plots, but the readme does not describe the recommender using the categories at any point. The described mechanism is tf-idf over the plot summaries, with the categories available in the data. That is worth checking in the source if you care about it, because categories would be a cheap improvement on vocabulary overlap, and it is not obvious from the documentation whether they are used or merely carried along.

The repository layout is consistent with a small research package. There is a moviebox/ directory holding the package, a bin/ directory, a docs/ directory, a fabfile.py for the build tasks, a movie-titles.md file, media/ for the header image, a requirements.txt and a setup.py. The package metadata lists the topics of Software Development and Scientific/Engineering and marks the operating system as independent.

## Installing on a modern Python is the first hurdle

The install instruction is a single pip command.

```bash
pip install moviebox
```

The readme states that Python 2.7+ or Python 3.4+ is required to install or build the code, and the package metadata puts it more precisely as python_requires of 2.7 and above with 3.0 through 3.3 excluded and less than 4. The classifiers in setup.py list Python 2.7 and then 3.4, 3.5 and 3.6.

Here is the practical problem. The requirements file pins its dependencies to versions from 2017 and early 2018: pandas 0.21.1, scikit-learn 0.19.1, scipy 1.0.0, click 6.2, termcolor 1.1.0 and colorama 0.3.9, plus setuptools 38.4.0, flake8 3.5.0 and yapf 0.20.0 for the development side. Several of those are very old releases of packages that have had breaking changes since.

scikit-learn 0.19.1 in particular predates the major API reorganisation of the library, and pandas 0.21.1 predates the current release series by many years. On a current Python, installing these from source is where the friction appears, and the pinned versions predate the availability of wheels for modern interpreter versions, so pip will attempt a build.

The install_requires in setup.py is looser than the requirements file, listing click, pandas, scikit-learn, termcolor and colorama without versions, so a plain pip install of the package from a wheel would pull current releases of those. Whether the code works against current releases of scikit-learn is a question the documentation does not answer, since the readme predates any of those releases.

If you want to run it today, the safer path is to work from a clone in a virtual environment, install the pinned requirements, and expect to work on the Python 3.6 era. The readme does not describe a supported upgrade path.

## The CLI is the best part of the package

The command line interface is where this project shows the most care, and it is the fastest way to understand what the library does.

The help output is a compact summary of the whole API surface.

```bash
$ moviebox --help

  Machine learning movie recommending system

  Usage
    $ moviebox [<options> ...]

  Options
    --help, -h              Display help message
    --search, -s            Search movie by ID
    --movie, -m <int>       Input movie ID [Can be any integer 0-4999]
    --plot, -p              Display movie plot
    --interactive, -i       Display process info
    --list, -l              List available movie titles
    --recommend, -r <int>   Number of recommendations [Can be any integer 1-30]
    --version, -v           Display installed version
```

Two things stand out. The ranges are stated in the help text itself, so a user is told that a movie ID is any integer from 0 to 4999 and that the number of recommendations is any integer from 1 to 30. And the option set covers the full workflow: list the available titles, search by ID, pick a movie, ask for a number of recommendations, optionally show the plot of each result, and toggle interactive output that displays process information while running.

The examples given are the same as the API example, using movie 2874, which the readme identifies as Asterix and Obelix: God save Britannia, with three recommendations.

The --interactive flag is the one to know about. Because the implementation is a batch vectorisation of 5000 documents, a run does real work and shows nothing while it happens, which is a bad experience for a user who has just typed a command. The interactive mode prints process information as it goes, which is a small thoughtful touch that many research packages skip.

The list of all movies with their IDs is published separately in movie-titles.md, so a user can pick a film without guessing a number between 0 and 4999.

## The Python API is one function with four arguments

The programmatic entry point is a single function imported from the recommender module.

```python
from moviebox.recommender import recommender

movieID = 2874  # Movie ID of `Asterix & Obelix: God save Britannia`
recommendationsNumber = 3  # Get 3 movie recommendations
showPlots = True  # Display the plot of each recommended movie
interactive = True  # Display process info while running

# Generate the recommendations
recommender(
    movieID=movieID,
    recommendationsNumber=recommendationsNumber,
    showPlots=showPlots,
    interactive=interactive)
```

The API documentation then describes each of the four parameters with a type, a default and whether it is optional. movieID is an Integer defaulting to 2874, with any integer between 0 and 4999 accepted. recommendationsNumber is an Integer defaulting to 3, with any integer between 1 and 30 accepted. showPlots is a Boolean defaulting to False, and controls whether the plot summary of each recommended film is displayed. interactive is a Boolean also defaulting to False, controlling whether process-related information is shown while running.

The defaults are chosen well for demonstration purposes. Running the function with no arguments at all produces three recommendations for the same Asterix and Obelix film, which is enough to see the shape of the output without reading any code.

The dependency on the console_scripts entry point in setup.py is that moviebox maps to moviebox.cli:main, so the command line and the library are the same code path. The click dependency in the requirements list and the termcolor and colorama packages explain where the coloured interactive output comes from, and colorama is there to make that colouring work on Windows.

One design note: the parameters are passed as keyword arguments in the example, and the parameter names in the function signature match the names documented in the API section exactly. There is no separate configuration object and no global state, which keeps the surface small.

## Where a plot similarity recommender falls short

The limitations are not subtle, and they are worth stating plainly if you are considering whether this approach fits your problem.

First, the similarity measure is lexical. Two films with completely different plots that happen to share common English words will be recommended to each other, and two films with genuinely similar stories told in different vocabulary will not. Term frequency and inverse document frequency weight words by rarity, which helps with common words, but it does nothing about synonyms, and it does nothing about the fact that a plot summary is a description rather than the film itself.

Second, there is no personalisation. You cannot ask for a recommendation for a person, only for a film. A system serving many users with the same underlying content similarity has no way to express taste, and the readme does not attempt it.

Third, the corpus is a decade-old academic dataset. It was assembled for research on plot summarisation, not for recommending films, and the plots are newspaper style summaries rather than structured metadata. There is no rating, no cast, no genre weighting, no popularity signal.

Fourth, the maintenance situation. The readme records the project as published on GitHub on January 23, 2018 and on the PyPI registry on January 26, 2018, and the listed releases stop at v0.3.0 from February 4, 2018, with v0.2.1 and v0.2.0 shortly before it. The last push to the repository was on 2026-07-23, so the repository is not archived, but a push is not a release and the version you can install from the registry is from 2018. The pinned dependency versions in requirements.txt are from that same period, which is the practical reason the package is awkward to install today.

On the alternative, the honest comparison is with a modern collaborative or hybrid recommender, which learns from what people actually watched and rated rather than from text. The difference in approach is fundamental. A content based system on tf-idf needs no interaction data at all, so it works on a cold catalogue and explains its reasoning, since you can show which terms matched. A collaborative system needs user behaviour, which it gets right for popular films and gets wrong for obscure ones, and it will happily recommend sequels. If your problem is a small catalogue with no user data, content based is a reasonable place to start, which is the argument Moviebox makes by being built this way in the first place.

The licence is MIT, so the code is free to use and modify with attribution, and the readme links to the licence file for the details. The authors are Mario Sinani and Klaudio Sinani.

## Conclusion

Moviebox suits a developer who wants to read a complete recommender end to end in an afternoon, or a student who needs a working example of tf-idf and cosine similarity applied to text, and it does not suit anyone building a recommendation service, because the dataset is a fixed 5000 film subset, the method ignores ratings and viewer behaviour entirely, and the package has not been released since v0.3.0 in February 2018. Before you build on it, check that its pinned dependencies still install on your Python version, since the requirements file lists pandas 0.21.1 and scikit-learn 0.19.1, and decide whether plot summary similarity is the signal you actually want.

## FAQ

### What is Moviebox and how does it recommend movies?

Moviebox is a content based recommender that vectorises the plot summaries of 5000 films with tf-idf and ranks them by cosine similarity to the film you selected. It takes a movie ID from 0 to 4999 and returns a number of recommendations between 1 and 30.

### How do I install Moviebox?

Run pip install moviebox. The readme states that Python 2.7 or Python 3.4 or newer is required, and the requirements file pins old versions of pandas and scikit-learn, so installing the pinned set on a current interpreter may need work.

### What dataset does Moviebox use?

A random subset of the Carnegie Mellon Movie Summary Corpus consisting of 5000 movie titles with their categories and plots. It ships inside the package as moviebox/dataset/movies.csv.

### What is the Moviebox Python API?

It is a single function, recommender, imported from moviebox.recommender. It takes movieID, recommendationsNumber, showPlots and interactive, all optional, with defaults of 2874, 3, False and False.

### Is Moviebox still maintained?

The repository is not archived and the last push was on 2026-07-23, but the published releases stop at v0.3.0 from 2018-02-04. The version available from the package registry is from 2018.

## Sources

- [klaudiosinani/moviebox on GitHub](https://github.com/klaudiosinani/moviebox)
- [License: MIT](https://github.com/klaudiosinani/moviebox/blob/master/LICENSE)
- [Project website](https://klaudiosinani.com/moviebox)
- [README](https://github.com/klaudiosinani/moviebox/blob/master/README.md)
- [Releases](https://github.com/klaudiosinani/moviebox/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/klaudiosinani-moviebox
