ConversationalPrediction / documentation.md
fusin001's picture
Upload documentation.md with huggingface_hub
c1d9865 verified
|
Raw
History Blame Contribute Delete
13.1 kB

A newer version of the Gradio SDK is available: 6.20.0

Upgrade

Documentation – Zurich Apartment Rent Conversational Agent

1. Project Summary

A conversational Gradio web application that lets users describe an apartment in plain natural language and receive an estimated monthly rental price for the Canton of Zurich.

The app combines three key components:

  • Language understanding – OpenAI's GPT language model reads the user's free-text description and extracts structured apartment parameters as JSON
  • ML prediction – A Gradient Boosting Regressor model (pre-trained on ~800 Zurich apartment listings) turns those parameters into a CHF / month estimate
  • Natural language response – OpenAI generates a friendly, contextualised explanation that contextualises the predicted price

The flow is: Natural language in → JSON extraction → ML prediction → Explanation generated → Natural language out.


2. Files Used

File Purpose
app.py Gradio application and main logic
requirements.txt Python dependencies (gradio, openai, scikit-learn, etc.)
apartment_rf_model.pkl Saved Gradient Boosting Regressor model
README.md User-facing readme for Hugging Face
documentation.md This documentation file

3. Numeric Prediction Part

3.1 Reused Model

Which saved model did you use?
apartment_rf_model.pkl – A Gradient Boosting Regressor trained on Zurich apartment rental data

What does the model predict?
The monthly rental price (CHF) for an apartment in the Canton of Zurich based on the provided apartment characteristics and local municipality features.

Which input features are used for prediction?

  1. rooms – Number of rooms (e.g., 3.5)
  2. area_m2 – Living area in square meters
  3. kreis – District (e.g., "Kreis 3", "Kreis 8")
  4. furnished – Boolean flag for furnished apartment
  5. attika – Boolean flag for penthouse/attic
  6. seesicht – Boolean flag for lake view
  7. tax_income – Mean taxable income in municipality (CHF, default: 80000)

3.2 Prediction Logic

  1. User provides a free-text description of their apartment requirements in German or English.
  2. OpenAI's GPT model extracts structured parameters (rooms, area, district, etc.) and returns them as JSON.
  3. Python validates that at minimum rooms and area_m2 are present.
  4. The JSON values are passed to the preprocessed model features.
  5. The Gradient Boosting Regressor predicts the monthly rent in CHF.
  6. The prediction is passed to a second OpenAI call to generate a contextualised explanation.

4. LLM Extraction Part (Step 1: JSON Extraction)

4.1 Goal

The LLM must read the user's natural language apartment description and extract structured parameters that the regression model requires, specifically:

  • rooms (required)
  • area_m2 (required)
  • kreis (optional)
  • furnished, attika, seesicht (optional booleans)

If rooms or area_m2 are missing, the LLM should ask a clarifying question instead of guessing.

4.2 Prompt Design

The system prompt instructs OpenAI to act as a Zurich real estate assistant. Key design decisions:

  • Strict JSON output – The model is instructed to return a JSON code block with predefined field names matching the regression model's expectations
  • Schema specified – All possible fields, their types, and default values are explicitly documented in the prompt
  • Language-agnostic – The prompt asks the model to respond in the language the user uses (German/English/mixed)
  • Sensible defaults – For optional fields not mentioned, the prompt provides defaults (e.g., tax_income: 80000, kreis: "None", booleans: false)
  • Validation fields – The prompt asks the model to also output a list of assumptions made for any unspecified optional fields

Example system message excerpt:
"Extract the following apartment parameters into strict JSON: rooms, area_m2, kreis, furnished, attika, seesicht, tax_income. If rooms or area are missing, ask a clarifying question instead. Respond in the user's language."

4.3 Expected Output Format

When parameters are present:

{
  "rooms": 3.5,
  "area_m2": 85,
  "kreis": "Kreis 3",
  "furnished": false,
  "attika": false,
  "seesicht": false,
  "tax_income": 80000,
  "assumptions": "Assumed unfurnished, no special features; typical Zurich municipality income used."
}

When parameters are missing:

"How many rooms does the apartment have? Also, what is the approximate size in m²?"

4.4 Validation

Python validates the extracted JSON by:

  1. Checking that rooms and area_m2 are present and numeric
  2. Ensuring kreis matches known Zurich districts if provided
  3. Confirming all boolean flags are True/False
  4. Handling edge cases (e.g., if kreis is missing, a default or average is used)

If validation fails, the error is logged and the user is prompted again.


5. LLM Explanation Part (Step 2: Explanation Generation)

5.1 Goal

After the regression model has predicted a rental price, a second OpenAI call generates a friendly, contextualised explanation that:

  1. Clearly states the predicted rent – "CHF X,XXX per month"
  2. Contextualises it – References the location, apartment size, and market context
  3. Acknowledges uncertainty – Notes that this is an ML estimate and actual prices depend on additional factors
  4. Invites refinement – Encourages the user to adjust parameters and query again

5.2 Prompt Design

The second prompt embeds:

  • The predicted rental price (CHF per month)
  • The extracted apartment parameters (for context)
  • A gentle reminder that the estimate has limitations

Key design decisions:

  • No recalculation – The prompt is explicit that OpenAI should not attempt to recalculate the price
  • Contextual grounding – Mentions real Zurich market knowledge (e.g., Kreis 8 is typically expensive)
  • Uncertainty note – The prompt requires acknowledgment that factors like condition, renovation, and hyperlocal details are not captured
  • Response language – Matches the user's input language (German/English)

Example system message excerpt:
"You are a Zurich real estate assistant. The regression model has predicted a monthly rent of CHF X for an apartment with the provided parameters. Explain this prediction in 3-5 sentences. Do NOT recalculate the price. Acknowledge uncertainty. Respond in the user's language."

5.3 Expected Output Format

{
  "explanation": "Für eine 3.5-Zimmer-Wohnung mit 85 m² im Kreis 3 schätzt das Modell eine Monatsmiete von etwa CHF 2,800. Der Kreis 3 ist zentral gelegen mit guter Infrastruktur, was den Preis begründet. Beachte, dass dieser Preis auf historischen Daten basiert und nicht alle Faktoren wie Zustand, Renovierung oder genaue Mikrolage erfasst. Versuche, die Parameter anzupassen, um verschiedene Szenarien zu erkunden."
}

6. End-to-End Pipeline

  1. User input – User enters a German or English description of their apartment needs via the Gradio text input
  2. LLM extraction – OpenAI extracts rooms, area_m2, and optional parameters into JSON; if required fields are missing, it asks a clarifying question
  3. Validation – Python validates the JSON structure and values
  4. Model prediction – The Gradient Boosting Regressor receives the structured data and predicts monthly rent (CHF)
  5. LLM explanation – OpenAI receives the prediction and generates a contextualised explanation
  6. Output display – Gradio displays:
    • The extracted JSON (so user can verify what was understood)
    • The predicted monthly rent (CHF)
    • The natural language explanation

7. Test Cases

Test Input Extracted Output Correct? Prediction Returned? Explanation Returned? Notes
"I'm looking for a 3-room apartment, about 80 m², in Kreis 3." Yes Yes Yes Standard Zurich city apartment; price ~CHF 2,500–2,800
"Ich suche eine 1.5-Zimmer-Wohnung, ca. 40 m², möbliert im Stadtzentrum." Yes Yes Yes Furnished apartment; smaller, so lower price; German input handled correctly
"4.5-Zimmer Penthouse mit Seeblick, 150 m², Kreis 8, luxuriös." Yes Yes Yes Multiple luxury flags (attika, seesicht, higher status district); premium price predicted (~CHF 4,500+)
"I want a 2-room apartment in Zurich" No (missing area) No No LLM correctly requests clarification ("How large?"); no prediction fired
"3 bed flat, around 95 m square in district 7" Yes Yes Yes English input; "3 bed" correctly mapped to rooms=3; Kreis 7 recognized

8. Errors and Problems

Problem 1: Invalid JSON from OpenAI

Cause: Occasionally OpenAI might wrap JSON in markdown code blocks or return partially malformed responses.
Fix: Added try-catch blocks and JSON parsing with fallback prompts to request strict JSON output. The system prompt was updated to specify: "Always respond with valid JSON in a code block."

Problem 2: Missing or mismatched kreis values

Cause: Users might specify district names in different formats ("Kreis 3" vs "Zurich District 3").
Fix: Added mapping logic to normalize district names. If the district is unrecognised, the app defaults to kreis: "None" and the model uses the canton-wide average.


9. Deployment Notes

9.1 Files Included in Deployment

  • app.py – Main Gradio application
  • requirements.txt – Dependencies (gradio, openai, scikit-learn, pandas, numpy)
  • README.md – User-facing documentation for Hugging Face Spaces
  • apartment_rf_model.pkl – Pre-trained Gradient Boosting Regressor
  • documentation.md – This documentation

9.2 Secrets / Environment Variables

Required:

  • OPENAI_API_KEY – Your OpenAI API key (obtained from platform.openai.com)

9.3 Deployment Result

The Space is deployed at: https://huggingface.co/spaces/fusin001/ConversationalPrediction

Status: ✅ Running
Model: OpenAI GPT (via API)
Regression Model: Gradient Boosting Regressor

The app successfully:

  • Accepts free-text apartment descriptions in German and English
  • Extracts structured parameters via OpenAI
  • Predicts rental prices using the pre-trained model
  • Generates contextualised explanations

Known limitations:

  • Predictions are based on historical data (~800 listings from 2023); real current prices may vary
  • The model captures district, size, and luxury features but not micro-level details (exact street, building age, etc.)
  • OpenAI API response time affects user experience; international rate limiting may apply

9.4 Screenshots

Screenshot 1 – Example apartment query and result

Example 1

Query: Ich suche eine 3-Zimmer-Wohnung mit ca. 85 m² im Kreis 3.


Screenshot 2 – Example luxury apartment

Example 2

Query: 4.5-Zimmer Penthouse mit Seeblick, ca. 150 m², Kreis 8.


10. Reflection

What worked well:
The combination of OpenAI's language capabilities and a pre-trained regression model proved effective. The multi-step pipeline (extract → predict → explain) creates a natural user experience where users can describe an apartment conversationally and receive an instant estimate without filling out a form. German language support was crucial for the target user base.

Where the system is fragile:
The biggest weakness is dependency on OpenAI's API for both extraction and explanation—network latency, API costs, and rate limiting are factors. Additionally, the regression model was trained on limited, historical data; market shifts or new apartment types (e.g., co-living spaces) may produce inaccurate predictions. The LLM extraction can still misparse edge cases (e.g., unconventional room descriptions).

Why German input matters:
The Swiss apartment market is German-speaking (in Zürich); users think and describe apartments in German/Swiss German dialect. Supporting German directly (not just translating) makes the experience feel native and reduces misunderstandings in extraction.


11. Responsible Use Note

The predicted rental price is an estimate based on a limited dataset of approximately 800 historical Zürich listings and should not be used as a basis for financial or legal decisions. The model captures only a small set of structured features (room count, area, district, and a few boolean flags) and cannot account for factors such as building condition, renovation status, exact street location, or current market dynamics. Additionally, the LLM extraction step may misinterpret ambiguous or unconventional apartment descriptions, leading to incorrect feature values being passed to the model. Real rental prices in Zürich depend on many additional factors not represented here, and users should always verify estimates against current listings from established real estate platforms.