JairoCesar commited on
Commit
4471cba
verified
1 Parent(s): e02bebc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +24 -15
app.py CHANGED
@@ -270,14 +270,21 @@ def sanitize_text(text):
270
  def extract_and_infer_with_gemini(query, condiciones):
271
  if not model: return None
272
  condiciones_str = "\n".join([f"- {c}" for c in condiciones])
 
 
273
  system_prompt = f"""
274
  Eres un asistente de triaje cl铆nico experto. Tu tarea es analizar la consulta de un usuario y extraer tres tipos de informaci贸n:
275
  1. `alimentos`: Lista de alimentos consumidos.
276
- 2. `sintomas`: Lista de s铆ntomas descritos, normalizados a un t茅rmino com煤n.
277
- 3. `condicion_probable`: Tu mejor inferencia sobre cu谩l de las siguientes condiciones podr铆a explicar los s铆ntomas. **Intenta siempre proporcionar una, incluso si la confianza es moderada.**
 
278
  LISTA DE CONDICIONES POSIBLES:
279
  {condiciones_str}
280
- Devuelve la respuesta 脷NICAMENTE en formato JSON.
 
 
 
 
281
  Consulta: "{query}"
282
  """
283
  try:
@@ -292,46 +299,43 @@ def extract_and_infer_with_gemini(query, condiciones):
292
  logger.error(f"Error en la extracci贸n/inferencia con Gemini: {e}")
293
  st.error(f"Hubo un problema al interpretar tu consulta con la IA.")
294
  return None
 
295
  def find_best_matches_hybrid(entities, data):
296
  if not entities or not data: return []
297
 
298
- # 1. Extracci贸n de entidades del usuario (sin cambios)
299
  user_symptoms = set(sanitize_text(s) for s in entities.get("sintomas", []))
300
  user_foods = set(sanitize_text(f) for f in entities.get("alimentos", []))
301
  inferred_condition_raw = sanitize_text(entities.get("condicion_probable", ""))
302
 
303
- # 2. Obtenci贸n de t茅rminos de b煤squeda (sin cambios)
304
  candidate_terms = set(user_foods)
305
  for food in user_foods:
306
  food_sanitized = sanitize_text(food)
307
  if food_sanitized in FOOD_TO_COMPOUND_MAP:
308
  candidate_terms.update(c.lower() for c in FOOD_TO_COMPOUND_MAP[food_sanitized])
 
 
 
309
 
310
- # 3. L贸gica de puntuaci贸n CORREGIDA Y ROBUSTA
311
  results = []
312
  for entry in data:
313
- # --- PASO CLAVE: FILTRO OBLIGATORIO POR ALIMENTO ---
314
  entry_compounds_text = sanitize_text(entry.get("compuesto_alimento", ""))
315
  food_match = any(term in entry_compounds_text for term in candidate_terms)
316
 
317
- # Si NO hay conexi贸n entre la comida del usuario y la condici贸n, se ignora por completo.
318
  if not food_match:
319
  continue
320
 
321
- # --- Si pasa el filtro, procedemos a puntuar ---
322
- score_details = {'condition': 0, 'food': 15, 'symptoms': 0, 'total': 0} # Damos puntos de comida por defecto
323
 
324
- # Bono de Condici贸n: Si la IA la sugiri贸, recibe un gran bono.
325
  if inferred_condition_raw:
326
  entry_condition_sanitized = sanitize_text(entry.get("condicion_asociada", ""))
327
  is_match = (entry_condition_sanitized == inferred_condition_raw)
328
  if not is_match and entry_condition_sanitized in CONDITION_SYNONYMS:
329
- if inferred_condition_raw in [sanitize_text(s) for s in CONDITION_SYNONYMS[entry_condition_sanitized]]:
330
  is_match = True
331
  if is_match:
332
  score_details['condition'] = 100
333
 
334
- # Puntuaci贸n por S铆ntomas
335
  entry_symptoms_keys = set(sanitize_text(s) for s in entry.get("sintomas_clave", []))
336
  symptom_score = 0
337
  matched_symptoms = []
@@ -343,8 +347,9 @@ def find_best_matches_hybrid(entities, data):
343
  break
344
  score_details['symptoms'] = symptom_score
345
 
346
- # C谩lculo final
347
- total_score = sum(score_details.values())
 
348
 
349
  results.append({
350
  'entry': entry,
@@ -354,6 +359,10 @@ def find_best_matches_hybrid(entities, data):
354
 
355
  if not results: return []
356
 
 
 
 
 
357
  # 4. Ordenar y devolver (sin cambios)
358
  sorted_results = sorted(results, key=lambda x: x['score']['total'], reverse=True)
359
  return sorted_results
 
270
  def extract_and_infer_with_gemini(query, condiciones):
271
  if not model: return None
272
  condiciones_str = "\n".join([f"- {c}" for c in condiciones])
273
+
274
+ # Prompt mejorado para ser m谩s estricto
275
  system_prompt = f"""
276
  Eres un asistente de triaje cl铆nico experto. Tu tarea es analizar la consulta de un usuario y extraer tres tipos de informaci贸n:
277
  1. `alimentos`: Lista de alimentos consumidos.
278
+ 2. `sintomas`: Lista de s铆ntomas descritos.
279
+ 3. `condicion_probable`: Tu mejor inferencia sobre cu谩l de las siguientes condiciones podr铆a explicar la **conexi贸n directa entre los alimentos y los s铆ntomas mencionados**. Debes elegir la opci贸n m谩s l贸gica de la lista. Si ninguna encaja bien, puedes dejarlo en blanco.
280
+
281
  LISTA DE CONDICIONES POSIBLES:
282
  {condiciones_str}
283
+
284
+ Devuelve la respuesta 脷NICAMENTE en formato JSON estricto.
285
+
286
+ Ejemplo: si el usuario dice "vino tinto y dolor de cabeza", la condici贸n probable es "Histaminosis / Intolerancia a la Histamina." o "Migra帽a.", no "Intolerancia a la Lactosa.".
287
+
288
  Consulta: "{query}"
289
  """
290
  try:
 
299
  logger.error(f"Error en la extracci贸n/inferencia con Gemini: {e}")
300
  st.error(f"Hubo un problema al interpretar tu consulta con la IA.")
301
  return None
302
+
303
  def find_best_matches_hybrid(entities, data):
304
  if not entities or not data: return []
305
 
 
306
  user_symptoms = set(sanitize_text(s) for s in entities.get("sintomas", []))
307
  user_foods = set(sanitize_text(f) for f in entities.get("alimentos", []))
308
  inferred_condition_raw = sanitize_text(entities.get("condicion_probable", ""))
309
 
 
310
  candidate_terms = set(user_foods)
311
  for food in user_foods:
312
  food_sanitized = sanitize_text(food)
313
  if food_sanitized in FOOD_TO_COMPOUND_MAP:
314
  candidate_terms.update(c.lower() for c in FOOD_TO_COMPOUND_MAP[food_sanitized])
315
+ # A帽adir tambi茅n los componentes del vino directamente para ser m谩s robusto
316
+ if food_sanitized in ["vino", "vino tinto", "vino rojo"]:
317
+ candidate_terms.update(["histamina", "tiramina", "sulfitos"])
318
 
 
319
  results = []
320
  for entry in data:
 
321
  entry_compounds_text = sanitize_text(entry.get("compuesto_alimento", ""))
322
  food_match = any(term in entry_compounds_text for term in candidate_terms)
323
 
 
324
  if not food_match:
325
  continue
326
 
327
+ # Inicializamos el diccionario SIN el total
328
+ score_details = {'condition': 0, 'food': 15, 'symptoms': 0}
329
 
 
330
  if inferred_condition_raw:
331
  entry_condition_sanitized = sanitize_text(entry.get("condicion_asociada", ""))
332
  is_match = (entry_condition_sanitized == inferred_condition_raw)
333
  if not is_match and entry_condition_sanitized in CONDITION_SYNONYMS:
334
+ if inferred_condition_raw in [sanitize_text(s) for s in CONDITION_SYNONYMS.get(entry_condition_sanitized, [])]:
335
  is_match = True
336
  if is_match:
337
  score_details['condition'] = 100
338
 
 
339
  entry_symptoms_keys = set(sanitize_text(s) for s in entry.get("sintomas_clave", []))
340
  symptom_score = 0
341
  matched_symptoms = []
 
347
  break
348
  score_details['symptoms'] = symptom_score
349
 
350
+ # --- L脥NEA CORREGIDA Y CR脥TICA ---
351
+ # Calculamos la puntuaci贸n total y la a帽adimos al diccionario
352
+ score_details['total'] = score_details['condition'] + score_details['food'] + score_details['symptoms']
353
 
354
  results.append({
355
  'entry': entry,
 
359
 
360
  if not results: return []
361
 
362
+ # Ahora el ordenamiento funcionar谩 correctamente porque 'total' tiene el valor correcto
363
+ sorted_results = sorted(results, key=lambda x: x['score']['total'], reverse=True)
364
+ return sorted_results
365
+
366
  # 4. Ordenar y devolver (sin cambios)
367
  sorted_results = sorted(results, key=lambda x: x['score']['total'], reverse=True)
368
  return sorted_results