Capabilities¶
Practical API overview. Formal contracts: CONTRACTS.md.
Install & run¶
pip install streamlit-recommenders # or, from a clone: pip install -e ".[dev]"
python -m streamlit_recommenders.data.prepare --dataset ml-latest-small # or ml-latest, ml-25m, ml-32m; add --with-posters (needs TMDB_API_KEY)
python examples/train_baseline_artifacts.py --data data/ml-latest-small # Additional training script for baseline models and exporting artifacts
SR_DATA_DIR=data/ml-latest-small streamlit run examples/compare_models_rows.py # 3 models comparison (in rows layout) library demonstration
Requires Python ≥3.10.
Keys (TMDB_API_KEY / TMDB_BEARER_TOKEN, KAGGLE_USERNAME / KAGGLE_KEY) and SR_DATA_DIR can go in a .env file (copy .env.example) or be set inline as above. The preparation CLI auto-loads .env; the example apps read SR_DATA_DIR from the shell (export it or pass it inline). .env keeps the showcase commands clean.
Public API¶
| Area | API |
|---|---|
| App | sr.run(...) |
| Data | load_items, load_interactions, load_users, load_dataset, load_dataset_from_paths, resolve_image_urls, Dataset, ColumnMap, validate_dataset |
| Data prep | prepare_movielens, prepare_goodbooks, is_complete |
| Params | slider, selectbox, param_value |
| Layouts | rows, grid, cards |
| Session | current_user, selected_items, disliked_items, displayed_items, selections |
| Content | plot, table, markdown, markdown_file |
| Viz helpers | dataset_info, recommendation_overlap_matrix, plot_overlap_heatmap, plot_metric_comparison, plot_ranked_items, plot_score_distribution |
| Metrics | evaluate, hit_rate_at_k, recall_at_k, ndcg_at_k, mrr_at_k, coverage |
| Models | BaseRecommender (subclass to define a model), ArtifactRecommender (load exported .npz) |
sr.run()¶
sr.run(
get_recommendations=fn_or_model_or_dict,
items=items,
interactions=train,
layout="rows",
params={"alpha": sr.slider("alpha", 0.0, 1.0, 0.5)},
intro=lambda: sr.markdown("### Model contract"),
body=lambda: sr.table(metrics),
)
Pass a dict for compare mode:
Compare mode shows one shared Get Recommendations button so all rows refresh against the same session profile.
Model-specific controls are keyed by recommender label:
sr.run(
get_recommendations={"Ours": ours, "EASE": ease},
items=items,
interactions=train,
params={"Ours": {"alpha": sr.slider("alpha", 0.0, 1.0, 0.5)}},
)
Data¶
dataset = sr.load_dataset_from_paths(
items="items.csv",
interactions="train_interactions.csv",
users="users.csv",
test="test_interactions.csv",
)
Default logical columns: user_id, item_id, rating, timestamp, title, image_url, description.
Only item_id is required for items. Movie demos should prefer title, image_url, and description; missing images render with a placeholder. Local protected datasets should live under data/ and stay out of git.
Load a prepared folder (resolves poster paths to local files) with:
Data preparation¶
Prepare datasets from inside the library (no standalone scripts required):
sr.prepare_movielens("ml-32m") # items.csv + interactions.csv
sr.prepare_movielens("ml-32m", with_posters=True) # + TMDB descriptions/posters (TMDB_API_KEY)
sr.prepare_goodbooks() # books carry cover image URLs (kagglehub optional)
Or via CLI:
Each prepared folder gets a dataset.json manifest; sr.is_complete(root) guards against
re-running collection, so preparation is idempotent and a finished dataset is not re-fetched
before a demo run. TMDB enrichment is robust (retry/backoff, 429 handling) and writes a
metadata_completeness.csv report listing items still missing a poster or description.
External model training¶
The core package does not train heavy models. Train with any external code, export pure artifacts, then pass a function/object that returns ordered item ids:
def get_recommendations(user_id, k, session_items=None, **params):
return trained_model.rank(user_id, session_items=session_items)[:k]
sr.run(
get_recommendations={"Ours": get_recommendations, "EASE": ease_baseline},
items=items,
interactions=train,
)
One optional script trains the three default baseline families and exports NumPy artifacts:
.venv/bin/python examples/train_baseline_artifacts.py --data data/<dataset-name>
SR_DATA_DIR=data/<dataset-name> streamlit run examples/compare_models_rows.py
The script writes artifacts/itemknn.npz, artifacts/ease.npz, and artifacts/sequential_cf.npz. Each artifact contains item_ids, weights, and popularity; the demo loads only these arrays and never imports the training code.
Reference baselines are defined in examples/reference_recommenders.py (subclassing
BaseRecommender), not shipped by the library — copy one as a starting point:
| Family | Reference class | Use |
|---|---|---|
| ItemKNN | ItemKNNRecommender |
classic item-item CF baseline |
| EASE | EASERecommender |
strong shallow linear implicit-feedback baseline |
| Sequential CF | SequentialCFRecommender |
timestamped next-item baseline (first-order item transitions) |
Item cards and layouts¶
rows: one horizontal row with fixed-width clickable poster cards and side scroll.grid: wrapped clickable poster gallery for catalog-style browsing.cards: swipe deck. One card at a time with Like / Dislike / Skip buttons.- Clickable layouts (
rows,grid): selected items stay in place as greyed cards; click again to unselect. - Compare mode always uses
rows.
Swipe deck (cards)¶
Like adds the item to the session profile (same signal as a card click); Dislike records
negative feedback and removes the card; Skip just advances. After swipes_per_refresh
like/dislike swipes the queue is refreshed against the updated profile:
sr.run(get_recommendations=model, items=items, interactions=train, layout="cards", swipes_per_refresh=5)
swipes_per_refresh defaults to 5 and can also be overridden via a reserved sidebar param.
Swipe is single-model; compare mode (dict input) stays on rows.
Metrics¶
metrics = sr.evaluate(
{"Ours": {0: [1, 2, 3]}},
test_interactions=test,
k=10,
all_item_ids=items.item_id,
)
sr.table(metrics)
sr.plot_metric_comparison(metrics)
Dataset Inspection¶
The reusable dataset block shows headline metrics (item/user/interaction counts, matrix density) and a tabbed switcher over distribution plots — item genres (default), interactions per user, interactions per item (popularity long tail), rating distribution, and categorical item metadata. The tabs and chart styling match the results-inspection plots for a consistent look.
Recommendation Agreement¶
overlap = sr.recommendation_overlap_matrix({"ItemKNN": [1, 2, 3], "EASE": [2, 3, 4]})
sr.plot_overlap_heatmap(overlap, title="Top-k recommendation overlap")
The overlap helper computes pairwise Jaccard agreement between model outputs and renders it as a compact heatmap for compare-mode demos.
Examples¶
| File | Shows |
|---|---|
reference_recommenders.py |
Way 2: define models by subclassing BaseRecommender (ItemKNN/EASE/SeqCF), fit in memory, and compare |
compare_models_rows.py |
Lead demo (way 1): compare ItemKNN, EASE, and Sequential CF artifacts in rows layout |
swipe_deck_cards.py |
Single-model swipe deck (cards layout) with like/dislike/skip; wraps EASE in a feedback-aware model that uses dislikes as a negative signal |
compare_models_grid.py |
Grid layout with a sidebar model selector (one artifact at a time) |
train_baseline_artifacts.py |
Train/export SciPy/NumPy baseline artifacts on a local data/<dataset-name> folder |
Not yet implemented¶
- Polars backend
- UI file upload for models
- Optional wrappers/examples for RecBole / RecPack / LensKit