Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -624,7 +624,49 @@ def find_best_matches_hybrid(entities, data):
|
|
| 624 |
if not results: return []
|
| 625 |
return sorted(results, key=lambda x: x['score']['total'], reverse=True)
|
| 626 |
|
|
|
|
| 627 |
@retry(wait=wait_random_exponential(min=1, max=10), stop=stop_after_attempt(3))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 628 |
def generate_detailed_analysis(query, match):
|
| 629 |
if not model: return "Error: El modelo de IA no está disponible."
|
| 630 |
if not match or not isinstance(match, dict):
|
|
@@ -812,13 +854,14 @@ if st.session_state.search_results is not None:
|
|
| 812 |
score_col3.metric("PUNTUACIÓN TOTAL", f"{best_match_data['score']['total']}", delta="Máxima coincidencia")
|
| 813 |
|
| 814 |
with col2_expander:
|
|
|
|
| 815 |
st.write("")
|
| 816 |
if foodb_index:
|
| 817 |
with st.popover("🔬 Componentes Moleculares Relevantes"):
|
| 818 |
|
| 819 |
REMEDIAL_PREFIXES = ("anti", "preventive", "remedy", "treatment", "inhibitor")
|
| 820 |
|
| 821 |
-
st.info("Compuestos en
|
| 822 |
|
| 823 |
user_foods_mentioned = st.session_state.entities.get("alimentos", [])
|
| 824 |
user_symptoms_es = st.session_state.entities.get("sintomas", [])
|
|
@@ -826,67 +869,57 @@ if st.session_state.search_results is not None:
|
|
| 826 |
if not user_foods_mentioned or not user_symptoms_es:
|
| 827 |
st.warning("Se necesita al menos un alimento y un síntoma para el análisis molecular.")
|
| 828 |
else:
|
| 829 |
-
|
| 830 |
-
|
| 831 |
-
|
| 832 |
-
|
| 833 |
-
|
| 834 |
-
|
| 835 |
-
|
| 836 |
-
|
| 837 |
-
|
| 838 |
-
|
| 839 |
-
|
| 840 |
-
|
| 841 |
-
|
| 842 |
-
|
| 843 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 844 |
|
| 845 |
-
|
| 846 |
-
|
| 847 |
-
|
| 848 |
-
|
| 849 |
-
|
| 850 |
-
|
| 851 |
-
|
| 852 |
-
|
| 853 |
-
|
| 854 |
-
|
| 855 |
-
|
| 856 |
-
|
| 857 |
-
|
| 858 |
-
|
| 859 |
-
|
| 860 |
-
|
| 861 |
-
|
| 862 |
-
|
| 863 |
-
|
| 864 |
-
|
| 865 |
-
|
| 866 |
-
if causative_compounds or remedial_compounds:
|
| 867 |
-
found_any_data = True
|
| 868 |
-
with st.container(border=True):
|
| 869 |
-
st.subheader(f"Análisis de: {foodb_key.capitalize()}")
|
| 870 |
-
|
| 871 |
-
# Mostrar compuestos causantes primero
|
| 872 |
-
if causative_compounds:
|
| 873 |
-
st.markdown("###### 🔬 Posibles Compuestos Causantes:")
|
| 874 |
-
for item in causative_compounds[:3]:
|
| 875 |
-
st.write(f"**Compuesto:** {item['compound']}")
|
| 876 |
-
relevant_effects = [eff for eff in item['effects'] if any(kw in eff.lower() and not eff.lower().startswith(REMEDIAL_PREFIXES) for kw in symptom_keywords_en)]
|
| 877 |
-
st.write(f"**Efectos Relevantes:** {', '.join(relevant_effects)}")
|
| 878 |
-
|
| 879 |
-
# Mostrar compuestos remediales después
|
| 880 |
-
if remedial_compounds:
|
| 881 |
-
st.markdown("###### 💊 Compuestos con Efectos Potencialmente Beneficiosos:")
|
| 882 |
-
for item in remedial_compounds[:3]:
|
| 883 |
-
st.write(f"**Compuesto:** {item['compound']}")
|
| 884 |
-
relevant_effects = [eff for eff in item['effects'] if any(kw in eff.lower() and eff.lower().startswith(REMEDIAL_PREFIXES) for kw in symptom_keywords_en)]
|
| 885 |
-
st.write(f"**Efectos Relevantes:** {', '.join(relevant_effects)}")
|
| 886 |
-
st.markdown("---")
|
| 887 |
-
|
| 888 |
-
if not found_any_data:
|
| 889 |
-
st.warning("No se encontraron compuestos moleculares directamente relacionados con tus síntomas para los alimentos mencionados.")
|
| 890 |
|
| 891 |
st.markdown("---")
|
| 892 |
|
|
|
|
| 624 |
if not results: return []
|
| 625 |
return sorted(results, key=lambda x: x['score']['total'], reverse=True)
|
| 626 |
|
| 627 |
+
|
| 628 |
@retry(wait=wait_random_exponential(min=1, max=10), stop=stop_after_attempt(3))
|
| 629 |
+
|
| 630 |
+
def find_best_foodb_match(user_foods_es, foodb_index_keys, food_name_map):
|
| 631 |
+
"""
|
| 632 |
+
Encuentra la mejor y única coincidencia de alimento en la base de datos de FoodB.
|
| 633 |
+
"""
|
| 634 |
+
if not user_foods_es:
|
| 635 |
+
return None
|
| 636 |
+
|
| 637 |
+
# 1. Traducir y encontrar el término más específico (el más largo)
|
| 638 |
+
search_terms_en = set()
|
| 639 |
+
for food_es in user_foods_es:
|
| 640 |
+
for key_es, value_en_list in food_name_map.items():
|
| 641 |
+
if key_es in food_es.lower():
|
| 642 |
+
search_terms_en.update(value_en_list)
|
| 643 |
+
|
| 644 |
+
if not search_terms_en:
|
| 645 |
+
return None
|
| 646 |
+
|
| 647 |
+
sorted_terms = sorted(list(search_terms_en), key=len, reverse=True)
|
| 648 |
+
|
| 649 |
+
# 2. Búsqueda por prioridades
|
| 650 |
+
# Prioridad 1: Coincidencia perfecta
|
| 651 |
+
for term in sorted_terms:
|
| 652 |
+
for key in foodb_index_keys:
|
| 653 |
+
if term == key.lower():
|
| 654 |
+
return key
|
| 655 |
+
|
| 656 |
+
# Prioridad 2: Coincidencia de inicio de palabra
|
| 657 |
+
for term in sorted_terms:
|
| 658 |
+
for key in foodb_index_keys:
|
| 659 |
+
if key.lower().startswith(term):
|
| 660 |
+
return key
|
| 661 |
+
|
| 662 |
+
# Prioridad 3: Coincidencia general (contiene)
|
| 663 |
+
for term in sorted_terms:
|
| 664 |
+
for key in foodb_index_keys:
|
| 665 |
+
if term in key.lower():
|
| 666 |
+
return key
|
| 667 |
+
|
| 668 |
+
return None # No se encontró ninguna coincidencia
|
| 669 |
+
|
| 670 |
def generate_detailed_analysis(query, match):
|
| 671 |
if not model: return "Error: El modelo de IA no está disponible."
|
| 672 |
if not match or not isinstance(match, dict):
|
|
|
|
| 854 |
score_col3.metric("PUNTUACIÓN TOTAL", f"{best_match_data['score']['total']}", delta="Máxima coincidencia")
|
| 855 |
|
| 856 |
with col2_expander:
|
| 857 |
+
|
| 858 |
st.write("")
|
| 859 |
if foodb_index:
|
| 860 |
with st.popover("🔬 Componentes Moleculares Relevantes"):
|
| 861 |
|
| 862 |
REMEDIAL_PREFIXES = ("anti", "preventive", "remedy", "treatment", "inhibitor")
|
| 863 |
|
| 864 |
+
st.info("Compuestos en el alimento más relevante que podrían estar relacionados con tus síntomas.")
|
| 865 |
|
| 866 |
user_foods_mentioned = st.session_state.entities.get("alimentos", [])
|
| 867 |
user_symptoms_es = st.session_state.entities.get("sintomas", [])
|
|
|
|
| 869 |
if not user_foods_mentioned or not user_symptoms_es:
|
| 870 |
st.warning("Se necesita al menos un alimento y un síntoma para el análisis molecular.")
|
| 871 |
else:
|
| 872 |
+
# 1. Encontrar la mejor y única coincidencia de alimento
|
| 873 |
+
best_food_match_key = find_best_foodb_match(user_foods_mentioned, foodb_index.keys(), FOOD_NAME_TO_FOODB_KEY)
|
| 874 |
+
|
| 875 |
+
if not best_food_match_key:
|
| 876 |
+
st.warning("No se encontraron datos moleculares para los alimentos específicos mencionados.")
|
| 877 |
+
else:
|
| 878 |
+
# 2. Realizar el análisis solo en la mejor coincidencia
|
| 879 |
+
st.subheader(f"Análisis de: {best_food_match_key.capitalize()}")
|
| 880 |
+
|
| 881 |
+
compounds_data = foodb_index[best_food_match_key]
|
| 882 |
+
symptom_keywords_en = []
|
| 883 |
+
for symptom_es in user_symptoms_es:
|
| 884 |
+
if symptom_es in MASTER_SYMPTOM_MAP:
|
| 885 |
+
symptom_keywords_en.extend(MASTER_SYMPTOM_MAP[symptom_es].get('keywords_en', []))
|
| 886 |
+
|
| 887 |
+
causative_compounds = []
|
| 888 |
+
remedial_compounds = []
|
| 889 |
+
|
| 890 |
+
for item in compounds_data:
|
| 891 |
+
effects_en = item.get("effects", [])
|
| 892 |
+
is_causative = False
|
| 893 |
+
is_remedial = False
|
| 894 |
+
|
| 895 |
+
for effect in effects_en:
|
| 896 |
+
if any(keyword in effect.lower() for keyword in symptom_keywords_en):
|
| 897 |
+
if effect.lower().startswith(REMEDIAL_PREFIXES):
|
| 898 |
+
is_remedial = True
|
| 899 |
+
else:
|
| 900 |
+
is_causative = True
|
| 901 |
|
| 902 |
+
if is_causative:
|
| 903 |
+
causative_compounds.append(item)
|
| 904 |
+
elif is_remedial:
|
| 905 |
+
remedial_compounds.append(item)
|
| 906 |
+
|
| 907 |
+
# 3. Mostrar los resultados de forma priorizada
|
| 908 |
+
if causative_compounds:
|
| 909 |
+
st.markdown("###### 🔬 Posibles Compuestos Desencadenantes:")
|
| 910 |
+
for item in causative_compounds[:5]:
|
| 911 |
+
st.write(f"**Compuesto:** {item['compound']}")
|
| 912 |
+
relevant_effects = [eff for eff in item['effects'] if any(kw in eff.lower() and not eff.lower().startswith(REMEDIAL_PREFIXES) for kw in symptom_keywords_en)]
|
| 913 |
+
st.write(f"**Efectos Relevantes:** {', '.join(relevant_effects)}")
|
| 914 |
+
elif remedial_compounds:
|
| 915 |
+
st.markdown("###### 💊 Compuestos con Efectos Potencialmente Beneficiosos:")
|
| 916 |
+
st.caption("No se encontraron compuestos desencadenantes directos. Sin embargo, se encontraron estos compuestos con efectos potencialmente positivos.")
|
| 917 |
+
for item in remedial_compounds[:5]:
|
| 918 |
+
st.write(f"**Compuesto:** {item['compound']}")
|
| 919 |
+
relevant_effects = [eff for eff in item['effects'] if any(kw in eff.lower() and eff.lower().startswith(REMEDIAL_PREFIXES) for kw in symptom_keywords_en)]
|
| 920 |
+
st.write(f"**Efectos Relevantes:** {', '.join(relevant_effects)}")
|
| 921 |
+
else:
|
| 922 |
+
st.write("No se encontraron compuestos relevantes para tus síntomas en este alimento.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 923 |
|
| 924 |
st.markdown("---")
|
| 925 |
|