CoolFace
Apppublic

essainsham/UAE-Real-Estate-Agent

sourceHugging Faceupdated 1mo agoView on Hugging Face
0likes
App README

๐Ÿ˜๏ธ Intelligent UAE Real Estate Advisory Agent

An agentic AI advisor for the UAE rental market. Ask it about a property in plain English โ€” it works out what you're asking, extracts the details, tells you what's missing, predicts the rent, and answers legal questions grounded in UAE property law.

[โ–ถ๏ธ Try the live demo](https://huggingface.co/spaces/essainsham/UAE-Real-Estate-Agent)

<!-- TODO: Replace with a GIF of the demo running. Record with a screen recorder, drop the file in docs/ and reference it here. This is the single highest-value thing on this page. --> [image]


What it does

Most LLM chatbots guess when they don't have enough information. This one doesn't โ€” it asks. The agent routes each query to a specialised path, and refuses to predict a price until it actually has the fields it needs.

  • โ€”Rental price prediction โ€” a Random Forest model trained on UAE listings data, wired into the agent rather than bolted on beside it
  • โ€”Legal Q&A โ€” RAG over UAE real estate law documents, so legal answers are grounded in source text instead of model memory
  • โ€”Live market research โ€” Tavily web search for questions that need current data
  • โ€”Financial breakdown โ€” monthly/annual rent, security deposit, agent commission
  • โ€”Multi-turn memory โ€” the conversation holds state across turns

Architecture

Nine nodes in a LangGraph StateGraph, with conditional routing at two decision points.

mermaid
graph TD
    START([START]) --> intent[intent<br/>classify_intent]
    intent -->|valuation| extractor[extractor<br/>extract_property_info]
    intent -->|legal| legal[legal<br/>legal_advisor ยท RAG]
    intent -->|market research| research[research<br/>Tavily search]
    intent -->|contact| contact[contact<br/>contact_details]

    extractor --> validator{validator<br/>validate_inputs}
    validator -->|complete| predictor[predictor<br/>Random Forest]
    validator -->|missing fields| responder

    predictor --> rental[rental<br/>rental_calculator]
    rental --> responder[responder<br/>generate_response]

    responder --> END([END])
    legal --> END
    research --> END
    contact --> END

<!-- TODO: verify the validator branch labels against rout_validator() in nodes.py โ€” confirm where the "incomplete" branch actually goes. -->

The flow: intent classifies the query and routes it. Valuation queries go through extractor โ†’ validator. If required fields are missing, the agent asks the user instead of guessing. Once complete, predictor runs the ML model, rental computes the financials, and responder synthesises a natural-language answer. Legal, research, and contact queries bypass the ML path entirely.


Design decisions

The things worth explaining, and what I'd do differently.

Human-in-the-loop over silent defaults. The validator node exists because the first version happily predicted prices from incomplete queries. Extracting Beds=None and predicting anyway produces a confident, wrong number โ€” worse than no answer. Now incomplete extractions route back to the user for clarification.

Pydantic schema as the extraction prompt. PropertyExtraction in state.py carries the instructions in its Field descriptions rather than in a long prompt string:

python
Area_in_sqft: Optional[float] = Field(
    default=750,
    description="Total area in square feet. If not explicitly mentioned, "
                "estimate it by multiplying the number of Bedrooms by 750, plus 24."
)

This keeps the schema and its semantics in one place, and the LLM gets the rule and the type together. The 750 ร— bedrooms + 24 heuristic is a rough regression on typical UAE unit sizes โ€” a deliberate fallback, not an accident. Same idea for Baths defaulting to bedrooms + 1 and City defaulting to Dubai.

A graph, not a ReAct loop. An open-ended agent choosing tools freely would be more flexible and less predictable. The query space here is narrow โ€” valuation, legal, market, contact โ€” so a deterministic StateGraph with explicit routing is easier to reason about, cheaper, and easier to debug when it misroutes.

RAG only where it earns its place. Legal questions need grounding in source text, so they get retrieval. Price prediction doesn't โ€” a trained model on structured features beats an LLM guessing from retrieved listings.

<!-- TODO: Add one concrete failure you found and fixed. E.g. "v1 routed queries mentioning a number to the price model even when they were legal questions โ€” I tightened the intent prompt and added X." This is the section interviewers care about most. Add it once you have a real example. -->


Stack

LayerChoice
OrchestrationLangGraph (StateGraph, MemorySaver checkpointing)
LLMGroq API (Llama 3.3 70B)
Structured outputPydantic
RetrievalChromaDB + HuggingFace embeddings
Web searchTavily
MLscikit-learn (RandomForestRegressor), joblib
UIStreamlit
DeploymentHugging Face Spaces via GitHub Actions

Running locally

bash
git clone https://github.com/essainsham17/UAE-Real-Estate-Agent.git
cd UAE-Real-Estate-Agent

python -m venv venv
source venv/bin/activate        # Windows: venv\Scripts\activate

pip install -r requirements.txt

Create a .env in the project root:

env
GROQ_API_KEY=your_groq_key
TAVILY_API_KEY=your_tavily_key

<!-- TODO: add any other env vars the app actually needs (LangSmith? HF token?) -->

Then:

bash
streamlit run app.py

Opens at http://localhost:8501.


Deployment

Pushes to main trigger .github/workflows/sync.yml, which authenticates with an HF_TOKEN secret and pushes the repo to the Hugging Face Space. Deployment is automatic on merge.


Repo layout

agent.py              # StateGraph definition โ€” nodes, edges, routing
nodes.py              # Node implementations
state.py              # AgentState + PropertyExtraction (Pydantic)
config.py             # LLM + checkpointer setup
app.py                # Streamlit UI
notebooks/            # Model training + LangGraph prototyping
*.pkl                 # Trained Random Forest + column schema

Known limitations

  • โ€”Trained on a fixed dataset; predictions don't reflect live market movement
  • โ€”Legal RAG covers a limited set of documents โ€” not a substitute for legal advice
  • โ€”Dependencies are unpinned <!-- TODO: pin these and delete this line -->
  • โ€”No automated eval suite yet โ€” output quality is checked manually

Author

Essa Insham โ€” AI Engineer, Abu Dhabi, UAE <<<<<<< HEAD GitHub ยท LinkedIn ยท essainsham17@gmail.com ======= GitHub ยท LinkedIn ยท essainsham17@gmail.com

>>>>>> 3fb9600 (updated sync for readme push)