Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -490,30 +490,37 @@ def extract_entities_with_gemini(query):
|
|
| 490 |
logger.error(f"Error en la extracción con Gemini (puede ser reintentado): {e}")
|
| 491 |
raise e
|
| 492 |
|
| 493 |
-
def reinforce_entities_with_keywords(entities, query, food_map,
|
| 494 |
if not entities:
|
| 495 |
entities = {"alimentos": [], "sintomas": []}
|
| 496 |
|
| 497 |
query_sanitized = sanitize_text(query)
|
| 498 |
|
|
|
|
| 499 |
current_foods = entities.get("alimentos", []) or []
|
| 500 |
current_foods_sanitized = {sanitize_text(f) for f in current_foods}
|
| 501 |
for food_keyword in food_map.keys():
|
| 502 |
if food_keyword in query_sanitized and food_keyword not in current_foods_sanitized:
|
| 503 |
-
logger.info(f"Red de seguridad (Alimento): Añadiendo '{food_keyword}'.")
|
| 504 |
current_foods.append(food_keyword)
|
| 505 |
entities["alimentos"] = list(set(current_foods))
|
| 506 |
|
|
|
|
| 507 |
current_symptoms = entities.get("sintomas", []) or []
|
| 508 |
query_to_search_symptoms = " " + query_sanitized + " "
|
| 509 |
|
| 510 |
-
|
| 511 |
-
|
| 512 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 513 |
if main_symptom not in current_symptoms:
|
| 514 |
-
logger.info(f"
|
| 515 |
current_symptoms.append(main_symptom)
|
| 516 |
-
|
|
|
|
|
|
|
| 517 |
|
| 518 |
entities["sintomas"] = list(set(current_symptoms))
|
| 519 |
return entities
|
|
@@ -723,7 +730,8 @@ if st.session_state.start_analysis:
|
|
| 723 |
except Exception as e:
|
| 724 |
logger.warning(f"La extracción con Gemini falló; se usará el sistema de respaldo: {e}")
|
| 725 |
|
| 726 |
-
|
|
|
|
| 727 |
st.session_state.entities = entities
|
| 728 |
|
| 729 |
if entities and (entities.get("alimentos") or entities.get("sintomas")):
|
|
@@ -735,6 +743,7 @@ if st.session_state.start_analysis:
|
|
| 735 |
else:
|
| 736 |
st.error("No se pudieron identificar alimentos o síntomas claros en tu descripción. Intenta ser más específico.")
|
| 737 |
st.session_state.search_results = []
|
|
|
|
| 738 |
if st.session_state.search_results is not None:
|
| 739 |
results = st.session_state.search_results
|
| 740 |
|
|
@@ -769,18 +778,18 @@ if st.session_state.search_results is not None:
|
|
| 769 |
score_col2.metric("Puntos por Síntomas", f"{best_match_data['score']['symptoms']}")
|
| 770 |
score_col3.metric("PUNTUACIÓN TOTAL", f"{best_match_data['score']['total']}", delta="Máxima coincidencia")
|
| 771 |
|
| 772 |
-
# ---
|
| 773 |
with col2:
|
| 774 |
st.write("")
|
| 775 |
if foodb_index:
|
| 776 |
with st.popover("🔬 Componentes Moleculares Relevantes"):
|
| 777 |
-
st.info("Compuestos en los alimentos mencionados que podrían estar relacionados con tus síntomas
|
| 778 |
|
| 779 |
user_foods_mentioned = st.session_state.entities.get("alimentos", [])
|
| 780 |
-
|
| 781 |
|
| 782 |
-
if not user_foods_mentioned:
|
| 783 |
-
st.warning("
|
| 784 |
else:
|
| 785 |
found_relevant_data = False
|
| 786 |
|
|
@@ -790,13 +799,17 @@ if st.session_state.search_results is not None:
|
|
| 790 |
if key_es in alimento_es.lower():
|
| 791 |
search_terms_en.extend(value_en_list)
|
| 792 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 793 |
for foodb_key, compounds_data in foodb_index.items():
|
| 794 |
if any(term in foodb_key.lower() for term in set(search_terms_en)):
|
| 795 |
-
|
| 796 |
relevant_compounds = []
|
| 797 |
for item in compounds_data:
|
| 798 |
-
|
| 799 |
-
if any(
|
| 800 |
relevant_compounds.append(item)
|
| 801 |
|
| 802 |
if relevant_compounds:
|
|
@@ -805,13 +818,13 @@ if st.session_state.search_results is not None:
|
|
| 805 |
st.subheader(f"Análisis de: {foodb_key.capitalize()}")
|
| 806 |
for item in relevant_compounds[:5]:
|
| 807 |
st.write(f"**Compuesto:** {item['compound']}")
|
| 808 |
-
relevant_effects = [eff for eff in item['effects'] if any(
|
| 809 |
-
st.write(f"**Efectos Relevantes:** {', '.join(relevant_effects)}")
|
| 810 |
st.markdown("---")
|
| 811 |
|
| 812 |
if not found_relevant_data:
|
| 813 |
st.warning("No se encontraron compuestos moleculares directamente relacionados con tus síntomas para los alimentos mencionados.")
|
| 814 |
-
|
| 815 |
st.markdown("---")
|
| 816 |
|
| 817 |
with st.container(border=True):
|
|
|
|
| 490 |
logger.error(f"Error en la extracción con Gemini (puede ser reintentado): {e}")
|
| 491 |
raise e
|
| 492 |
|
| 493 |
+
def reinforce_entities_with_keywords(entities, query, food_map, master_symptom_map):
|
| 494 |
if not entities:
|
| 495 |
entities = {"alimentos": [], "sintomas": []}
|
| 496 |
|
| 497 |
query_sanitized = sanitize_text(query)
|
| 498 |
|
| 499 |
+
# --- Parte 1: Reforzar Alimentos (sin cambios en la lógica) ---
|
| 500 |
current_foods = entities.get("alimentos", []) or []
|
| 501 |
current_foods_sanitized = {sanitize_text(f) for f in current_foods}
|
| 502 |
for food_keyword in food_map.keys():
|
| 503 |
if food_keyword in query_sanitized and food_keyword not in current_foods_sanitized:
|
|
|
|
| 504 |
current_foods.append(food_keyword)
|
| 505 |
entities["alimentos"] = list(set(current_foods))
|
| 506 |
|
| 507 |
+
# --- Parte 2: Normalizar y Reforzar Síntomas usando el Diccionario Maestro ---
|
| 508 |
current_symptoms = entities.get("sintomas", []) or []
|
| 509 |
query_to_search_symptoms = " " + query_sanitized + " "
|
| 510 |
|
| 511 |
+
# Iterar sobre el diccionario maestro para encontrar coincidencias
|
| 512 |
+
for main_symptom, details in master_symptom_map.items():
|
| 513 |
+
# Ordenar las frases de la más larga a la más corta para máxima precisión
|
| 514 |
+
phrases_es = details.get("frases_es", [])
|
| 515 |
+
for phrase in sorted(phrases_es, key=len, reverse=True):
|
| 516 |
+
if (" " + phrase + " ") in query_to_search_symptoms:
|
| 517 |
+
# Si encontramos una coincidencia, añadimos el término estandarizado (la clave)
|
| 518 |
if main_symptom not in current_symptoms:
|
| 519 |
+
logger.info(f"Sistema de respaldo: Normalizando '{phrase}' a '{main_symptom}'.")
|
| 520 |
current_symptoms.append(main_symptom)
|
| 521 |
+
|
| 522 |
+
# Reemplazamos la frase encontrada para evitar sub-coincidencias
|
| 523 |
+
query_to_search_symptoms = query_to_search_symptoms.replace(" " + phrase + " ", " ")
|
| 524 |
|
| 525 |
entities["sintomas"] = list(set(current_symptoms))
|
| 526 |
return entities
|
|
|
|
| 730 |
except Exception as e:
|
| 731 |
logger.warning(f"La extracción con Gemini falló; se usará el sistema de respaldo: {e}")
|
| 732 |
|
| 733 |
+
# --- Aquí se usa el nuevo Diccionario Maestro ---
|
| 734 |
+
entities = reinforce_entities_with_keywords(entities, query_to_analyze, FOOD_TO_COMPOUND_MAP, MASTER_SYMPTOM_MAP)
|
| 735 |
st.session_state.entities = entities
|
| 736 |
|
| 737 |
if entities and (entities.get("alimentos") or entities.get("sintomas")):
|
|
|
|
| 743 |
else:
|
| 744 |
st.error("No se pudieron identificar alimentos o síntomas claros en tu descripción. Intenta ser más específico.")
|
| 745 |
st.session_state.search_results = []
|
| 746 |
+
|
| 747 |
if st.session_state.search_results is not None:
|
| 748 |
results = st.session_state.search_results
|
| 749 |
|
|
|
|
| 778 |
score_col2.metric("Puntos por Síntomas", f"{best_match_data['score']['symptoms']}")
|
| 779 |
score_col3.metric("PUNTUACIÓN TOTAL", f"{best_match_data['score']['total']}", delta="Máxima coincidencia")
|
| 780 |
|
| 781 |
+
# --- POPOVER INTELIGENTE USANDO EL DICCIONARIO MAESTRO ---
|
| 782 |
with col2:
|
| 783 |
st.write("")
|
| 784 |
if foodb_index:
|
| 785 |
with st.popover("🔬 Componentes Moleculares Relevantes"):
|
| 786 |
+
st.info("Compuestos en los alimentos mencionados que podrían estar relacionados con tus síntomas.")
|
| 787 |
|
| 788 |
user_foods_mentioned = st.session_state.entities.get("alimentos", [])
|
| 789 |
+
user_symptoms_es = st.session_state.entities.get("sintomas", [])
|
| 790 |
|
| 791 |
+
if not user_foods_mentioned or not user_symptoms_es:
|
| 792 |
+
st.warning("Se necesita al menos un alimento y un síntoma para el análisis molecular.")
|
| 793 |
else:
|
| 794 |
found_relevant_data = False
|
| 795 |
|
|
|
|
| 799 |
if key_es in alimento_es.lower():
|
| 800 |
search_terms_en.extend(value_en_list)
|
| 801 |
|
| 802 |
+
symptom_keywords_en = []
|
| 803 |
+
for symptom_es in user_symptoms_es:
|
| 804 |
+
if symptom_es in MASTER_SYMPTOM_MAP:
|
| 805 |
+
symptom_keywords_en.extend(MASTER_SYMPTOM_MAP[symptom_es].get('keywords_en', []))
|
| 806 |
+
|
| 807 |
for foodb_key, compounds_data in foodb_index.items():
|
| 808 |
if any(term in foodb_key.lower() for term in set(search_terms_en)):
|
|
|
|
| 809 |
relevant_compounds = []
|
| 810 |
for item in compounds_data:
|
| 811 |
+
effects_en = item.get("effects", [])
|
| 812 |
+
if any(keyword_en in effect.lower() for keyword_en in symptom_keywords_en for effect in effects_en):
|
| 813 |
relevant_compounds.append(item)
|
| 814 |
|
| 815 |
if relevant_compounds:
|
|
|
|
| 818 |
st.subheader(f"Análisis de: {foodb_key.capitalize()}")
|
| 819 |
for item in relevant_compounds[:5]:
|
| 820 |
st.write(f"**Compuesto:** {item['compound']}")
|
| 821 |
+
relevant_effects = [eff for eff in item['effects'] if any(kw in eff.lower() for kw in symptom_keywords_en)]
|
| 822 |
+
st.write(f"**Efectos Relevantes (en inglés):** {', '.join(relevant_effects)}")
|
| 823 |
st.markdown("---")
|
| 824 |
|
| 825 |
if not found_relevant_data:
|
| 826 |
st.warning("No se encontraron compuestos moleculares directamente relacionados con tus síntomas para los alimentos mencionados.")
|
| 827 |
+
|
| 828 |
st.markdown("---")
|
| 829 |
|
| 830 |
with st.container(border=True):
|