Spaces:
Sleeping
A newer version of the Gradio SDK is available: 6.20.0
Documentation
Week 2: Apartment Predictor (Saved Regression Model + LLM Workflow)
This file documents the apartment rent prediction app that I built, tested, and deployed on Hugging Face Spaces.
1. Project Summary
The app accepts a German natural language apartment request. The user writes a sentence that includes the number of rooms, the apartment size and the town.
The LLM extracts the structured values rooms, area_m2 and town from the user text. A saved Random Forest regression model then predicts the estimated monthly rent in CHF. Finally, the LLM generates a short German explanation of the prediction and mentions that the result is only an estimate.
2. Files Used
| File | Purpose |
|---|---|
app.py |
Final deployable app used by Hugging Face Spaces |
app_student.py |
Student implementation with the completed TODOs |
random_forest_regression.pkl |
Saved Random Forest regression model |
bfs_municipality_and_tax_data.csv |
Municipality data used for prediction |
requirements.txt |
Python dependencies for Hugging Face Spaces |
README.md |
Hugging Face Space configuration and short app description |
documentation.md |
Written documentation for the submission |
screenshot1.png |
Screenshot of the first working app test |
screenshot2.png |
Screenshot of the second working app test |
3. Numeric Prediction Part
3.1 Reused Model
I used the saved model file:
random_forest_regression.pkl
The model predicts the estimated monthly apartment rent in CHF.
The model uses apartment information and municipality information for the prediction.
3.2 Input Features
The model uses these features:
roomsareapoppop_densfrg_pctemptax_income
In the user interface and in the LLM extraction step, the apartment size is called area_m2.
For the model input, I map area_m2 to the trained model feature area, because the saved model expects the feature name area.
3.3 Prediction Logic
First, the LLM extracts the number of rooms, the apartment area and the town from the German user text.
Then the app matches the extracted town to the municipality data in bfs_municipality_and_tax_data.csv.
After that, the app combines the apartment values with the municipality values and passes them to the saved Random Forest model.
The model returns a monthly rent prediction in CHF.
4. LLM Extraction Part
4.1 Goal
The goal of the first LLM step is to transform a free German apartment request into structured JSON.
The LLM extracts:
roomsarea_m2town
4.2 Prompt Design
The system prompt tells the LLM to extract apartment preferences from German text.
It requires strict JSON output only, without Markdown or additional explanation.
The required JSON keys are:
roomsarea_m2town
The prompt also tells the model to use null if a value is missing.
4.3 Expected Output Format
Example:
{
"rooms": 3.5,
"area_m2": 85,
"town": "Winterthur"
}
4.4 Validation
The app validates the LLM response before using it.
It checks whether the response is valid JSON and whether all required keys are present.
It also checks that rooms, area and town are not missing.
The town is matched against the BFS municipality data before the prediction is made.
5. LLM Explanation Part
5.1 Goal
The second LLM step generates a short German explanation of the model prediction.
The LLM does not calculate the rent itself.
It only explains the numeric prediction returned by the Random Forest model.
5.2 Prompt Design
The explanation prompt includes the extracted apartment preferences and the predicted monthly rent.
The LLM is instructed to answer in German, mention the predicted rent in CHF and include one short uncertainty note.
The response is also required to be valid JSON with the key answer.
5.3 Expected Output Format
Example:
{
"answer": "Die Wohnung mit 3.5 Zimmern und 85 m² in Winterthur hat eine geschätzte Monatsmiete von etwa 2117 CHF. Diese Schätzung basiert auf einem numerischen Modell und kommunalen Daten. Bitte beachten Sie, dass es leichte Abweichungen geben kann."
}
6. End-to-End Pipeline
The full pipeline works like this:
- The user enters a German apartment request.
- The LLM extracts
rooms,area_m2andtown. - Python validates the extracted JSON.
- The app matches the town to the municipality data.
- The app builds the model input features.
- The Random Forest model predicts the estimated monthly rent.
- The LLM generates a short German explanation.
- The app returns the extracted JSON, the predicted rent and the final explanation.
7. Test Cases
| Test Input | Extracted Output Correct? | Prediction Returned? | Explanation Returned? | Notes |
|---|---|---|---|---|
Ich suche eine 3.5-Zimmer-Wohnung mit etwa 85 m2 in Winterthur. |
Yes | Yes | Yes | Extracted 3.5 rooms, 85 m² and Winterthur. Prediction and explanation were returned successfully. |
Ich möchte eine 2-Zimmer-Wohnung mit ungefähr 60 m2 in Zürich mieten. |
Yes | Yes | Yes | Extracted 2 rooms, 60 m² and Zürich. Prediction and explanation were returned successfully. |
Ich suche eine 4.5-Zimmer-Wohnung mit 110 m2 in Bern. |
Yes | Yes | Yes | This was used as an additional German test prompt to check another Swiss city. |
8. Errors and Problems
Problem 1: Missing API key
At first, the app returned an error saying that the API key was missing.
The reason was that the OpenAI API key was not set as an environment variable.
I fixed this by adding the API key as a Hugging Face secret named OPENAI_API_KEY.
Problem 2: Wrong or invalid API key
On Hugging Face, the app returned an error saying that the API key was incorrect.
The reason was that the API key was copied incorrectly or an invalid key was used.
I fixed this by replacing the secret with a valid key and restarting the Space.
Problem 3: Model feature name mismatch
The model returned an error because it expected the feature name area, but the app originally passed area_m2.
The saved model was trained with the feature name area.
I fixed this by mapping the extracted value area_m2 to the model feature area.
Problem 4: Model version warning
A warning appeared because the Random Forest model was saved with a different scikit-learn version.
This warning did not stop the app. The model still loaded and returned predictions.
9. Deployment Notes
9.1 Files included
The following files were uploaded to Hugging Face Spaces:
app.pyapp_student.pyrequirements.txtREADME.mddocumentation.mdbfs_municipality_and_tax_data.csvrandom_forest_regression.pklscreenshot1.pngscreenshot2.png
9.2 Secrets / Environment Variables
The app requires these Hugging Face secrets:
OPENAI_API_KEYOPENAI_MODEL
The model name used was:
gpt-4.1-mini
9.3 Deployment Result
The Hugging Face Space ran successfully.
The app accepted German apartment requests, extracted structured JSON, returned a rent prediction and generated a German explanation.
10. Screenshots
Example 1
In this example, the app extracted 3.5 rooms, 85 m² and Winterthur from the German input. It returned a monthly rent prediction and a short German explanation.
Example 2
In this example, the app extracted 2 rooms, 60 m² and Zürich from the German input. It returned a monthly rent prediction and explained that the result is an estimate.
11. Reflection
The combination of a regression model and an LLM worked well because both parts have a clear role.
The LLM is useful for understanding natural language and extracting structured values.
The regression model is useful for making the numeric prediction.
The system is still fragile because the LLM could extract values incorrectly or the town might not match the municipality data.
I would improve the app by adding better town suggestions and more apartment features.
12. Responsible Use Note
The prediction is only an estimate and should not be used as a guaranteed rental price.
Real rental prices depend on many additional factors, such as location quality, building condition, floor, balcony, renovation status and market situation.
The LLM may also extract values incorrectly, so the extracted JSON should always be checked.
The app is useful as a learning prototype, but not as a final real estate pricing tool.

