MatteoAldovardi commited on
Commit
d95bed5
·
1 Parent(s): 9bb522b
.DS_Store ADDED
Binary file (6.15 kB). View file
 
Dockerfile ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use an official Python runtime as a parent image
2
+ FROM python:3.9-slim-buster
3
+
4
+ # Set the working directory in the container
5
+ WORKDIR /app
6
+
7
+ # Copy the current directory contents into the container at /app
8
+ # This includes main.py, requirements.txt, and the models/ directory
9
+ COPY . /app
10
+
11
+ # Install any needed packages specified in requirements.txt
12
+ RUN pip install --no-cache-dir -r requirements.txt
13
+
14
+ # Create a directory for your models if it doesn't exist
15
+ # (though it should be copied from local)
16
+ RUN mkdir -p models
17
+
18
+ # Expose the port FastAPI will run on. Hugging Face Spaces often expects
19
+ # port 7860 for web apps.
20
+ EXPOSE 7860
21
+
22
+ # Command to run the Uvicorn server
23
+ # The --host 0.0.0.0 makes the server accessible from outside the
24
+ # container
25
+ # The --port 7860 matches the EXPOSE instruction
26
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,11 +1,111 @@
1
  ---
 
2
  title: My Fastapi Endpoint
3
- emoji: 📈
4
  colorFrom: gray
5
- colorTo: blue
6
  sdk: docker
7
  pinned: false
8
  license: mit
9
  ---
10
 
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ <<<<<<< HEAD
3
  title: My Fastapi Endpoint
4
+ emoji: 🏃
5
  colorFrom: gray
6
+ colorTo: purple
7
  sdk: docker
8
  pinned: false
9
  license: mit
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
13
+ =======
14
+ title: My FastAPI App
15
+ emoji: 🌍
16
+ colorFrom: red
17
+ colorTo: red
18
+ sdk: docker
19
+ pinned: false
20
+ license: mit
21
+ short_description: This is a taxi predictor!
22
+ ---
23
+
24
+ # FastAPI Taxi Trip Duration Prediction API
25
+
26
+ This project provides a FastAPI-based REST API for predicting taxi trip durations in different cities using pre-trained Ridge regression models.
27
+
28
+ ## How to Use
29
+
30
+ ### 1. Running the API
31
+
32
+ - **Locally:**
33
+ Start the server with:
34
+ ```sh
35
+ uvicorn main:app --host 0.0.0.0 --port 7860
36
+ ```
37
+ - **On Hugging Face Spaces:**
38
+ The API will be available at
39
+ `https://<your-username>-<your-space-name>.hf.space/predict`
40
+
41
+ ### 2. Sending a Prediction Request
42
+
43
+ You can send a POST request to the `/predict` endpoint using any HTTP client (such as `curl`, Postman, or Python's `requests` library).
44
+
45
+ #### Example Python snippet
46
+
47
+ ```python
48
+ import requests
49
+
50
+ API_URL = "https://<your-username>-<your-space-name>.hf.space/predict"
51
+ # If your Space is private, uncomment and set your token:
52
+ # HF_TOKEN = "hf_xxx..."
53
+ # headers = {"Authorization": f"Bearer {HF_TOKEN}"}
54
+ headers = {}
55
+
56
+ data = {
57
+ "vendor_id": "Bogotá UberX",
58
+ "dist_meters": 18.976,
59
+ "wait_sec": 1640,
60
+ "geodetic_dist": 15.439039,
61
+ "mean_velocity": 17.172851,
62
+ "is_rush_hour": False,
63
+ "model_name": "bog"
64
+ }
65
+
66
+ response = requests.post(API_URL, json=data, headers=headers)
67
+ print(response.json())
68
+ ```
69
+
70
+ ### 3. Datapoint Format
71
+
72
+ The API expects a JSON object with the following fields:
73
+
74
+ | Field | Type | Example Value | Description |
75
+ | ------------- | ------ | -------------- | ------------------------------------------------ |
76
+ | vendor_id | string | "Bogotá UberX" | The taxi vendor or service name |
77
+ | dist_meters | float | 18.976 | Distance of the trip in meters |
78
+ | wait_sec | float | 1640 | Waiting time in seconds |
79
+ | geodetic_dist | float | 15.439039 | Geodetic (straight-line) distance |
80
+ | mean_velocity | float | 17.172851 | Mean velocity during the trip |
81
+ | is_rush_hour | bool | false | Whether the trip occurred during rush hour |
82
+ | model_name | string | "bog" | Which model to use: `"bog"`, `"mex"`, or `"uio"` |
83
+
84
+ **Example JSON datapoint:**
85
+
86
+ ```json
87
+ {
88
+ "vendor_id": "Bogotá UberX",
89
+ "dist_meters": 18.976,
90
+ "wait_sec": 1640,
91
+ "geodetic_dist": 15.439039,
92
+ "mean_velocity": 17.172851,
93
+ "is_rush_hour": false,
94
+ "model_name": "bog"
95
+ }
96
+ ```
97
+
98
+ ### 4. Response Format
99
+
100
+ The API will return a JSON response like:
101
+
102
+ ```json
103
+ {
104
+ "trip_duration": 123.45,
105
+ "model_used": "bog",
106
+ "message": "Inference successful using BOG model."
107
+ }
108
+ ```
109
+
110
+ ---
111
+ >>>>>>> 531d625 (Commiiitt!)
__pycache__/main.cpython-39.pyc ADDED
Binary file (2.95 kB). View file
 
app.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from pydantic import BaseModel
3
+ import uvicorn
4
+ import os
5
+ import joblib
6
+ import pandas as pd
7
+
8
+ # --- 0. Initialize FastAPI app ---
9
+ app = FastAPI()
10
+
11
+ @app.get("/")
12
+ def read_root():
13
+ return {"message": "Welcome to the Taxi Fare Prediction API. Use POST /predict to get predictions."}
14
+
15
+ # --- 1. Define Input and Output Data Models ---
16
+ class InferenceInput(BaseModel):
17
+ vendor_id: str
18
+ dist_meters: float
19
+ wait_sec: float
20
+ geodetic_dist: float
21
+ mean_velocity: float
22
+ is_rush_hour: bool
23
+ model_name: str # "bog", "mex", or "uio"
24
+
25
+ class InferenceOutput(BaseModel):
26
+ trip_duration: float
27
+ model_used: str
28
+ message: str
29
+
30
+ # --- 2. Define ML Model Manager Class ---
31
+ class MLModels:
32
+ def __init__(self):
33
+ model_dir = "models"
34
+ self.bog_pipeline = self.load_pipeline(os.path.join(model_dir, "bog_ridge_pipeline.pkl"))
35
+ self.mex_pipeline = self.load_pipeline(os.path.join(model_dir, "mex_ridge_pipeline.pkl"))
36
+ self.uio_pipeline = self.load_pipeline(os.path.join(model_dir, "uio_ridge_pipeline.pkl"))
37
+
38
+ def load_pipeline(self, path):
39
+ if os.path.exists(path):
40
+ return joblib.load(path)
41
+ else:
42
+ raise FileNotFoundError(f"Model file not found: {path}")
43
+
44
+ def predict_one(self, features: dict, model_name: str):
45
+ model_map = {
46
+ "bog": self.bog_pipeline,
47
+ "mex": self.mex_pipeline,
48
+ "uio": self.uio_pipeline
49
+ }
50
+ pipeline = model_map.get(model_name.lower())
51
+ if not pipeline:
52
+ raise ValueError(f"Model '{model_name}' not found. Choose from 'bog', 'mex', or 'uio'.")
53
+ X_df = pd.DataFrame([features])
54
+ pred = pipeline.predict(X_df)[0]
55
+ return float(pred)
56
+
57
+ # --- 3. Initialize ML Model Manager ---
58
+ ml_models = MLModels()
59
+
60
+ # --- 4. Define Inference Endpoint ---
61
+ @app.post("/predict", response_model=InferenceOutput)
62
+ async def predict_inference(data: InferenceInput):
63
+ try:
64
+ features = data.dict()
65
+ model_name = features.pop("model_name")
66
+ trip_duration = ml_models.predict_one(features, model_name)
67
+ return InferenceOutput(
68
+ trip_duration=trip_duration,
69
+ model_used=model_name,
70
+ message=f"Inference successful using {model_name.upper()} model."
71
+ )
72
+ except Exception as e:
73
+ raise HTTPException(status_code=400, detail=f"Inference failed: {str(e)}")
74
+
75
+ # --- 5. Run the Application (for local development) ---
76
+ if __name__ == "__main__":
77
+ port_number = 7860 # Use 7860 to match Gradio UI port if needed
78
+ host = os.getenv("FASTAPI_HOST", "127.0.0.1")
79
+ port = int(os.getenv("FASTAPI_PORT", port_number))
80
+ print(f"FastAPI application starting on http://{host}:{port}")
81
+ print(f"Access the API documentation (Swagger UI) at http://{host}:{port}/docs")
82
+ uvicorn.run(app, host=host, port=port)
models/bog_ridge_pipeline.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c5708a4e33b6c3f4b1e9ca38abc12ed241ae558bc95b66f75011b5f22778ec33
3
+ size 3473
models/mex_ridge_pipeline.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7779475db1d7865b5df33131aa66bc82b09c7031fe48f82821f1ca56c97e0833
3
+ size 3553
models/uio_ridge_pipeline.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:23c71ea9c30a02dccc12dadbfcf19d8b67fd1eb2e88c8bcd9da035b1825145fa
3
+ size 3449
requirements.txt ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ annotated-types==0.7.0
2
+ anyio==4.9.0
3
+ certifi==2025.4.26
4
+ charset-normalizer==3.4.2
5
+ click==8.1.8
6
+ exceptiongroup==1.3.0
7
+ fastapi==0.115.12
8
+ h11==0.16.0
9
+ idna==3.10
10
+ joblib==1.5.1
11
+ lightgbm==4.6.0
12
+ numpy==2.0.2
13
+ pandas==2.3.0
14
+ pip==25.1
15
+ pydantic==2.11.5
16
+ pydantic_core==2.33.2
17
+ python-dateutil==2.9.0.post0
18
+ pytz==2025.2
19
+ requests==2.32.4
20
+ scikit-learn==1.6.1
21
+ scipy==1.13.1
22
+ setuptools==78.1.1
23
+ six==1.17.0
24
+ sniffio==1.3.1
25
+ starlette==0.46.2
26
+ threadpoolctl==3.6.0
27
+ typing_extensions==4.14.0
28
+ typing-inspection==0.4.1
29
+ tzdata==2025.2
30
+ urllib3==2.4.0
31
+ uvicorn==0.34.3
32
+ wheel==0.45.1