nniehaus commited on
Commit
df7994d
·
verified ·
1 Parent(s): fb8767e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +139 -184
app.py CHANGED
@@ -1,199 +1,154 @@
1
  import streamlit as st
2
- import openai
3
  import requests
4
  from bs4 import BeautifulSoup
5
- from urllib.parse import urljoin, urlparse
6
  import os
7
  import re
8
-
9
- # Ensure your OpenAI API key is set in your environment variables
10
- openai.api_key = os.getenv("OPENAI_API_KEY")
11
-
12
- def scrape_website(url, max_pages=5):
13
- """
14
- Crawls and scrapes content from the given website URL.
15
- Follows internal links and extracts meaningful information from up to `max_pages` pages.
16
- """
17
- if not url.startswith("http"):
18
- url = f"https://{url}"
19
-
20
- visited = set()
21
- to_visit = [url]
22
- all_content = []
23
- scrape_successful = False
24
-
25
- while to_visit and len(visited) < max_pages:
26
- current_url = to_visit.pop(0)
27
- if current_url in visited:
28
- continue
29
-
30
  try:
31
- response = requests.get(current_url, timeout=10)
32
- response.raise_for_status()
33
- soup = BeautifulSoup(response.content, "html.parser")
34
- visited.add(current_url)
35
- scrape_successful = True
36
-
37
- # Extract meaningful content
38
- meta_description = soup.find("meta", {"name": "description"})
39
- if meta_description and meta_description.get("content"):
40
- all_content.append(meta_description["content"])
41
-
42
- paragraphs = soup.find_all("p")
43
- for para in paragraphs:
44
- all_content.append(para.get_text(strip=True))
45
-
46
- links = soup.find_all("a", href=True)
47
- for link in links:
48
- full_url = urljoin(current_url, link["href"])
49
- if url in full_url and full_url not in visited:
50
- to_visit.append(full_url)
51
-
52
- except Exception:
53
  continue
54
-
55
- return " ".join(all_content[:3000]), scrape_successful
56
-
57
- def extract_location(content):
 
 
 
 
 
 
 
 
 
58
  """
59
- Extract a possible location from the website content using regular expressions.
60
- """
61
- location_match = re.search(r'\b(?:serving|located in|offices in|based in)\s([\w\s,]+)', content, re.IGNORECASE)
62
- return location_match.group(1).strip() if location_match else None
63
-
64
- def infer_business_info_from_url(url):
65
- """
66
- Infer business details from the domain name.
67
- """
68
- domain_name = urlparse(url).netloc
69
- inferred_info = openai.ChatCompletion.create(
70
- model="gpt-4",
71
- messages=[
72
- {
73
- "role": "system",
74
- "content": "You are a business analyst. Based on domain names, generate likely information about a business, including its industry, target audience, and goals."
75
- },
76
- {
77
- "role": "user",
78
- "content": f"The domain is {domain_name}. What can you infer about this business?"
79
- }
80
- ]
81
  )
82
- return inferred_info["choices"][0]["message"]["content"]
83
 
84
- def generate_marketing_plan(content, goals, budget, location_focus, campaign_focus, location, inferred_info, messages, fallback=False):
85
- """
86
- Generates a marketing plan based on provided content, goals, budget, and optional focuses.
87
- """
88
- location_info = f"The business is located in {location}." if location else "No specific location was mentioned."
89
- additional_info = f"Inferred details: {inferred_info}" if inferred_info else "No additional business details were inferred."
90
- location_focus_info = "Focus on location-specific strategies." if location_focus else "No explicit focus on location-specific strategies."
91
- campaign_focus_info = f"Specific focus: {campaign_focus}" if campaign_focus else "No specific campaign focus provided."
92
-
93
- query = f"""
94
- The user has provided the following details:
95
- - Content: {content if not fallback else "N/A (no content provided)"}
96
- - Goals for 2025: {goals}
97
- - Marketing budget for 2025: ${budget}
98
- - {location_info}
99
- - {location_focus_info}
100
- - {campaign_focus_info}
101
- - {additional_info}
102
-
103
- Create a detailed 1-year marketing plan that includes:
104
- 1. **Overview Summary**: Summarize the key focus areas for the business to achieve its goals. Include video marketing as a top priority.
105
- 2. **Advanced Keywords**: Provide at least 10 long-tail keywords specific to the industry and location (if applicable).
106
- 3. **Content Topics**: Provide at least 10 blog, YouTube, or social media topics, each with a brief description.
107
- 4. **SEO Strategies**: Detailed recommendations for improving search rankings, including tools and methods.
108
- 5. **Content Marketing Plan**: How to leverage the provided content topics to achieve the stated goals.
109
- 6. **Social Media Strategies**: Platforms, posting frequency, campaign ideas, and location-specific tactics.
110
- 7. **Advertising Campaigns**: Platforms, budget allocation, target audience details, and creative strategies.
111
- 8. **Execution Timeline**: A quarterly breakdown of actionable steps with measurable KPIs.
112
-
113
- Ensure the recommendations are detailed, actionable, and tailored to the business's specific goals, budget, and location.
114
- Avoid generic suggestions and provide unique, high-value insights.
115
  """
116
 
117
- messages.append({"role": "user", "content": query})
118
- response = openai.ChatCompletion.create(
119
- model="gpt-4",
120
- messages=messages
 
121
  )
122
- return response["choices"][0]["message"]["content"]
123
 
124
- # Define initial_messages
125
- initial_messages = [{
126
- "role": "system",
127
- "content": """You are a world-class marketing strategist trained by Neil Patel, David Ogilvy, and Seth Godin.
128
- Your task is to create highly customized marketing plans based on user input. Incorporate any business location
129
- or target areas explicitly mentioned in the website content or user-provided details into the recommendations.
130
- Go beyond generic suggestions, and include:
131
- - Specific, long-tail keywords to target.
132
- - Detailed content ideas, including blogs, videos, and social media campaigns.
133
- - Unique strategies tailored to the business's goals, location, and target audience.
134
- - Innovative advertising campaigns and emerging platform recommendations.
135
- - Video marketing as a critical strategy across all platforms.
136
- Ensure every suggestion is actionable and includes measurable KPIs."""
137
- }]
138
-
139
- # Streamlit setup
140
  st.set_page_config(layout="wide")
141
-
142
- # Initialize session state
143
- if "reply" not in st.session_state:
144
- st.session_state["reply"] = None
145
- if "show_notice" not in st.session_state:
146
- st.session_state["show_notice"] = False
147
-
148
- # Centered title
149
- st.markdown("<h1 style='text-align: center; color: black;'>2025 Marketing Planner</h1>", unsafe_allow_html=True)
150
-
151
- # User inputs
152
- st.markdown("<h2 style='text-align: center; color: black;'>Enter Business Details</h2>", unsafe_allow_html=True)
153
- website_url = st.text_input("Enter your business website (optional)", placeholder="e.g., https://example.com")
154
- manual_details = st.text_area(
155
- "Enter details about your business (if no website is provided or cannot be scanned)",
156
- placeholder="E.g., Business name, target audience, goals, and location."
157
- )
158
- goals = st.text_area("Goals for 2025 (optional)", placeholder="E.g., increase brand awareness, drive online sales")
159
- budget = st.number_input("Marketing Budget for 2025 ($)", min_value=1000, step=1000)
160
-
161
- # Additional inputs for focus areas
162
- location_focus = st.checkbox("Focus on location-specific strategies?")
163
- campaign_focus = st.text_input(
164
- "Specific campaign focus (optional)",
165
- placeholder="E.g., lead generation, email campaigns, brand awareness"
166
- )
167
-
168
- generate_button = st.button('Generate Marketing Plan')
169
-
170
- # Process results on button click
171
- if generate_button:
172
- st.session_state["show_notice"] = True
173
- with st.spinner("Analyzing provided details and preparing your report..."):
174
- # Attempt to scrape website content if a URL is provided
175
- website_content, scrape_successful = scrape_website(website_url) if website_url else ("", False)
176
- location = extract_location(website_content) if scrape_successful else None
177
- inferred_info = infer_business_info_from_url(website_url) if not scrape_successful and website_url else None
178
-
179
- # Use manual details as fallback content
180
- content = website_content if scrape_successful else manual_details
181
- fallback_mode = not scrape_successful and not manual_details
182
-
183
- if fallback_mode:
184
- st.warning("No valid website content or manual details provided. Please enter business details.")
185
-
186
- messages = initial_messages.copy()
187
- st.session_state["reply"] = generate_marketing_plan(
188
- content, goals, budget, location_focus, campaign_focus, location, inferred_info, messages, fallback=fallback_mode
189
- )
190
- st.session_state["show_notice"] = False # Remove the notice once the report is ready
191
-
192
- # Display the waiting notice
193
- if st.session_state["show_notice"]:
194
- st.info("Generating your marketing plan. This process may take a minute or two. Please wait...")
195
-
196
- # Display results if there is a reply in session state
197
- if st.session_state["reply"]:
198
- st.markdown("<h2 style='text-align: center; color: black;'>Your 2025 Marketing Plan ⬇️</h2>", unsafe_allow_html=True)
199
- st.markdown(st.session_state["reply"])
 
1
  import streamlit as st
 
2
  import requests
3
  from bs4 import BeautifulSoup
 
4
  import os
5
  import re
6
+ from deepseek_api import DeepSeek # Replace with actual Deepseek SDK
7
+
8
+ # Configure Deepseek API
9
+ DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
10
+ ds = DeepSeek(api_key=DEEPSEEK_API_KEY)
11
+
12
+ def search_neighborhood_data(query):
13
+ """Search for neighborhood information across various sources"""
14
+ sources = {
15
+ "Niche": f"https://www.niche.com/places-to-live/search/{query}",
16
+ "AreaVibes": f"https://www.areavibes.com/search/?query={query}",
17
+ "Walkscore": f"https://www.walkscore.com/score/{query}"
18
+ }
19
+
20
+ results = {}
21
+ for source, url in sources.items():
 
 
 
 
 
 
22
  try:
23
+ response = requests.get(url, timeout=10)
24
+ soup = BeautifulSoup(response.text, 'html.parser')
25
+
26
+ if source == "Niche":
27
+ listings = soup.find_all('div', class_='search-results__list__item')
28
+ results[source] = [{
29
+ 'name': item.find('h2').text.strip(),
30
+ 'details': item.find('div', class_='search-result-tagline').text.strip(),
31
+ 'score': item.find('div', class_='search-result-grade').text.strip()
32
+ } for item in listings[:3]]
33
+
34
+ elif source == "AreaVibes":
35
+ # Similar parsing for other sources
36
+ ...
37
+
38
+ except Exception as e:
 
 
 
 
 
 
39
  continue
40
+
41
+ return results
42
+
43
+ def analyze_preferences(preferences):
44
+ """Use Deepseek to analyze user preferences and generate search parameters"""
45
+ prompt = f"""
46
+ User preferences: {preferences}
47
+ Generate search parameters for neighborhood hunting considering:
48
+ - Key demographic factors
49
+ - Important amenities
50
+ - Commute considerations
51
+ - Lifestyle priorities
52
+ - Budget constraints
53
  """
54
+
55
+ response = ds.generate(
56
+ model="neighborhood-matcher",
57
+ prompt=prompt,
58
+ max_tokens=500
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  )
60
+ return response['choices'][0]['text']
61
 
62
+ def generate_recommendations(criteria, locations):
63
+ """Generate neighborhood recommendations with Deepseek's analysis"""
64
+ base_prompt = f"""
65
+ Based on these verified neighborhood data:
66
+ {locations}
67
+
68
+ And user criteria:
69
+ {criteria}
70
+
71
+ Create 5 recommendations including:
72
+ 1. Best overall match
73
+ 2. Best value option
74
+ 3. Best for families
75
+ 4. Best for young professionals
76
+ 5. 'Outside the Box' option (creative suggestion)
77
+
78
+ For each include:
79
+ - Key strengths
80
+ - Potential drawbacks
81
+ - Notable amenities
82
+ - Average home prices
83
+ - Commute times
84
+ - Unique character
 
 
 
 
 
 
 
 
85
  """
86
 
87
+ response = ds.generate(
88
+ model="neighborhood-matcher",
89
+ prompt=base_prompt,
90
+ max_tokens=1500,
91
+ temperature=0.7
92
  )
93
+ return response['choices'][0]['text']
94
 
95
+ # Streamlit UI
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  st.set_page_config(layout="wide")
97
+ st.title("🏡 Neighborhood Matchmaker")
98
+
99
+ with st.expander("🔍 Your Lifestyle Preferences"):
100
+ col1, col2 = st.columns(2)
101
+ with col1:
102
+ budget = st.slider("Monthly Housing Budget ($)", 1000, 10000, 3000)
103
+ commute = st.selectbox("Max Commute Time", ["15 mins", "30 mins", "45 mins", "1 hour"])
104
+ amenities = st.multiselect("Must-Have Amenities", [
105
+ "Good Schools", "Parks", "Public Transport",
106
+ "Nightlife", "Shopping Centers", "Healthcare"
107
+ ])
108
+
109
+ with col2:
110
+ lifestyle = st.selectbox("Primary Lifestyle", [
111
+ "Family-Friendly", "Urban Professional", "Retirement",
112
+ "Student", "Remote Worker", "Outdoor Enthusiast"
113
+ ])
114
+ safety = st.slider("Safety Priority (1-10)", 1, 10, 8)
115
+ extra = st.text_input("Special Requirements", placeholder="e.g., Dog parks, historic district")
116
+
117
+ # Generate recommendations
118
+ if st.button("Find My Perfect Neighborhood"):
119
+ with st.spinner("Analyzing preferences and searching neighborhoods..."):
120
+ # Collect preferences
121
+ preferences = {
122
+ "budget": budget,
123
+ "commute": commute,
124
+ "amenities": amenities,
125
+ "lifestyle": lifestyle,
126
+ "safety": safety,
127
+ "extra": extra
128
+ }
129
+
130
+ # Analyze preferences with AI
131
+ search_params = analyze_preferences(preferences)
132
+
133
+ # Search for matching locations
134
+ location_data = search_neighborhood_data(search_params)
135
+
136
+ # Generate final recommendations
137
+ recommendations = generate_recommendations(preferences, location_data)
138
+
139
+ # Display results
140
+ st.subheader("Your Custom Neighborhood Recommendations")
141
+ st.markdown(recommendations)
142
+
143
+ # Always include an "outside the box" suggestion
144
+ st.subheader("🚀 Outside the Box Option")
145
+ st.markdown("""**Emerging Neighborhood - Innovation District**
146
+ *Why we suggest it:*
147
+ - Up-and-coming tech hub with new amenities
148
+ - Lower prices before expected growth
149
+ - Community development initiatives
150
+ *Consider if:* You want to get in early on a growing area""")
151
+
152
+ # Disclaimer
153
+ st.markdown("---")
154
+ st.caption("Recommendations are AI-generated and should be verified with local experts.")