This repository is now structured as a minimal MLOps-style laptop price prediction project.
It keeps the original notebook for exploration, but moves the runnable path into Python modules with:
- reproducible feature engineering
- a trainable sklearn pipeline with named columns
- saved model and metadata artifacts
- a FastAPI prediction service
- a Streamlit UI
- a product-grade Next.js frontend
- local inference logging and recent prediction history
- API authentication and request rate limiting
- tests and CI scaffolding
src/laptop_price/
config.py
features.py
schemas.py
train.py
predict.py
api.py
app/
streamlit_app.py
frontend/
tests/
models/registry/
models/production/
logs/
reports/metrics/
reports/drift/
.env.example
render.yaml
Install the project in editable mode so the CLI, tests, and local services all work from a fresh clone:
python -m pip install -e ".[dev]"If you only want the runtime dependencies, python -m pip install . also works.
Generate the production model artifact and metadata:
make trainThis writes:
models/production/model.joblibmodels/production/metadata.jsonmodels/registry/<model_version>/model.joblibmodels/registry/<model_version>/metadata.jsonmodels/registry/index.jsonreports/metrics/latest_metrics.json
Each training run is registered as a versioned artifact set and automatically promoted to production. If a newly trained candidate does not beat the current production model on the primary selection rule, it is kept in the registry but not promoted.
List registered versions:
make versionsPromote a previous version back into production:
make activate VERSION=<model_version>Promotion rule:
- higher
r2beats lowerr2 - if
r2ties, lowerrmsewins
make apiEndpoints:
GET /healthGET /readyGET /metadataGET /predictions/recentGET /monitoring/driftGET /monitoring/summaryPOST /predict
Example request:
curl -X POST http://127.0.0.1:8000/predict \
-H "Content-Type: application/json" \
-d '{
"company": "Dell",
"type_name": "Notebook",
"ram": 8,
"weight": 2.1,
"touchscreen": false,
"ips": true,
"screen_size": 15.6,
"screen_resolution": "1920x1080",
"cpu_brand": "Intel Core i5",
"hdd": 1000,
"ssd": 256,
"gpu_brand": "Nvidia",
"os": "Windows"
}'Use realistic values in /docs or API clients. The autogenerated placeholder example from generic OpenAPI forms is not a valid laptop configuration and may be rejected with 422.
make appThe app reads the saved model metadata and uses the same prediction contract as the API.
The new product frontend lives in frontend/ and proxies requests to FastAPI through Next.js server routes so the backend API key stays on the server side.
Create a frontend env file:
cp frontend/.env.example frontend/.env.localRun the frontend:
make frontend-devBuild it for production:
make frontend-buildStart the production preview locally:
make frontend-startThe frontend expects:
API_BASE_URLpointing at the FastAPI serviceAPI_KEYmatching the backend protected API key
The API reads these environment variables:
API_HOSTdefault0.0.0.0API_PORTdefault8000API_KEYdefault disabledRATE_LIMIT_REQUESTSdefault60RATE_LIMIT_WINDOW_SECONDSdefault60RECENT_PREDICTIONS_LIMITdefault20
Example:
API_HOST=0.0.0.0 API_PORT=8000 PYTHONPATH=src uvicorn laptop_price.api:app --host 0.0.0.0 --port 8000Prediction requests are logged to logs/predictions.jsonl, persisted to logs/predictions.db, and can be inspected from the API or locally.
Protected endpoints:
GET /metadataGET /predictions/recentGET /monitoring/driftPOST /predict
If API_KEY is set, these endpoints require an x-api-key header.
Health and readiness remain open so deployment platforms can probe them.
Example:
curl http://127.0.0.1:8000/metadata -H "x-api-key: replace-with-a-secret"Rate limiting is enabled in-process for protected endpoints and is configured by RATE_LIMIT_REQUESTS and RATE_LIMIT_WINDOW_SECONDS.
Generate a drift report from recent logged predictions:
make driftThis writes:
reports/drift/latest_drift_report.json
The current report checks:
- numeric mean shift in standard deviations relative to training data
- unseen categorical rate relative to the production model UI/training value space
Alerting rule:
- drift only triggers an alert when the report sample size is at least
MIN_DRIFT_ALERT_SAMPLE_SIZE - when that threshold is met and drift is detected,
make alertexits non-zero
You can also retrieve the latest saved report from the API:
GET /monitoring/drift
Operational summary endpoint:
GET /monitoring/summary
make testCheck whether the local machine is ready for deployment work:
make preflightSmoke-test a running API:
make smokeYou can override the target URL:
make smoke BASE_URL=http://127.0.0.1:8000Run the full local release gate:
make release-checkWhat is already done in the repository:
- backend training, serving, monitoring, auth, and tests
- minimal product frontend with server-side API proxying
- Dockerfiles for API and frontend
- CI for backend and frontend
- Render blueprint for API, frontend, and Streamlit
- deploy workflow with optional Render deploy hooks
What still must be configured outside the repository before production deployment is complete:
- GitHub secrets
RENDER_API_DEPLOY_HOOK_URLandRENDER_FRONTEND_DEPLOY_HOOK_URL - production
API_KEYin the deployment platform - actual Render service creation or blueprint sync in your account
The repository is effectively code-complete; the remaining work is infrastructure configuration in GitHub and Render.
See DEPLOYMENT.md for the exact final handoff checklist.
make train
make api
make app
make frontend-dev
make frontend-build
make test
make versions
make activate VERSION=<model_version>
make recent
make drift
make alert
make docker-build
make preflight
make smoke- The notebook remains in the repo for exploration, not production training.
- The training pipeline uses the same core engineered features as the notebook: RAM, weight, touchscreen, IPS, PPI, CPU brand, HDD, SSD, GPU brand, and OS buckets.
- The current implementation keeps a local model registry for version history and rollback, logs inference requests locally, and exposes recent prediction history from the API.
- A drift report can be generated locally or in CI from the logged inference data to detect feature distribution changes.
- The API can be protected with an API key and rate limiting for safer public deployment.
- The Next.js frontend is now the recommended user-facing product surface; Streamlit can remain as an internal demo or ops UI.
This repo now includes:
- Dockerfile for the API container
- frontend/Dockerfile for the Next.js frontend container
- render.yaml for Render service provisioning
- .github/workflows/deploy.yml to build both containers and optionally trigger Render deploy hooks
- .env.example with runtime settings
Operational helpers:
- src/laptop_price/ops.py for deployment preflight and API smoke testing
To make deployment real in your environment, set the RENDER_API_DEPLOY_HOOK_URL and RENDER_FRONTEND_DEPLOY_HOOK_URL repository secrets and configure the production API_KEY in the hosting platform.