Skip to content

Repository files navigation

ARES — Accra Rental Estimation System

Estimates market rent for residential properties across Greater Accra, Ghana, using gradient-boosted regression. ARES combines a CatBoost pricing model with a FastAPI serving layer and a Streamlit frontend for exploration, prediction, and reporting.

Architecture

┌──────────┐     ┌──────────┐     ┌──────────┐
│  Client  │────▶│  FastAPI │────▶│ CatBoost │
│ (Stream- │     │  (port   │     │  Model   │
│  lit)    │     │   8000)  │     │          │
└──────────┘     └──────────┘     └──────────┘
                       │
                       ▼
                  ┌──────────┐
                  │   Groq   │
                  │   LLM    │ (optional
                  │          │  explanation)
                  └──────────┘
  • CatBoostRegressor — Gradient-boosted model trained on ~19k historical listings
  • FastAPI — Synchronous REST API with Pydantic-validated request/response schemas
  • Streamlit — Three-page UI: market explorer, valuation predictor, and detailed report
  • Groq LLM — Optional natural-language explanation of valuation results (falls back gracefully)

Quick Start

Prerequisites

  • Python 3.12
  • uv package manager

Setup

# Install dependencies (including dev tools)
uv sync --dev

# Train the pricing model
uv run python -m lib.train

# Start the API server
uv run uvicorn api.server:app --host 127.0.0.1 --port 8000

# In a separate terminal, launch the UI
BACKEND_URL="http://127.0.0.1:8000" uv run streamlit run ui/app.py --server.port=8080

Or use the combined launcher:

./run.sh

Run Tests

uv run pytest -q --cov

Project Structure

├── api/                  # REST API layer
│   ├── server.py         # FastAPI app — /predict, /explain, /health
│   └── schemas.py        # Pydantic models for validation
├── lib/                  # Core ML pipeline
│   ├── train.py          # Training orchestration with hyperparameters
│   ├── features.py       # Feature engineering (encoding, stats, cleaning)
│   ├── predict.py        # Inference: point estimate + uncertainty bands
│   ├── llm.py            # Groq-powered market explanation (optional)
│   └── utils.py          # Shared config, logging, I/O helpers
├── ui/                   # Streamlit frontend
│   ├── app.py            # Landing page with market snapshot
│   ├── utils.py          # CSS, chart config, HTML builders
│   └── pages/
│       ├── Explorer.py   # Filter, visualize, and segment listings
│       ├── Predictor.py  # Property form → model valuation
│       └── Report.py     # Detailed report with comparables
├── data/raw.csv          # Training dataset (Jiji.com.gh listings)
├── models/               # Serialized model + training metadata
├── tests/                # Pytest suite
├── pyproject.toml        # Dependency + tool config
└── Dockerfile            # Containerised deployment

API Endpoints

Method Path Description
GET / Service info
GET /health Health check + model existence
POST /predict Estimate rent from property features
POST /explain Estimate + natural-language explanation

Example: /predict

{
  "house_type": "apartment",
  "condition": "newly built",
  "furnishing": "furnished",
  "loc": "tesano",
  "bathrooms": 2,
  "bedrooms": 2,
  "air_conditioning": 1,
  "balcony": 1,
  "wi_fi": 1
}

Response:

{
  "estimated_price": 3850.00,
  "lower_band": 3200.00,
  "upper_band": 4620.00,
  "market_volatility_idx": 0.38,
  "market_volatility_pct": 46.2,
  "market_volatility_tier": "Moderate"
}

Feature Engineering

The model uses three categories of features:

  • Numerical — bedrooms, bathrooms
  • Categorical — location, property type, condition, furnishing (one-hot encoded)
  • Amenity flags — 18 binary indicators (air conditioning, Wi-Fi, balcony, etc.)
  • Derived — total amenity count, luxury amenity count, location-level statistics (median log-price, volatility, listing density)

The prediction outputs an uncertainty band derived from the log-scale interquartile range of comparable listings, adjusted for listing depth at the location level.

Configuration

Environment Variable Default Description
GROQ_API_KEY — API key for LLM explanations
GROQ_MODEL llama-3.3-70b-versatile Groq model name
GROQ_MAX_TOKENS 512 Max tokens per LLM call
GROQ_TIMEOUT_SECONDS 10 Timeout for Groq explanation calls
ARES_API_KEY — Optional shared key required by write endpoints when set
ARES_RATE_LIMIT_REQUESTS 60 Per-client request limit for write endpoints
ARES_RATE_LIMIT_WINDOW_SECONDS 60 Rate-limit window in seconds
ARES_ENABLE_LLM 1 Set to 0 to disable external LLM calls
ARES_MODEL_SHA256 — Optional SHA256 checksum required before loading models/model.joblib
LOG_LEVEL INFO Logging verbosity

Deployment

Docker

docker compose up --build

Environment

Copy .env.example to .env and populate GROQ_API_KEY if LLM explanations are desired. The API and model will function without it using a fallback explanation. Only load trusted model artifacts; joblib model files are executable Python serialization formats. Set ARES_MODEL_SHA256 in production if you want startup/inference to reject an unexpected model file.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages