End-to-end data science competition solution for customer segmentation, cross-sell and up-sell recommendations on historical B2B invoice-line data.
The repository contains the reproducible Python implementation, REST API, technical documentation, CRISP-DM report, run book, presentation and supporting visual assets. Proprietary competition data and generated model artifacts are deliberately excluded.
- Final presentation (PDF)
- CRISP-DM project report (PDF)
- Technical run book (PDF)
- Competition brief (PDF)
- Complete deliverables index
The solution addresses the complete competition brief:
- deterministic preparation of transactional data
- interpretable buyer persona discovery
- analysis of products bought together
- personalized cross-sell recommendations
- hierarchy- and price-aware up-sell recommendations
- temporal offline evaluation
- a FastAPI serving layer
- CRISP-DM and operational documentation
The problem is modeled as implicit-feedback recommendation rather than ordinary classification. Each invoice represents a basket, historical purchases provide positive behavioral signals, and models rank future products for an existing customer.
flowchart LR
A[Invoice-line data] --> B[Cleaning and anomaly flags]
B --> C[Customer, item and basket features]
C --> D[Buyer personas]
C --> E[Cross-sell candidate models]
C --> F[Up-sell candidate model]
D --> G[Business-priority reranker]
E --> G
F --> G
G --> H[Temporal evaluation]
G --> I[FastAPI service]
The recommendation layer combines complementary signals:
- invoice co-occurrence for products bought together
- sequential transitions between purchases
- latent item similarity and implicit collaborative filtering
- segment and recency popularity fallbacks
- product group, product family, price-step, spend-band and margin context
- a learned business-priority reranker for final ordering
| Model | Role | Interpretation |
|---|---|---|
HybridRecommender |
Strict benchmark | Strongest reference model on the main next-invoice exact-SKU split |
ImplicitBlendRecommender |
Collaborative component | Adds ALS/BM25 and hierarchy-aware collaborative information |
EnsembleRecommender |
Serving fallback | Stable combination of hybrid and implicit recommendations |
BusinessPriorityRerankerRecommender |
Primary serving model | Prioritizes product-group, product-family and exact-SKU relevance |
The API loads the first available artifact in this order:
business_reranker_recommender.pklensemble_recommender.pklimplicit_blend_recommender.pklhybrid_recommender.pkl
Evaluation follows time rather than using a random split. The main benchmark trains on purchases before 2020-04-01 and evaluates on future invoices from customers already observed in training. Additional experiments cover multiple split dates, future invoice horizons and 30/60/90-day windows.
The project reports two complementary metric layers:
- strict ranking metrics: Precision@10, Recall@10, MAP@10, NDCG@10 and catalog coverage
- business metrics: product-group, product-family and exact-SKU precision, recall, F1 and hit rate
This distinction matters in a sparse B2B catalog: a recommendation can match the correct commercial need even when the exact future SKU differs.
Selected documented results for the primary serving model at top 10 are:
| Metric | Value |
|---|---|
| Product-group F1 | 0.745819 |
| Product-group hit rate | 0.966072 |
| Product-family F1 | 0.968250 |
| Product-family hit rate | 0.998743 |
| Exact-SKU F1 | 0.118004 |
| Exact-SKU hit rate | 0.634582 |
The evaluation design, limitations and full model comparison are documented in Evaluation Notes and Metric Interpretation.
| Path | Purpose |
|---|---|
src/lumen_recommender/ |
Reusable cleaning, features, personas, recommenders, evaluation, pipeline and API modules |
scripts/ |
Reproducible pipeline, training, evaluation, experiment and export entry points |
tests/ |
Lightweight contract and metric tests used by CI |
notebooks/ |
Sanitized exploratory analysis retained as project history |
docs/ |
Technical, methodological and business documentation |
deliverables/ |
Final report, run book, presentation and presentation assets |
data/ |
Dataset availability notice and expected local layout |
artifacts/ |
Local generated outputs; contents are not versioned |
task/ |
Original competition brief |
See Documentation Index for a guided reading order.
The transaction CSV files are not distributed in this repository. The competition brief states that the data belongs to Atomic Intelligence d.o.o. and must be deleted after the challenge. Keeping the dataset out of Git history is therefore intentional.
For an authorized full run, place the canonical input at:
data/raw/LUMEN_DS_really_clean.csv
The expected local layout and generated data files are described in data/README.md. Source code, documentation and all publishable submission materials are versioned; proprietary input data and reproducible generated artifacts are not.
The primary environment uses Python 3.12 and uv for dependency management.
uv sync --lockedThe native implicit training path uses a dedicated Python 3.11 environment:
uv python install 3.11
uv venv --python 3.11 .venv311
.venv311/bin/python -m ensurepip --upgrade
.venv311/bin/python -m pip install implicitPlatform-specific notes are available in the Environment Checklist.
From the repository root:
PYTHONPATH=src uv run python scripts/run_pipeline.pyThe main pipeline:
- loads and cleans the canonical CSV input
- builds customer, item and invoice-basket features
- compares clustering configurations and assigns buyer personas
- trains the hybrid recommender
- optionally trains implicit, ensemble and business-reranker artifacts through
.venv311 - evaluates the available models
- writes processed tables, models, metrics and analysis assets locally
Expected output locations are documented in artifacts/README.md and the Run Book.
PYTHONPATH=src uv run python scripts/run_clustering_analysis.py
PYTHONPATH=src uv run python scripts/run_extended_evaluation.py
PYTHONPATH=src uv run python scripts/evaluate_upsell_summary.py
PYTHONPATH=src uv run python scripts/export_api_demo_examples.pyAdvanced and model-specific scripts are described in docs/experiments.md and deliverables/runbook/run_book_hr.md.
After generating model artifacts:
PYTHONPATH=src uv run uvicorn lumen_recommender.api:app --reloadInteractive OpenAPI documentation is then available at http://127.0.0.1:8000/docs.
Main endpoints:
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/health |
Service and active-model status |
GET |
/model-info |
Model selection and stored metrics |
GET |
/metrics |
Strict and business-oriented evaluation results |
GET |
/dataset-summary |
Cleaning, dataset and persona metadata |
GET |
/personas |
All persona summaries |
GET |
/personas/{customer_id} |
Persona context for one customer |
GET |
/customer-summary/{customer_id} |
Combined customer and recommendation view |
GET |
/recommendations/explanations/{customer_id} |
Recommendations with business explanations |
POST |
/recommendations |
General ranked recommendations |
POST |
/cross-sell |
Basket-expansion candidates |
POST |
/up-sell |
Bounded higher-value alternatives |
Example request:
curl -X POST http://127.0.0.1:8000/recommendations \
-H "Content-Type: application/json" \
-d '{"customer_id": 224029, "top_k": 10}'The complete request and response contract is in API Reference.
- Fran Galić
- Borna Rebić Taučer
- Ivan Dujmić
- Ana Vuksanović
The competition brief states that the source code remains the property of the team. No separate open-source license is granted by this repository. The proprietary competition dataset is not included.