import re from smolagents import CodeAgent, Model from config import authorized_libraries def check_no_refusal(final_answer: str, **kwargs) -> str | None: refusal_phrases = [ "cannot answer", "unable to answer", "i don't know", "no se puede responder", "lo siento", "no tengo acceso", "provide more information" ] answer_lower = str(final_answer).lower() if any(phrase in answer_lower for phrase in refusal_phrases): return "Your answer shows that you were unable to complete your task. Please, try using a different tool or rephrase your search strategy to find the answer. Don't give up yet, you can do it." return None def validate_format_gaia(final_answer: str, **kwargs) -> str | None: """ Valida que la respuesta cumpla estrictamente con el formato de GAIA. """ ans = str(final_answer).strip() # 1. REGLA DE CONCISIÓN (No frases largas) # Si tiene más de 20 palabras, probablemente está explicando algo. GAIA quiere el dato crudo. if len(ans.split()) > 20: return f"Your answer is too long ({len(ans.split())} words). GAIA expects only a number, a short string, or a comma-separated list. Eliminate explanations." # 2. REGLA DE UNIDADES (No $ ni %) if "$" in ans or "%" in ans: return "FORMAT VIOLATION: Do not use units such as '$' or '%'. Returns only the numeric value." # 3. REGLA DE ARTÍCULOS (Para Strings) # Comprobamos si empieza por "The ", "A " o "An " (case insensitive) lower_ans = ans.lower() if lower_ans.startswith(("the ", "a ", "an ")): return "FORMAT VIOLATION: Do not use articles ('The', 'A', 'An') at the beginning of the response. Write only the noun or noun." # 4. REGLA DE NÚMEROS (No usar comas como separador de miles) # Buscamos el patrón específico de dígito + coma + 3 dígitos (ej: 1,000) # Ojo: No bloqueamos listas (10, 20) porque hay un espacio después de la coma normalmente. # Bloqueamos "1,200" pero permitimos "1.200" (decimal) o "1, 2" (lista) if re.search(r'\d,\d{3}', ans): return "FORMAT VIOLATION: Do not use commas to separate thousands (e.g. use '1200' instead of '1,200')." # 5. REGLA DE DIGITOS EN TEXTO (Para Strings) # La docu dice "write the digits in plain text unless specified otherwise". # Esto es difícil de validar automáticamente sin saber la pregunta, # pero podemos avisar si vemos mezcla rara. Por ahora lo dejamos pasar para no ser demasiado estrictos. return None # Todo correcto def create_manager(model: Model, agents: list[CodeAgent], **kwargs) -> CodeAgent: return CodeAgent( model=model, managed_agents=agents, add_base_tools=True, additional_authorized_imports=authorized_libraries, verbosity_level=2, final_answer_checks=[], # validate_format_gaia, check_no_refusal], max_steps=25, **kwargs )