From ca7b2e33156942f40f4db7c56a0184c82c97abd0 Mon Sep 17 00:00:00 2001 From: Patrick Huembeli Date: Wed, 19 Feb 2025 10:23:52 +0100 Subject: [PATCH] initial commit --- backend/.DS_Store | Bin 0 -> 6148 bytes backend/app/.DS_Store | Bin 0 -> 6148 bytes backend/app/core/config.py | 10 +++++++++ backend/app/main.py | 21 +++++++++++++++++ backend/app/models/prediction.py | 21 +++++++++++++++++ backend/app/routers/predictions.py | 27 ++++++++++++++++++++++ backend/app/services/ml_model.py | 35 +++++++++++++++++++++++++++++ backend/requirements.txt | 3 +++ 8 files changed, 117 insertions(+) create mode 100644 backend/.DS_Store create mode 100644 backend/app/.DS_Store create mode 100644 backend/app/core/config.py create mode 100644 backend/app/main.py create mode 100644 backend/app/models/prediction.py create mode 100644 backend/app/routers/predictions.py create mode 100644 backend/app/services/ml_model.py create mode 100644 backend/requirements.txt diff --git a/backend/.DS_Store b/backend/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..338d7d9714d534306c1eb9143c28250a70169072 GIT binary patch literal 6148 zcmeHKPfNov6i>G4GKSEDg5CmN2X?{^;-%F21+3^nWwvx^u{LGx>|qRg*DvH3@$>jz zl7hpYMf5#Le(!J6{Gj>67~}pj9y8`J#soA(j!KK5yEW9Y$%q`sDDo&(5m@h0Zezb4 z@Y}mAWI4;D>g)HXNm07)2k&%yTibon7ejFuJgO=v!*W^p;o=6ZOQq7N(ZlE}nO8Gs z_e^DFm}K*XE=b}zq}*O7S*$8wEwi}LwSftUff&r3gVkz$a_o+zyBa7Dhygp;Rhlm0?z9kT)MbBbw5F#MllmePkZl4(3l!IT| zJkMfn(3CT-XNGa?%+2G4>)F9CbvomoLF$PCVqlYjt}z`v|Igu0fvXBJ7H literal 0 HcmV?d00001 diff --git a/backend/app/.DS_Store b/backend/app/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0ae1d8de8035ece8073a53215fc61caa66e54f62 GIT binary patch literal 6148 zcmeHK!A`Wo z-NguK!pRuiNoL>f>`a^Y=1bc7}uJ;R@5Lq8Ti zj^9?YO~5E%6!>cj(Au@&0R*HFeqF!*Fpjd^ao$;}Y;9GlyvpnR&U+FQFYo80tkX|# zXmlw=?9cms|0)V6y~ggDNb-J^gsCiuf)G<~ucIUola3fAK_+WGHNk7V)@vM0r>&D? zr)fL0rmedzr`?{-YJBhT==7rZ91jxlq7-Df;Yi!jIEPp4d=eUaX%dU%5o45JfdLW? zAcPpQO(DBLYKd?ae^mh^$dPioIh2=ZEs^GsNxEZ*@WT!_hxQ7wCF1iXurBH)#Ov!8 zm^`C^QQ+SwK>LG@PUvbZ6w0jw8+iplv@k3U`*fF}8e5~Qu~3LJXiSwNs#2z}7)+I8 z+}3%n#zLVg2c|C{Ouw1w8w!(e$LHHJ9hj@ov_=7=z@h?WHEhuNfBy6Rf3e7ni~>f1 zjZ%PFU9a0gO8RVFAxCGejed_#MtOxoS%Qr|j%A0A;(c^!IA>D_(bZTe#0Z-CBOqlk KjZxrN75D&Yi3Z*P literal 0 HcmV?d00001 diff --git a/backend/app/core/config.py b/backend/app/core/config.py new file mode 100644 index 0000000..e3ed20f --- /dev/null +++ b/backend/app/core/config.py @@ -0,0 +1,10 @@ +from pydantic_settings import BaseSettings + +class Settings(BaseSettings): + API_V1_STR: str = "/api/v1" + PROJECT_NAME: str = "House Price Predictor" + + class Config: + case_sensitive = True + +settings = Settings() \ No newline at end of file diff --git a/backend/app/main.py b/backend/app/main.py new file mode 100644 index 0000000..d6becef --- /dev/null +++ b/backend/app/main.py @@ -0,0 +1,21 @@ +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware +from app.routers import predictions + +app = FastAPI( + title="Housing Price Predictor API", + description="API for predicting housing prices", + version="1.0.0" +) + +# Add CORS middleware +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +# Include routers +app.include_router(predictions.router, prefix="/api/v1") \ No newline at end of file diff --git a/backend/app/models/prediction.py b/backend/app/models/prediction.py new file mode 100644 index 0000000..587255c --- /dev/null +++ b/backend/app/models/prediction.py @@ -0,0 +1,21 @@ +from pydantic import BaseModel, Field +from typing import List + +class HousePredictionInput(BaseModel): + square_feet: float = Field(..., gt=0, description="Square footage of the house") + bedrooms: int = Field(..., ge=1, description="Number of bedrooms") + bathrooms: float = Field(..., gt=0, description="Number of bathrooms") + + class Config: + json_schema_extra = { + "example": { + "square_feet": 2000, + "bedrooms": 3, + "bathrooms": 2.5 + } + } + +class HousePredictionOutput(BaseModel): + predicted_price: float + confidence_score: float + similar_listings: List[float] \ No newline at end of file diff --git a/backend/app/routers/predictions.py b/backend/app/routers/predictions.py new file mode 100644 index 0000000..fe869b0 --- /dev/null +++ b/backend/app/routers/predictions.py @@ -0,0 +1,27 @@ +from fastapi import APIRouter, HTTPException +from app.models.prediction import HousePredictionInput, HousePredictionOutput +from app.services.ml_model import HousePricePredictor + +router = APIRouter() +model = HousePricePredictor() + +@router.post("/predict", + response_model=HousePredictionOutput, + summary="Predict house price", + description="Predicts the price of a house based on its features" +) +async def predict_price(input_data: HousePredictionInput) -> HousePredictionOutput: + try: + predicted_price, confidence_score, similar_listings = model.predict( + input_data.square_feet, + input_data.bedrooms, + input_data.bathrooms + ) + + return HousePredictionOutput( + predicted_price=predicted_price, + confidence_score=confidence_score, + similar_listings=similar_listings + ) + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) \ No newline at end of file diff --git a/backend/app/services/ml_model.py b/backend/app/services/ml_model.py new file mode 100644 index 0000000..3a64818 --- /dev/null +++ b/backend/app/services/ml_model.py @@ -0,0 +1,35 @@ +import random +from typing import List, Tuple + +class HousePricePredictor: + """ + Mock ML model that predicts house prices. + In a real scenario, this would load a trained model. + """ + + def __init__(self): + # Mock initialization - in reality would load model weights + pass + + def predict(self, square_feet: float, bedrooms: int, bathrooms: float) -> Tuple[float, float, List[float]]: + """ + Mock prediction method that returns: + - predicted price + - confidence score + - similar listing prices + """ + # Mock prediction logic + base_price = square_feet * 200 + bedroom_value = bedrooms * 25000 + bathroom_value = bathrooms * 15000 + + predicted_price = base_price + bedroom_value + bathroom_value + + # Add some randomness to make it interesting + confidence_score = random.uniform(0.8, 0.99) + similar_listings = [ + predicted_price * random.uniform(0.9, 1.1) + for _ in range(3) + ] + + return predicted_price, confidence_score, similar_listings \ No newline at end of file diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000..6f745c3 --- /dev/null +++ b/backend/requirements.txt @@ -0,0 +1,3 @@ +fastapi +pydantic +uvicorn \ No newline at end of file