Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -22,6 +22,18 @@ from gemini import responder_con_gemini
|
|
| 22 |
SPREADSHEET_ID = "1YizPDOaelHY-vTTrBSWy6Iv8P0SvNOTPNrAEgEiWIIY"
|
| 23 |
NOMBRE_HOJA = "Hoja 1" # Cambia esto si tu pestaña tiene otro nombre exacto
|
| 24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
ENCABEZADOS = [
|
| 26 |
"fecha_hora",
|
| 27 |
"folio_atencion",
|
|
@@ -153,6 +165,106 @@ def asegurar_encabezados(sheet):
|
|
| 153 |
except Exception as e:
|
| 154 |
print(f"No se pudieron verificar/agregar encabezados: {repr(e)}")
|
| 155 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
# =====================================================
|
| 157 |
# FUNCIONES DE RESPALDO FOSO II
|
| 158 |
# =====================================================
|
|
@@ -1203,182 +1315,292 @@ with gr.Blocks(theme=tema_visual, css=css, title="Sistema de Orientación para e
|
|
| 1203 |
</div>
|
| 1204 |
""")
|
| 1205 |
|
| 1206 |
-
with gr.
|
| 1207 |
-
|
| 1208 |
-
|
| 1209 |
-
<
|
| 1210 |
-
|
| 1211 |
-
|
| 1212 |
-
|
| 1213 |
-
|
| 1214 |
-
|
| 1215 |
-
|
| 1216 |
-
|
| 1217 |
-
|
| 1218 |
-
|
| 1219 |
-
<
|
| 1220 |
-
|
| 1221 |
-
|
| 1222 |
-
|
| 1223 |
-
|
| 1224 |
-
|
| 1225 |
-
|
| 1226 |
-
|
| 1227 |
-
|
| 1228 |
-
|
| 1229 |
-
|
| 1230 |
-
|
| 1231 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1232 |
label="Matrícula (opcional)",
|
| 1233 |
-
placeholder="Ej. 22012345
|
| 1234 |
)
|
| 1235 |
-
|
| 1236 |
-
|
| 1237 |
-
|
| 1238 |
-
with gr.Column(scale=2):
|
| 1239 |
-
gr.HTML("""
|
| 1240 |
-
<div class="bloque">
|
| 1241 |
-
<p style="font-size:19px; font-weight:900; color:#0b6b43; margin-bottom:10px;">
|
| 1242 |
-
🔒 Hola, este es un espacio seguro para ti.
|
| 1243 |
-
</p>
|
| 1244 |
-
<p style="font-size:16px; line-height:1.6; color:#333;">
|
| 1245 |
-
Puedes hablar conmigo con confianza.<br>
|
| 1246 |
-
Todo lo que compartas será tratado con seriedad, respeto y
|
| 1247 |
-
<b>confidencialidad</b>, conforme al aviso de privacidad institucional.<br><br>
|
| 1248 |
-
Estoy aquí para apoyarte. Si te sientes en riesgo o necesitas ayuda urgente,
|
| 1249 |
-
busca a tu tutor, orientador del bienestar o a un adulto de confianza.<br><br>
|
| 1250 |
-
<span style="font-weight:900; font-size:17px;">No estás solo.</span>
|
| 1251 |
-
</p>
|
| 1252 |
-
</div>
|
| 1253 |
-
""")
|
| 1254 |
-
|
| 1255 |
-
historial = gr.Textbox(
|
| 1256 |
-
label="Conversación",
|
| 1257 |
-
lines=16,
|
| 1258 |
-
interactive=False,
|
| 1259 |
-
placeholder="Aquí aparecerá la conversación..."
|
| 1260 |
)
|
| 1261 |
-
|
| 1262 |
-
|
| 1263 |
-
|
| 1264 |
-
placeholder="Escribe aquí cómo te sientes o qué necesitas..."
|
| 1265 |
)
|
| 1266 |
|
| 1267 |
-
|
| 1268 |
-
|
| 1269 |
-
|
| 1270 |
-
|
| 1271 |
-
)
|
|
|
|
|
|
|
| 1272 |
|
| 1273 |
-
|
| 1274 |
-
|
| 1275 |
-
|
| 1276 |
-
|
| 1277 |
-
)
|
| 1278 |
|
| 1279 |
-
|
| 1280 |
-
|
| 1281 |
-
|
| 1282 |
-
|
| 1283 |
-
|
| 1284 |
-
|
| 1285 |
-
|
| 1286 |
-
|
| 1287 |
-
|
| 1288 |
-
|
| 1289 |
-
|
| 1290 |
-
|
| 1291 |
-
<
|
| 1292 |
-
|
| 1293 |
-
|
| 1294 |
-
|
| 1295 |
-
|
| 1296 |
-
|
| 1297 |
-
|
| 1298 |
-
|
| 1299 |
-
|
| 1300 |
-
|
| 1301 |
-
|
| 1302 |
-
|
| 1303 |
-
|
| 1304 |
-
|
| 1305 |
-
|
| 1306 |
-
|
| 1307 |
-
|
| 1308 |
-
|
| 1309 |
-
|
| 1310 |
-
|
| 1311 |
-
|
| 1312 |
-
|
| 1313 |
-
|
| 1314 |
-
|
| 1315 |
-
|
| 1316 |
-
|
| 1317 |
-
|
| 1318 |
-
|
| 1319 |
-
|
| 1320 |
-
|
| 1321 |
-
|
| 1322 |
-
|
| 1323 |
-
|
| 1324 |
-
|
| 1325 |
-
|
| 1326 |
-
|
| 1327 |
-
|
| 1328 |
-
|
| 1329 |
-
|
| 1330 |
-
|
| 1331 |
-
|
| 1332 |
-
|
| 1333 |
-
|
| 1334 |
-
|
| 1335 |
-
|
| 1336 |
-
|
| 1337 |
-
|
| 1338 |
-
|
| 1339 |
-
|
| 1340 |
-
|
| 1341 |
-
|
| 1342 |
-
|
| 1343 |
-
|
| 1344 |
-
|
| 1345 |
-
|
| 1346 |
-
|
| 1347 |
-
|
| 1348 |
-
|
| 1349 |
-
|
| 1350 |
-
|
| 1351 |
-
|
| 1352 |
-
|
| 1353 |
-
|
| 1354 |
-
|
| 1355 |
-
|
| 1356 |
-
|
| 1357 |
-
|
| 1358 |
-
|
| 1359 |
-
|
| 1360 |
-
|
| 1361 |
-
|
| 1362 |
-
|
| 1363 |
-
|
| 1364 |
-
|
| 1365 |
-
|
| 1366 |
-
|
| 1367 |
-
|
| 1368 |
-
|
| 1369 |
-
|
| 1370 |
-
|
| 1371 |
-
|
| 1372 |
-
|
| 1373 |
-
<
|
| 1374 |
-
|
| 1375 |
-
|
| 1376 |
-
|
| 1377 |
-
|
| 1378 |
-
|
| 1379 |
-
|
| 1380 |
-
|
| 1381 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1382 |
|
| 1383 |
enviar.click(
|
| 1384 |
responder_chat_con_voz,
|
|
|
|
| 22 |
SPREADSHEET_ID = "1YizPDOaelHY-vTTrBSWy6Iv8P0SvNOTPNrAEgEiWIIY"
|
| 23 |
NOMBRE_HOJA = "Hoja 1" # Cambia esto si tu pestaña tiene otro nombre exacto
|
| 24 |
|
| 25 |
+
VERSION_CONSENTIMIENTO = "1.0"
|
| 26 |
+
NOMBRE_HOJA_CONSENTIMIENTOS = "Consentimientos"
|
| 27 |
+
|
| 28 |
+
ENCABEZADOS_CONSENTIMIENTO = [
|
| 29 |
+
"fecha_hora",
|
| 30 |
+
"matricula",
|
| 31 |
+
"nombre",
|
| 32 |
+
"grupo",
|
| 33 |
+
"consentimiento",
|
| 34 |
+
"version_consentimiento"
|
| 35 |
+
]
|
| 36 |
+
|
| 37 |
ENCABEZADOS = [
|
| 38 |
"fecha_hora",
|
| 39 |
"folio_atencion",
|
|
|
|
| 165 |
except Exception as e:
|
| 166 |
print(f"No se pudieron verificar/agregar encabezados: {repr(e)}")
|
| 167 |
|
| 168 |
+
|
| 169 |
+
# =====================================================
|
| 170 |
+
# CONSENTIMIENTO INFORMADO Y REGISTRO
|
| 171 |
+
# =====================================================
|
| 172 |
+
|
| 173 |
+
def conectar_sheet_consentimientos():
|
| 174 |
+
"""
|
| 175 |
+
Abre o crea la pestaña Consentimientos en el mismo archivo de Google Sheets.
|
| 176 |
+
Utiliza el mismo Secret GOOGLE_CREDENTIALS y el mismo SPREADSHEET_ID.
|
| 177 |
+
"""
|
| 178 |
+
scope = [
|
| 179 |
+
"https://spreadsheets.google.com/feeds",
|
| 180 |
+
"https://www.googleapis.com/auth/drive"
|
| 181 |
+
]
|
| 182 |
+
|
| 183 |
+
creds_json = os.getenv("GOOGLE_CREDENTIALS")
|
| 184 |
+
if not creds_json:
|
| 185 |
+
raise ValueError(
|
| 186 |
+
"No se encontró el Secret GOOGLE_CREDENTIALS. "
|
| 187 |
+
"Verifica en Hugging Face: Settings > Secrets."
|
| 188 |
+
)
|
| 189 |
+
|
| 190 |
+
creds_dict = json.loads(creds_json)
|
| 191 |
+
creds = ServiceAccountCredentials.from_json_keyfile_dict(creds_dict, scope)
|
| 192 |
+
client = gspread.authorize(creds)
|
| 193 |
+
archivo = client.open_by_key(SPREADSHEET_ID)
|
| 194 |
+
|
| 195 |
+
try:
|
| 196 |
+
sheet = archivo.worksheet(NOMBRE_HOJA_CONSENTIMIENTOS)
|
| 197 |
+
except Exception:
|
| 198 |
+
sheet = archivo.add_worksheet(
|
| 199 |
+
title=NOMBRE_HOJA_CONSENTIMIENTOS,
|
| 200 |
+
rows=1000,
|
| 201 |
+
cols=len(ENCABEZADOS_CONSENTIMIENTO)
|
| 202 |
+
)
|
| 203 |
+
|
| 204 |
+
primera_fila = sheet.row_values(1)
|
| 205 |
+
if not primera_fila:
|
| 206 |
+
sheet.append_row(
|
| 207 |
+
ENCABEZADOS_CONSENTIMIENTO,
|
| 208 |
+
value_input_option="USER_ENTERED"
|
| 209 |
+
)
|
| 210 |
+
|
| 211 |
+
return sheet
|
| 212 |
+
|
| 213 |
+
|
| 214 |
+
def guardar_consentimiento(acepta, matricula, nombre, grupo):
|
| 215 |
+
"""
|
| 216 |
+
Registra la aceptación en Google Sheets y habilita la interfaz de SOFIA.
|
| 217 |
+
"""
|
| 218 |
+
if not acepta:
|
| 219 |
+
return (
|
| 220 |
+
gr.update(visible=True),
|
| 221 |
+
gr.update(visible=False),
|
| 222 |
+
matricula or "",
|
| 223 |
+
nombre or "",
|
| 224 |
+
grupo or "",
|
| 225 |
+
"⚠️ Debes marcar la casilla de aceptación para continuar."
|
| 226 |
+
)
|
| 227 |
+
|
| 228 |
+
matricula_final = str(matricula or "").strip() or "ANONIMO"
|
| 229 |
+
nombre_final = str(nombre or "").strip() or "ANONIMO"
|
| 230 |
+
grupo_final = str(grupo or "").strip()
|
| 231 |
+
|
| 232 |
+
try:
|
| 233 |
+
sheet = conectar_sheet_consentimientos()
|
| 234 |
+
sheet.append_row(
|
| 235 |
+
[
|
| 236 |
+
datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 237 |
+
matricula_final,
|
| 238 |
+
nombre_final,
|
| 239 |
+
grupo_final,
|
| 240 |
+
"SI",
|
| 241 |
+
VERSION_CONSENTIMIENTO
|
| 242 |
+
],
|
| 243 |
+
value_input_option="USER_ENTERED",
|
| 244 |
+
insert_data_option="INSERT_ROWS"
|
| 245 |
+
)
|
| 246 |
+
|
| 247 |
+
return (
|
| 248 |
+
gr.update(visible=False),
|
| 249 |
+
gr.update(visible=True),
|
| 250 |
+
"" if matricula_final == "ANONIMO" else matricula_final,
|
| 251 |
+
"" if nombre_final == "ANONIMO" else nombre_final,
|
| 252 |
+
grupo_final,
|
| 253 |
+
"✅ Consentimiento registrado correctamente."
|
| 254 |
+
)
|
| 255 |
+
|
| 256 |
+
except Exception as e:
|
| 257 |
+
print(f"Error al registrar consentimiento: {repr(e)}")
|
| 258 |
+
return (
|
| 259 |
+
gr.update(visible=True),
|
| 260 |
+
gr.update(visible=False),
|
| 261 |
+
matricula or "",
|
| 262 |
+
nombre or "",
|
| 263 |
+
grupo or "",
|
| 264 |
+
"❌ No fue posible registrar el consentimiento. Intenta nuevamente."
|
| 265 |
+
)
|
| 266 |
+
|
| 267 |
+
|
| 268 |
# =====================================================
|
| 269 |
# FUNCIONES DE RESPALDO FOSO II
|
| 270 |
# =====================================================
|
|
|
|
| 1315 |
</div>
|
| 1316 |
""")
|
| 1317 |
|
| 1318 |
+
with gr.Group(visible=True) as pantalla_consentimiento:
|
| 1319 |
+
gr.HTML("""
|
| 1320 |
+
<div class="bloque" style="max-width:1000px; margin:0 auto 18px auto;">
|
| 1321 |
+
<h2 style="text-align:center;">🔒 Consentimiento Informado, Aviso de Privacidad y Confidencialidad</h2>
|
| 1322 |
+
|
| 1323 |
+
<h3>Bienvenido(a) a SOFIA</h3>
|
| 1324 |
+
<p>
|
| 1325 |
+
SOFIA es un agente conversacional basado en Inteligencia Artificial,
|
| 1326 |
+
diseñado para brindar orientación inicial, apoyo socioemocional y
|
| 1327 |
+
acompañamiento pedagógico a estudiantes.
|
| 1328 |
+
</p>
|
| 1329 |
+
|
| 1330 |
+
<h3>🤖 Uso de Inteligencia Artificial</h3>
|
| 1331 |
+
<p>
|
| 1332 |
+
Las respuestas de SOFIA tienen fines informativos, preventivos y de
|
| 1333 |
+
orientación inicial. Pueden ser generadas mediante modelos de
|
| 1334 |
+
Inteligencia Artificial.
|
| 1335 |
+
</p>
|
| 1336 |
+
|
| 1337 |
+
<h3>🔐 Aviso de Privacidad</h3>
|
| 1338 |
+
<p>
|
| 1339 |
+
Los datos que proporciones voluntariamente, como nombre, matrícula,
|
| 1340 |
+
grupo y mensajes, serán utilizados para brindar orientación inicial,
|
| 1341 |
+
detectar indicadores de riesgo socioemocional, mejorar el sistema,
|
| 1342 |
+
generar información estadística y realizar seguimiento institucional
|
| 1343 |
+
cuando sea necesario.
|
| 1344 |
+
</p>
|
| 1345 |
+
<p>
|
| 1346 |
+
Los datos serán tratados conforme al Aviso de Privacidad institucional
|
| 1347 |
+
de la Universidad Estatal del Valle de Toluca y a la normativa aplicable
|
| 1348 |
+
en materia de protección de datos personales.
|
| 1349 |
+
</p>
|
| 1350 |
+
|
| 1351 |
+
<h3>🔒 Confidencialidad</h3>
|
| 1352 |
+
<p>
|
| 1353 |
+
La información compartida será tratada con confidencialidad. Cuando se
|
| 1354 |
+
detecten indicadores de riesgo grave para la integridad del estudiante
|
| 1355 |
+
o de terceras personas, el sistema podrá recomendar la canalización
|
| 1356 |
+
inmediata con personal institucional, servicios de salud o emergencias.
|
| 1357 |
+
</p>
|
| 1358 |
+
|
| 1359 |
+
<h3>⚠️ Limitaciones</h3>
|
| 1360 |
+
<p>
|
| 1361 |
+
SOFIA no sustituye la atención psicológica, médica o psiquiátrica;
|
| 1362 |
+
no realiza diagnósticos clínicos, no prescribe medicamentos y no
|
| 1363 |
+
reemplaza la valoración de un profesional.
|
| 1364 |
+
</p>
|
| 1365 |
+
|
| 1366 |
+
<h3>🚨 Emergencias</h3>
|
| 1367 |
+
<p>
|
| 1368 |
+
Si existe peligro inmediato, llama al <b>911</b>, comunícate con la
|
| 1369 |
+
<b>Línea de la Vida: 800 911 2000</b> y busca el acompañamiento de una
|
| 1370 |
+
persona adulta, familiar, tutor u orientador.
|
| 1371 |
+
</p>
|
| 1372 |
+
|
| 1373 |
+
<p>
|
| 1374 |
+
El uso de SOFIA es voluntario. Puedes abandonar la conversación en
|
| 1375 |
+
cualquier momento.
|
| 1376 |
+
</p>
|
| 1377 |
+
</div>
|
| 1378 |
+
""")
|
| 1379 |
+
|
| 1380 |
+
with gr.Row():
|
| 1381 |
+
consentimiento_matricula = gr.Textbox(
|
| 1382 |
label="Matrícula (opcional)",
|
| 1383 |
+
placeholder="Ej. 22012345"
|
| 1384 |
)
|
| 1385 |
+
consentimiento_nombre = gr.Textbox(
|
| 1386 |
+
label="Nombre (opcional)",
|
| 1387 |
+
placeholder="Escribe tu nombre"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1388 |
)
|
| 1389 |
+
consentimiento_grupo = gr.Textbox(
|
| 1390 |
+
label="Grupo (opcional)",
|
| 1391 |
+
placeholder="Ej. 210"
|
|
|
|
| 1392 |
)
|
| 1393 |
|
| 1394 |
+
acepta_consentimiento = gr.Checkbox(
|
| 1395 |
+
label=(
|
| 1396 |
+
"He leído y acepto el Aviso de Privacidad, el Consentimiento "
|
| 1397 |
+
"Informado y las condiciones de uso de SOFIA."
|
| 1398 |
+
),
|
| 1399 |
+
value=False
|
| 1400 |
+
)
|
| 1401 |
|
| 1402 |
+
aceptar_consentimiento_btn = gr.Button(
|
| 1403 |
+
"✅ Aceptar e iniciar conversación",
|
| 1404 |
+
variant="primary"
|
| 1405 |
+
)
|
|
|
|
| 1406 |
|
| 1407 |
+
estado_consentimiento = gr.Markdown("")
|
| 1408 |
+
|
| 1409 |
+
with gr.Group(visible=False) as pantalla_agente:
|
| 1410 |
+
with gr.Row():
|
| 1411 |
+
with gr.Column(scale=1):
|
| 1412 |
+
gr.HTML("""
|
| 1413 |
+
<div class="bloque">
|
| 1414 |
+
<h2>¿Qué puedo hacer por ti?</h2>
|
| 1415 |
+
<p>✅ Brindarte acompañamiento inicial</p>
|
| 1416 |
+
<p>✅ Detectar señales de riesgo socioemocional</p>
|
| 1417 |
+
<p>✅ Orientarte en temas emocionales y escolares</p>
|
| 1418 |
+
<p>✅ Canalizarte si necesitas ayuda urgente</p>
|
| 1419 |
+
</div>
|
| 1420 |
+
""")
|
| 1421 |
+
|
| 1422 |
+
gr.HTML("""
|
| 1423 |
+
<div class="bloque">
|
| 1424 |
+
<h3>🔒 Espacio confidencial</h3>
|
| 1425 |
+
<p>Este agente no sustituye atención psicológica, médica o de emergencia.</p>
|
| 1426 |
+
<p>
|
| 1427 |
+
Si existe peligro inmediato, llama al
|
| 1428 |
+
<span style="font-weight:900; font-size:18px; color:#d32f2f;">911</span>
|
| 1429 |
+
o a la
|
| 1430 |
+
<span style="font-weight:900; font-size:18px; color:#b71c1c;">Línea de la Vida: 800 911 2000</span>.
|
| 1431 |
+
</p>
|
| 1432 |
+
</div>
|
| 1433 |
+
""")
|
| 1434 |
+
|
| 1435 |
+
matricula = gr.Textbox(
|
| 1436 |
+
label="Matrícula (opcional)",
|
| 1437 |
+
placeholder="Ej. 22012345 o deja vacío si prefieres anonimato"
|
| 1438 |
+
)
|
| 1439 |
+
nombre = gr.Textbox(label="Nombre", placeholder="Escribe tu nombre")
|
| 1440 |
+
grupo = gr.Textbox(label="Grupo", placeholder="Ej. 210")
|
| 1441 |
+
|
| 1442 |
+
with gr.Column(scale=2):
|
| 1443 |
+
gr.HTML("""
|
| 1444 |
+
<div class="bloque">
|
| 1445 |
+
<p style="font-size:19px; font-weight:900; color:#0b6b43; margin-bottom:10px;">
|
| 1446 |
+
🔒 Hola, este es un espacio seguro para ti.
|
| 1447 |
+
</p>
|
| 1448 |
+
<p style="font-size:16px; line-height:1.6; color:#333;">
|
| 1449 |
+
Puedes hablar conmigo con confianza.<br>
|
| 1450 |
+
Todo lo que compartas será tratado con seriedad, respeto y
|
| 1451 |
+
<b>confidencialidad</b>, conforme al aviso de privacidad institucional.<br><br>
|
| 1452 |
+
Estoy aquí para apoyarte. Si te sientes en riesgo o necesitas ayuda urgente,
|
| 1453 |
+
busca a tu tutor, orientador del bienestar o a un adulto de confianza.<br><br>
|
| 1454 |
+
<span style="font-weight:900; font-size:17px;">No estás solo.</span>
|
| 1455 |
+
</p>
|
| 1456 |
+
</div>
|
| 1457 |
+
""")
|
| 1458 |
+
|
| 1459 |
+
historial = gr.Textbox(
|
| 1460 |
+
label="Conversación",
|
| 1461 |
+
lines=16,
|
| 1462 |
+
interactive=False,
|
| 1463 |
+
placeholder="Aquí aparecerá la conversación..."
|
| 1464 |
+
)
|
| 1465 |
+
|
| 1466 |
+
mensaje = gr.Textbox(
|
| 1467 |
+
label="Mensaje del estudiante",
|
| 1468 |
+
placeholder="Escribe aquí cómo te sientes o qué necesitas..."
|
| 1469 |
+
)
|
| 1470 |
+
|
| 1471 |
+
audio_entrada = gr.Audio(
|
| 1472 |
+
sources=["microphone"],
|
| 1473 |
+
type="filepath",
|
| 1474 |
+
label="🎤 Habla con SOFIA"
|
| 1475 |
+
)
|
| 1476 |
+
|
| 1477 |
+
audio_salida = gr.Audio(
|
| 1478 |
+
label="🔊 Voz de SOFIA",
|
| 1479 |
+
autoplay=True,
|
| 1480 |
+
interactive=False
|
| 1481 |
+
)
|
| 1482 |
+
|
| 1483 |
+
with gr.Row():
|
| 1484 |
+
enviar = gr.Button("Enviar", variant="primary")
|
| 1485 |
+
limpiar = gr.Button("Limpiar")
|
| 1486 |
+
|
| 1487 |
+
respuesta_box = gr.Textbox(label="Respuesta del agente", lines=10, visible=False)
|
| 1488 |
+
|
| 1489 |
+
with gr.Column(scale=1):
|
| 1490 |
+
gr.HTML("""
|
| 1491 |
+
<div class="bloque">
|
| 1492 |
+
<h2>Acciones rápidas</h2>
|
| 1493 |
+
<p>📋 Evaluación rápida</p>
|
| 1494 |
+
<p>📚 Recursos de apoyo</p>
|
| 1495 |
+
<p>📞 Contactar tutor u orientador</p>
|
| 1496 |
+
<p>🧠 Acompañamiento emocional inicial</p>
|
| 1497 |
+
</div>
|
| 1498 |
+
""")
|
| 1499 |
+
|
| 1500 |
+
gr.HTML("""
|
| 1501 |
+
<div class="bloque estado">
|
| 1502 |
+
Estado del agente: En línea 🟢
|
| 1503 |
+
</div>
|
| 1504 |
+
""")
|
| 1505 |
+
|
| 1506 |
+
crisis_btn = gr.Button("🚨 ¡Necesito ayuda urgente!", variant="stop")
|
| 1507 |
+
|
| 1508 |
+
gr.HTML("""
|
| 1509 |
+
<div class="bloque" style="padding:14px; margin-top:10px;">
|
| 1510 |
+
<h3 style="margin-top:0;">📞 Contactos de apoyo</h3>
|
| 1511 |
+
|
| 1512 |
+
<a href="https://wa.me/527299068258?text=Hola,%20soy%20estudiante%20y%20necesito%20apoyo%20socioemocional."
|
| 1513 |
+
target="_blank" rel="noopener noreferrer" style="text-decoration:none;">
|
| 1514 |
+
<button style="
|
| 1515 |
+
width:100%;
|
| 1516 |
+
background:#25D366;
|
| 1517 |
+
color:white;
|
| 1518 |
+
padding:12px;
|
| 1519 |
+
border:none;
|
| 1520 |
+
border-radius:10px;
|
| 1521 |
+
font-size:16px;
|
| 1522 |
+
font-weight:bold;
|
| 1523 |
+
cursor:pointer;
|
| 1524 |
+
margin-top:8px;">
|
| 1525 |
+
💬 Orientador 1
|
| 1526 |
+
</button>
|
| 1527 |
+
</a>
|
| 1528 |
+
|
| 1529 |
+
<!-- Sustituye 52XXXXXXXXXX por el número real del segundo orientador -->
|
| 1530 |
+
<a href="https://wa.me/52XXXXXXXXXX?text=Hola,%20soy%20estudiante%20y%20necesito%20apoyo%20socioemocional."
|
| 1531 |
+
target="_blank" rel="noopener noreferrer" style="text-decoration:none;">
|
| 1532 |
+
<button style="
|
| 1533 |
+
width:100%;
|
| 1534 |
+
background:#128C7E;
|
| 1535 |
+
color:white;
|
| 1536 |
+
padding:12px;
|
| 1537 |
+
border:none;
|
| 1538 |
+
border-radius:10px;
|
| 1539 |
+
font-size:16px;
|
| 1540 |
+
font-weight:bold;
|
| 1541 |
+
cursor:pointer;
|
| 1542 |
+
margin-top:8px;">
|
| 1543 |
+
💬 Orientador 2
|
| 1544 |
+
</button>
|
| 1545 |
+
</a>
|
| 1546 |
+
|
| 1547 |
+
<a href="tel:8009112000" style="text-decoration:none;">
|
| 1548 |
+
<button style="
|
| 1549 |
+
width:100%;
|
| 1550 |
+
background:#7E22CE;
|
| 1551 |
+
color:white;
|
| 1552 |
+
padding:12px;
|
| 1553 |
+
border:none;
|
| 1554 |
+
border-radius:10px;
|
| 1555 |
+
font-size:16px;
|
| 1556 |
+
font-weight:bold;
|
| 1557 |
+
cursor:pointer;
|
| 1558 |
+
margin-top:8px;">
|
| 1559 |
+
☎️ Línea de la Vida: 800 911 2000
|
| 1560 |
+
</button>
|
| 1561 |
+
</a>
|
| 1562 |
+
|
| 1563 |
+
<a href="tel:911" style="text-decoration:none;">
|
| 1564 |
+
<button style="
|
| 1565 |
+
width:100%;
|
| 1566 |
+
background:#D32F2F;
|
| 1567 |
+
color:white;
|
| 1568 |
+
padding:12px;
|
| 1569 |
+
border:none;
|
| 1570 |
+
border-radius:10px;
|
| 1571 |
+
font-size:16px;
|
| 1572 |
+
font-weight:bold;
|
| 1573 |
+
cursor:pointer;
|
| 1574 |
+
margin-top:8px;">
|
| 1575 |
+
🚨 Llamar al 911
|
| 1576 |
+
</button>
|
| 1577 |
+
</a>
|
| 1578 |
+
</div>
|
| 1579 |
+
""")
|
| 1580 |
+
|
| 1581 |
+
analisis_box = gr.Textbox(
|
| 1582 |
+
label="Análisis emocional",
|
| 1583 |
+
lines=18,
|
| 1584 |
+
visible=False
|
| 1585 |
+
)
|
| 1586 |
+
|
| 1587 |
+
aceptar_consentimiento_btn.click(
|
| 1588 |
+
guardar_consentimiento,
|
| 1589 |
+
inputs=[
|
| 1590 |
+
acepta_consentimiento,
|
| 1591 |
+
consentimiento_matricula,
|
| 1592 |
+
consentimiento_nombre,
|
| 1593 |
+
consentimiento_grupo
|
| 1594 |
+
],
|
| 1595 |
+
outputs=[
|
| 1596 |
+
pantalla_consentimiento,
|
| 1597 |
+
pantalla_agente,
|
| 1598 |
+
matricula,
|
| 1599 |
+
nombre,
|
| 1600 |
+
grupo,
|
| 1601 |
+
estado_consentimiento
|
| 1602 |
+
]
|
| 1603 |
+
)
|
| 1604 |
|
| 1605 |
enviar.click(
|
| 1606 |
responder_chat_con_voz,
|