Spaces:
Sleeping
Sleeping
Enhance demo_chatbot_responses.py with comprehensive simulation - Added detailed mock data for listings, violations, subway, and school information - Expanded response logic with intelligent filtering by bedrooms, borough, budget, and voucher acceptance - Added comprehensive non-pertinent question handling with contextual housing connections - Included voucher program details, email drafting, and neighborhood guidance - Demonstrates full agent orchestration including intent detection, tool integration, and graceful redirection
Browse files- demo_chatbot_responses.py +419 -102
demo_chatbot_responses.py
CHANGED
|
@@ -17,7 +17,9 @@ MOCK_LISTINGS = [
|
|
| 17 |
"violations": 0,
|
| 18 |
"risk_level": "β
Safe",
|
| 19 |
"subway_distance": 0.3,
|
| 20 |
-
"school_distance": 0.5
|
|
|
|
|
|
|
| 21 |
},
|
| 22 |
{
|
| 23 |
"address": "456 Oak Ave, Queens, NY",
|
|
@@ -27,7 +29,21 @@ MOCK_LISTINGS = [
|
|
| 27 |
"violations": 2,
|
| 28 |
"risk_level": "β οΈ Moderate",
|
| 29 |
"subway_distance": 0.8,
|
| 30 |
-
"school_distance": 0.3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
}
|
| 32 |
]
|
| 33 |
|
|
@@ -36,188 +52,475 @@ MOCK_VIOLATIONS = {
|
|
| 36 |
"violations": 0,
|
| 37 |
"risk_level": "β
Safe",
|
| 38 |
"last_inspection": "2024-01-15",
|
| 39 |
-
"summary": "No violations found. Building is in good condition."
|
|
|
|
| 40 |
},
|
| 41 |
"456 Oak Ave, Queens, NY": {
|
| 42 |
"violations": 2,
|
| 43 |
"risk_level": "β οΈ Moderate",
|
| 44 |
"last_inspection": "2024-02-20",
|
| 45 |
-
"summary": "Minor violations for maintenance issues. Generally safe for occupancy."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
}
|
| 47 |
}
|
| 48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
def mock_search_housing(query: str) -> List[Dict[str, Any]]:
|
| 50 |
-
"""Mock housing search function"""
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
def mock_check_violations(address: str) -> Dict[str, Any]:
|
| 60 |
-
"""Mock violation check function"""
|
| 61 |
return MOCK_VIOLATIONS.get(address, {
|
| 62 |
"violations": 0,
|
| 63 |
"risk_level": "β
Safe",
|
| 64 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
})
|
| 66 |
|
| 67 |
-
def
|
| 68 |
-
"""Mock
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
return f"""
|
| 70 |
-
Subject:
|
| 71 |
|
| 72 |
Dear Property Manager,
|
| 73 |
|
| 74 |
-
{user_info}
|
| 75 |
|
| 76 |
-
I
|
| 77 |
|
| 78 |
-
|
|
|
|
|
|
|
| 79 |
|
| 80 |
Best regards,
|
| 81 |
[Your Name]
|
|
|
|
|
|
|
| 82 |
"""
|
| 83 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
def simulate_chatbot_response(user_input: str) -> str:
|
| 85 |
"""
|
| 86 |
Simulate how the chatbot would respond to different inputs.
|
| 87 |
-
This demonstrates pertinent vs non-pertinent question handling.
|
| 88 |
"""
|
| 89 |
|
| 90 |
input_lower = user_input.lower()
|
| 91 |
|
| 92 |
# Pertinent questions - housing/voucher related
|
| 93 |
if any(keyword in input_lower for keyword in [
|
| 94 |
-
"housing", "apartment", "rent", "voucher", "section 8", "cityfheps",
|
| 95 |
-
"violation", "building safety", "subway", "school", "email", "landlord"
|
|
|
|
| 96 |
]):
|
| 97 |
|
| 98 |
-
# Housing search queries
|
| 99 |
-
if any(word in input_lower for word in ["search", "find", "looking for", "need"]):
|
| 100 |
listings = mock_search_housing(user_input)
|
| 101 |
if listings:
|
| 102 |
-
response = "π
|
| 103 |
-
for listing in listings:
|
| 104 |
-
response += f"
|
| 105 |
-
response += f"
|
| 106 |
-
response += f"
|
| 107 |
-
response += f" Schools: {listing['school_distance']}mi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
return response
|
| 109 |
else:
|
| 110 |
-
return "π I couldn't find
|
| 111 |
-
|
| 112 |
-
# Violation checking
|
| 113 |
-
elif "violation" in input_lower or "safety" in input_lower:
|
| 114 |
-
#
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
|
| 122 |
-
|
| 123 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
response += f"**Violations:** {violations['violations']}\n"
|
|
|
|
| 125 |
response += f"**Summary:** {violations['summary']}\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
return response
|
| 127 |
|
| 128 |
# Email drafting
|
| 129 |
-
elif "email" in input_lower or "draft" in input_lower:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
return mock_email_draft(
|
| 131 |
-
"I
|
| 132 |
-
"I
|
|
|
|
| 133 |
)
|
| 134 |
|
| 135 |
-
#
|
| 136 |
-
elif any(word in input_lower for word in ["voucher", "section 8", "cityfheps"]):
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
|
| 141 |
-
|
| 142 |
-
- Income must be below certain limits
|
| 143 |
-
- Must be a US citizen or eligible immigrant
|
| 144 |
-
- Background check required
|
| 145 |
|
| 146 |
-
**
|
| 147 |
-
-
|
| 148 |
-
-
|
| 149 |
|
| 150 |
-
|
| 151 |
|
| 152 |
# Subway/school proximity
|
| 153 |
-
elif "subway" in input_lower or "school" in input_lower:
|
| 154 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
|
| 156 |
-
|
| 157 |
|
| 158 |
-
Please provide an address, and I'll give you
|
| 159 |
- Nearest subway stations and walking distance
|
| 160 |
-
- Nearby schools
|
| 161 |
-
- Public transportation options
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
|
| 163 |
# Non-pertinent questions - redirect appropriately
|
| 164 |
else:
|
| 165 |
# Weather questions
|
| 166 |
-
if "weather" in input_lower:
|
| 167 |
return """π€οΈ **Weather & Housing Connection**
|
| 168 |
|
| 169 |
-
|
| 170 |
|
| 171 |
-
**
|
|
|
|
|
|
|
| 172 |
|
| 173 |
-
|
|
|
|
|
|
|
| 174 |
|
| 175 |
# Food/restaurant questions
|
| 176 |
-
elif any(word in input_lower for word in ["food", "restaurant", "eat"]):
|
| 177 |
return """π½οΈ **Food & Housing Connection**
|
| 178 |
|
| 179 |
-
|
| 180 |
|
| 181 |
-
**Housing
|
|
|
|
|
|
|
|
|
|
|
|
|
| 182 |
|
| 183 |
-
Would you like help finding apartments in foodie neighborhoods or checking
|
| 184 |
|
| 185 |
# Sports/entertainment
|
| 186 |
-
elif any(word in input_lower for word in ["sports", "game", "movie", "entertainment"]):
|
| 187 |
return """π¬ **Entertainment & Housing**
|
| 188 |
|
| 189 |
-
NYC
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 190 |
|
| 191 |
-
**
|
|
|
|
|
|
|
|
|
|
| 192 |
|
| 193 |
-
|
|
|
|
|
|
|
|
|
|
| 194 |
|
| 195 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
else:
|
| 197 |
-
return """π€ **Staying
|
| 198 |
|
| 199 |
-
I specialize in helping NYC residents find safe, affordable, voucher-friendly housing. While I'm happy to
|
| 200 |
|
| 201 |
- Housing searches and listings
|
| 202 |
- Building safety and violations
|
| 203 |
- Transit and school proximity
|
| 204 |
- Voucher program information
|
|
|
|
|
|
|
|
|
|
|
|
|
| 205 |
|
| 206 |
-
|
| 207 |
|
| 208 |
# Demo function to show various responses
|
| 209 |
def run_demo():
|
| 210 |
print("π€ VoucherBot Response Simulation Demo")
|
| 211 |
print("=" * 50)
|
| 212 |
|
| 213 |
-
# Pertinent questions
|
| 214 |
pertinent_questions = [
|
| 215 |
"I need help finding housing with Section 8 voucher",
|
| 216 |
-
"Search for 2 bedroom apartments in Brooklyn under $2000",
|
| 217 |
-
"Check building violations for 123 Main St, Brooklyn",
|
| 218 |
-
"Draft an email to a landlord about my
|
| 219 |
-
"How do I apply for
|
| 220 |
-
"Find apartments near subway stations"
|
|
|
|
|
|
|
|
|
|
| 221 |
]
|
| 222 |
|
| 223 |
print("\nπ PERTINENT QUESTIONS (Housing/Voucher Related):")
|
|
@@ -226,32 +529,46 @@ def run_demo():
|
|
| 226 |
for i, question in enumerate(pertinent_questions, 1):
|
| 227 |
print(f"\n{i}. User: {question}")
|
| 228 |
response = simulate_chatbot_response(question)
|
| 229 |
-
print(f"π€ Bot: {response[:
|
| 230 |
|
| 231 |
-
# Non-pertinent questions
|
| 232 |
non_pertinent_questions = [
|
| 233 |
"What's the weather like today?",
|
| 234 |
-
"Where's a good place to eat
|
| 235 |
-
"Who won the game last night?",
|
| 236 |
-
"Can you
|
| 237 |
-
"What
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 238 |
]
|
| 239 |
|
| 240 |
-
print("\n\nπ« NON-PERTINENT QUESTIONS (Off-Topic):")
|
| 241 |
print("-" * 40)
|
| 242 |
|
| 243 |
for i, question in enumerate(non_pertinent_questions, 1):
|
| 244 |
print(f"\n{i}. User: {question}")
|
| 245 |
response = simulate_chatbot_response(question)
|
| 246 |
-
print(f"π€ Bot: {response[:
|
| 247 |
|
| 248 |
print("\n" + "=" * 50)
|
| 249 |
-
print("π Demo Complete!")
|
| 250 |
-
print("\nThis simulation
|
| 251 |
-
print("β
|
| 252 |
-
print("β
|
| 253 |
-
print("β
|
| 254 |
-
print("β
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 255 |
|
| 256 |
if __name__ == "__main__":
|
| 257 |
run_demo()
|
|
|
|
| 17 |
"violations": 0,
|
| 18 |
"risk_level": "β
Safe",
|
| 19 |
"subway_distance": 0.3,
|
| 20 |
+
"school_distance": 0.5,
|
| 21 |
+
"amenities": ["Laundry", "Gym"],
|
| 22 |
+
"accepts_vouchers": True
|
| 23 |
},
|
| 24 |
{
|
| 25 |
"address": "456 Oak Ave, Queens, NY",
|
|
|
|
| 29 |
"violations": 2,
|
| 30 |
"risk_level": "β οΈ Moderate",
|
| 31 |
"subway_distance": 0.8,
|
| 32 |
+
"school_distance": 0.3,
|
| 33 |
+
"amenities": ["Parking", "Balcony"],
|
| 34 |
+
"accepts_vouchers": True
|
| 35 |
+
},
|
| 36 |
+
{
|
| 37 |
+
"address": "789 Pine St, Manhattan, NY",
|
| 38 |
+
"bedrooms": 1,
|
| 39 |
+
"rent": 2500,
|
| 40 |
+
"borough": "Manhattan",
|
| 41 |
+
"violations": 1,
|
| 42 |
+
"risk_level": "β
Safe",
|
| 43 |
+
"subway_distance": 0.1,
|
| 44 |
+
"school_distance": 0.7,
|
| 45 |
+
"amenities": ["Doorman", "Rooftop"],
|
| 46 |
+
"accepts_vouchers": False
|
| 47 |
}
|
| 48 |
]
|
| 49 |
|
|
|
|
| 52 |
"violations": 0,
|
| 53 |
"risk_level": "β
Safe",
|
| 54 |
"last_inspection": "2024-01-15",
|
| 55 |
+
"summary": "No violations found. Building is in good condition.",
|
| 56 |
+
"details": []
|
| 57 |
},
|
| 58 |
"456 Oak Ave, Queens, NY": {
|
| 59 |
"violations": 2,
|
| 60 |
"risk_level": "β οΈ Moderate",
|
| 61 |
"last_inspection": "2024-02-20",
|
| 62 |
+
"summary": "Minor violations for maintenance issues. Generally safe for occupancy.",
|
| 63 |
+
"details": ["Elevator maintenance overdue", "Minor plumbing issues"]
|
| 64 |
+
},
|
| 65 |
+
"789 Pine St, Manhattan, NY": {
|
| 66 |
+
"violations": 1,
|
| 67 |
+
"risk_level": "β
Safe",
|
| 68 |
+
"last_inspection": "2024-03-10",
|
| 69 |
+
"summary": "Single minor violation resolved. Building is safe.",
|
| 70 |
+
"details": ["Fire alarm system updated"]
|
| 71 |
+
}
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
MOCK_SUBWAY_DATA = {
|
| 75 |
+
"123 Main St, Brooklyn, NY": {
|
| 76 |
+
"nearest_station": "Atlantic Avenue-Barclays Center",
|
| 77 |
+
"lines": ["2", "3", "4", "5", "B", "D", "N", "Q", "R"],
|
| 78 |
+
"distance": 0.3,
|
| 79 |
+
"walking_time": 7
|
| 80 |
+
},
|
| 81 |
+
"456 Oak Ave, Queens, NY": {
|
| 82 |
+
"nearest_station": "Jamaica Center-Parsons/Archer",
|
| 83 |
+
"lines": ["E", "J", "Z"],
|
| 84 |
+
"distance": 0.8,
|
| 85 |
+
"walking_time": 18
|
| 86 |
}
|
| 87 |
}
|
| 88 |
|
| 89 |
+
MOCK_SCHOOL_DATA = {
|
| 90 |
+
"123 Main St, Brooklyn, NY": [
|
| 91 |
+
{"name": "PS 123", "type": "Elementary", "distance": 0.5, "rating": "A"},
|
| 92 |
+
{"name": "Brooklyn High School", "type": "High School", "distance": 1.2, "rating": "B+"}
|
| 93 |
+
],
|
| 94 |
+
"456 Oak Ave, Queens, NY": [
|
| 95 |
+
{"name": "Queens Elementary", "type": "Elementary", "distance": 0.3, "rating": "B"},
|
| 96 |
+
{"name": "Jamaica High School", "type": "High School", "distance": 0.9, "rating": "A-"}
|
| 97 |
+
]
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
def mock_search_housing(query: str) -> List[Dict[str, Any]]:
|
| 101 |
+
"""Mock housing search function with detailed filtering"""
|
| 102 |
+
results = []
|
| 103 |
+
query_lower = query.lower()
|
| 104 |
+
|
| 105 |
+
for listing in MOCK_LISTINGS:
|
| 106 |
+
# Filter by bedrooms
|
| 107 |
+
if "studio" in query_lower and listing["bedrooms"] != 0:
|
| 108 |
+
continue
|
| 109 |
+
if "1 bedroom" in query_lower and listing["bedrooms"] != 1:
|
| 110 |
+
continue
|
| 111 |
+
if "2 bedroom" in query_lower and listing["bedrooms"] != 2:
|
| 112 |
+
continue
|
| 113 |
+
if "3 bedroom" in query_lower and listing["bedrooms"] != 3:
|
| 114 |
+
continue
|
| 115 |
+
|
| 116 |
+
# Filter by borough
|
| 117 |
+
if "brooklyn" in query_lower and listing["borough"] != "Brooklyn":
|
| 118 |
+
continue
|
| 119 |
+
if "queens" in query_lower and listing["borough"] != "Queens":
|
| 120 |
+
continue
|
| 121 |
+
if "manhattan" in query_lower and listing["borough"] != "Manhattan":
|
| 122 |
+
continue
|
| 123 |
+
|
| 124 |
+
# Filter by budget
|
| 125 |
+
if "under" in query_lower:
|
| 126 |
+
try:
|
| 127 |
+
budget = int(query_lower.split("under")[1].split()[0].replace("$", "").replace(",", ""))
|
| 128 |
+
if listing["rent"] >= budget:
|
| 129 |
+
continue
|
| 130 |
+
except:
|
| 131 |
+
pass
|
| 132 |
+
|
| 133 |
+
# Filter by voucher acceptance
|
| 134 |
+
if "voucher" in query_lower and not listing["accepts_vouchers"]:
|
| 135 |
+
continue
|
| 136 |
+
|
| 137 |
+
results.append(listing)
|
| 138 |
+
|
| 139 |
+
return results if results else MOCK_LISTINGS[:2] # Fallback
|
| 140 |
|
| 141 |
def mock_check_violations(address: str) -> Dict[str, Any]:
|
| 142 |
+
"""Mock violation check function with detailed data"""
|
| 143 |
return MOCK_VIOLATIONS.get(address, {
|
| 144 |
"violations": 0,
|
| 145 |
"risk_level": "β
Safe",
|
| 146 |
+
"last_inspection": "Unknown",
|
| 147 |
+
"summary": "No violation data available for this address.",
|
| 148 |
+
"details": []
|
| 149 |
+
})
|
| 150 |
+
|
| 151 |
+
def mock_subway_info(address: str) -> Dict[str, Any]:
|
| 152 |
+
"""Mock subway proximity data"""
|
| 153 |
+
return MOCK_SUBWAY_DATA.get(address, {
|
| 154 |
+
"nearest_station": "Unknown Station",
|
| 155 |
+
"lines": ["A", "B", "C"],
|
| 156 |
+
"distance": 0.5,
|
| 157 |
+
"walking_time": 12
|
| 158 |
})
|
| 159 |
|
| 160 |
+
def mock_school_info(address: str) -> List[Dict[str, Any]]:
|
| 161 |
+
"""Mock school proximity data"""
|
| 162 |
+
return MOCK_SCHOOL_DATA.get(address, [
|
| 163 |
+
{"name": "Local Elementary", "type": "Elementary", "distance": 0.5, "rating": "B+"}
|
| 164 |
+
])
|
| 165 |
+
|
| 166 |
+
def mock_email_draft(landlord_info: str, user_info: str, voucher_type: str = "Section 8") -> str:
|
| 167 |
+
"""Mock email generation with customization"""
|
| 168 |
return f"""
|
| 169 |
+
Subject: Housing Voucher Inquiry for {voucher_type}
|
| 170 |
|
| 171 |
Dear Property Manager,
|
| 172 |
|
| 173 |
+
I am writing to express my interest in renting an apartment at your property. {user_info}
|
| 174 |
|
| 175 |
+
I currently hold a {voucher_type} voucher and am seeking a suitable apartment that accepts housing vouchers. {landlord_info}
|
| 176 |
|
| 177 |
+
I would appreciate any information about available units and the application process for voucher holders.
|
| 178 |
+
|
| 179 |
+
Thank you for your time and consideration.
|
| 180 |
|
| 181 |
Best regards,
|
| 182 |
[Your Name]
|
| 183 |
+
Phone: [Your Phone Number]
|
| 184 |
+
Email: [Your Email Address]
|
| 185 |
"""
|
| 186 |
|
| 187 |
+
def mock_voucher_info(voucher_type: str) -> str:
|
| 188 |
+
"""Mock voucher program information"""
|
| 189 |
+
info = {
|
| 190 |
+
"section 8": {
|
| 191 |
+
"name": "Section 8 Housing Choice Voucher",
|
| 192 |
+
"admin": "NYCHA (NYC Housing Authority)",
|
| 193 |
+
"website": "nyc.gov/nycha",
|
| 194 |
+
"income_limit": "80% of Area Median Income",
|
| 195 |
+
"payment": "Up to 30% of tenant income + voucher portion"
|
| 196 |
+
},
|
| 197 |
+
"cityfheps": {
|
| 198 |
+
"name": "CityFHEPS",
|
| 199 |
+
"admin": "HRA (Human Resources Administration)",
|
| 200 |
+
"website": "nyc.gov/hra",
|
| 201 |
+
"income_limit": "200% of Federal Poverty Level",
|
| 202 |
+
"payment": "Covers rent up to payment standard"
|
| 203 |
+
},
|
| 204 |
+
"hasa": {
|
| 205 |
+
"name": "HASA",
|
| 206 |
+
"admin": "HIV/AIDS Services Administration",
|
| 207 |
+
"website": "nyc.gov/hasa",
|
| 208 |
+
"income_limit": "No income limit for eligible individuals",
|
| 209 |
+
"payment": "Full rent coverage for eligible units"
|
| 210 |
+
}
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
voucher_lower = voucher_type.lower()
|
| 214 |
+
if voucher_lower in info:
|
| 215 |
+
data = info[voucher_lower]
|
| 216 |
+
return f"""π **{data['name']} Information**
|
| 217 |
+
|
| 218 |
+
**Administered by:** {data['admin']}
|
| 219 |
+
**Website:** {data['website']}
|
| 220 |
+
**Income Requirements:** {data['income_limit']}
|
| 221 |
+
**Payment Structure:** {data['payment']}
|
| 222 |
+
|
| 223 |
+
**How to Apply:**
|
| 224 |
+
1. Contact {data['admin']} for application
|
| 225 |
+
2. Gather required documents (ID, income proof, etc.)
|
| 226 |
+
3. Attend orientation and interview
|
| 227 |
+
4. Receive voucher upon approval
|
| 228 |
+
|
| 229 |
+
**Next Steps:** Visit {data['website']} for detailed requirements."""
|
| 230 |
+
else:
|
| 231 |
+
return "Please specify a voucher type (Section 8, CityFHEPS, HASA) for detailed information."
|
| 232 |
+
|
| 233 |
def simulate_chatbot_response(user_input: str) -> str:
|
| 234 |
"""
|
| 235 |
Simulate how the chatbot would respond to different inputs.
|
| 236 |
+
This demonstrates pertinent vs non-pertinent question handling with comprehensive logic.
|
| 237 |
"""
|
| 238 |
|
| 239 |
input_lower = user_input.lower()
|
| 240 |
|
| 241 |
# Pertinent questions - housing/voucher related
|
| 242 |
if any(keyword in input_lower for keyword in [
|
| 243 |
+
"housing", "apartment", "rent", "voucher", "section 8", "cityfheps", "hasa",
|
| 244 |
+
"violation", "building safety", "subway", "school", "email", "landlord",
|
| 245 |
+
"bedroom", "studio", "lease", "application", "income", "payment"
|
| 246 |
]):
|
| 247 |
|
| 248 |
+
# Housing search queries with detailed filtering
|
| 249 |
+
if any(word in input_lower for word in ["search", "find", "looking for", "need", "available"]):
|
| 250 |
listings = mock_search_housing(user_input)
|
| 251 |
if listings:
|
| 252 |
+
response = "π **Voucher-Friendly Housing Options Found**\n\n"
|
| 253 |
+
for i, listing in enumerate(listings, 1):
|
| 254 |
+
response += f"**{i}. {listing['address']}**\n"
|
| 255 |
+
response += f" π {listing['bedrooms']} BR | π° ${listing['rent']:,}/month\n"
|
| 256 |
+
response += f" ποΈ Borough: {listing['borough']} | β
Safety: {listing['risk_level']}\n"
|
| 257 |
+
response += f" π Subway: {listing['subway_distance']}mi | π« Schools: {listing['school_distance']}mi\n"
|
| 258 |
+
response += f" β Amenities: {', '.join(listing['amenities'])}\n"
|
| 259 |
+
if listing['accepts_vouchers']:
|
| 260 |
+
response += " π« **Accepts Vouchers**\n"
|
| 261 |
+
response += "\n"
|
| 262 |
+
response += "π‘ **Tips:** Contact landlords directly and mention your voucher type. I can help draft emails!"
|
| 263 |
return response
|
| 264 |
else:
|
| 265 |
+
return "π I couldn't find listings matching your exact criteria. Try broadening your search or let me know your preferences!"
|
| 266 |
+
|
| 267 |
+
# Violation checking with address detection
|
| 268 |
+
elif "violation" in input_lower or "safety" in input_lower or "inspection" in input_lower:
|
| 269 |
+
# Try to detect address from input
|
| 270 |
+
addresses = ["123 Main St, Brooklyn, NY", "456 Oak Ave, Queens, NY", "789 Pine St, Manhattan, NY"]
|
| 271 |
+
detected_address = None
|
| 272 |
+
|
| 273 |
+
for addr in addresses:
|
| 274 |
+
if any(part.lower() in input_lower for part in addr.split(",")[0].split()):
|
| 275 |
+
detected_address = addr
|
| 276 |
+
break
|
| 277 |
+
|
| 278 |
+
if not detected_address:
|
| 279 |
+
return """π’ **Building Safety Check**
|
| 280 |
+
|
| 281 |
+
To check building violations and safety, please provide a specific NYC address like:
|
| 282 |
+
- "123 Main St, Brooklyn, NY"
|
| 283 |
+
- "456 Oak Ave, Queens"
|
| 284 |
+
|
| 285 |
+
I can provide:
|
| 286 |
+
- Violation count and risk level
|
| 287 |
+
- Last inspection date
|
| 288 |
+
- Detailed safety report
|
| 289 |
|
| 290 |
+
What's the address you'd like me to check?"""
|
| 291 |
+
|
| 292 |
+
violations = mock_check_violations(detected_address)
|
| 293 |
+
subway = mock_subway_info(detected_address)
|
| 294 |
+
schools = mock_school_info(detected_address)
|
| 295 |
+
|
| 296 |
+
response = f"π’ **Comprehensive Building Report: {detected_address}**\n\n"
|
| 297 |
+
response += f"**Safety Status:** {violations['risk_level']}\n"
|
| 298 |
response += f"**Violations:** {violations['violations']}\n"
|
| 299 |
+
response += f"**Last Inspection:** {violations['last_inspection']}\n"
|
| 300 |
response += f"**Summary:** {violations['summary']}\n"
|
| 301 |
+
|
| 302 |
+
if violations['details']:
|
| 303 |
+
response += f"**Details:** {', '.join(violations['details'])}\n"
|
| 304 |
+
|
| 305 |
+
response += f"\nπ **Transit Access:**\n"
|
| 306 |
+
response += f" Nearest Station: {subway['nearest_station']}\n"
|
| 307 |
+
response += f" Lines: {', '.join(subway['lines'])}\n"
|
| 308 |
+
response += f" Distance: {subway['distance']}mi ({subway['walking_time']} min walk)\n"
|
| 309 |
+
|
| 310 |
+
response += f"\nπ« **Nearby Schools:**\n"
|
| 311 |
+
for school in schools:
|
| 312 |
+
response += f" {school['name']} ({school['type']}): {school['distance']}mi, Rating: {school['rating']}\n"
|
| 313 |
+
|
| 314 |
return response
|
| 315 |
|
| 316 |
# Email drafting
|
| 317 |
+
elif "email" in input_lower or "draft" in input_lower or "contact" in input_lower:
|
| 318 |
+
# Detect voucher type
|
| 319 |
+
voucher_type = "Section 8"
|
| 320 |
+
if "cityfheps" in input_lower:
|
| 321 |
+
voucher_type = "CityFHEPS"
|
| 322 |
+
elif "hasa" in input_lower:
|
| 323 |
+
voucher_type = "HASA"
|
| 324 |
+
|
| 325 |
return mock_email_draft(
|
| 326 |
+
"I am currently looking for apartments and would like to know if you accept housing vouchers.",
|
| 327 |
+
f"I hold a {voucher_type} voucher and am seeking a suitable apartment. Please let me know about availability and requirements.",
|
| 328 |
+
voucher_type
|
| 329 |
)
|
| 330 |
|
| 331 |
+
# Voucher information
|
| 332 |
+
elif any(word in input_lower for word in ["voucher", "section 8", "cityfheps", "hasa", "program"]):
|
| 333 |
+
# Detect specific voucher type
|
| 334 |
+
if "section 8" in input_lower:
|
| 335 |
+
return mock_voucher_info("section 8")
|
| 336 |
+
elif "cityfheps" in input_lower:
|
| 337 |
+
return mock_voucher_info("cityfheps")
|
| 338 |
+
elif "hasa" in input_lower:
|
| 339 |
+
return mock_voucher_info("hasa")
|
| 340 |
+
else:
|
| 341 |
+
return """π **NYC Housing Voucher Programs**
|
| 342 |
|
| 343 |
+
NYC offers several housing voucher programs:
|
|
|
|
|
|
|
|
|
|
| 344 |
|
| 345 |
+
**Section 8** (Federal) - Income-based rental assistance
|
| 346 |
+
**CityFHEPS** (City) - For families in shelter system
|
| 347 |
+
**HASA** (City) - For people with HIV/AIDS
|
| 348 |
|
| 349 |
+
Which program are you interested in learning about?"""
|
| 350 |
|
| 351 |
# Subway/school proximity
|
| 352 |
+
elif "subway" in input_lower or "school" in input_lower or "transit" in input_lower:
|
| 353 |
+
# Try to detect address
|
| 354 |
+
addresses = ["123 Main St, Brooklyn, NY", "456 Oak Ave, Queens, NY"]
|
| 355 |
+
detected_address = None
|
| 356 |
+
|
| 357 |
+
for addr in addresses:
|
| 358 |
+
if any(part.lower() in input_lower for part in addr.split(",")[0].split()):
|
| 359 |
+
detected_address = addr
|
| 360 |
+
break
|
| 361 |
+
|
| 362 |
+
if detected_address:
|
| 363 |
+
subway = mock_subway_info(detected_address)
|
| 364 |
+
schools = mock_school_info(detected_address)
|
| 365 |
+
|
| 366 |
+
response = f"π **Transit & Education Report: {detected_address}**\n\n"
|
| 367 |
+
response += f"**Nearest Subway:**\n"
|
| 368 |
+
response += f" Station: {subway['nearest_station']}\n"
|
| 369 |
+
response += f" Lines: {', '.join(subway['lines'])}\n"
|
| 370 |
+
response += f" Distance: {subway['distance']}mi ({subway['walking_time']} min walk)\n"
|
| 371 |
+
|
| 372 |
+
response += f"\n**Nearby Schools:**\n"
|
| 373 |
+
for school in schools:
|
| 374 |
+
response += f" {school['name']} ({school['type']}): {school['distance']}mi away, Rating: {school['rating']}\n"
|
| 375 |
+
|
| 376 |
+
return response
|
| 377 |
+
else:
|
| 378 |
+
return """π **Transit & Education Access**
|
| 379 |
|
| 380 |
+
I can provide detailed information about subway access and nearby schools for specific addresses.
|
| 381 |
|
| 382 |
+
Please provide an NYC address, and I'll give you:
|
| 383 |
- Nearest subway stations and walking distance
|
| 384 |
+
- Nearby schools with ratings
|
| 385 |
+
- Public transportation options
|
| 386 |
+
|
| 387 |
+
What's the address you're interested in?"""
|
| 388 |
+
|
| 389 |
+
# Neighborhood or general housing advice
|
| 390 |
+
elif any(word in input_lower for word in ["neighborhood", "area", "borough", "recommend"]):
|
| 391 |
+
return """ποΈ **NYC Neighborhood Guide**
|
| 392 |
+
|
| 393 |
+
Each borough offers different housing options:
|
| 394 |
+
|
| 395 |
+
**Brooklyn:** Diverse neighborhoods, good transit access
|
| 396 |
+
**Queens:** More affordable, family-friendly areas
|
| 397 |
+
**Manhattan:** Central location, higher rents
|
| 398 |
+
**Bronx:** Affordable options, growing communities
|
| 399 |
+
**Staten Island:** Suburban feel, ferry access
|
| 400 |
+
|
| 401 |
+
**Tips for Voucher Holders:**
|
| 402 |
+
- Look for buildings that explicitly accept vouchers
|
| 403 |
+
- Consider proximity to work, schools, and transit
|
| 404 |
+
- Check building safety records before applying
|
| 405 |
+
|
| 406 |
+
Which borough or type of neighborhood interests you?"""
|
| 407 |
|
| 408 |
# Non-pertinent questions - redirect appropriately
|
| 409 |
else:
|
| 410 |
# Weather questions
|
| 411 |
+
if "weather" in input_lower or "temperature" in input_lower:
|
| 412 |
return """π€οΈ **Weather & Housing Connection**
|
| 413 |
|
| 414 |
+
NYC weather varies by season, which can impact housing choices:
|
| 415 |
|
| 416 |
+
**Winter:** Consider heated buildings and proximity to transit
|
| 417 |
+
**Summer:** Look for AC and good ventilation
|
| 418 |
+
**Spring/Fall:** Generally comfortable for apartment hunting
|
| 419 |
|
| 420 |
+
**Housing Tip:** Buildings in flood-prone areas may have higher insurance costs.
|
| 421 |
+
|
| 422 |
+
Would you like help finding weather-resilient housing or checking building locations?"""
|
| 423 |
|
| 424 |
# Food/restaurant questions
|
| 425 |
+
elif any(word in input_lower for word in ["food", "restaurant", "eat", "pizza", "dining"]):
|
| 426 |
return """π½οΈ **Food & Housing Connection**
|
| 427 |
|
| 428 |
+
NYC's incredible food scene is a major quality-of-life factor!
|
| 429 |
|
| 430 |
+
**Housing Tips:**
|
| 431 |
+
- **Kitchen Size:** Consider if you cook often
|
| 432 |
+
- **Neighborhood Dining:** Areas like Queens offer diverse international cuisine
|
| 433 |
+
- **Transit Access:** Easy subway access means more restaurant options
|
| 434 |
+
- **Budget Impact:** Factor in dining costs when budgeting for rent
|
| 435 |
|
| 436 |
+
Would you like help finding apartments in foodie neighborhoods or checking transit access to restaurants?"""
|
| 437 |
|
| 438 |
# Sports/entertainment
|
| 439 |
+
elif any(word in input_lower for word in ["sports", "game", "movie", "entertainment", "concert", "theater"]):
|
| 440 |
return """π¬ **Entertainment & Housing**
|
| 441 |
|
| 442 |
+
NYC is an entertainment hub! Your location affects access to:
|
| 443 |
+
|
| 444 |
+
**Sports:** Proximity to stadiums (Yankee Stadium, Barclays Center)
|
| 445 |
+
**Theater:** Broadway access from Manhattan locations
|
| 446 |
+
**Concerts:** Venues throughout the city
|
| 447 |
+
|
| 448 |
+
**Housing Tips:**
|
| 449 |
+
- Consider commute time to venues
|
| 450 |
+
- Apartments near subway lines provide flexibility
|
| 451 |
+
- Some buildings offer entertainment amenities
|
| 452 |
+
|
| 453 |
+
Would you like help finding housing near entertainment venues or checking transit access?"""
|
| 454 |
+
|
| 455 |
+
# Work/job related
|
| 456 |
+
elif any(word in input_lower for word in ["job", "work", "employment", "commute"]):
|
| 457 |
+
return """πΌ **Work & Housing Connection**
|
| 458 |
+
|
| 459 |
+
Your job location significantly impacts housing choices:
|
| 460 |
|
| 461 |
+
**Commute Considerations:**
|
| 462 |
+
- Proximity to subway lines reduces travel time
|
| 463 |
+
- Consider work-life balance and transportation costs
|
| 464 |
+
- Some voucher programs prioritize employment
|
| 465 |
|
| 466 |
+
**Housing Tips:**
|
| 467 |
+
- Calculate total commuting costs when budgeting
|
| 468 |
+
- Look for apartments with good transit access
|
| 469 |
+
- Consider work-from-home setup if applicable
|
| 470 |
|
| 471 |
+
Would you like help finding housing based on your work location or checking transit options?"""
|
| 472 |
+
|
| 473 |
+
# Health/medical questions
|
| 474 |
+
elif any(word in input_lower for word in ["health", "medical", "doctor", "hospital"]):
|
| 475 |
+
return """π₯ **Healthcare & Housing**
|
| 476 |
+
|
| 477 |
+
Access to healthcare is crucial for quality of life:
|
| 478 |
+
|
| 479 |
+
**NYC Healthcare:**
|
| 480 |
+
- Major hospitals throughout all boroughs
|
| 481 |
+
- Public transportation provides access to medical facilities
|
| 482 |
+
- Some neighborhoods have more healthcare options
|
| 483 |
+
|
| 484 |
+
**Housing Tips:**
|
| 485 |
+
- Proximity to hospitals for medical emergencies
|
| 486 |
+
- Consider accessibility features for health needs
|
| 487 |
+
- Transit access ensures you can reach appointments
|
| 488 |
+
|
| 489 |
+
Would you like help finding housing near medical facilities or checking accessibility features?"""
|
| 490 |
+
|
| 491 |
+
# Completely off-topic or unclear
|
| 492 |
else:
|
| 493 |
+
return """π€ **Staying Focused on Housing**
|
| 494 |
|
| 495 |
+
I specialize in helping NYC residents find safe, affordable, voucher-friendly housing. While I'm happy to connect other topics to housing decisions, my core expertise includes:
|
| 496 |
|
| 497 |
- Housing searches and listings
|
| 498 |
- Building safety and violations
|
| 499 |
- Transit and school proximity
|
| 500 |
- Voucher program information
|
| 501 |
+
- Neighborhood recommendations
|
| 502 |
+
- Email drafting for landlords
|
| 503 |
+
|
| 504 |
+
**Quick Housing Check:** Are you looking for apartments, need safety information, or have voucher questions?
|
| 505 |
|
| 506 |
+
If your question is completely unrelated to housing, I recommend consulting specialized resources for that topic. What housing-related help do you need?"""
|
| 507 |
|
| 508 |
# Demo function to show various responses
|
| 509 |
def run_demo():
|
| 510 |
print("π€ VoucherBot Response Simulation Demo")
|
| 511 |
print("=" * 50)
|
| 512 |
|
| 513 |
+
# Pertinent questions - comprehensive housing scenarios
|
| 514 |
pertinent_questions = [
|
| 515 |
"I need help finding housing with Section 8 voucher",
|
| 516 |
+
"Search for 2 bedroom apartments in Brooklyn under $2000 that accept vouchers",
|
| 517 |
+
"Check building violations for 123 Main St, Brooklyn and tell me about nearby schools",
|
| 518 |
+
"Draft an email to a landlord about my CityFHEPS voucher for a 3 bedroom apartment",
|
| 519 |
+
"How do I apply for Section 8 in NYC?",
|
| 520 |
+
"Find apartments near subway stations in Queens",
|
| 521 |
+
"What are the requirements for HASA vouchers?",
|
| 522 |
+
"Show me safe buildings in Manhattan with good transit access",
|
| 523 |
+
"I need a studio apartment under $1500 in Brooklyn"
|
| 524 |
]
|
| 525 |
|
| 526 |
print("\nπ PERTINENT QUESTIONS (Housing/Voucher Related):")
|
|
|
|
| 529 |
for i, question in enumerate(pertinent_questions, 1):
|
| 530 |
print(f"\n{i}. User: {question}")
|
| 531 |
response = simulate_chatbot_response(question)
|
| 532 |
+
print(f"π€ Bot: {response[:150]}{'...' if len(response) > 150 else ''}")
|
| 533 |
|
| 534 |
+
# Non-pertinent questions - expanded scenarios
|
| 535 |
non_pertinent_questions = [
|
| 536 |
"What's the weather like today?",
|
| 537 |
+
"Where's a good place to eat authentic Italian food?",
|
| 538 |
+
"Who won the Knicks game last night?",
|
| 539 |
+
"Can you recommend a good movie to watch?",
|
| 540 |
+
"What's the best way to get around NYC?",
|
| 541 |
+
"I'm looking for a job in tech - any advice?",
|
| 542 |
+
"How do I get to the airport from Manhattan?",
|
| 543 |
+
"What's the population of New York City?",
|
| 544 |
+
"Can you help me with my math homework?",
|
| 545 |
+
"Tell me about the history of Brooklyn"
|
| 546 |
]
|
| 547 |
|
| 548 |
+
print("\n\nπ« NON-PERTINENT QUESTIONS (Off-Topic with Housing Connections):")
|
| 549 |
print("-" * 40)
|
| 550 |
|
| 551 |
for i, question in enumerate(non_pertinent_questions, 1):
|
| 552 |
print(f"\n{i}. User: {question}")
|
| 553 |
response = simulate_chatbot_response(question)
|
| 554 |
+
print(f"π€ Bot: {response[:150]}{'...' if len(response) > 150 else ''}")
|
| 555 |
|
| 556 |
print("\n" + "=" * 50)
|
| 557 |
+
print("π Comprehensive Demo Complete!")
|
| 558 |
+
print("\nThis simulation demonstrates VoucherBot's capabilities:")
|
| 559 |
+
print("β
**Intelligent Filtering:** Searches by bedrooms, borough, budget, voucher acceptance")
|
| 560 |
+
print("β
**Comprehensive Reports:** Building safety with violations, transit, and school data")
|
| 561 |
+
print("β
**Smart Detection:** Automatically identifies addresses, voucher types, and query intent")
|
| 562 |
+
print("β
**Contextual Help:** Provides detailed voucher program information and application guidance")
|
| 563 |
+
print("β
**Graceful Redirection:** Connects non-housing topics back to housing decisions")
|
| 564 |
+
print("β
**User-Centric:** Offers practical tips and maintains helpful, conversational tone")
|
| 565 |
+
print("β
**Multi-Modal Support:** Handles housing searches, safety checks, emails, and neighborhood advice")
|
| 566 |
+
print("\nπ **Agent Orchestration Features Shown:**")
|
| 567 |
+
print(" β’ Message routing and intent classification")
|
| 568 |
+
print(" β’ Tool integration (violation checker, geocoding, enrichment)")
|
| 569 |
+
print(" β’ State management and conversation flow")
|
| 570 |
+
print(" β’ Error handling and user feedback")
|
| 571 |
+
print(" β’ Multilingual and contextual awareness")
|
| 572 |
|
| 573 |
if __name__ == "__main__":
|
| 574 |
run_demo()
|