Spaces:
Sleeping
Sleeping
File size: 10,091 Bytes
7f53bc2 4c8b4d5 1f2416b fc8894f 346db32 f303655 1f2416b ddfb219 f91d245 0cffa94 7aa3d69 d0c9a6e 7aa3d69 0cffa94 7aa3d69 dd2c1ff 7aa3d69 3f8e536 7aa3d69 f008966 7aa3d69 b5edb7c 7aa3d69 b5edb7c 7aa3d69 1f70408 7aa3d69 1f70408 7aa3d69 b5edb7c 7aa3d69 b5edb7c 607a134 e330d29 607a134 5fedc81 bfbcf7a 39a2183 bfbcf7a 5fedc81 f008966 39a2183 b5edb7c 3f8e536 f838ca7 b5edb7c 5fedc81 b5edb7c 5fedc81 b5edb7c 5fedc81 b5edb7c 5fedc81 b5edb7c 5fedc81 ad12a02 00ce247 5fedc81 6c6ae46 5fedc81 ad12a02 5fedc81 6c6ae46 5fedc81 00ce247 ad12a02 5fedc81 00ce247 1f63ae9 5fedc81 00ce247 1f63ae9 5fedc81 ddfb219 5fedc81 62d34d5 5fedc81 00ce247 e913fba f5896e7 b71c7ab 00ce247 7e172cd b71c7ab 7e172cd 17b4f07 edbe9e1 698c8f7 edbe9e1 4cdc7b6 dcdae15 e89993d 4cdc7b6 dcdae15 b2a70cb 4cdc7b6 e19c0bb 9652bfc df10d63 9652bfc df10d63 9652bfc a66d277 df10d63 9652bfc df10d63 9652bfc 80532b3 edbe9e1 67a935e edbe9e1 |
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 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
import streamlit as st
import json
import pandas as pd
import requests
import os
import math
from openai import OpenAI
def call_gpt(user_needs, shelter_services, api_key):
client = OpenAI(api_key = api_key)
completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Given two variables 'user needs' (the ideal qualities/services of a shelter) and 'shelter services' (the services offered by a shelter), return an integer 0-10 that scores how well the 'shelter services' match the 'user needs' where 0 is the best fit and 10 is the worst fit. IMPORTANT: NO MATTER WHAT, ONLY RETURN THE INTEGER (NO EXTRA WORDS, PUNCTUATION, ETC.)"},
{"role": "user", "content": f"user_needs: {user_needs}, shelter_services: {shelter_services}"}
]
)
score = completion.choices[0].message.content.strip()
return int(score)
def get_urgency_score(user, shelter):
if user == "Today":
if shelter == "Immidiate": return 0
if shelter == "High": return 0.75
if shelter == "Moderate": return 1
elif user == "In the next few days":
if shelter == "Immidiate": return 0.25
if shelter == "High": return 0
if shelter == "Moderate": return 0.75
elif user == "In a week or more":
if shelter == "Immidiate": return 0.75
if shelter == "High": return 0.25
if shelter == "Moderate": return 0
def get_duration_score(user, shelter):
if user == "Overnight":
if shelter == "Overnight": return 0
if shelter == "Temporary": return 0.5
if shelter == "Transitional": return 0.75
if shelter == "Long-Term": return 1
elif user == "A month or less":
if shelter == "Overnight": return 0.5
if shelter == "Temporary": return 0
if shelter == "Transitional": return 0.25
if shelter == "Long-Term": return 0.75
elif user == "A couple of months":
if shelter == "Overnight": return 0.75
if shelter == "Temporary": return 0.25
if shelter == "Transitional": return 0
if shelter == "Long-Term": return 0.5
elif user == "A year or more":
if shelter == "Overnight": return 1
if shelter == "Temporary": return 0.75
if shelter == "Transitional": return 0.5
if shelter == "Long-Term": return 0
def get_coordinates(zipcode: str, api_key: str) -> list:
"""
Get the coordinates (latitude and longitude) of an address using the OpenWeather Geocoding API.
Parameters:
zipcode (str): The zipcode to geocode.
api_key (str): Your OpenWeather API key.
Returns:
list: A list containing the latitude and longitude of the address.
"""
base_url = "http://api.openweathermap.org/geo/1.0/zip"
params = {
'zip': str(zipcode) + ",US",
'appid': api_key
}
response = requests.get(base_url, params=params)
data = response.json()
return [data.get('lat'), data.get('lon')]
def haversine(lat1, lon1, lat2, lon2):
R = 6371 # Earth radius in kilometers. Use 3956 for miles.
dlat = math.radians(lat2 - lat1)
dlon = math.radians(lon2 - lon1)
a = math.sin(dlat / 2) ** 2 + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(dlon / 2) ** 2
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
distance = R * c
return distance
# Initialize session state
if 'form_submitted' not in st.session_state:
st.session_state.form_submitted = False
if 'shelter_index' not in st.session_state:
st.session_state.shelter_index = 0
# Page config
st.set_page_config(
page_title="ShelterSearch",
layout="wide",
)
st.title("ShelterSearch")
if not st.session_state.form_submitted:
st.write("Fill out this form")
# should be updated manually annually - use zipcodebase API
zipcodes = {
'San Francisco': ['94101', '94102', '94103', '94104', '94105', '94107', '94108', '94109', '94110', '94111', '94112', '94114', '94115', '94116', '94117', '94118', '94119', '94120', '94121', '94122', '94123', '94124', '94125', '94126', '94127', '94128', '94129', '94130', '94131', '94132', '94133', '94134', '94140', '94141', '94142', '94146', '94147', '94157', '94159', '94164', '94165', '94166', '94167', '94168', '94169', '94170', '94172', '94188'],
'Oakland': ['94601', '94602', '94603', '94604', '94605', '94606', '94607', '94608', '94609', '94610', '94611', '94612', '94613', '94614', '94615', '94617', '94618', '94619', '94620', '94621', '94623', '94624', '94661', '94662'],
'Berkeley': ['94701', '94702', '94703', '94704', '94705', '94706', '94707', '94708', '94709', '94710', '94712']
}
city = st.selectbox("City", ['San Francisco', 'Oakland', 'Berkeley'])
zipcode = st.selectbox("Zipcode", ['Unsure'] + zipcodes[city])
sex = st.radio("Sex", ["Male", "Female", "Other"])
lgbtq = st.radio("Do you identify as LGBTQ+ (some shelters serve this community specifically)", ["No", "Yes"])
domestic_violence = st.radio("Have you experienced domestic violence (some shelters serve these individuals specifically", ["No", "Yes"])
urgency = st.radio("How quickly do you need help?", ("Today", "In the next few days", "In a week or more"))
duration = st.radio("How long do you need a place to stay?", ("Overnight", "A month or less", "A couple of months", "A year or more"))
needs = st.text_area("Optional - Needs (tell us what you need and how we can help)")
if st.button("Submit"):
data = {
"City": city,
"Zip Code": zipcode,
"Sex": sex,
"LGBTQ": lgbtq,
"Domestic Violence": domestic_violence,
"Urgency": urgency,
"Duration": duration,
"Needs": needs
}
with open('data.json', 'w') as f:
json.dump(data, f)
st.session_state.form_submitted = True
st.session_state.data = data
st.rerun()
else:
with open('data.json', 'r') as f:
data = json.load(f)
shelters = pd.read_csv("database.csv")
# filter city
shelters = shelters[(shelters['City'] == data['City'])]
# filter sex
shelters = shelters[(shelters['Sex'] == data['Sex']) | (shelters['Sex'] == 'All')]
# filter lgbtq
if data['LGBTQ'] == 'No':
shelters = shelters[(shelters['LGBTQ'] == "No")]
# filter domestic violence
if data['Domestic Violence'] == "No":
shelters = shelters[(shelters['Domestic Violence'] == "No")]
# keep track of which scores are calculated
scores = []
# calculate distances between zipcodes
if data['Zip Code'] != "Unsure":
geocoding_api_key = os.environ['OpenWeather_API_KEY']
shelters_coordinates = shelters.apply(lambda row: get_coordinates(row['Zip Code'], geocoding_api_key), axis=1).tolist()
user_coordinates = get_coordinates(data['Zip Code'], geocoding_api_key)
distances = []
for coordinates in shelters_coordinates:
distances.append(haversine(coordinates[0], coordinates[1], user_coordinates[0], user_coordinates[1]))
max = max(distances) if (max(distances) != 0) else 1
shelters['zipcode_score'] = [d / max for d in distances]
scores.append('zipcode_score')
# get urgency scores
urgency_scores = shelters.apply(lambda row: get_urgency_score(data['Urgency'], row['Urgency']), axis=1).tolist()
shelters['urgency_score'] = urgency_scores
scores.append('urgency_score')
# get duration scores
duration_scores = shelters.apply(lambda row: get_duration_score(data['Duration'], row['Duration']), axis=1).tolist()
shelters['duration_score'] = duration_scores
scores.append('duration_score')
# services
if data['Needs'] != "":
OpenAI_API_KEY = os.environ["OPENAI_API_KEY"]
services_scores = shelters.apply(lambda row: call_gpt(data['Needs'], row['Services'], OpenAI_API_KEY), axis=1).tolist()
services_scores = [s / 10 for s in services_scores]
shelters['services_score'] = services_scores
scores.append('services_score')
# calcualte cumulative score
shelters['total_score'] = shelters[scores].sum(axis=1)
shelters['total_score'] = shelters['total_score'] / len(scores)
shelters = shelters.sort_values(by='total_score', ascending=True)
shelters = shelters.head(3)
# convert pandas df into list of dicts
shelters = shelters.to_dict(orient='records')
# Display the current shelter information
shelter = shelters[st.session_state.shelter_index]
st.header(f"{shelter['Organization Name']}: {shelter['Program Name']}")
st.divider()
st.subheader("Shelter Summary")
st.write(shelter['Summary'])
st.divider()
st.subheader("How to Receive Help")
st.write(shelter['Application Details'])
st.markdown(f"- Open Hours: {shelter['Open Hours']}")
st.markdown(f"- Address: {shelter['Address']}")
st.markdown(f"- Phone Number: {shelter['Phone']}")
st.divider()
with st.expander("More Information"):
tabs = st.tabs(["Full List of Services", "More About the Program", "More About the Organization", "Webpage Link"])
with tabs[0]:
st.write(shelter['Services'])
with tabs[1]:
st.write(shelter['Program About'])
with tabs[2]:
st.write(shelter['Organization About'])
with tabs[3]:
st.write(shelter['Webpage'])
# Create two columns
col1, col2 = st.columns([1,1])
# Add buttons to each column
with col1:
if st.button("Previous"):
if st.session_state.shelter_index > 0:
st.session_state.shelter_index -= 1
st.experimental_rerun()
with col2:
if st.button("Next"):
if st.session_state.shelter_index < len(shelters) - 1:
st.session_state.shelter_index += 1
st.experimental_rerun() |