Predicts what score you would give an anime — trained on your own completed AniList list, not a generic dataset.
It logs in to your AniList account (OAuth2), downloads every anime you've
marked COMPLETED along with the score you gave it, trains a small neural
network on your genre/tag preferences, and then predicts a score (0–10) for
any anime you point it at — with a breakdown of which genres/tags drove the
prediction and how confident it is.
============================================================
Kimi no Na wa. (Your Name.)
ID: 20958 Format: MOVIE Eps: 1 Status: FINISHED
AniList community score: 85 / 100
------------------------------------------------------------
GENRES (your weighted avg score per genre)
GENRE YOUR AVG SEEN SIGNAL
-------------------------------------------------------
Drama 8.1/10 34x [+] Liked
Romance 7.9/10 28x [+] Liked
Supernatural 6.8/10 19x [~] Neutral
...
------------------------------------------------------------
PREDICTED SCORE : 8.2 / 10 ★★★★☆
Likely range : 7.6 to 8.8 (+-0.61 model MAE)
Confidence : High (86% of tags/genres seen before)
============================================================
- Login (OAuth2) — opens your browser to AniList's login/consent page, captures the redirect on a short-lived local server, and exchanges the authorization code for an access token.
- Session persistence — the token is saved to
session.pickleso you only log in once; future runs reuse it until it expires. - Data collection — paginates your AniList list via GraphQL and keeps
every
COMPLETEDentry (title, genres, tags, your score). - Training — encodes each anime as a genre/tag feature vector and
trains a small residual MLP (
AnimeNet) to regress your score, plus a simple weighted-average preference map per genre/tag for the human-readable breakdown. - Prediction — feeds a new anime through the trained model and reports a predicted score, an estimated range (± validation MAE), and a confidence level based on how many of its tags/genres you've rated before.
- Python 3.10+
- An AniList account
- An AniList API client (free, takes a minute to create)
Go to https://anilist.co/settings/developer and create a new client with:
- Redirect URL:
http://localhost:8000/callback
Copy the Client ID and Client Secret it gives you.
git clone https://github.com/Kurdeus/twin-pt.git
cd twin-pt
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtcp .env.example .envEdit .env:
ANILIST_CLIENT_ID=your-client-id
ANILIST_CLIENT_SECRET=your-client-secret
ANILIST_REDIRECT_URL=http://localhost:8000/callback.env and session.pickle are both in .gitignore — never commit either
one, since they grant access to your AniList account.
python main.pyOn first run:
- Your browser opens to AniList's login/consent screen.
- After you approve, the app captures the token and saves it to
session.pickle. - It downloads your completed list to
anime_data.jsonand trains a model, saved toanime_model.pt. - It predicts a score for a default sample anime.
Predict a specific anime by its AniList ID:
python main.py --id 20958(Find the ID in any AniList URL: anilist.co/anime/20958/...)
Log out (delete the saved session so the next run re-authenticates):
python main.py --logoutTo retrain from scratch, delete anime_data.json and/or anime_model.pt
and run main.py again.
twin-pt/
├── main.py # Thin CLI entry point (delegates to twin_pt.cli)
├── twin_pt/ # Main package
│ ├── cli.py # CLI argument parsing and orchestration
│ ├── auth/
│ │ ├── oauth.py # AniList OAuth2 login (browser + local callback server)
│ │ └── session.py # Loads/saves session.pickle, validates saved tokens
│ ├── api/
│ │ ├── client.py # requests.Session with retry / rate-limit handling
│ │ └── anilist.py # AniList data fetching, list collection, vocabulary building
│ ├── ml/
│ │ └── predictor.py # Feature engineering, AnimeNet model, training, prediction
│ ├── display/
│ │ └── report.py # Pretty-print console output
│ └── config/
│ ├── settings.py # Loads credentials from environment / .env
│ └── constants.py # Endpoints, GraphQL queries, file paths (no secrets)
├── requirements.txt
├── setup.py
└── .env.example
- The model is only as good as your list: it needs a reasonable number of
scored
COMPLETEDentries to learn meaningful genre/tag preferences. - Scores you haven't given yet (0) are excluded from training.
- Access tokens issued by AniList are long-lived but do expire; when that
happens
main.pywill automatically prompt you to log in again and refreshsession.pickle.
- No credentials are hardcoded anywhere in this repository. Client ID/secret
come from environment variables (
.env, gitignored), and the OAuth access token is stored only in your local, gitignoredsession.pickle. - If you ever accidentally commit
.envorsession.pickle, revoke access at https://anilist.co/settings/apps and rotate your client secret.
If you enjoy this project, feel free to check out my AniList profile and add me as a friend or follow my activity:
https://anilist.co/user/Shahabadin/
MIT — see LICENSE.