NutriLoop / README.md
AB1N05's picture
Fix README frontmatter for Hugging Face Space
95e2503
|
Raw
History Blame Contribute Delete
8.49 kB
metadata
title: NutriLoop AI
emoji: 🍱
colorFrom: blue
colorTo: green
sdk: docker
app_port: 7860

NutriLoop AI

Food demand forecasting backend using Facebook Prophet, KMeans clustering for cold-start restaurants, and NewsAPI-based demand adjustment.

Features

  • Prophet Forecasting: Trained per restaurant+item combination with Indian public holidays
  • Cold-Start Clustering: KMeans-based fallback for new restaurants without historical data
  • Restaurant Metadata: Optional restaurants table stores location and cuisine data for deterministic fallback behavior
  • News Adjustment: Real-time demand multiplier from news headlines (festival, weather, events)
  • Nightly Retraining: GitHub Actions cron job pulls latest Supabase data and retrains models
  • Hugging Face Spaces: Containerized FastAPI app deploys to *.hf.space

Quick Start (Local Development)

1. Install Dependencies

# Use Python 3.13 for this project
# Create or refresh the venv if needed, then install dependencies
uv sync

2. Configure Environment

cp .env.example .env
# Edit .env with your credentials:
# - SUPABASE_URL / SUPABASE_KEY from Supabase project settings
# - NEWSAPI_KEY from https://newsapi.org (free tier)
# - HF_TOKEN / HF_REPO_ID from Hugging Face

3. Seed Supabase with Kaggle Data

Download the Kaggle dataset from: https://www.kaggle.com/datasets/mer-sun/restaurant-sales

# Print the SQL schema to run in Supabase dashboard
python scripts/seed_supabase.py --print-sql

# Seed data from CSV
python scripts/seed_supabase.py /path/to/kaggle/sales.csv

4. Train Models

# Train Prophet models from Supabase data
python training/train_prophet.py

# Train KMeans clustering model
python training/train_clusters.py

# Upload models to Hugging Face Hub
python training/upload_models.py

5. Run the API

uvicorn app.main:app --reload --port 7860

API will be available at: http://localhost:7860

6. Test the API

python scripts/test_api.py

API Endpoints

GET /health

Health check with model count and version.

curl http://localhost:7860/health

POST /predict

Forecast demand for an existing restaurant with trained Prophet model.

curl -X POST http://localhost:7860/predict \
  -H "Content-Type: application/json" \
  -d '{
    "restaurant_id": "rest_001",
    "item_name": "biriyani",
    "city": "Kochi",
    "days": 7
  }'

POST /cold-start

Forecast demand for a new restaurant using cluster-based averaging.

curl -X POST http://localhost:7860/cold-start \
  -H "Content-Type: application/json" \
  -d '{
    "latitude": 9.9312,
    "longitude": 76.2673,
    "cuisine_type": "indian",
    "avg_daily_quantity": 25.0,
    "item_name": "puttu",
    "days": 7
  }'

Calling from Next.js

// In your Next.js kiosk dashboard page:
const HF_API = process.env.NEXT_PUBLIC_NUTRILOOP_AI_URL
// e.g. "https://your-username-nutriloop-ai.hf.space"

export async function getForecast(restaurantId: string, itemName: string, city: string) {
  const res = await fetch(`${HF_API}/predict`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      restaurant_id: restaurantId,
      item_name: itemName,
      city: city,
      days: 7
    })
  })
  return res.json()
  // Returns: { predictions: [{date, quantity, adjusted_quantity}], news_multiplier, source, ... }
}

Deployment to Hugging Face Spaces

1. Create a new Space

Go to https://huggingface.co/new-space and create a Docker-based Space named nutriloop-ai.

2. Push to HF

git init
git add .
git commit -m "NutriLoop AI initial commit"
git remote add origin https://huggingface.co/spaces/<your-username>/nutriloop-ai
git push origin main

3. Set Secrets in HF Space Settings

In your HF Space settings, add these secrets:

  • SUPABASE_URL
  • SUPABASE_KEY
  • NEWSAPI_KEY
  • HF_TOKEN
  • HF_REPO_ID

4. Access your deployed API

Your API will be live at: https://<your-username>-nutriloop-ai.hf.space

Supabase Schema

Run this SQL in your Supabase SQL editor:

-- Enable PostGIS extension
CREATE EXTENSION IF NOT EXISTS postgis;

-- Table: sales_logs
CREATE TABLE sales_logs (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    restaurant_id text NOT NULL,
    item_name text NOT NULL,
    quantity integer NOT NULL,
    sale_date date NOT NULL,
    location geography(Point, 4326),
    created_at timestamptz DEFAULT now()
);

CREATE INDEX idx_sales_logs_restaurant_id ON sales_logs(restaurant_id);
CREATE INDEX idx_sales_logs_sale_date ON sales_logs(sale_date);
CREATE INDEX idx_sales_logs_restaurant_item ON sales_logs(restaurant_id, item_name);

-- Table: restaurants
CREATE TABLE restaurants (
  restaurant_id text PRIMARY KEY,
  restaurant_name text,
  latitude double precision,
  longitude double precision,
  cuisine_type text,
  avg_daily_quantity double precision,
  created_at timestamptz DEFAULT now()
);

-- Table: retrain_log
CREATE TABLE retrain_log (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    run_at timestamptz DEFAULT now(),
    model_version text NOT NULL,
    rows_used integer,
    mae_score float,
    status text CHECK (status IN ('success', 'failed')),
    error_msg text
);

Nightly Retraining (GitHub Actions)

The .github/workflows/retrain.yml workflow runs automatically at 1:00 AM IST daily. It executes scripts/retrain.py which:

  1. Pulls latest data from Supabase
  2. Retrains all Prophet models
  3. Retrains KMeans clusters
  4. Uploads updated models to Hugging Face Hub

You can also trigger manually from the GitHub Actions tab.

Environment Variables

Variable Description
SUPABASE_URL Your Supabase project URL
SUPABASE_KEY Supabase anon/public key
NEWSAPI_KEY NewsAPI key (free tier at newsapi.org)
HF_TOKEN Hugging Face access token
HF_REPO_ID HF Space repo ID (e.g. username/nutriloop-ai)

Project Structure

nutriloop-ai/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ main.py          # FastAPI app entry point
β”‚   β”œβ”€β”€ predict.py       # Prophet model loading and inference
β”‚   β”œβ”€β”€ cold_start.py    # KMeans cold-start forecasting
β”‚   β”œβ”€β”€ news_adjuster.py # NewsAPI-based demand multiplier
β”‚   └── schemas.py       # Pydantic request/response models
β”œβ”€β”€ training/
β”‚   β”œβ”€β”€ train_prophet.py # Full Prophet training pipeline
β”‚   β”œβ”€β”€ train_clusters.py# KMeans clustering training
β”‚   β”œβ”€β”€ load_kaggle_data.py # Kaggle CSV loader and cleaner
β”‚   └── upload_models.py # Hugging Face model upload
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ retrain.py       # Master retraining orchestrator
β”‚   β”œβ”€β”€ seed_supabase.py # First-run data seeding
β”‚   └── test_api.py      # End-to-end API tests
β”œβ”€β”€ models/              # Trained .pkl files (gitignored)
β”œβ”€β”€ data/                # Raw Kaggle CSV (gitignored)
β”œβ”€β”€ .github/workflows/
β”‚   └── retrain.yml      # GitHub Actions nightly cron
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ requirements.txt
└── README.md

Tech Stack

  • Runtime: Python 3.11
  • Web Framework: FastAPI + Uvicorn
  • Forecasting: Facebook Prophet (with Indian holidays)
  • Clustering: scikit-learn KMeans
  • Database: Supabase (PostgreSQL + PostGIS)
  • Model Registry: joblib + JSON
  • Model Storage: Hugging Face Spaces
  • CI/CD: GitHub Actions
  • Hosting: Hugging Face Spaces (Docker)## Contributing

Contributions are welcome! To contribute:

  1. Fork the repository
  2. Create a new branch for your feature or bugfix
  3. Make your changes and add tests if applicable
  4. Submit a pull request with a clear description

Please follow the existing code style and add documentation where needed.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Contact & Support

For questions, issues, or feature requests, please open an issue on GitHub or contact the maintainer:

Acknowledgements