File size: 5,056 Bytes
fb08fdb
 
 
051fb4e
 
5265454
38f3b7b
fb08fdb
7a3b5ba
38f3b7b
fb08fdb
7a3b5ba
fb08fdb
 
38f3b7b
 
 
 
 
 
7a3b5ba
38f3b7b
 
 
 
 
 
 
 
fb08fdb
38f3b7b
 
fb08fdb
7a3b5ba
fb08fdb
 
38f3b7b
fb08fdb
 
 
38f3b7b
fb08fdb
 
 
 
38f3b7b
 
7a3b5ba
38f3b7b
 
 
 
 
 
 
 
 
 
 
 
 
 
fb08fdb
38f3b7b
 
 
 
 
 
 
 
 
 
7a3b5ba
38f3b7b
 
 
 
 
 
 
 
 
7a3b5ba
38f3b7b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7a3b5ba
38f3b7b
 
 
 
 
 
7a3b5ba
38f3b7b
 
 
 
 
7a3b5ba
38f3b7b
 
 
 
 
 
 
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import streamlit as st
import os
import sys
from crewai import Agent, Task, Crew, Process
from crewai.tools import BaseTool
from crewai_tools import SerperDevTool
from langchain_openai import ChatOpenAI 


st.set_page_config(page_title="Smart Relocation Assistant", page_icon="🏘️", layout="wide")

st.title("Smart Relocation Assistant")
st.markdown("Use AI Agents to find your perfect neighborhood based on budget and lifestyle.")

# --- 2. API KEY SETUP ---
# Fetch keys from environment variables (Hugging Face Secrets)
openai_api_key = os.getenv("OPENAI_API_KEY")
serper_api_key = os.getenv("SERPER_API_KEY")

if not (openai_api_key and serper_api_key):
    st.error(" API Keys not found!")
    st.warning("Please set OPENAI_API_KEY and SERPER_API_KEY in your Hugging Face Space 'Settings' -> 'Variables and secrets'.")
    st.stop()

# Set keys back into environment for the tools/libraries
os.environ["OPENAI_API_KEY"] = openai_api_key
os.environ["SERPER_API_KEY"] = serper_api_key

# --- 3. TOOL DEFINITIONS ---

# The Search Tool is now initialized here
search_tool = SerperDevTool()

# Custom Calculator Tool 
class CalculatorTool(BaseTool):
    name: str = "Budget Calculator"
    description: str = "Useful for calculating if a rent price fits within a budget. Input must be a mathematical expression."

    def _run(self, expression: str) -> str:
        try:
            # Safe evaluation of simple math
            return str(eval(expression))
        except:
            return "Error in calculation"

calc_tool = CalculatorTool()

# --- 4. LLM DEFINITION
gpt_4o_mini = ChatOpenAI(
    model="gpt-4o-mini",
    temperature=0.7 
)


# --- 5. STREAMLIT INPUTS ---
st.header("1. Enter Your Relocation Details")
col1, col2 = st.columns(2)
with col1:
    city = st.text_input("Target City", "Austin, TX")
    budget = st.number_input("Max Monthly Rent ($)", min_value=500, value=2500)
with col2:
    work_location = st.text_input("Work Location", "Downtown")
    
preferences = st.text_area("Lifestyle Preferences", "Walkable, near coffee shops, safe, good for young professionals")

# --- 6. AGENT & TASK DEFINITIONS (Defined in the function for cleaner scope) ---

def run_crew_analysis(city, work_location, budget, preferences):
    city_scout = Agent(
        role='City Neighborhood Scout',
        goal=f'Identify the top 3 neighborhoods in {city} that match these preferences: {preferences}.',
        backstory="You are a local expert who knows every corner of the city. You prioritize safety, commute, and lifestyle fit.",
        tools=[search_tool],
        llm=gpt_4o_mini, 
        verbose=True,
        allow_delegation=False
    )

    budget_analyst = Agent(
        role='Relocation Financial Advisor',
        goal=f'Assess the affordability of specific neighborhoods and ensure rent is within {budget}.',
        backstory="You are a pragmatic financial advisor. You strictly filter out any options that exceed the user's budget.",
        tools=[search_tool, calc_tool],
        llm=gpt_4o_mini, 
        verbose=True,
        allow_delegation=False
    )

    scout_task = Task(
        description=f"Search for neighborhoods in {city} that are: {preferences}. Consider commute to {work_location}. Select top 5 candidates.",
        expected_output="List of 5 neighborhoods with vibe descriptions.",
        agent=city_scout
    )

    analysis_task = Task(
        description=f"For the 5 neighborhoods found, search current average rent for a 1-bedroom. Filter out any where rent > {budget}. Calculate remaining budget.",
        expected_output="Filtered list of affordable neighborhoods with costs.",
        agent=budget_analyst
    )

    report_task = Task(
        description="""Compile a final report. Rank top 3 affordable neighborhoods. Include: Neighborhood Name, Vibe, Rent Cost, Remaining Budget, and one Local Highlight. Format as clear Markdown.""",
        expected_output="Markdown formatted relocation guide.",
        agent=budget_analyst
    )

    # --- CREW EXECUTION ---
    relocation_crew = Crew(
        agents=[city_scout, budget_analyst],
        tasks=[scout_task, analysis_task, report_task],
        process=Process.sequential,
        llm=gpt_4o_mini 
    )

    return relocation_crew.kickoff()

# --- 7. BUTTON TRIGGER ---
if st.button("Start Research", type="primary"):
    with st.spinner('AI Agents are scouting neighborhoods and crunching numbers...'):
        try:
            result = run_crew_analysis(city, work_location, budget, preferences)
            
            # Display Results
            st.success("Research Complete!")
            st.markdown("### Your Relocation Plan")
            st.markdown(result)
            
        except Exception as e:
            st.error("An error occurred during crew execution. This often means a temporary API issue or a failure to parse a search result.")
            st.exception(e)
            st.markdown("---")
            st.warning("Please wait a few minutes (for rate limit cooldown) and try again, or check your API keys.")