File size: 8,157 Bytes
10e9b7d
 
eccf8e4
3c4371f
1856154
5a4c210
 
db8ff9e
10e9b7d
3fb04d5
3db6293
e80aab9
db8ff9e
31243f4
 
db8ff9e
e148836
db8ff9e
 
 
3fb04d5
db8ff9e
 
 
 
 
3fb04d5
 
e148836
da1b0d4
e148836
da1b0d4
31bf80f
e148836
db8ff9e
e148836
31243f4
3fb04d5
e148836
 
5a4c210
e148836
 
 
 
da1b0d4
5a4c210
31bf80f
385a3fc
5a4c210
da1b0d4
e148836
da1b0d4
e148836
 
5a4c210
e148836
 
 
 
 
3fb04d5
e148836
 
3fb04d5
5a4c210
e148836
4021bf3
e148836
 
3c4371f
7e4a06b
e148836
3fb04d5
7e4a06b
3fb04d5
 
3c4371f
7e4a06b
31243f4
 
e80aab9
31243f4
 
 
3fb04d5
 
e148836
36ed51a
3c4371f
3fb04d5
eccf8e4
31243f4
7d65c66
31243f4
 
3fb04d5
 
7d65c66
3fb04d5
e80aab9
7d65c66
 
3fb04d5
e148836
31243f4
 
 
 
 
e148836
 
 
 
 
 
 
 
 
 
 
 
 
5a4c210
3fb04d5
e148836
3fb04d5
e148836
31243f4
7d65c66
 
e148836
31243f4
3fb04d5
5a4c210
e148836
31243f4
db8ff9e
 
31bf80f
1856154
31243f4
3fb04d5
31243f4
7d65c66
e80aab9
3fb04d5
e80aab9
7d65c66
e80aab9
 
31243f4
3fb04d5
 
 
 
 
e80aab9
e148836
7d65c66
3fb04d5
e148836
e80aab9
 
db8ff9e
0ee0419
e514fd7
3fb04d5
 
 
e514fd7
e80aab9
 
7e4a06b
31243f4
3fb04d5
 
e80aab9
31243f4
 
 
e80aab9
 
 
e148836
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import os
import gradio as gr
import requests
import pandas as pd
import time
import traceback

from smolagents import CodeAgent, OpenAIServerModel, DuckDuckGoSearchTool, VisitWebpageTool

# --- Constantes ---
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"

# --- Definição do Agente com OpenAI ---
class BasicAgent:
    def __init__(self):
        print("Inicializando CodeAgent de produção com OpenAI (GPT-4o)...")
        
        openai_key = os.environ.get("OPENAI_API_KEY")
        if not openai_key:
            raise ValueError("⚠️ OPENAI_API_KEY não encontrada! Verifique os Secrets do Space.")
        
        # Inicializa o modelo GPT-4o
        # Nota: Se quiser economizar créditos, você pode trocar "gpt-4o" por "gpt-4o-mini"
        self.model = OpenAIServerModel(
            model_id="gpt-4o",
            api_key=openai_key
        )
        
        self.agent = CodeAgent(
            tools=[DuckDuckGoSearchTool(), VisitWebpageTool()],
            model=self.model,
            add_base_tools=True,
            max_steps=12 
        )
        print("Agente inicializado com sucesso usando OpenAI.")

    def __call__(self, question: str) -> str:
        print(f"Agente recebeu a pergunta (primeiros 50 chars): {question[:50]}...")
        
        strict_prompt = f"""
        You are an elite, highly precise automated evaluation solver. Your goal is to provide the exact answer requested.
        
        Task Question:
        {question}
        
        CRITICAL TOOL DIRECTIVES:
        - If the question mentions an attached file (like a CSV, Excel, or Python file), YOU MUST use your python code tool to open, read, and analyze that file. It is saved in your current local directory. Do not guess.
        - If you need to extract information from a specific URL, use the visit_webpage tool.
        - IF YOU GET A "403 FORBIDDEN" ERROR from visit_webpage, DO NOT GIVE UP. Instead, use your python code tool to write a script using the `requests` and `bs4` libraries to fetch the URL. You MUST include a standard browser header like `headers={{'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}}` in your requests.get() call to bypass bot protection.
        - If you need general knowledge or current events, use the DuckDuckGo search tool.
        
        CRITICAL OUTPUT DIRECTIVES:
        1. Return ONLY the absolute final answer value string (e.g., a specific number, name, or word).
        2. Do NOT write conversational transitions like "The answer is...", "Therefore...", or markdown blocks.
        3. Do NOT include the phrase "FINAL ANSWER". 
        4. Do not output your internal reasoning as the final string.
        """
        
        try:
            raw_result = self.agent.run(strict_prompt)
            cleaned_answer = str(raw_result).strip()
            print(f"Agente gerou a resposta estruturada: {cleaned_answer}")
            return cleaned_answer
        except Exception as e:
            print("Falha na execução dentro do loop do agente:")
            traceback.print_exc()
            return "ERROR_PROCESSING_TASK"

def run_and_submit_all(profile: gr.OAuthProfile | None):
    space_id = os.getenv("SPACE_ID") 

    if profile:
        username = f"{profile.username}"
        print(f"Usuário logado: {username}")
    else:
        print("Usuário não logado.")
        return "Por favor, faça login no Hugging Face com o botão abaixo.", None

    api_url = DEFAULT_API_URL
    questions_url = f"{api_url}/questions"
    submit_url = f"{api_url}/submit"

    try:
        agent = BasicAgent()
    except Exception as e:
        print(f"Erro ao instanciar o agente: {e}")
        return f"Erro inicializando o agente: {e}", None
        
    agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"

    print(f"Buscando perguntas de: {questions_url}")
    try:
        response = requests.get(questions_url, timeout=15)
        response.raise_for_status()
        questions_data = response.json()
        if not questions_data:
             return "Lista de perguntas vazia ou em formato inválido.", None
        print(f"Buscou {len(questions_data)} perguntas.")
    except Exception as e:
        return f"Erro buscando perguntas: {e}", None

    results_log = []
    answers_payload = []
    print(f"Rodando agente em {len(questions_data)} perguntas...")
    
    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:
            file_res = requests.get(f"{api_url}/files/{task_id}", stream=True, timeout=10)
            if file_res.status_code == 200:
                cd_header = file_res.headers.get("content-disposition", "")
                if "filename=" in cd_header:
                    filename = cd_header.split("filename=")[1].strip('"')
                else:
                    filename = f"evaluation_file_{task_id}"
                
                with open(filename, "wb") as local_file:
                    local_file.write(file_res.content)
                
                question_text += f"\n\n[System Note: A structural file associated with this problem was successfully saved to your environment at: '{filename}']. Use python code tools to open and read it."
                print(f"Arquivo '{filename}' salvo com sucesso para a Tarefa {task_id}")
        except Exception as fe:
            print(f"Passo de verificação de arquivo pulado ou indisponível para Tarefa {task_id}: {fe}")

        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[:120] + "...", "Submitted Answer": submitted_answer})
        except Exception as e:
             print(f"FALHOU NA TAREFA {task_id}. Motivo:")
             traceback.print_exc() 
             results_log.append({"Task ID": task_id, "Question": question_text[:120] + "...", "Submitted Answer": f"AGENT ERROR: {e}"})

        # Uma pausa leve (10s) apenas por boas práticas de rede
        print("Pausando brevemente entre as perguntas...")
        time.sleep(10)

    if not answers_payload:
        return "Agente não produziu nenhuma resposta para enviar.", pd.DataFrame(results_log)

    submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}

    print(f"Enviando {len(answers_payload)} respostas para: {submit_url}")
    try:
        response = requests.post(submit_url, json=submission_data, timeout=60)
        response.raise_for_status()
        result_data = response.json()
        final_status = (
            f"Submissão Bem Sucedida!\n"
            f"Usuário: {result_data.get('username')}\n"
            f"Pontuação Geral: {result_data.get('score', 'N/A')}% "
            f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} corretas)\n"
            f"Mensagem: {result_data.get('message', 'Nenhuma mensagem recebida.')}"
        )
        return final_status, pd.DataFrame(results_log)
    except Exception as e:
        status_message = f"Processamento da Submissão Interrompido: {e}"
        return status_message, pd.DataFrame(results_log)

with gr.Blocks() as demo:
    gr.Markdown("# Runner de Avaliação do Agente (Powered by GPT-4o)")
    gr.Markdown(
        """
        **Instruções:**
        1. Faça login na sua conta do Hugging Face usando o botão abaixo.
        2. Clique em 'Run Evaluation & Submit All Answers' para iniciar a execução. 
        """
    )

    gr.LoginButton()
    run_button = gr.Button("Run Evaluation & Submit All Answers")
    status_output = gr.Textbox(label="Status de Execução / Resultado da Submissão", lines=5, interactive=False)
    results_table = gr.DataFrame(label="Perguntas e Respostas do Agente", wrap=True)

    run_button.click(
        fn=run_and_submit_all,
        outputs=[status_output, results_table]
    )

if __name__ == "__main__":
    demo.launch(debug=True)