GustavoDLRA commited on
Commit
698febc
·
verified ·
1 Parent(s): 920666b

Changed it back to working version

Browse files
Files changed (1) hide show
  1. app.py +270 -58
app.py CHANGED
@@ -1,55 +1,261 @@
1
- import os
2
- import sys
3
- from pathlib import Path
4
 
5
- from dotenv import load_dotenv
6
- env_path = Path(__file__).parent / ".env"
7
- load_dotenv(dotenv_path=env_path, override=True)
8
 
9
- # Add src to sys.path so gaia_agent can be imported even if not installed as a package
10
- sys.path.append(str(Path(__file__).parent / "src"))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  import gradio as gr
13
- import pandas as pd
14
  import requests
 
 
15
 
16
- from gaia_agent.api_client import GaiaApiClient
17
- from gaia_agent.config import Config
18
- from gaia_agent.graph import build_graph
19
- from gaia_agent.models import get_cheap_model, get_strong_model, get_extra_strong_model
20
- from gaia_agent.nodes.perception import make_perception_node
21
- from gaia_agent.runner import run_agent_on_questions
22
- from gaia_agent.tools import build_tools
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
 
24
  # --- Constants ---
25
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
- class GaiaAgent:
29
- """Plan → Tiered-Execute → Verify agent built on LangGraph."""
 
 
 
 
30
 
31
- def __init__(self, cfg: Config | None = None, client=None) -> None:
32
- self.cfg = cfg or Config.from_env()
33
- self.client = client if client is not None else GaiaApiClient(self.cfg.api_url)
34
- self.tools = build_tools(self.cfg)
35
- self.cheap = get_cheap_model(self.cfg)
36
- self.strong = get_strong_model(self.cfg)
37
- self.extra_strong = get_extra_strong_model(self.cfg)
38
 
39
- file_dir = Path(self.cfg.checkpoint_dir) / "files"
40
- file_dir.mkdir(parents=True, exist_ok=True)
41
- perception = make_perception_node(self.client, file_dir)
42
- self.graph = build_graph(
43
- perception_node=perception,
44
- planner_model=self.extra_strong,
45
- strong_model=self.strong,
46
- cheap_model=self.cheap,
47
- verifier_model=self.strong,
48
- tools=self.tools,
49
- caveman=self.cfg.caveman,
50
- caveman_mode=self.cfg.caveman_mode,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  )
52
- print("GaiaAgent initialized.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
  def run_and_submit_all( profile: gr.OAuthProfile | None):
55
  """
@@ -70,9 +276,9 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
70
  questions_url = f"{api_url}/questions"
71
  submit_url = f"{api_url}/submit"
72
 
73
- # 1. Instantiate Agent
74
  try:
75
- agent = GaiaAgent()
76
  except Exception as e:
77
  print(f"Error instantiating agent: {e}")
78
  return f"Error initializing agent: {e}", None
@@ -83,7 +289,9 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
83
  # 2. Fetch Questions
84
  print(f"Fetching questions from: {questions_url}")
85
  try:
86
- questions_data = agent.client.get_questions()
 
 
87
  if not questions_data:
88
  print("Fetched questions list is empty.")
89
  return "Fetched questions list is empty or invalid format.", None
@@ -91,25 +299,31 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
91
  except requests.exceptions.RequestException as e:
92
  print(f"Error fetching questions: {e}")
93
  return f"Error fetching questions: {e}", None
 
 
 
 
94
  except Exception as e:
95
  print(f"An unexpected error occurred fetching questions: {e}")
96
  return f"An unexpected error occurred fetching questions: {e}", None
97
 
98
- # 3. Run the agent with checkpointing
 
 
99
  print(f"Running agent on {len(questions_data)} questions...")
100
- answers_payload = run_agent_on_questions(
101
- agent.graph, questions_data, agent.cfg.checkpoint_dir
102
- )
103
- answers_by_id = {a["task_id"]: a["submitted_answer"] for a in answers_payload}
104
- results_log = [
105
- {
106
- "Task ID": item.get("task_id"),
107
- "Question": item.get("question"),
108
- "Submitted Answer": answers_by_id.get(item.get("task_id"), ""),
109
- }
110
- for item in questions_data
111
- if item.get("task_id") and item.get("question") is not None
112
- ]
113
 
114
  if not answers_payload:
115
  print("Agent did not produce any answers to submit.")
@@ -170,11 +384,9 @@ with gr.Blocks() as demo:
170
  gr.Markdown(
171
  """
172
  **Instructions:**
173
-
174
  1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
175
  2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
176
  3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
177
-
178
  ---
179
  **Disclaimers:**
180
  Once clicking on the "submit button, it can take quite some time ( this is the time for the agent to go through all the questions).
@@ -217,4 +429,4 @@ if __name__ == "__main__":
217
  print("-"*(60 + len(" App Starting ")) + "\n")
218
 
219
  print("Launching Gradio Interface for Basic Agent Evaluation...")
220
- demo.launch(debug=True, share=False)
 
 
 
 
1
 
2
+ Hugging Face's logo Hugging Face
 
 
3
 
4
+ Models
5
+ Datasets
6
+ Spaces
7
+ Buckets new
8
+ Docs
9
+ Enterprise
10
+ Pricing
11
+ Website
12
+ Tasks
13
+ HuggingChat
14
+ Collections
15
+ Languages
16
+ Organizations
17
+ Community
18
+ Blog
19
+ Posts
20
+ Daily Papers
21
+ Learn
22
+ Discord
23
+ Forum
24
+ GitHub
25
+ Solutions
26
+ Team & Enterprise
27
+ Hugging Face PRO
28
+ Enterprise Support
29
+ Inference Providers
30
+ Inference Endpoints
31
+ Storage Buckets
32
 
33
+ Spaces:
34
+ GustavoDLRA
35
+ /
36
+ Final_Assignment_Template
37
+ App
38
+ Files
39
+ Community
40
+ Settings
41
+ Final_Assignment_Template
42
+ / app.py
43
+ GustavoDLRA's picture
44
+ GustavoDLRA
45
+ Added HF environment model
46
+ edfb300
47
+ verified
48
+ 37 minutes ago
49
+ raw
50
+ history
51
+ blame
52
+ 14.8 kB
53
+ import os
54
  import gradio as gr
 
55
  import requests
56
+ import inspect
57
+ import pandas as pd
58
 
59
+ # --------- AGENT IMPORTS ---------------
60
+ # Read Data
61
+ # Retriever Tool
62
+ #from langchain_community.retrievers import BM25Retriever
63
+ from langchain_core.tools import Tool
64
+ # Web Search Tool
65
+ from langchain_community.tools import DuckDuckGoSearchRun
66
+ # Agent
67
+ from typing import TypedDict, Annotated
68
+ from langgraph.graph.message import add_messages
69
+ from langchain_core.messages import AnyMessage, HumanMessage, AIMessage, SystemMessage
70
+ from langgraph.prebuilt import ToolNode
71
+ from langgraph.graph import START, StateGraph
72
+ from langgraph.prebuilt import tools_condition
73
+ from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint
74
+ # Additional Libraries
75
+ import re
76
+ import requests
77
+ from langchain_community.utilities import WikipediaAPIWrapper
78
+ import subprocess
79
+ # -------------------------------------------------------
80
 
81
+ # (Keep Constants as is)
82
  # --- Constants ---
83
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
84
 
85
+ SYSTEM_PROMPT = "You are a general AI assistant. I will ask you a question. Report your thoughts, and finish 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."
86
+
87
+ # --- Basic Agent Definition ---
88
+
89
+
90
+ llm = HuggingFaceEndpoint(
91
+ repo_id="Qwen/Qwen2.5-7B-Instruct",
92
+ task="text-generation",
93
+ huggingfacehub_api_token=os.getenv("HF_TOKEN"),
94
+ temperature=0,
95
+ max_new_tokens=512,
96
+ )
97
+
98
+ def fetch_webpage(url: str) -> str:
99
+ """Fetch and read the text content of any webpage given its URL."""
100
+ try:
101
+ headers = {"User-Agent": "Mozilla/5.0 (compatible; GAIAAgent/1.0)"}
102
+ resp = requests.get(url.strip(), headers=headers, timeout=15)
103
+ resp.raise_for_status()
104
+
105
+ text = re.sub(r"<[^>]+>", " ", resp.text)
106
+ text = re.sub(r"\s+", " ", text).strip()
107
+
108
+ return text[:4000]
109
+
110
+ except Exception as e:
111
+ return f"Error fetching URL: {e}"
112
+
113
+
114
+ def python_repl(code: str) -> str:
115
+ """Execute Python code for calculations, data parsing, or logic."""
116
+ try:
117
+ result = subprocess.run(
118
+ ["python3", "-c", code],
119
+ capture_output=True,
120
+ text=True,
121
+ timeout=15,
122
+ )
123
+
124
+ output = result.stdout.strip()
125
+ error = result.stderr.strip()
126
+
127
+ if error:
128
+ return f"stderr: {error}\nstdout: {output}"
129
+
130
+ return output if output else "(no output)"
131
+
132
+ except subprocess.TimeoutExpired:
133
+ return "Error: code execution timed out"
134
+
135
+ except Exception as e:
136
+ return f"Error running code: {e}"
137
+
138
+ class AgentState(TypedDict):
139
+ messages: Annotated[list[AnyMessage], add_messages]
140
+
141
+ class BasicAgent:
142
+ def __init__(self):
143
+ print("BasicAgent initialized.")
144
+
145
+ self.search_tool = DuckDuckGoSearchRun()
146
+
147
+ self.wikipedia = WikipediaAPIWrapper(
148
+ top_k_results=2,
149
+ doc_content_chars_max=3000,
150
+ )
151
+
152
+ self.fetch_webpage_tool = Tool(
153
+ name="fetch_webpage",
154
+ func=fetch_webpage,
155
+ description=(
156
+ "Fetch and read the text content of any webpage given its URL. "
157
+ "Use this when a question references a specific URL, or after "
158
+ "web search returns a URL you want to read in full. "
159
+ "Input: a full URL including https://."
160
+ ),
161
+ )
162
+
163
+ self.wikipedia_search_tool = Tool(
164
+ name="wikipedia_search",
165
+ func=self.wikipedia_search,
166
+ description=(
167
+ "Search Wikipedia for factual information about a topic. "
168
+ "Input: a topic or search query."
169
+ ),
170
+ )
171
+
172
+ self.python_repl_tool = Tool(
173
+ name="python_repl",
174
+ func=python_repl,
175
+ description=(
176
+ "Execute Python code for calculations, data parsing, or logic. "
177
+ "Use this for arithmetic, unit conversions, list operations, "
178
+ "or structured data processing. Input: valid Python code."
179
+ ),
180
+ )
181
 
182
+ self.tools = [
183
+ self.search_tool,
184
+ self.fetch_webpage_tool,
185
+ self.wikipedia_search_tool,
186
+ self.python_repl_tool,
187
+ ]
188
 
 
 
 
 
 
 
 
189
 
190
+
191
+ self.chat = ChatHuggingFace(llm=llm)
192
+
193
+ self.chat_with_tools = self.chat.bind_tools(self.tools)
194
+
195
+ self.graph = self.build_graph()
196
+
197
+ def wikipedia_search(self, query: str) -> str:
198
+ try:
199
+ return self.wikipedia.run(query)
200
+ except Exception as e:
201
+ return f"Wikipedia search error: {e}"
202
+
203
+ def assistant(self, state: AgentState):
204
+ return {
205
+ "messages": [self.chat_with_tools.invoke(state["messages"])]
206
+ }
207
+
208
+ def build_graph(self):
209
+ builder = StateGraph(AgentState)
210
+
211
+ builder.add_node("assistant", self.assistant)
212
+ builder.add_node("tools", ToolNode(self.tools))
213
+
214
+ builder.add_edge(START, "assistant")
215
+
216
+ builder.add_conditional_edges(
217
+ "assistant",
218
+ tools_condition,
219
+ )
220
+
221
+ builder.add_edge("tools", "assistant")
222
+
223
+ return builder.compile()
224
+
225
+ def extract_final_answer(self, text: str) -> str:
226
+ match = re.search(
227
+ r"FINAL ANSWER:\s*(.*)",
228
+ text,
229
+ flags=re.IGNORECASE | re.DOTALL,
230
  )
231
+
232
+ if match:
233
+ return match.group(1).strip()
234
+
235
+ return text.strip()
236
+
237
+ def __call__(self, question: str) -> str:
238
+ print(f"Agent received question: {question[:100]}...")
239
+
240
+ messages = [
241
+ SystemMessage(content=SYSTEM_PROMPT),
242
+ HumanMessage(content=question),
243
+ ]
244
+
245
+ try:
246
+ response = self.graph.invoke({"messages": messages})
247
+ raw_answer = response["messages"][-1].content
248
+
249
+ final_answer = self.extract_final_answer(raw_answer)
250
+
251
+ print(f"Raw answer: {raw_answer}")
252
+ print(f"Submitted answer: {final_answer}")
253
+
254
+ return final_answer
255
+
256
+ except Exception as e:
257
+ print(f"Agent error: {e}")
258
+ return f"AGENT ERROR: {e}"
259
 
260
  def run_and_submit_all( profile: gr.OAuthProfile | None):
261
  """
 
276
  questions_url = f"{api_url}/questions"
277
  submit_url = f"{api_url}/submit"
278
 
279
+ # 1. Instantiate Agent ( modify this part to create your agent)
280
  try:
281
+ agent = BasicAgent()
282
  except Exception as e:
283
  print(f"Error instantiating agent: {e}")
284
  return f"Error initializing agent: {e}", None
 
289
  # 2. Fetch Questions
290
  print(f"Fetching questions from: {questions_url}")
291
  try:
292
+ response = requests.get(questions_url, timeout=15)
293
+ response.raise_for_status()
294
+ questions_data = response.json()
295
  if not questions_data:
296
  print("Fetched questions list is empty.")
297
  return "Fetched questions list is empty or invalid format.", None
 
299
  except requests.exceptions.RequestException as e:
300
  print(f"Error fetching questions: {e}")
301
  return f"Error fetching questions: {e}", None
302
+ except requests.exceptions.JSONDecodeError as e:
303
+ print(f"Error decoding JSON response from questions endpoint: {e}")
304
+ print(f"Response text: {response.text[:500]}")
305
+ return f"Error decoding server response for questions: {e}", None
306
  except Exception as e:
307
  print(f"An unexpected error occurred fetching questions: {e}")
308
  return f"An unexpected error occurred fetching questions: {e}", None
309
 
310
+ # 3. Run your Agent
311
+ results_log = []
312
+ answers_payload = []
313
  print(f"Running agent on {len(questions_data)} questions...")
314
+ for item in questions_data:
315
+ task_id = item.get("task_id")
316
+ question_text = item.get("question")
317
+ if not task_id or question_text is None:
318
+ print(f"Skipping item with missing task_id or question: {item}")
319
+ continue
320
+ try:
321
+ submitted_answer = agent(question_text)
322
+ answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
323
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
324
+ except Exception as e:
325
+ print(f"Error running agent on task {task_id}: {e}")
326
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
327
 
328
  if not answers_payload:
329
  print("Agent did not produce any answers to submit.")
 
384
  gr.Markdown(
385
  """
386
  **Instructions:**
 
387
  1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
388
  2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
389
  3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
 
390
  ---
391
  **Disclaimers:**
392
  Once clicking on the "submit button, it can take quite some time ( this is the time for the agent to go through all the questions).
 
429
  print("-"*(60 + len(" App Starting ")) + "\n")
430
 
431
  print("Launching Gradio Interface for Basic Agent Evaluation...")
432
+ demo.launch(debug=True, share=False)