Spaces:
Runtime error
Runtime error
| # Streamlit frontend for the Airbnb Rental Price Prediction service. | |
| # This UI collects property details from the user, sends them to the | |
| # deployed Flask backend, and displays the predicted rental price. | |
| import streamlit as st | |
| import pandas as pd | |
| import requests | |
| # ----------------------------------------------------------------------------- | |
| # Configure the backend API endpoints | |
| # ----------------------------------------------------------------------------- | |
| # Replace the base URL below with the URL of your deployed backend Space. | |
| MODEL_ROOT_URL = "https://uohna-RentalPricePredictionBackend.hf.space" | |
| ONLINE_URL = f"{MODEL_ROOT_URL}/v1/rental" | |
| BATCH_URL = f"{MODEL_ROOT_URL}/v1/rentalbatch" | |
| # ----------------------------------------------------------------------------- | |
| # Page configuration | |
| # ----------------------------------------------------------------------------- | |
| st.set_page_config( | |
| page_title="Airbnb Rental Price Predictor", | |
| page_icon="🏡", | |
| layout="centered", | |
| ) | |
| st.title("🏡 Airbnb Rental Price Predictor") | |
| st.write( | |
| "Predict the nightly rental price for a property using our deployed " | |
| "machine learning model." | |
| ) | |
| # Two tabs: one for single-property prediction, one for batch uploads | |
| online_tab, batch_tab = st.tabs(["Single Prediction", "Batch Prediction"]) | |
| # ----------------------------------------------------------------------------- | |
| # Online (single property) inference | |
| # ----------------------------------------------------------------------------- | |
| with online_tab: | |
| st.subheader("Enter Property Details") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| room_type = st.selectbox( | |
| "Room Type", | |
| ["Entire home/apt", "Private room", "Shared room"], | |
| ) | |
| accommodates = st.number_input( | |
| "Accommodates", min_value=1, max_value=20, value=2, step=1 | |
| ) | |
| bathrooms = st.number_input( | |
| "Bathrooms", min_value=0.0, max_value=10.0, value=1.0, step=0.5 | |
| ) | |
| bedrooms = st.number_input( | |
| "Bedrooms", min_value=0, max_value=15, value=1, step=1 | |
| ) | |
| beds = st.number_input( | |
| "Beds", min_value=0, max_value=20, value=1, step=1 | |
| ) | |
| with col2: | |
| cancellation_policy = st.selectbox( | |
| "Cancellation Policy", | |
| ["flexible", "moderate", "strict", "super_strict_30", "super_strict_60"], | |
| ) | |
| cleaning_fee = st.selectbox("Cleaning Fee Charged?", [True, False]) | |
| instant_bookable = st.selectbox("Instant Bookable?", ["t", "f"]) | |
| review_scores_rating = st.slider( | |
| "Review Scores Rating", min_value=0, max_value=100, value=90, step=1 | |
| ) | |
| if st.button("Predict Price", type="primary"): | |
| payload = { | |
| "room_type": room_type, | |
| "accommodates": int(accommodates), | |
| "bathrooms": float(bathrooms), | |
| "cancellation_policy": cancellation_policy, | |
| "cleaning_fee": bool(cleaning_fee), | |
| "instant_bookable": instant_bookable, | |
| "review_scores_rating": int(review_scores_rating), | |
| "bedrooms": int(bedrooms), | |
| "beds": int(beds), | |
| } | |
| try: | |
| response = requests.post(ONLINE_URL, json=payload, timeout=30) | |
| if response.status_code == 200: | |
| result = response.json() | |
| price = result.get("Predicted Price (in dollars)") | |
| st.success(f"💰 Predicted Nightly Price: **${price}**") | |
| else: | |
| st.error(f"Request failed ({response.status_code}): {response.text}") | |
| except requests.exceptions.RequestException as err: | |
| st.error(f"Could not reach the backend API: {err}") | |
| # ----------------------------------------------------------------------------- | |
| # Batch inference | |
| # ----------------------------------------------------------------------------- | |
| with batch_tab: | |
| st.subheader("Upload a CSV for Batch Predictions") | |
| st.caption( | |
| "Your CSV should contain the same feature columns the model was trained on " | |
| "(e.g., room_type, accommodates, bathrooms, cancellation_policy, cleaning_fee, " | |
| "instant_bookable, review_scores_rating, bedrooms, beds, and an 'id' column)." | |
| ) | |
| uploaded_file = st.file_uploader("Choose a CSV file", type=["csv"]) | |
| if uploaded_file is not None: | |
| df_preview = pd.read_csv(uploaded_file) | |
| st.write("Preview of uploaded data:") | |
| st.dataframe(df_preview.head()) | |
| if st.button("Run Batch Prediction"): | |
| # Rewind so we can send the raw CSV bytes | |
| uploaded_file.seek(0) | |
| try: | |
| response = requests.post( | |
| BATCH_URL, | |
| files={"file": uploaded_file.getvalue()}, | |
| timeout=120, | |
| ) | |
| if response.status_code == 200: | |
| predictions = response.json() | |
| st.success(f"✅ Received {len(predictions)} predictions.") | |
| results_df = pd.DataFrame( | |
| list(predictions.items()), | |
| columns=["Property ID", "Predicted Price (in dollars)"], | |
| ) | |
| st.dataframe(results_df) | |
| st.download_button( | |
| "Download Predictions as CSV", | |
| data=results_df.to_csv(index=False).encode("utf-8"), | |
| file_name="rental_price_predictions.csv", | |
| mime="text/csv", | |
| ) | |
| else: | |
| st.error( | |
| f"Request failed ({response.status_code}): {response.text}" | |
| ) | |
| except requests.exceptions.RequestException as err: | |
| st.error(f"Could not reach the backend API: {err}") | |