JairoCesar commited on
Commit
767e492
·
verified ·
1 Parent(s): f314660

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -93
app.py CHANGED
@@ -684,15 +684,13 @@ def find_best_matches_hybrid(entities, data):
684
 
685
  @retry(wait=wait_random_exponential(min=1, max=10), stop=stop_after_attempt(3))
686
 
687
- def find_best_foodb_match(user_foods_es, foodb_index_keys, food_name_map):
688
  """
689
- Encuentra la mejor y única coincidencia de alimento en la base de datos de FoodB
690
- utilizando un algoritmo de "embudo de especificidad".
691
  """
692
  if not user_foods_es:
693
- return None
694
 
695
- # 1. Traducir y ordenar los términos de búsqueda del más al menos específico
696
  search_terms_en = set()
697
  for food_es in user_foods_es:
698
  for key_es, value_en_list in food_name_map.items():
@@ -700,35 +698,28 @@ def find_best_foodb_match(user_foods_es, foodb_index_keys, food_name_map):
700
  search_terms_en.update(value_en_list)
701
 
702
  if not search_terms_en:
703
- return None
704
 
705
  sorted_terms = sorted(list(search_terms_en), key=len, reverse=True)
706
-
707
- # 2. Búsqueda por prioridades (Embudo de Especificidad)
708
 
709
- # Prioridad 1: Coincidencia Perfecta
 
 
710
  for term in sorted_terms:
 
711
  for key in foodb_index_keys:
712
- if term == key.lower():
713
- logger.info(f"Coincidencia Perfecta encontrada para '{term}': {key}")
714
- return key
715
-
716
- # Prioridad 2: Coincidencia de Inicio de Palabra
717
- for term in sorted_terms:
718
  for key in foodb_index_keys:
719
- if key.lower().startswith(term):
720
- logger.info(f"Coincidencia de Inicio encontrada para '{term}': {key}")
721
- return key
722
-
723
- # Prioridad 3: Coincidencia General (contiene)
724
- for term in sorted_terms:
725
  for key in foodb_index_keys:
726
- if term in key.lower():
727
- logger.info(f"Coincidencia General encontrada para '{term}': {key}")
728
- return key
729
-
730
- logger.warning(f"No se encontró ninguna coincidencia molecular para los términos: {sorted_terms}")
731
- return None # No se encontró ninguna coincidencia
732
 
733
  def generate_detailed_analysis(query, match):
734
  if not model: return "Error: El modelo de IA no está disponible."
@@ -920,81 +911,49 @@ if st.session_state.search_results is not None:
920
 
921
  st.write("")
922
  if foodb_index:
923
- with st.popover("🔬 Componentes Moleculares Relevantes"):
924
 
925
- REMEDIAL_PREFIXES = ("anti", "preventive", "remedy", "treatment", "inhibitor", "anxiolytic", "analgesic")
926
-
927
- st.info("Compuestos en el alimento más relevante que podrían estar relacionados con tus síntomas.")
928
 
929
  user_foods_mentioned = st.session_state.entities.get("alimentos", [])
930
- user_symptoms_es = st.session_state.entities.get("sintomas", [])
931
 
932
- if not user_foods_mentioned or not user_symptoms_es:
933
- st.warning("Se necesita al menos un alimento y un síntoma para el análisis molecular.")
934
  else:
935
- best_food_match_key = find_best_foodb_match(user_foods_mentioned, foodb_index.keys(), FOOD_NAME_TO_FOODB_KEY)
 
 
 
 
 
 
936
 
937
- if not best_food_match_key:
938
  st.warning("No se encontraron datos moleculares para los alimentos específicos mencionados.")
939
  else:
940
- st.subheader(f"Análisis de: {best_food_match_key.capitalize()}")
941
-
942
- compounds_data = foodb_index[best_food_match_key]
943
- symptom_keywords_en = {kw for sym in user_symptoms_es if sym in MASTER_SYMPTOM_MAP for kw in MASTER_SYMPTOM_MAP[sym].get('keywords_en', [])}
944
-
945
- causative_compounds = []
946
- remedial_compounds = []
947
-
948
- for item in compounds_data:
949
- compound_name = item['compound']
950
- effects_en = item.get("effects", [])
951
 
952
- # --- LÓGICA DE PRIORIDAD ---
953
- # 1. ¿Es un desencadenante conocido para ESTE síntoma?
954
- is_known_trigger = False
955
- if compound_name in KNOWN_TRIGGERS_MAP:
956
- if any(symptom in KNOWN_TRIGGERS_MAP[compound_name] for symptom in user_symptoms_es):
957
- causative_compounds.append(item)
958
- is_known_trigger = True
959
-
960
- if is_known_trigger:
961
- continue # Si ya es un culpable, no lo analizamos más
962
-
963
- # 2. Si no, analizar efectos para causas o remedios
964
- is_causative = False
965
- is_remedial = False
966
- for effect in effects_en:
967
- if any(keyword in effect.lower() for keyword in symptom_keywords_en):
968
- if effect.lower().startswith(REMEDIAL_PREFIXES):
969
- is_remedial = True
970
- else:
971
- is_causative = True
972
-
973
- if is_causative:
974
- causative_compounds.append(item)
975
- elif is_remedial:
976
- remedial_compounds.append(item)
977
-
978
- # 3. Mostrar los resultados de forma priorizada
979
- if causative_compounds:
980
- st.markdown("###### 🔬 Posibles Compuestos Desencadenantes:")
981
- for item in causative_compounds[:5]:
982
- st.write(f"**Compuesto:** {item['compound']}")
983
- # Mostramos por qué es un desencadenante conocido, o los efectos relevantes
984
- if item['compound'] in KNOWN_TRIGGERS_MAP:
985
- st.write(f"**Efectos Relevantes:** Desencadenante conocido de {', '.join([s for s in user_symptoms_es if s in KNOWN_TRIGGERS_MAP[item['compound']]])}")
986
- else:
987
- 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)]
988
- st.write(f"**Efectos Relevantes:** {', '.join(relevant_effects)}")
989
- elif remedial_compounds:
990
- st.markdown("###### 💊 Compuestos con Efectos Potencialmente Beneficiosos:")
991
- st.caption("No se encontraron compuestos desencadenantes directos en la base de datos.")
992
- for item in remedial_compounds[:5]:
993
- st.write(f"**Compuesto:** {item['compound']}")
994
- 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)]
995
- st.write(f"**Efectos Relevantes:** {', '.join(relevant_effects)}")
996
- else:
997
- st.write("No se encontraron compuestos relevantes para tus síntomas en este alimento.")
998
 
999
  st.markdown("---")
1000
 
 
684
 
685
  @retry(wait=wait_random_exponential(min=1, max=10), stop=stop_after_attempt(3))
686
 
687
+ def find_best_foodb_matches(user_foods_es, foodb_index_keys, food_name_map, limit=3):
688
  """
689
+ Encuentra una lista de las mejores coincidencias de alimentos en FoodB, priorizando la especificidad.
 
690
  """
691
  if not user_foods_es:
692
+ return []
693
 
 
694
  search_terms_en = set()
695
  for food_es in user_foods_es:
696
  for key_es, value_en_list in food_name_map.items():
 
698
  search_terms_en.update(value_en_list)
699
 
700
  if not search_terms_en:
701
+ return []
702
 
703
  sorted_terms = sorted(list(search_terms_en), key=len, reverse=True)
 
 
704
 
705
+ found_matches = []
706
+
707
+ # Búsqueda por prioridades
708
  for term in sorted_terms:
709
+ # Prioridad 1: Coincidencia perfecta
710
  for key in foodb_index_keys:
711
+ if term == key.lower() and key not in found_matches:
712
+ found_matches.append(key)
713
+ # Prioridad 2: Coincidencia de inicio
 
 
 
714
  for key in foodb_index_keys:
715
+ if key.lower().startswith(term) and key not in found_matches:
716
+ found_matches.append(key)
717
+ # Prioridad 3: Coincidencia general
 
 
 
718
  for key in foodb_index_keys:
719
+ if term in key.lower() and key not in found_matches:
720
+ found_matches.append(key)
721
+
722
+ return found_matches[:limit]
 
 
723
 
724
  def generate_detailed_analysis(query, match):
725
  if not model: return "Error: El modelo de IA no está disponible."
 
911
 
912
  st.write("")
913
  if foodb_index:
914
+ with st.popover("🔬 Componentes Moleculares del Diagnóstico"):
915
 
916
+ st.info("Análisis de los compuestos en los alimentos mencionados que están directamente implicados en el diagnóstico principal.")
 
 
917
 
918
  user_foods_mentioned = st.session_state.entities.get("alimentos", [])
 
919
 
920
+ if not user_foods_mentioned:
921
+ st.warning("No se identificó un alimento específico para buscar.")
922
  else:
923
+ # 1. IDENTIFICAR LOS COMPUESTOS OBJETIVO DEL DIAGNÓSTICO
924
+ target_compounds_text = best_match.get("compuesto_alimento", "").lower()
925
+ # Extraer palabras clave del texto (ej. "purinas", "histamina")
926
+ target_keywords = set(re.findall(r'\b\w+\b', re.sub(r'\(.*?\)', '', target_compounds_text)))
927
+
928
+ # 2. ENCONTRAR LOS ALIMENTOS MÁS RELEVANTES
929
+ best_food_matches = find_best_foodb_matches(user_foods_mentioned, foodb_index.keys(), FOOD_NAME_TO_FOODB_KEY)
930
 
931
+ if not best_food_matches:
932
  st.warning("No se encontraron datos moleculares para los alimentos específicos mencionados.")
933
  else:
934
+ found_any_data = False
935
+ for food_key in best_food_matches:
936
+ compounds_data = foodb_index.get(food_key, [])
 
 
 
 
 
 
 
 
937
 
938
+ # 3. BUSCAR LOS COMPUESTOS OBJETIVO EN CADA ALIMENTO
939
+ relevant_compounds = []
940
+ for item in compounds_data:
941
+ compound_name_lower = item['compound'].lower()
942
+ # Comprobar si el nombre del compuesto está relacionado con los objetivos
943
+ if any(keyword in compound_name_lower for keyword in target_keywords):
944
+ relevant_compounds.append(item)
945
+
946
+ if relevant_compounds:
947
+ found_any_data = True
948
+ with st.container(border=True):
949
+ st.subheader(f"Análisis de: {food_key.capitalize()}")
950
+ st.markdown("###### 🔬 Compuestos Relevantes para el Diagnóstico:")
951
+ for item in relevant_compounds[:5]:
952
+ st.write(f"**Compuesto:** {item['compound']}")
953
+ st.caption(f"Este compuesto está directamente relacionado con '{best_match.get('condicion_asociada')}'.")
954
+
955
+ if not found_any_data:
956
+ st.warning(f"No se encontraron los compuestos específicos de '{best_match.get('condicion_asociada')}' en los alimentos analizados en la base de datos FoodB.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
957
 
958
  st.markdown("---")
959