import os import re import gradio as gr import requests import pandas as pd from huggingface_hub import InferenceClient # --- Constants --- DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space" # --- Smart Agent HF --- class BasicAgent: def __init__(self): # Usa token de HF si existe (opcional pero recomendable) self.client = InferenceClient( token=os.environ.get("HF_TOKEN") ) print("HF Agent initialized.") def clean_answer(self, answer: str) -> str: answer = answer.strip() # quitar todo lo que no sea necesario answer = answer.split("\n")[0] answer = answer.split(".")[0] answer = answer.split(",")[0] # quitar frases típicas import re answer = re.sub(r"(?i)^.*answer is[:\s]*", "", answer) return answer.strip() def __call__(self, question: str) -> str: print(f"Question: {question[:100]}") q = question.lower() # ✅ fallback SIEMPRE (evita blanks) fallback = "unknown" # ✅ 1. detectar números simples import re nums = re.findall(r"\d+", question) if "how many" in q and nums: return nums[-1] # ✅ 2. matemáticas simples if any(x in q for x in ["sum", "add", "multiply", "divide"]): try: expr = re.findall(r"[0-9\+\-\*\/\.\(\) ]+", question)[0] return str(eval(expr)) except: pass # ✅ 3. llamada HF con protección try: response = self.client.text_generation( model="google/flan-t5-large", prompt=f"Answer with one word or number: {question}", max_new_tokens=20 ) # ✅ controlar respuesta vacía if not response or response.strip() == "": print("Empty HF response → fallback") return fallback answer = response.strip() # limpiar answer = answer.split("\n")[0] answer = answer.split(".")[0] answer = answer.split(",")[0].strip() if answer == "": return fallback return answer except Exception as e: print(f"HF error: {e}") return fallback def run_and_submit_all(profile: gr.OAuthProfile | None): space_id = os.getenv("SPACE_ID") if profile: username = f"{profile.username}" print(f"User logged in: {username}") else: return "Please Login to Hugging Face.", None api_url = DEFAULT_API_URL questions_url = f"{api_url}/questions" submit_url = f"{api_url}/submit" # Crear agente agent = BasicAgent() agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main" # Obtener preguntas try: response = requests.get(questions_url, timeout=15) response.raise_for_status() questions_data = response.json() except Exception as e: return f"Error fetching questions: {e}", None results_log = [] answers_payload = [] # Ejecutar agente for item in questions_data: task_id = item.get("task_id") question_text = item.get("question") if not task_id or question_text is None: continue try: submitted_answer = agent(question_text) answers_payload.append({ "task_id": task_id, "submitted_answer": submitted_answer }) results_log.append({ "Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer }) except Exception as e: results_log.append({ "Task ID": task_id, "Question": question_text, "Submitted Answer": f"ERROR: {e}" }) if not answers_payload: return "No answers generated.", pd.DataFrame(results_log) submission_data = { "username": username.strip(), "agent_code": agent_code, "answers": answers_payload } # Enviar resultados try: response = requests.post(submit_url, json=submission_data, timeout=60) response.raise_for_status() result_data = response.json() final_status = ( f"✅ Submission Successful!\n" f"User: {result_data.get('username')}\n" f"Score: {result_data.get('score')}% " f"({result_data.get('correct_count')}/{result_data.get('total_attempted')})" ) return final_status, pd.DataFrame(results_log) except Exception as e: return f"Submission failed: {e}", pd.DataFrame(results_log) # --- UI --- with gr.Blocks() as demo: gr.Markdown("# HF Free Agent") gr.LoginButton() run_button = gr.Button("Run Evaluation & Submit") status_output = gr.Textbox(label="Result", lines=5) results_table = gr.DataFrame() run_button.click( fn=run_and_submit_all, outputs=[status_output, results_table] ) if __name__ == "__main__": demo.launch(debug=True)