Spaces:
Sleeping
Sleeping
File size: 8,004 Bytes
28df62a b5cd87f 28df62a b5cd87f 28df62a b5cd87f 28df62a b5cd87f 28df62a b5cd87f 28df62a b5cd87f 28df62a b5cd87f 28df62a b5cd87f 28df62a b5cd87f 28df62a 353ef89 b5cd87f 28df62a | 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 | import os
import re
import streamlit as st
import folium
from streamlit_folium import st_folium
import openai
from bs4 import BeautifulSoup
# Configuraci贸n de la p谩gina
st.set_page_config(page_title="Mapa Interactivo de Puerto Rico", layout="wide")
st.title("Mapa Interactivo de Puerto Rico y Chatbot de Recomendaciones")
# =============================================================================
# Funciones para parsear archivos
# =============================================================================
def parse_text_file(filepath):
"""
Parseo para archivos de texto plano.
Busca l铆neas con 'Name:', 'Latitude:' y 'Longitude:'.
"""
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
name_match = re.search(r'Name:\s*(.*)', content, re.IGNORECASE)
name = name_match.group(1).strip() if name_match else os.path.splitext(os.path.basename(filepath))[0]
lat_match = re.search(r'Latitude:\s*([-+]?[0-9]*\.?[0-9]+)', content, re.IGNORECASE)
lon_match = re.search(r'Longitude:\s*([-+]?[0-9]*\.?[0-9]+)', content, re.IGNORECASE)
if lat_match and lon_match:
try:
lat = float(lat_match.group(1))
except ValueError:
lat = None
try:
lon = float(lon_match.group(1))
except ValueError:
lon = None
else:
lat, lon = None, None
return {
"name": name,
"lat": lat,
"lon": lon,
"content": content
}
def parse_html_file(filepath):
"""
Parseo para archivos HTML (por ejemplo, de Wikipedia).
Extrae el t铆tulo, las coordenadas desde el bloque "wgCoordinates" y, si es posible,
la secci贸n hist贸rica (buscando un encabezado que contenga "History" o "Historia").
"""
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# Parsear con BeautifulSoup
soup = BeautifulSoup(content, "html.parser")
title = soup.title.string.strip() if soup.title else os.path.splitext(os.path.basename(filepath))[0]
# Extraer coordenadas (pueden venir en el bloque "wgCoordinates")
coord_match = re.search(r'"wgCoordinates":\s*{\s*"lat":\s*([0-9\.-]+),\s*"lon":\s*([0-9\.-]+)', content)
if coord_match:
lat_str = coord_match.group(1)
lon_str = coord_match.group(2)
try:
lat = float(lat_str) if lat_str not in ['-', ''] else None
except ValueError:
lat = None
try:
lon = float(lon_str) if lon_str not in ['-', ''] else None
except ValueError:
lon = None
else:
lat, lon = None, None
# Intentar extraer datos hist贸ricos: se busca un encabezado que contenga "History" o "Historia"
history = ""
history_header = soup.find(lambda tag: tag.name in ["h2", "h3"] and ("History" in tag.get_text() or "Historia" in tag.get_text()))
if history_header:
history_parts = []
# Recorrer los hermanos hasta llegar a otro encabezado del mismo nivel (o superior)
for sibling in history_header.find_next_siblings():
if sibling.name and sibling.name.startswith("h"):
break
history_parts.append(sibling.get_text(strip=True))
history = "\n".join(history_parts)
return {
"name": title,
"lat": lat,
"lon": lon,
"content": content,
"history": history
}
def load_data_from_directory(directory, parser_func):
"""
Carga todos los archivos .txt de un directorio usando la funci贸n de parseo indicada.
"""
data_points = []
if os.path.exists(directory):
for filename in os.listdir(directory):
if filename.endswith(".txt"):
filepath = os.path.join(directory, filename)
data_points.append(parser_func(filepath))
return data_points
# =============================================================================
# Carga de los datos desde las carpetas correspondientes
# =============================================================================
landmarks_dir = os.path.join("data", "landmarks")
municipalities_dir = os.path.join("data", "municipalities")
news_dir = os.path.join("data", "news")
# Para landmarks y news se asume que los archivos son de texto plano.
landmarks = load_data_from_directory(landmarks_dir, parse_text_file)
news_data = load_data_from_directory(news_dir, parse_text_file)
# Para municipalities, se usa el parseo de HTML (que ahora incluye datos hist贸ricos)
municipalities = load_data_from_directory(municipalities_dir, parse_html_file)
# =============================================================================
# Creaci贸n del mapa interactivo usando Folium
# =============================================================================
# Coordenadas centrales aproximadas de Puerto Rico
map_center = [18.2208, -66.5901]
m = folium.Map(location=map_center, zoom_start=10)
# Agregar marcadores para Landmarks
for landmark in landmarks:
if landmark["lat"] is not None and landmark["lon"] is not None:
folium.Marker(
location=[landmark["lat"], landmark["lon"]],
popup=folium.Popup(f"<b>{landmark['name']}</b><br>{landmark['content'][:200]}...", max_width=300),
icon=folium.Icon(color='blue', icon='info-sign')
).add_to(m)
# Agregar marcadores para Municipios, incluyendo datos hist贸ricos si est谩n disponibles
for municipality in municipalities:
if municipality["lat"] is not None and municipality["lon"] is not None:
history_text = municipality.get("history", "")
history_excerpt = history_text[:300] + "..." if len(history_text) > 300 else history_text
popup_content = f"<b>{municipality['name']}</b><br><b>Historia:</b><br>{history_excerpt}"
folium.Marker(
location=[municipality["lat"], municipality["lon"]],
popup=folium.Popup(popup_content, max_width=300),
icon=folium.Icon(color='green', icon='home')
).add_to(m)
# Agregar marcadores para Noticias (si se disponen de coordenadas)
for news_item in news_data:
if news_item["lat"] is not None and news_item["lon"] is not None:
folium.Marker(
location=[news_item["lat"], news_item["lon"]],
popup=folium.Popup(f"<b>{news_item['name']}</b><br>{news_item['content'][:200]}...", max_width=300),
icon=folium.Icon(color='red', icon='newspaper')
).add_to(m)
st.subheader("Mapa Interactivo")
st_data = st_folium(m, width=700, height=500)
# =============================================================================
# Secci贸n del Chatbot con API de OpenAI
# =============================================================================
st.markdown("---")
st.subheader("Chatbot de Recomendaciones")
st.write("Consulta recomendaciones sobre Puerto Rico.")
# Entrada de usuario para la consulta
user_input = st.text_input("Escribe tu consulta:")
if st.button("Enviar consulta"):
if user_input:
# Configura tu clave API de OpenAI (def铆nela en st.secrets)
openai.api_key = st.secrets[""]
with st.spinner("Consultando a OpenAI..."):
try:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "Eres un asistente experto en recomendaciones tur铆sticas y culturales de Puerto Rico. Ayudas a los usuarios a descubrir lugares de inter茅s y actividades en la isla."},
{"role": "user", "content": user_input}
]
)
answer = response.choices[0].message.content.strip()
st.markdown("**Respuesta:**")
st.write(answer)
except Exception as e:
st.error(f"Error al conectarse con la API de OpenAI: {e}")
else:
st.warning("Por favor, ingresa una consulta.")
|