File size: 4,834 Bytes
7a6c242
 
 
 
 
 
 
 
 
ea73781
7a6c242
 
 
 
 
 
 
 
 
 
 
 
 
8d944f0
7a6c242
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from smolagents import tool, CodeAgent, InferenceClientModel
import os
import dotenv
from sqlalchemy import create_engine, text
import gradio as gr

dotenv.load_dotenv()

DB_PATH = "real_estate.db"
MODEL_ID = "Qwen/Qwen3-235B-A22B-Instruct-2507"
HF_TOKEN = os.environ.get("HF_TOKEN", None)
if HF_TOKEN is None:
    raise RuntimeError("HF_TOKEN missing. Add it in Space Settings β†’ Repository secrets.")

engine = create_engine(f"sqlite:///{DB_PATH}", echo=True, future=True)

@tool
def sql_engine(query: str) -> str:
    """
    Executes a SQL query on the 'real_estate.db' SQLite database and returns the results as a string. The database contains a table named 'real_estate' with the following schema:
        Columns:
    - id: TEXT β€” Unique identifier of the listing.
    - ref: TEXT β€” Reference number of the property listing.
    - bua: TEXT β€” Built-up area of the property in square feet.
    - title: TEXT β€” Title or headline of the property listing.
    - no_of_leads: BIGINT β€” Number of customer leads or inquiries for the property.
    - location: TEXT β€” Full address or general location of the property.
    - sublocation: TEXT β€” Sub-location or neighborhood within the main location.
    - building: TEXT β€” Name of the building in which the property is located.
    - unit: TEXT β€” Unit number or identifier within the building.
    - price: FLOAT β€” Price of the property in AED (United Arab Emirates Dirham).
    - category: TEXT β€” Category or type of property (e.g., Apartment, Villa, Townhouse, Duplex, Penthouse, Hotel Apartment, Land Residential, Loft Apartment, Residential Building, Bungalow, Full Floor Residential, Bulk Units).
    - score: BIGINT β€” Quality or ranking score of the property (0–100 scale).
    - beds: FLOAT β€” Number of bedrooms in the property.
    - baths: FLOAT β€” Number of bathrooms in the property.
    - property_for: TEXT β€” Type of contract: either "Rental" or "Sales".
    - views: TEXT β€” List of view features (comma-separated, e.g., "Sea View, City View").
    - features: TEXT β€” Comma-separated list of property features (e.g., "Balcony, Pool, Parking").
    - furnishing: TEXT β€” Furnishing status (e.g., Partly Furnished, Unfurnished, Furnished, Fitted, Not Fitted, Shell And Core).
    - assigned_agent_name: TEXT β€” Name of the agent currently assigned to the property.
    - marketed_agent_name: TEXT β€” Name of the agent marketing the property.
    - portals: TEXT β€” List of online portals where the property is listed (comma-separated).

    Use LIKE for partial matches on fields like location, sublocation, building, features, and portals, assigned_agent_name, marketed_agent_name, views, features.
    Args:
        query (str): The SQL query to be executed.

    """
    output = ""

    with engine.connect() as connection:
        result = connection.execute(text(query))
        rows = result.fetchall()
        if not rows:
            return "No results found."
        for row in rows:
            output += str(row) + "\n"
    return output.strip()

def make_agent():

    agent = CodeAgent(model= InferenceClientModel(model_id=MODEL_ID, api_key=HF_TOKEN),
                    tools=[sql_engine],
                    description="A helpful agent that can answer questions about real estate properties in Dubai based on a database of listings.",
                    )

    return agent

agent = make_agent()

def run_agent(user_request: str) -> str:
    """
    Takes a natural language request, lets the agent decide the SQL via the tool,
    and returns a friendly response.
    """
    if not user_request or not user_request.strip():
        return "Please enter a request."
    try:
        return agent.run(user_request.strip())
    except Exception as e:
        return f"Agent error: {e}"

# ---- Gradio UI ----
with gr.Blocks(title="Real Estate Text-to-SQL") as demo:
    gr.Markdown(
        """
        # 🏑 Nazem's personal Driven Text-to-SQL Agent
        Ask natural-language questions to the CRM's listings database.

        **Examples**
        - "Write me a message to send my client who is asking me to propose 3 properties to show him. He is looking for flat with 2 to 3 bedrooms a marina view and a swimming pool between 1 and 5 million AED."
        - "Show 5 apartments in Dubai Marina with β‰₯3 beds, β‰₯2 baths, price 1M–2M AED. Include id, title, location, price, beds, baths, features."
        - "Top 10 cheapest villas in Palm Jumeirah with at least 4 bedrooms."
        - "
        """
    )
    with gr.Row():
        inp = gr.Textbox(label="Your request", lines=5, placeholder="Ask for properties, filters, columns, limits…")
    btn = gr.Button("Run")
    out = gr.Markdown(label="Response")

    btn.click(run_agent, inputs=inp, outputs=out)

if __name__ == "__main__":
    demo.launch()