Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -279,34 +279,69 @@ def find_best_matches_hybrid(entities, data):
|
|
| 279 |
if not entities or not data: return []
|
| 280 |
user_symptoms = set(sanitize_text(s) for s in entities.get("sintomas", []))
|
| 281 |
user_foods = set(sanitize_text(f) for f in entities.get("alimentos", []))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 282 |
candidate_terms = set(user_foods)
|
| 283 |
for food in user_foods:
|
| 284 |
if food in FOOD_TO_COMPOUND_MAP:
|
| 285 |
candidate_terms.update(c.lower() for c in FOOD_TO_COMPOUND_MAP[food])
|
|
|
|
| 286 |
results = []
|
| 287 |
for entry in data:
|
| 288 |
entry_compounds_text = sanitize_text(entry.get("compuesto_alimento", ""))
|
| 289 |
food_match = any(term in entry_compounds_text for term in candidate_terms)
|
|
|
|
| 290 |
if not food_match:
|
| 291 |
continue
|
|
|
|
| 292 |
score_details = {'food': 20, 'symptoms': 0}
|
|
|
|
| 293 |
entry_symptoms_keys = set(sanitize_text(s) for s in entry.get("sintomas_clave", []))
|
| 294 |
symptom_score = 0
|
| 295 |
matched_symptoms = []
|
| 296 |
for user_symptom in user_symptoms:
|
| 297 |
for key in entry_symptoms_keys:
|
| 298 |
if key in user_symptom or user_symptom in key:
|
| 299 |
-
symptom_score += 30
|
| 300 |
matched_symptoms.append(key)
|
| 301 |
break
|
|
|
|
| 302 |
score_details['symptoms'] = symptom_score
|
| 303 |
-
|
| 304 |
if score_details['symptoms'] > 0:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 305 |
results.append({
|
| 306 |
'entry': entry,
|
| 307 |
'score': score_details,
|
| 308 |
'matched_symptoms': list(set(matched_symptoms))
|
| 309 |
})
|
|
|
|
| 310 |
if not results: return []
|
| 311 |
return sorted(results, key=lambda x: x['score']['total'], reverse=True)
|
| 312 |
|
|
@@ -352,15 +387,27 @@ def generate_detailed_analysis(query, match):
|
|
| 352 |
raise e
|
| 353 |
|
| 354 |
def create_relevance_chart(results):
|
| 355 |
-
|
|
|
|
|
|
|
| 356 |
condition_names = [re.sub(r'\(.*\)', '', res['entry']['condicion_asociada']).strip() for res in top_results]
|
| 357 |
chart_data = {"Condici贸n": condition_names, "Relevancia": [res['score']['total'] for res in top_results]}
|
| 358 |
source = pd.DataFrame(chart_data)
|
|
|
|
| 359 |
chart = alt.Chart(source).mark_bar(color='#1f77b4').encode(
|
| 360 |
x=alt.X('Relevancia:Q', title='Puntuaci贸n de Relevancia'),
|
| 361 |
y=alt.Y('Condici贸n:N', sort='-x', title='', axis=alt.Axis(labelLimit=300)),
|
| 362 |
tooltip=[alt.Tooltip('Condici贸n:N', title='Condici贸n'), alt.Tooltip('Relevancia:Q', title='Puntuaci贸n')]
|
| 363 |
-
).properties(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 364 |
return chart
|
| 365 |
|
| 366 |
def generate_report_text(query, results):
|
|
|
|
| 279 |
if not entities or not data: return []
|
| 280 |
user_symptoms = set(sanitize_text(s) for s in entities.get("sintomas", []))
|
| 281 |
user_foods = set(sanitize_text(f) for f in entities.get("alimentos", []))
|
| 282 |
+
|
| 283 |
+
# --- LISTA DE CONDICIONES RARAS (Centralizada para f谩cil mantenimiento) ---
|
| 284 |
+
# Cualquier condici贸n en esta lista recibir谩 una penalizaci贸n en su puntuaci贸n.
|
| 285 |
+
# El resto se considerar谩 de probabilidad normal.
|
| 286 |
+
RARE_CONDITIONS = [
|
| 287 |
+
"Porfiria Aguda Intermitente (PAI).",
|
| 288 |
+
"Enfermedad de Refsum del Adulto.",
|
| 289 |
+
"Ataxia por Gluten.",
|
| 290 |
+
"Encefalopat铆a por Gluten.",
|
| 291 |
+
"Enfermedad de Wilson.",
|
| 292 |
+
"Aciduria Argininosucc铆nica.",
|
| 293 |
+
"S铆ndrome de Alagille."
|
| 294 |
+
# A帽ade aqu铆 otras enfermedades raras a medida que las incorpores a tu JSON.
|
| 295 |
+
]
|
| 296 |
+
|
| 297 |
candidate_terms = set(user_foods)
|
| 298 |
for food in user_foods:
|
| 299 |
if food in FOOD_TO_COMPOUND_MAP:
|
| 300 |
candidate_terms.update(c.lower() for c in FOOD_TO_COMPOUND_MAP[food])
|
| 301 |
+
|
| 302 |
results = []
|
| 303 |
for entry in data:
|
| 304 |
entry_compounds_text = sanitize_text(entry.get("compuesto_alimento", ""))
|
| 305 |
food_match = any(term in entry_compounds_text for term in candidate_terms)
|
| 306 |
+
|
| 307 |
if not food_match:
|
| 308 |
continue
|
| 309 |
+
|
| 310 |
score_details = {'food': 20, 'symptoms': 0}
|
| 311 |
+
|
| 312 |
entry_symptoms_keys = set(sanitize_text(s) for s in entry.get("sintomas_clave", []))
|
| 313 |
symptom_score = 0
|
| 314 |
matched_symptoms = []
|
| 315 |
for user_symptom in user_symptoms:
|
| 316 |
for key in entry_symptoms_keys:
|
| 317 |
if key in user_symptom or user_symptom in key:
|
| 318 |
+
symptom_score += 30
|
| 319 |
matched_symptoms.append(key)
|
| 320 |
break
|
| 321 |
+
|
| 322 |
score_details['symptoms'] = symptom_score
|
| 323 |
+
|
| 324 |
if score_details['symptoms'] > 0:
|
| 325 |
+
base_score = score_details['food'] + score_details['symptoms']
|
| 326 |
+
|
| 327 |
+
# --- L脫GICA DE PONDERACI脫N SIMPLIFICADA ---
|
| 328 |
+
condition_name = entry.get("condicion_asociada", "")
|
| 329 |
+
|
| 330 |
+
if condition_name in RARE_CONDITIONS:
|
| 331 |
+
# Penalizaci贸n fuerte para condiciones raras
|
| 332 |
+
final_score = base_score * 0.4
|
| 333 |
+
else:
|
| 334 |
+
# Puntuaci贸n completa para el resto (comunes y poco comunes)
|
| 335 |
+
final_score = base_score * 1.0
|
| 336 |
+
|
| 337 |
+
score_details['total'] = int(final_score)
|
| 338 |
+
|
| 339 |
results.append({
|
| 340 |
'entry': entry,
|
| 341 |
'score': score_details,
|
| 342 |
'matched_symptoms': list(set(matched_symptoms))
|
| 343 |
})
|
| 344 |
+
|
| 345 |
if not results: return []
|
| 346 |
return sorted(results, key=lambda x: x['score']['total'], reverse=True)
|
| 347 |
|
|
|
|
| 387 |
raise e
|
| 388 |
|
| 389 |
def create_relevance_chart(results):
|
| 390 |
+
# Modificado para mostrar hasta 10 resultados en el gr谩fico
|
| 391 |
+
top_results = results[:10]
|
| 392 |
+
|
| 393 |
condition_names = [re.sub(r'\(.*\)', '', res['entry']['condicion_asociada']).strip() for res in top_results]
|
| 394 |
chart_data = {"Condici贸n": condition_names, "Relevancia": [res['score']['total'] for res in top_results]}
|
| 395 |
source = pd.DataFrame(chart_data)
|
| 396 |
+
|
| 397 |
chart = alt.Chart(source).mark_bar(color='#1f77b4').encode(
|
| 398 |
x=alt.X('Relevancia:Q', title='Puntuaci贸n de Relevancia'),
|
| 399 |
y=alt.Y('Condici贸n:N', sort='-x', title='', axis=alt.Axis(labelLimit=300)),
|
| 400 |
tooltip=[alt.Tooltip('Condici贸n:N', title='Condici贸n'), alt.Tooltip('Relevancia:Q', title='Puntuaci贸n')]
|
| 401 |
+
).properties(
|
| 402 |
+
title='Principales Coincidencias seg煤n tu Caso'
|
| 403 |
+
).configure_axis(
|
| 404 |
+
labelFontSize=12,
|
| 405 |
+
titleFontSize=14
|
| 406 |
+
).configure_title(
|
| 407 |
+
fontSize=16,
|
| 408 |
+
anchor='start'
|
| 409 |
+
)
|
| 410 |
+
|
| 411 |
return chart
|
| 412 |
|
| 413 |
def generate_report_text(query, results):
|