Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ jobs:
run: uv sync --dev

- name: Ruff lint
run: uv run ruff check src/
run: uv run ruff check foresight/

- name: Ruff format check
run: uv run ruff format --check src/
run: uv run ruff format --check foresight/

test:
name: Tests
Expand Down
28 changes: 15 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,21 @@ Commit messages must follow [Conventional Commits](https://www.conventionalcommi
```
foresight/
├── backend/
│ ├── src/
│ │ └── foresight/ # Installable package (see pyproject.toml)
│ │ ├── main.py # FastAPI app entrypoint (foresight.main:app)
│ │ ├── config.py # Settings (pydantic-settings)
│ │ ├── routes/ # API route handlers
│ │ ├── schemas/ # Pydantic request/response models
│ │ ├── services/ # Business logic
│ │ ├── repository/ # Data-access layer
│ │ └── database/ # SQLAlchemy + Alembic
│ │ ├── base.py # Declarative base
│ │ ├── session.py # Async session factory
│ │ ├── models/ # SQLAlchemy models
│ │ └── migrations/ # Alembic migrations
│ ├── foresight/ # Installable package (see pyproject.toml)
│ │ ├── main.py # FastAPI app entrypoint (foresight.main:app)
│ │ ├── config.py # Settings (pydantic-settings)
│ │ ├── routes/ # API route handlers
│ │ ├── schemas/ # Pydantic request/response models
│ │ ├── services/ # Business logic
│ │ │ ├── ml/ # ML models (regression, bayesian, ...)
│ │ │ └── parsers/ # Client data ingestion
│ │ ├── repository/ # Data-access layer
│ │ └── database/ # SQLAlchemy + Alembic
│ │ ├── base.py # Declarative base
│ │ ├── session.py # Async session factory
│ │ ├── models/ # SQLAlchemy models
│ │ └── migrations/ # Alembic migrations
│ ├── scripts/ # Dev tooling (mock data, model comparison)
│ ├── tests/ # Pytest suite
│ ├── alembic.ini
│ ├── pyproject.toml
Expand Down
2 changes: 1 addition & 1 deletion backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ EXPOSE 8000

# ---- dev -------------------------------------------------------------------
# Adds dev dependencies (pytest, ruff, ...) and runs uvicorn with --reload.
# docker-compose.yml bind-mounts ./backend/src over /app/src so edits are
# docker-compose.yml bind-mounts ./backend/foresight over /app/foresight so edits are
# picked up live. Selected via `build.target: dev` in docker-compose.yml.
FROM base AS dev

Expand Down
2 changes: 1 addition & 1 deletion backend/alembic.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[alembic]
script_location = src/foresight/database/migrations
script_location = foresight/database/migrations
# The `foresight` package is installed via `uv sync`, so no sys.path
# manipulation is needed for `from foresight...` imports in env.py to resolve.

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

from services.ml.base import Model
from foresight.services.ml.base import Model


class BayesianModel(Model):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

from services.ml.base import Model
from foresight.services.ml.base import Model

DEFAULTS = {
"hidden_layer_sizes": (32, 16),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import numpy as np
from sklearn.ensemble import HistGradientBoostingRegressor

from services.ml.base import Model
from foresight.services.ml.base import Model


class GBMModel(Model):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from statsmodels.tsa.statespace.sarimax import SARIMAX

from services.ml.base import Model
from foresight.services.ml.base import Model


class TimeSeriesModel(Model):
Expand Down
8 changes: 4 additions & 4 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ ml = [
]

[tool.hatch.build.targets.wheel]
packages = ["src/foresight"]
packages = ["foresight"]

[tool.ruff]
target-version = "py312"
src = ["src"]
exclude = ["src/foresight/database/migrations"]
src = ["."]
exclude = ["foresight/database/migrations"]
line-length = 88

[tool.ruff.lint]
Expand All @@ -69,4 +69,4 @@ known-first-party = ["foresight"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
pythonpath = ["src", "scripts"]
pythonpath = ["scripts"]
13 changes: 4 additions & 9 deletions backend/scripts/compare_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,14 @@
Run from backend/: uv run python scripts/compare_models.py
"""

import sys
from pathlib import Path

import numpy as np
import pandas as pd

from generate_mock_data import write_csv

sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
from services.ml.bayesian import BayesianModel
from services.ml.neural_net import NNModel
from services.ml.regression import GBMModel
from services.ml.timeseries import TimeSeriesModel
from foresight.services.ml.bayesian import BayesianModel
from foresight.services.ml.neural_net import NNModel
from foresight.services.ml.regression import GBMModel
from foresight.services.ml.timeseries import TimeSeriesModel

# Known only after the night, so never used to predict price.
POST_STAY_COLUMNS = ["rooms_sold", "occupancy", "room_revenue"]
Expand Down
11 changes: 6 additions & 5 deletions backend/tests/test_ml_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import pandas as pd
import pytest

from services.ml.base import Model
from services.ml.bayesian import BayesianModel
from services.ml.neural_net import NNModel
from services.ml.regression import GBMModel
from services.ml.timeseries import TimeSeriesModel
from foresight.services.ml.base import Model
from foresight.services.ml.bayesian import BayesianModel
from foresight.services.ml.neural_net import NNModel
from foresight.services.ml.regression import GBMModel
from foresight.services.ml.timeseries import TimeSeriesModel

MODELS = [BayesianModel, NNModel, GBMModel, TimeSeriesModel]

Expand Down Expand Up @@ -65,6 +65,7 @@ def test_nn_has_no_interval(price_split):
model.predict_interval(x_test)
assert model.evaluate(x_test, y_test)["coverage"] is None


class FixedModel(Model):
"""Returns preset predictions and a +/-5 band, recording the alpha asked for."""

Expand Down
Loading
Loading