nniehaus commited on
Commit
750ea5f
·
verified ·
1 Parent(s): 1776e1d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -92
app.py CHANGED
@@ -2,10 +2,7 @@ import streamlit as st
2
  import requests
3
  from bs4 import BeautifulSoup
4
  from geopy.geocoders import Nominatim
5
- from urllib.parse import urljoin, urlparse
6
- import re
7
  import os
8
- import pandas as pd
9
  import folium
10
  from streamlit_folium import folium_static
11
 
@@ -13,54 +10,41 @@ from streamlit_folium import folium_static
13
  DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_KEY")
14
  API_ENDPOINT = "https://api.deepseek.com/v1/chat/completions"
15
 
16
- # Cache expensive operations
17
- @st.cache_data
 
 
 
18
  def scrape_location_data(query):
19
- """Scrape location data from public sources"""
20
- sources = {
21
- "Niche": f"https://www.niche.com/places-to-live/search/{query}",
22
- "AreaVibes": f"https://www.areavibes.com/search/?query={query}",
23
- }
24
-
25
- results = []
26
- for source, url in sources.items():
27
- try:
28
- response = requests.get(url, timeout=15)
29
- soup = BeautifulSoup(response.text, 'html.parser')
30
-
31
- if source == "Niche":
32
- listings = soup.find_all('div', class_='search-results__list__item')
33
- for item in listings[:3]:
34
- results.append({
35
- 'name': item.find('h2').text.strip(),
36
- 'details': item.find('div', class_='search-result-tagline').text.strip(),
37
- 'score': item.find('div', class_='search-result-grade').text.strip()
38
- })
39
-
40
- except Exception as e:
41
- continue
42
-
43
- return results
44
 
45
  def generate_recommendations(preferences):
46
- """Generate neighborhood recommendations using Deepseek API"""
47
  headers = {
48
  "Authorization": f"Bearer {DEEPSEEK_API_KEY}",
49
  "Content-Type": "application/json"
50
  }
51
 
52
  prompt = f"""
53
- Create a neighborhood recommendation report based on these preferences:
54
- {preferences}
55
-
56
- Include these sections:
57
- 1. Top 5 Neighborhood Matches
58
- 2. Hidden Gem Recommendation
59
- 3. Key Amenities Analysis
60
- 4. Commute Times Overview
61
- 5. Safety & Community Insights
62
-
63
- Format with markdown headers and bullet points. Keep sections concise.
64
  """
65
 
66
  try:
@@ -70,10 +54,10 @@ def generate_recommendations(preferences):
70
  "model": "deepseek-chat",
71
  "messages": [{"role": "user", "content": prompt}],
72
  "temperature": 0.7,
73
- "max_tokens": 1500
74
  },
75
  headers=headers,
76
- timeout=30
77
  )
78
  return response.json()["choices"][0]["message"]["content"]
79
  except Exception as e:
@@ -81,53 +65,43 @@ def generate_recommendations(preferences):
81
  return None
82
 
83
  # Streamlit UI
84
- st.set_page_config(layout="wide", page_icon="🏡")
85
- st.title("Neighborhood Matchmaker")
86
-
87
- with st.sidebar:
88
- st.header("Search Preferences")
89
- city = st.text_input("City/Region", "New York, NY")
90
- budget = st.slider("Monthly Housing Budget ($)", 1000, 10000, 3000)
91
- commute = st.selectbox("Max Commute Time", ["15 mins", "30 mins", "45 mins", "1 hour"])
92
- amenities = st.multiselect("Must-Have Amenities", [
93
- "Good Schools", "Parks", "Public Transport",
94
- "Nightlife", "Shopping", "Healthcare"
95
- ])
96
- lifestyle = st.selectbox("Lifestyle Preference", [
97
- "Family-Friendly", "Urban Professional", "Retirement",
98
- "Student", "Remote Worker", "Outdoor Enthusiast"
99
- ])
100
 
101
- if st.button("Find My Neighborhood"):
102
- with st.spinner("Analyzing locations..."):
103
- # Collect preferences
104
- preferences = {
105
- "city": city,
106
- "budget": f"${budget}/mo",
107
- "max_commute": commute,
108
- "amenities": amenities,
109
- "lifestyle": lifestyle
110
- }
111
-
112
- # Get location data
113
- location_data = scrape_location_data(city)
114
-
115
- # Generate recommendations
116
- report = generate_recommendations(preferences)
117
-
118
- # Display results
119
- if report:
120
- st.subheader("Your Personalized Neighborhood Report")
121
- st.markdown(report)
122
 
123
- # Show map
124
- try:
125
- geolocator = Nominatim(user_agent="neighborhood_finder")
126
- location = geolocator.geocode(city)
127
- m = folium.Map(location=[location.latitude, location.longitude], zoom_start=12)
128
- folium_static(m, width=1200, height=500)
129
- except Exception as e:
130
- st.warning("Couldn't generate map visualization")
131
-
132
- st.markdown("---")
133
- st.caption("Note: Recommendations generated by AI. Verify with local experts.")
 
 
 
 
 
 
 
 
2
  import requests
3
  from bs4 import BeautifulSoup
4
  from geopy.geocoders import Nominatim
 
 
5
  import os
 
6
  import folium
7
  from streamlit_folium import folium_static
8
 
 
10
  DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_KEY")
11
  API_ENDPOINT = "https://api.deepseek.com/v1/chat/completions"
12
 
13
+ # Docker-compatible settings
14
+ st.set_page_config(layout="wide", page_icon="🏡")
15
+ geolocator = Nominatim(user_agent="docker_neighborhood_finder")
16
+
17
+ @st.cache_data(show_spinner=False)
18
  def scrape_location_data(query):
19
+ """Scrape location data with Docker-friendly timeout"""
20
+ try:
21
+ response = requests.get(
22
+ f"https://www.niche.com/places-to-live/search/{query}",
23
+ timeout=10
24
+ )
25
+ soup = BeautifulSoup(response.text, 'html.parser')
26
+ return [
27
+ item.find('h2').text.strip()
28
+ for item in soup.find_all('div', class_='search-results__list__item')[:3]
29
+ ]
30
+ except Exception:
31
+ return []
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  def generate_recommendations(preferences):
34
+ """Docker-optimized API call"""
35
  headers = {
36
  "Authorization": f"Bearer {DEEPSEEK_API_KEY}",
37
  "Content-Type": "application/json"
38
  }
39
 
40
  prompt = f"""
41
+ Analyze these preferences: {preferences}
42
+ Recommend neighborhoods with:
43
+ - Top 3 matches
44
+ - 1 hidden gem
45
+ - Key amenities
46
+ - Safety insights
47
+ Format with markdown bullet points
 
 
 
 
48
  """
49
 
50
  try:
 
54
  "model": "deepseek-chat",
55
  "messages": [{"role": "user", "content": prompt}],
56
  "temperature": 0.7,
57
+ "max_tokens": 1000
58
  },
59
  headers=headers,
60
+ timeout=20 # Docker-friendly timeout
61
  )
62
  return response.json()["choices"][0]["message"]["content"]
63
  except Exception as e:
 
65
  return None
66
 
67
  # Streamlit UI
68
+ st.title("🏡 Neighborhood Finder (Docker)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
+ with st.form("preferences"):
71
+ col1, col2 = st.columns(2)
72
+ with col1:
73
+ city = st.text_input("City/Region", "New York, NY")
74
+ budget = st.slider("Monthly Budget ($)", 1000, 10000, 3000)
75
+ with col2:
76
+ commute = st.selectbox("Max Commute", ["15m", "30m", "45m", "1h"])
77
+ lifestyle = st.selectbox("Lifestyle", ["Family", "Urban", "Remote"])
78
+
79
+ if st.form_submit_button("Find Neighborhoods"):
80
+ with st.spinner("Searching..."):
81
+ # Get data
82
+ locations = scrape_location_data(city)
83
+ preferences = {
84
+ "city": city,
85
+ "budget": budget,
86
+ "commute": commute,
87
+ "lifestyle": lifestyle
88
+ }
 
 
89
 
90
+ # Generate report
91
+ report = generate_recommendations(preferences)
92
+
93
+ # Show results
94
+ if report:
95
+ st.markdown(report)
96
+
97
+ # Docker-compatible map
98
+ try:
99
+ location = geolocator.geocode(city)
100
+ m = folium.Map(
101
+ location=[location.latitude, location.longitude],
102
+ zoom_start=12,
103
+ tiles="CartoDB positron"
104
+ )
105
+ folium_static(m, width=1000, height=400)
106
+ except Exception:
107
+ st.warning("Map unavailable - location not found")