Nathann / app.py
MasterOfHugs's picture
Update app.py
6d34e9e verified
import os
import gradio as gr
import requests
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
import pandas as pd
import json
# --- Constants ---
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
# --- Initialize Model ---
model_name = "mosaicml/mpt-7b-chat"
tokenizer = AutoTokenizer.from_pretrained(model_name)
# Offload folder pour éviter crash GPU
offload_folder = "offload"
os.makedirs(offload_folder, exist_ok=True)
model = AutoModelForCausalLM.from_pretrained(
model_name,
device_map="auto",
offload_folder=offload_folder,
torch_dtype=torch.float16,
)
# --- Define a simple tool for demonstration ---
def AddTwoNumbers(a: int, b: int) -> int:
return a + b
# --- Reasoning Agent Definition ---
class ReasoningAgent:
def __init__(self):
print("ReasoningAgent initialized.")
self.tools_description = (
"You have one tool available:\n"
"- AddTwoNumbers(a, b): returns the sum of two integers a and b.\n"
"Use this tool if you need to add numbers."
)
def __call__(self, question: str) -> str:
print(f"\n=== New Question ===\n{question}\n")
# Prompt structuré
prompt = f"""
You are an AI reasoning agent.
{self.tools_description}
Answer the question in the following JSON format:
{{
"thought": "Describe your reasoning step by step",
"action": "Action you decide to take (like calling a tool) or 'None' if no action",
"observation": "Result of the action (or empty if no action)",
"answer": "Final answer to the user"
}}
Question: {question}
"""
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
output = model.generate(**inputs, max_new_tokens=300)
text_output = tokenizer.decode(output[0], skip_special_tokens=True)
print(f"Raw model output:\n{text_output[:1000]}...\n") # on affiche un gros morceau du texte
# Parser le JSON
try:
parsed = json.loads(text_output)
except json.JSONDecodeError as e:
print(f"⚠️ JSON decode error: {e}")
parsed = {"thought": "", "action": "None", "observation": "", "answer": text_output}
thought = parsed.get("thought", "")
action = parsed.get("action", "None")
observation = parsed.get("observation", "")
answer = parsed.get("answer", "No answer returned.")
# Exécution de l'outil si nécessaire
if action.startswith("AddTwoNumbers"):
try:
numbers = action[action.find("(")+1:action.find(")")].split(",")
a, b = int(numbers[0].strip()), int(numbers[1].strip())
observation = AddTwoNumbers(a, b)
parsed["observation"] = str(observation)
print(f"✅ Tool executed: {action} -> {observation}")
except Exception as e:
observation = f"⚠️ Error executing tool: {e}"
parsed["observation"] = observation
print(observation)
# Print du raisonnement actuel
print(f"💭 Thought: {thought}")
print(f"🔧 Action: {action}")
print(f"👀 Observation: {observation}")
print(f"📝 Answer: {answer}\n{'-'*50}\n")
return answer
# --- Main Evaluation & Submission Function ---
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:
print("User not logged in.")
return "Please Login to Hugging Face with the button.", None
questions_url = f"{DEFAULT_API_URL}/questions"
submit_url = f"{DEFAULT_API_URL}/submit"
# Instantiate Agent
try:
agent = ReasoningAgent()
except Exception as e:
return f"Error initializing agent: {e}", None
agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
# Fetch Questions
try:
response = requests.get(questions_url, timeout=15)
response.raise_for_status()
questions_data = response.json()
if not questions_data:
return "Fetched questions list is empty or invalid format.", None
except Exception as e:
return f"Error fetching questions: {e}", None
# Run Agent
results_log = []
answers_payload = []
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"AGENT ERROR: {e}"
})
if not answers_payload:
return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
# Submit
submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
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"Overall Score: {result_data.get('score', 'N/A')}% "
f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
f"Message: {result_data.get('message', 'No message received.')}"
)
results_df = pd.DataFrame(results_log)
return final_status, results_df
except Exception as e:
results_df = pd.DataFrame(results_log)
return f"Submission Failed: {e}", results_df
# --- Build Gradio Interface ---
with gr.Blocks() as demo:
gr.Markdown("# Reasoning Agent with Tool Example")
gr.Markdown("""
**Instructions:**
1. Log in to Hugging Face.
2. Click 'Run Evaluation & Submit All Answers'.
3. The agent can use the AddTwoNumbers tool if needed.
""")
gr.LoginButton()
run_button = gr.Button("Run Evaluation & Submit All Answers")
status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
run_button.click(fn=run_and_submit_all, outputs=[status_output, results_table])
# --- Launch App ---
if __name__ == "__main__":
demo.launch(debug=True, share=False)