darrenphodgson76 commited on
Commit
edc547a
·
verified ·
1 Parent(s): 2ce2d7e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -51
app.py CHANGED
@@ -1,86 +1,111 @@
1
  import os
2
- import openai # ← official OpenAI client
3
- from openai import OpenAI
4
  import gradio as gr
5
  import requests
6
  import pandas as pd
7
- from smolagents import DuckDuckGoSearchTool, tool
8
 
9
  # --- Constants ---
10
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
11
 
12
- # --- Configure OpenAI SDK & Client ---
13
-
14
  openai_api_key = os.getenv("OPENAI_API_KEY")
15
  if not openai_api_key:
16
- raise RuntimeError("Set OPENAI_API_KEY in your Space secrets or env!")
17
-
18
  openai.api_key = openai_api_key
19
- client = OpenAI() # new client object
20
 
21
  # --- Tool Definitions ---
22
 
23
  @tool
24
  def summarize_query(query: str) -> str:
25
  """
26
- Provides a structured summary to reframe a query if search results are unclear or poor.
27
 
28
  Args:
29
- query (str): The search query that needs summarization.
30
  Returns:
31
- str: A concise summary of key facts about the given query.
32
  """
33
  return f"Summarize and reframe: {query}"
34
 
35
- search_tool = DuckDuckGoSearchTool()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
- # --- ReACT + Scratchpad + AutoRetry Instruction Prompt ---
38
 
39
  instruction_prompt = """
 
 
 
 
40
 
41
- You are a high-precision AI agent. Internally, you may follow the ReACT pattern—thinking step-by-step, invoking tools, observing results, retrying if needed—but you must NOT show any of that. Instead, after you finish reasoning privately, output **exactly** one line:
 
 
 
 
 
 
 
42
 
43
- FINAL ANSWER: [your concise answer]
44
 
45
- Rules for the final answer:
46
- - If it’s a number, output only the digits (no commas, units, or extra text).
47
- - If it’s a list, output a comma-separated list with no extra punctuation or articles.
48
- - If it’s a string, output only the words, no “um,” “the,” or other fillers.
49
 
50
  """
51
 
52
- # --- BasicAgent using the new OpenAI client ---
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
  class BasicAgent:
55
  def __init__(self):
56
- print("SmolAgent (GPT-4.1) with ReACT, Scratchpad & Retry initialized.")
57
 
58
  def __call__(self, question: str) -> str:
59
- # Build the full prompt
60
  prompt = instruction_prompt.strip() + "\n\nQUESTION: " + question.strip()
61
- print(f"Agent prompt (first 150 chars): {prompt[:150]}…")
62
- # Call GPT-4.1 via the new client.responses.create API
63
  try:
64
- response = client.responses.create(
65
- model="gpt-4.1",
66
- input=prompt
67
- )
68
- return response.output_text
69
  except Exception as e:
70
  return f"AGENT ERROR: {e}"
71
 
72
- # --- Gradio / HF‐Spaces submission logic ---
73
 
74
  def run_and_submit_all(profile: gr.OAuthProfile | None):
75
  if not profile:
76
- return "Please log in to Hugging Face using the login button above.", None
77
-
78
  username = profile.username
79
  space_id = os.getenv("SPACE_ID", "")
80
  agent = BasicAgent()
81
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
82
 
83
- # 1. Fetch questions
84
  try:
85
  resp = requests.get(f"{DEFAULT_API_URL}/questions", timeout=15)
86
  resp.raise_for_status()
@@ -88,12 +113,11 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
88
  except Exception as e:
89
  return f"Error fetching questions: {e}", None
90
 
91
- # 2. Run agent on each question
92
  logs, payload = [], []
93
  for item in questions:
94
  tid = item.get("task_id")
95
  q = item.get("question")
96
- if not tid or q is None:
97
  continue
98
  ans = agent(q)
99
  logs.append({"Task ID": tid, "Question": q, "Submitted Answer": ans})
@@ -102,7 +126,6 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
102
  if not payload:
103
  return "Agent did not produce any answers.", pd.DataFrame(logs)
104
 
105
- # 3. Submit answers
106
  submission = {"username": username, "agent_code": agent_code, "answers": payload}
107
  try:
108
  post = requests.post(f"{DEFAULT_API_URL}/submit", json=submission, timeout=60)
@@ -113,28 +136,23 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
113
  f"User: {res.get('username')}\n"
114
  f"Overall Score: {res.get('score', 'N/A')}% "
115
  f"({res.get('correct_count', '?')}/{res.get('total_attempted', '?')})\n"
116
- f"Message: {res.get('message', '')}"
117
  )
118
  return status, pd.DataFrame(logs)
119
  except Exception as e:
120
  return f"Submission Failed: {e}", pd.DataFrame(logs)
121
 
122
- # --- Gradio Interface ---
123
-
124
  with gr.Blocks() as demo:
125
- gr.Markdown("# SmolAgent GAIA Runner (GPT-4.1) 🚀")
126
- gr.Markdown(
127
- """
128
- **Instructions:**
129
- 1. Clone this space.
130
- 2. In Settings Secrets add `OPENAI_API_KEY`.
131
- 3. Log in to Hugging Face.
132
- 4. Click **Run Evaluation & Submit All Answers**.
133
- **Note:** Evaluation may take several minutes.
134
- """
135
- )
136
  gr.LoginButton()
137
- run_btn = gr.Button("Run Evaluation & Submit All Answers")
138
  status_out = gr.Textbox(label="Status", lines=5, interactive=False)
139
  table_out = gr.DataFrame(label="Questions & Answers", wrap=True)
140
 
 
1
  import os
2
+ import openai
 
3
  import gradio as gr
4
  import requests
5
  import pandas as pd
6
+ from smolagents import CodeAgent, LiteLLMModel, DuckDuckGoSearchTool, tool
7
 
8
  # --- Constants ---
9
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
10
 
11
+ # --- Configure OpenAI SDK ---
 
12
  openai_api_key = os.getenv("OPENAI_API_KEY")
13
  if not openai_api_key:
14
+ raise RuntimeError("Please set OPENAI_API_KEY in your Space secrets.")
 
15
  openai.api_key = openai_api_key
16
+ openai_model_id = os.getenv("OPENAI_MODEL_ID", "gpt-4.1")
17
 
18
  # --- Tool Definitions ---
19
 
20
  @tool
21
  def summarize_query(query: str) -> str:
22
  """
23
+ Reframes an unclear query into a better one.
24
 
25
  Args:
26
+ query (str): The search query to refine.
27
  Returns:
28
+ str: A concise, improved query.
29
  """
30
  return f"Summarize and reframe: {query}"
31
 
32
+ @tool
33
+ def wikipedia_search(page: str) -> str:
34
+ """
35
+ Fetches the summary extract of an English Wikipedia page.
36
+
37
+ Args:
38
+ page (str): The page title (e.g. 'Mercedes_Sosa_discography').
39
+ Returns:
40
+ str: The extract section text.
41
+ """
42
+ url = f"https://en.wikipedia.org/api/rest_v1/page/summary/{page}"
43
+ resp = requests.get(url, timeout=10)
44
+ resp.raise_for_status()
45
+ return resp.json().get("extract", "")
46
+
47
+ search_tool = DuckDuckGoSearchTool()
48
+ wiki_tool = wikipedia_search
49
+ summarize_tool = summarize_query
50
 
51
+ # --- ReACT + Scratchpad + Auto-Retry Prompt ---
52
 
53
  instruction_prompt = """
54
+ You are a ReACT agent with three tools:
55
+ • DuckDuckGoSearchTool(query: str)
56
+ • wikipedia_search(page: str)
57
+ • summarize_query(query: str)
58
 
59
+ Internally, for each question:
60
+ 1. Thought: decide which tool to call.
61
+ 2. Action: call the chosen tool.
62
+ 3. Observation: record the result.
63
+ 4. If empty/irrelevant:
64
+ Thought: retry with summarize_query + DuckDuckGoSearchTool.
65
+ Record new Observation.
66
+ 5. Thought: integrate observations.
67
 
68
+ Finally, output your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string.
69
 
 
 
 
 
70
 
71
  """
72
 
73
+ # --- Build the CodeAgent with the same model ---
74
+
75
+ llm = LiteLLMModel(
76
+ model_id=openai_model_id,
77
+ api_key=openai_api_key
78
+ )
79
+
80
+ smart_agent = CodeAgent(
81
+ tools=[search_tool, wiki_tool, summarize_tool],
82
+ model=llm
83
+ )
84
+
85
+ # --- Wrap in BasicAgent for Gradio ---
86
 
87
  class BasicAgent:
88
  def __init__(self):
89
+ print("SmolAgent (GPT-4.1) with ReACT & tools initialized.")
90
 
91
  def __call__(self, question: str) -> str:
 
92
  prompt = instruction_prompt.strip() + "\n\nQUESTION: " + question.strip()
93
+ print(f"Agent prompt: {prompt[:120]}…")
 
94
  try:
95
+ return smart_agent.run(prompt)
 
 
 
 
96
  except Exception as e:
97
  return f"AGENT ERROR: {e}"
98
 
99
+ # --- Gradio & Submission Logic ---
100
 
101
  def run_and_submit_all(profile: gr.OAuthProfile | None):
102
  if not profile:
103
+ return "Please log in to Hugging Face.", None
 
104
  username = profile.username
105
  space_id = os.getenv("SPACE_ID", "")
106
  agent = BasicAgent()
107
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
108
 
 
109
  try:
110
  resp = requests.get(f"{DEFAULT_API_URL}/questions", timeout=15)
111
  resp.raise_for_status()
 
113
  except Exception as e:
114
  return f"Error fetching questions: {e}", None
115
 
 
116
  logs, payload = [], []
117
  for item in questions:
118
  tid = item.get("task_id")
119
  q = item.get("question")
120
+ if not tid or not q:
121
  continue
122
  ans = agent(q)
123
  logs.append({"Task ID": tid, "Question": q, "Submitted Answer": ans})
 
126
  if not payload:
127
  return "Agent did not produce any answers.", pd.DataFrame(logs)
128
 
 
129
  submission = {"username": username, "agent_code": agent_code, "answers": payload}
130
  try:
131
  post = requests.post(f"{DEFAULT_API_URL}/submit", json=submission, timeout=60)
 
136
  f"User: {res.get('username')}\n"
137
  f"Overall Score: {res.get('score', 'N/A')}% "
138
  f"({res.get('correct_count', '?')}/{res.get('total_attempted', '?')})\n"
139
+ f"Message: {res.get('message','')}"
140
  )
141
  return status, pd.DataFrame(logs)
142
  except Exception as e:
143
  return f"Submission Failed: {e}", pd.DataFrame(logs)
144
 
 
 
145
  with gr.Blocks() as demo:
146
+ gr.Markdown("# SmolAgent GAIA Runner 🚀")
147
+ gr.Markdown("""
148
+ **Instructions:**
149
+ 1. Clone this space.
150
+ 2. Add `OPENAI_API_KEY` (and optionally `OPENAI_MODEL_ID`) in Settings → Secrets.
151
+ 3. Log in to Hugging Face.
152
+ 4. Click **Run Evaluation & Submit All Answers**.
153
+ """)
 
 
 
154
  gr.LoginButton()
155
+ run_btn = gr.Button("Run Evaluation & Submit All Answers")
156
  status_out = gr.Textbox(label="Status", lines=5, interactive=False)
157
  table_out = gr.DataFrame(label="Questions & Answers", wrap=True)
158