The Problem

Retail teams need a single place to turn raw sales, customer, and review data into forecasts, segmentations, and sentiment insights. Building and maintaining separate pipelines, APIs, and dashboards for each analytic task is time‑consuming and error‑prone.

What This Does

The repository is a portfolio of four self‑contained projects:

ProjectCore codeMain purpose
src/data preprocessing, model training, utilities, visualisation (src/data/, src/models/, src/utils/, src/visualization/)End‑to‑end pipelines for sales forecasting, customer segmentation, and review‑sentiment modelling.
api/FastAPI entry point (api/main.py) and routers (api/routers/*.py)HTTP layer exposing model inference, data retrieval, and RAG‑based Q&A.
dashboard/Streamlit app (dashboard/app.py) and UI components (dashboard/components/*.py, dashboard/pages/*.py)Interactive visualisation of forecasts, segmentations, and sentiment dashboards.
notebooks/Exploratory notebooks (notebooks/*.ipynb)Prototype analyses and visual output for data‑science validation.

Key files: src/cli.py (CLI that drives training/evaluation), api/models.py (validation helpers), src/models/sentiment.py (LLM‑based sentiment pipeline), src/models/forecasting.py (XGBoost/LightGBM/Prophet), src/models/segmentation.py (KMeans/DBSCAN), dashboard/components/charts.py (plot utilities), src/utils/config.py (central config loader).

How It Is Wired

  1. CLI entry points (src/cli.py) – train_models, evaluate_models, preprocess_data. train_models → loads config (load_config in src/utils/config.py – 11 callers) → prepares data (prepare_sentiment_data, prepare_forecasting_data) → calls model‑specific trainers (train_sentiment_model, train_xgboost_model, train_kmeans_model). evaluate_models → loads test data (load_data) → runs evaluate_models → persists metrics (save_plot – called from 14 places). * preprocess_data → reads raw CSV/JSON (load_data), cleans (clean_retail_sales_data), writes processed files (save_processed_data).
  1. API server (api/main.py) starts a FastAPI app. Routers (api/routers/*.py) import helpers from api/dependencies.py (13 functions, 2 classes). Typical request flow: /forecast → api/routers/forecasting.py → api/dependencies.get_forecasting_model → src/models/forecasting.get_model_config → model inference (model.predict). /sentiment → api/routers/reviews.py → src/models/sentiment.train_sentiment_model (or inference) → returns sentiment scores.
  1. Dashboard (dashboard/app.py) launches Streamlit. UI callbacks call the same utility functions used by the API (load_config, save_plot, generate_embeddings). The only external call is a requests call without a timeout (identified as a medium issue).

Hot‑spot modules (most inbound imports):

  • dashboard/components/charts.py (Ca = 5) – central plot creator.
  • src/utils/config.py (Ca = 6) – sole source of configuration loading.

Call‑graph highlights – save_plot is invoked from 14 distinct locations, making it a high‑impact change point. train_sentiment_model and train_kmeans_model each have 8–7 callers, indicating tightly coupled training logic.

No circular imports were detected; the import graph is shallow (47 edges across 57 modules). The most unstable module by metric is src/cli.py (instability = 1) because it imports many others but is not imported itself.

How To Use It

# Clone the repo (exact URL as requested)
git clone https://github.com/moses-y/retail-analytics.git
cd retail-analytics

# Virtual‑env install (as per README)
python -m venv venv
source venv/bin/activate   # Windows: venv\Scripts\activate
uv pip install -r requirements.txt   # uv is used in the README

# Copy and edit environment variables
cp .env.example .env
# Edit .env to set DB paths, API keys, etc.

# Run the API
uvicorn api.main:app --reload --port 8000

# Run the dashboard
streamlit run dashboard/app.py

# Or build/run everything with Docker
docker compose up -d

Configuration lives in config/ (api_config.yml, model_config.yml, monitoring_config.yml). The CLI and API both call src.utils.config.load_yaml_config to read these files. No secret values are committed; the .env.example shows required keys.

Real‑World Use

A retailer schedules a nightly CI job that executes python src/cli.py train_models. The script reads config/model_config.yml, trains the XGBoost forecasting model and a KMeans segmentation model, and writes serialized artifacts to models/. The FastAPI service then serves /forecast and /segment endpoints for downstream inventory‑management systems, while the Streamlit dashboard visualises the latest forecasts for business users.

Code Health & Issues

  • High – Pin GitHub Actions to commit SHAs (.github/workflows/*).
  • Medium – Declare least‑privilege permissions for GITHUB_TOKEN (.github/workflows/cd.yml).
  • Medium – Enable Dependabot/Renovate for dependency updates.
  • Medium – Pin Docker base image by digest (Dockerfile).
  • Medium – Add a dependency‑vulnerability scan step to CI.
  • Medium – Split oversized notebook cell (notebooks/sales_forecasting_customer_segmentation.ipynb).
  • Medium – Add timeout to outbound requests call (dashboard/app.py).
  • Medium – Set persist-credentials: false on checkout (.github/workflows/cd.yml).
  • Medium – Run container as non‑root user (Dockerfile).
  • Medium – Pin vulnerable package resolutions by committing a lockfile (currently none).
  • Low – Deep nesting (max indentation depth = 8) in api/models.py, src/data/preprocessing.py, src/utils/metrics.py.
  • Medium – Broad exception handling in api/dependencies.py and src/models/forecasting.py.
  • High – Duplicated 6‑line blocks across routers and dashboard pages.
  • Medium – Oversized files (src/visualization/plots.py, api/routers/reviews.py).

The repo includes tests (tests/), CI (.github/workflows/), a Dockerfile, and an MIT licence, but lacks a lockfile and several hardening practices noted above.

The Bottom Line

The codebase delivers a functional end‑to‑end retail analytics stack with clear separation between pipelines, API, and UI. It is usable out‑of‑the‑box but suffers from maintainability concerns (deep nesting, duplicated blocks) and security hygiene gaps (unpinned actions, no lockfile). Engineers comfortable refactoring Python code and tightening CI/CD can adopt it quickly; teams that need a production‑grade, reproducible build should first address the high‑severity health items.