flickpick
A personal movie recommender you can run in a browser, built so that AI agents can pick movies for you. It learns from your own ratings, scores the whole catalogue client-side, lets you ask for a mood ("slow-burn melancholic sci-fi, nothing gory"), and shows where a film streams and how the public rated it. A "for scientists" page compares your taste with the population's and measures how well the recommender does on your own history.
Try it in two commands
pip install "flickpick[embed]"
python -m flickpick build --sample --out ./artifacts # a small artifact set from MovieLens ml-latest-small
python -m flickpick recommend --artifacts ./artifacts --ratings my_ratings.csv --mood "slow-burn melancholic sci-fi" --exclude-genre Horror
my_ratings.csv can be a Letterboxd, IMDb or MovieLens export, or flickpick's own format (see flickpick/data/examples/movie_ratings_various.csv). Drop --sample to build from MovieLens ml-32m (about 10,000 films; a few minutes). Drop [embed] and add --no-embeddings if you do not want mood search.
The same core exists in TypeScript (js/, npm flickpick) and runs in the browser; the web app is in web/. From a fresh clone (Node 20 or later):
cd js && npm ci && npm test && npm run build # the TypeScript core; CLI: node dist/cli.js recommend --artifacts ../tests/fixtures/artifacts_small --ratings <csv>
cd web && npm install && npm run dev # the web app; dev, build and test build ../js first when it is missing or stale
How it works
- Offline build (Python). MovieLens ratings train an EASE item-item model (a closed-form linear recommender that matches or beats most neural models on this kind of data), sparsified to the top neighbours per film. Each film's genres and community tags are embedded with a small sentence-embedding model. Everything is written as plain typed-array files plus JSON (
docs/artifact-format.md). - Scoring (TypeScript in the browser, or Python). Your liked films select rows of the item-item matrix; their sum is your collaborative score for every film. A mood is embedded on the fly and compared with every film by cosine. Structured filters apply, the components are rank-normalised and combined, and each result carries its reasons ("because you liked …", "close to …").
- The LLM, when you add one, parses and explains. It never ranks. The ranking is deterministic and inspectable.
- Science. Hold-out evaluation of the recommender on your own ratings with confidence intervals; agreement statistics between your scores and the population's; cross-validated fits.
The design decisions and the research behind them are in docs/architecture.md and docs/research/ (start with the synthesis).
Data and licensing
Shipped artifacts are built only from openly usable sources: MovieLens (research, non-commercial, share-alike on transformations), Wikidata (CC0) and Wikipedia (CC BY-SA) in later versions. Posters, overviews, certifications and streaming availability come live from TMDB (and JustWatch through TMDB) with your own API key, are shown for display only, are cached locally for at most six months, and are never fed to the recommender or to an LLM, because TMDB's API terms exclude ML/AI applications. This product uses the TMDB API but is not endorsed or certified by TMDB.
Your ratings stay in your browser (or in the file you point the CLI at) unless you export them.
Layout
| Path | What |
|---|---|
flickpick/ |
Python package: build pipeline, EASE, scorer, importers, science, CLI (python -m flickpick) |
js/ |
TypeScript core (npm flickpick): the same scorer, importers and science for browser and Node, with a CLI |
web/ |
Vite + React web app over js/ |
tests/ |
Python tests and the small fixture artifact set |
docs/ |
architecture, artifact format, core contract, research |
Status
v1: Python and TypeScript cores with parity tests, CLI on both, the web app, MovieLens-only catalogue. Next: Wikidata and Wikipedia catalogue, LLM "vibe profiles", MCP server and in-app assistant, remote MCP for claude.ai connectors, int8 artifacts, a published data package.
Metadata
Release files for flickpick 0.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| flickpick-0.0.3.tar.gz | 1.4 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| flickpick-0.0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.4 MB
Release files / flickpick-0.0.3.tar.gz
| Download URL | flickpick-0.0.3.tar.gz |
|---|---|
| Size | 1.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cd294ce835a94cd9b5cd30654442c55fa5088acec12f41c36cc42ff6187b5c1a
|
|
BLAKE2b-256 checksum How to use checksums |
d14dbf5c9580f8f367ecf89fabd92635150c5a910947cd05f3078b64a4177a81
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / flickpick-0.0.3-py3-none-any.whl
| Download URL | flickpick-0.0.3-py3-none-any.whl |
|---|---|
| Size | 39.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5650175f446ec285a1ea303599a0ca319287ed8696fe218599785bef91de76af
|
|
BLAKE2b-256 checksum How to use checksums |
3eaad9e2f488cce73b46b4dbc1f908cfe028c6297e7784454ade50980e8d5793
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|