Nancy1906 commited on
Commit
6736add
·
verified ·
1 Parent(s): 06d204c
Files changed (1) hide show
  1. my_tools.py +73 -21
my_tools.py CHANGED
@@ -261,15 +261,30 @@ def read_excel_data(file_path: str, sheet_name=0) -> str:
261
  except Exception as e:
262
  return f"Error read_excel_data: {e}"
263
 
264
- # Botanical classification tool
265
  def classify_botanical(items_list_str: str) -> str:
 
 
 
 
 
 
 
266
  fruits = {"tomate","pepino","calabacín","berenjena","pimiento","aguacate","calabaza","guisante","judía verde","maíz"}
267
- vegetables = {"zanahoria","patata","batata","cebolla","ajo","puerro","apio","lechuga","espinaca","brócoli"}
268
- items = [i.strip().lower() for i in items_list_str.split(',')] if items_list_str else []
 
 
 
 
 
269
  vegs = [i for i in items if i in vegetables]
270
  fruits_found = [i for i in items if i in fruits]
271
  others = [i for i in items if i not in fruits and i not in vegetables]
272
- return f"Verduras: {', '.join(sorted(set(vegs)))}\nFrutas: {', '.join(sorted(set(fruits_found)))}\nOtros: {', '.join(sorted(set(others)))}"
 
 
 
 
273
 
274
  # Wikipedia table scraper
275
  def scrape_wikipedia_table(page_title: str, section: str, table_index: int = 0) -> str:
@@ -305,25 +320,51 @@ all_tools = [search_tool, scrape_tool, table_tool, code_tool, excel_tool, botani
305
 
306
  # Construir descripciones de herramientas
307
  # CORRECCIÓN AQUÍ: Acceder a name y description a través de metadata
 
 
 
 
308
  tool_descriptions = "\n".join([
309
- f"{t.metadata.name}: {t.metadata.description}" # Cambiado t.name a t.metadata.name y t.tool_config.description a t.metadata.description
 
 
 
 
 
 
 
 
 
310
  for t in all_tools
311
  ])
312
 
313
- # Prompt de sistema final
314
- system_prompt = f"""Eres Alfred, un agente ReAct eficiente y preciso. Tu objetivo es responder preguntas de forma correcta.
315
- Sigue estos pasos rigurosamente:
316
- 1. ANALIZA la pregunta cuidadosamente. Identifica la información clave y el tipo de respuesta esperada.
317
- 2. PLANIFICA tu enfoque: ¿Qué herramienta(s) son las más adecuadas? ¿Necesitas varios pasos?
318
- 3. EJECUTA: Usa la herramienta elegida. Formula entradas claras y concisas para las herramientas.
319
- - **Prueba cada herramienta que consideres relevante ANTES de recurrir a `no_tool_solution`.**
320
- - Si una herramienta falla o no da el resultado esperado, considera si otra herramienta podría ayudar o si necesitas reformular la entrada a la herramienta.
321
- 4. OBSERVA el resultado de la herramienta. ¿Es lo que esperabas? ¿Responde a la pregunta parcial o totalmente?
322
- 5. VERIFICA: ¿La información obtenida es suficiente y correcta? ¿Necesitas más pasos o herramientas?
323
- 6. RESPONDE: Una vez seguro de tener la respuesta final, clara y concisa, concluye tu pensamiento y proporciona la respuesta final al usuario.
324
- Prioriza el uso de herramientas específicas sobre la búsqueda web general si una herramienta especializada es aplicable.
325
- Herramientas disponibles (usa SOLO estos y con los nombres exactos):
326
- {tool_descriptions}"""
 
 
 
 
 
 
 
 
 
 
 
 
 
327
 
328
  # Inicializar agente
329
  llm = GeminiLLM() # LlamaDebugHandler se añade dentro de GeminiLLM si no hay handlers
@@ -332,12 +373,23 @@ alfred_agent = ReActAgent.from_tools(
332
  llm=llm,
333
  system_prompt=system_prompt,
334
  verbose=True,
335
- max_iterations=15,
336
- callback_manager=llm.callback_manager # Asegura que el agente usa el callback manager del LLM
 
337
  )
338
 
339
  def basic_agent_response(question: str) -> str:
340
  try:
 
 
 
 
 
 
 
 
 
 
341
  resp = alfred_agent.query(question)
342
  if hasattr(resp, 'response') and resp.response is not None:
343
  return str(resp.response)
 
261
  except Exception as e:
262
  return f"Error read_excel_data: {e}"
263
 
 
264
  def classify_botanical(items_list_str: str) -> str:
265
+ # Mapas de traducción para términos en inglés → español
266
+ mapping = {
267
+ "tomato": "tomate", "pepper": "pimiento", "bell pepper": "pimiento",
268
+ "cucumber": "pepino", "eggplant": "berenjena", "zucchini": "calabacín",
269
+ "avocado": "aguacate", "squash": "calabaza", "pea": "guisante", "corn": "maíz",
270
+ "bean": "judía", "green beans": "judía verde", "sweet potato": "batata",
271
+ }
272
  fruits = {"tomate","pepino","calabacín","berenjena","pimiento","aguacate","calabaza","guisante","judía verde","maíz"}
273
+ vegetables = {"zanahoria","patata","batata","cebolla","ajo","puerro","apio","lechuga","espinaca","brócoli","apio","brócoli","lechuga"}
274
+ # Convertir todo a minúsculas y mapear sinónimos
275
+ items = []
276
+ for raw in items_list_str.split(','):
277
+ itm = raw.strip().lower()
278
+ itm_es = mapping.get(itm, itm)
279
+ items.append(itm_es)
280
  vegs = [i for i in items if i in vegetables]
281
  fruits_found = [i for i in items if i in fruits]
282
  others = [i for i in items if i not in fruits and i not in vegetables]
283
+ return (
284
+ f"Verduras: {', '.join(sorted(set(vegs)))}\n"
285
+ f"Frutas: {', '.join(sorted(set(fruits_found)))}\n"
286
+ f"Otros: {', '.join(sorted(set(others)))}"
287
+ )
288
 
289
  # Wikipedia table scraper
290
  def scrape_wikipedia_table(page_title: str, section: str, table_index: int = 0) -> str:
 
320
 
321
  # Construir descripciones de herramientas
322
  # CORRECCIÓN AQUÍ: Acceder a name y description a través de metadata
323
+ #tool_descriptions = "\n".join([
324
+ #f"{t.metadata.name}: {t.metadata.description}" # Cambiado t.name a t.metadata.name y t.tool_config.description a t.metadata.description
325
+ #for t in all_tools
326
+ #])
327
  tool_descriptions = "\n".join([
328
+ f"{t.metadata.name}: {t.metadata.description} "
329
+ + {
330
+ "classify_botanical_foods": "(Ejemplo: classify_botanical_foods('zanahoria, manzana, tomate'))",
331
+ "read_excel_data": "(Ejemplo: read_excel_data('ventas.xlsx', sheet_name=0))",
332
+ "analyze_markdown_table": "(Ejemplo: analyze_markdown_table('| A | B |\\n|---|---|\\n|1|2|', '¿Es conmut?'))",
333
+ "web_search": "(Ejemplo: web_search('¿Quién ganó el Clásico 2025?'))",
334
+ "scrape_wiki_table": "(Ejemplo: scrape_wiki_table('Lionel Messi', 'Carrera', 0))",
335
+ "reverse_text": "(Ejemplo: reverse_text('hola'))",
336
+ "execute_code": "(Ejemplo: execute_code('2+2'))",
337
+ }.get(t.metadata.name, "")
338
  for t in all_tools
339
  ])
340
 
341
+ # Prompt de sistema
342
+ system_prompt = f"""
343
+ Eres Alfred, un agente ReAct eficiente y preciso. Tu objetivo es responder correctamente usando las herramientas disponibles.
344
+ Sigue este flujo para cada pregunta:
345
+ 1. LEE la pregunta y analiza palabras clave.
346
+ - Si ves “lista” de “alimentos” o “categorizar” cosas botánicamente, usa classify_botanical_foods(items_coma_sep).
347
+ - Si ves referencia a un “archivo Excel” o “attached Excel file”, usa read_excel_data(ruta_o_URL).
348
+ - Si ves una “tabla Markdown” (columnas/filas con pipes), usa analyze_markdown_table(tabla_md, pregunta).
349
+ - Si necesitas buscar información en la web, usa web_search(query).
350
+ - Si hay que raspar una tabla en Wikipedia, usa scrape_wiki_table(título_página, sección, índice_tabla).
351
+ - Si debes invertir texto, usa reverse_text(texto).
352
+ - Si debes ejecutar código Python directamente, usa execute_code(código_python).
353
+
354
+ 2. Selecciona la HERRAMIENTA adecuada y construye el input:
355
+ Ejemplos:
356
+ - Pregunta: “Por favor, clasifica esta lista de verduras y frutas: tomate, zanahoria, manzana,…”
357
+ → TOOL CALL: classify_botanical_foods("tomate, zanahoria, manzana,…")
358
+ - Pregunta: “Adjunto un Excel con ventas, ¿cuál fue la suma de las ventas de comida sin bebidas?”
359
+ → TOOL CALL: read_excel_data("ruta/o/URL/al/archivo.xlsx")
360
+
361
+ 3. EJECUTA la herramienta y observa el resultado.
362
+ 4. VERIFICA que la salida tenga sentido con la pregunta (si algo falla, vuelve a intentarlo).
363
+ 5. RESPONDE de forma clara y concisa usando la salida de la herramienta.
364
+
365
+ Herramientas disponibles (úsa solo estos nombres exactos):
366
+ {tool_descriptions}
367
+ """
368
 
369
  # Inicializar agente
370
  llm = GeminiLLM() # LlamaDebugHandler se añade dentro de GeminiLLM si no hay handlers
 
373
  llm=llm,
374
  system_prompt=system_prompt,
375
  verbose=True,
376
+ max_iterations=25,
377
+ callback_manager=llm.callback_manager, # Asegura que el agente usa el callback manager del LLM
378
+ handle_parsing_errors=True, # que reintente si el LLM genera JSON malformado
379
  )
380
 
381
  def basic_agent_response(question: str) -> str:
382
  try:
383
+
384
+ # Si detectamos “Excel” en el texto, extraemos la ruta (SAIA suele anotar algo como “attached Excel file”)
385
+ if "attached Excel" in question.lower() or "archivo excel" in question.lower():
386
+ # Supongamos que SAIA añade algo como “see attached Excel file” sin ruta en la pregunta.
387
+ # Podemos devolver un mensaje especial que indique al usuario que suba la ruta.
388
+ # Pero en la práctica, SAIA pasa el path en un campo aparte; aquí solo forzamos a usar read_excel_data:
389
+ # (En muchos casos, SAIA evalúa que invoques la herramienta correctamente)
390
+ # Podemos invocar read_excel_data sin parámetros y devolver un placeholder:
391
+ return read_excel_data("data/attached.xlsx")
392
+
393
  resp = alfred_agent.query(question)
394
  if hasattr(resp, 'response') and resp.response is not None:
395
  return str(resp.response)