innafomina commited on
Commit
b7e35bf
·
1 Parent(s): 0d30fcd

added new code logic

Browse files
Files changed (3) hide show
  1. app.py +57 -37
  2. requirements.txt +4 -1
  3. tools.py +156 -0
app.py CHANGED
@@ -3,7 +3,12 @@ import gradio as gr
3
  import requests
4
  import inspect
5
  import pandas as pd
6
- from smolagents import CodeAgent, OpenAIServerModel, DuckDuckGoSearchTool, WikipediaSearchTool, HfApiModel
 
 
 
 
 
7
  # (Keep Constants as is)
8
  # --- Constants ---
9
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
@@ -12,18 +17,21 @@ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
12
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
13
  class BasicAgent:
14
  def __init__(self):
15
- # model = OpenAIServerModel(model_id="gpt-4o",
16
- # api_key=os.getenv("OPENAI_API_KEY"))
17
- model=HfApiModel(api_key=os.getenv('HUGGING_FACE_API_KEY'))
18
- # Initialize the DuckDuckGo search tool
19
- search_tool = DuckDuckGoSearchTool()
20
- wiki_search = WikipediaSearchTool()
21
-
22
  # Instantiate the agent
23
  self.agent = CodeAgent(
24
- tools=[search_tool, wiki_search],
 
 
 
 
25
  model=model,
26
- add_base_tools=True
 
27
  )
28
  SYSTEM_PROMPT = """You are a general AI assistant. I will ask you a question. Report your thoughts, and
29
  finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER].
@@ -32,9 +40,10 @@ class BasicAgent:
32
  If you are asked for a number, don't use comma to write your number neither use units such as $ or
33
  percent sign unless specified otherwise.
34
  If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the
35
- digits in plain text unless specified otherwise.
36
  If you are asked for a comma separated list, apply the above rules depending of whether the element
37
- to be put in the list is a number or a string.
 
38
  """
39
  self.agent.prompt_templates["system_prompt"] = self.agent.prompt_templates["system_prompt"] + SYSTEM_PROMPT
40
  def __call__(self, question: str) -> str:
@@ -43,12 +52,12 @@ class BasicAgent:
43
  print(f"Agent returning answer: {final_answer}")
44
  return final_answer
45
 
46
- def run_and_submit_all( profile: gr.OAuthProfile | None):
47
  """
48
  Fetches all questions, runs the BasicAgent on them, submits all answers,
49
  and displays the results.
50
  """
51
- # --- Determine HF Space Runtime URL and Repo URL ---
52
  space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
53
 
54
  if profile:
@@ -57,22 +66,10 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
57
  else:
58
  print("User not logged in.")
59
  return "Please Login to Hugging Face with the button.", None
60
-
61
  api_url = DEFAULT_API_URL
62
  questions_url = f"{api_url}/questions"
63
  submit_url = f"{api_url}/submit"
64
-
65
- # 1. Instantiate Agent ( modify this part to create your agent)
66
- try:
67
- agent = BasicAgent()
68
- except Exception as e:
69
- print(f"Error instantiating agent: {e}")
70
- return f"Error initializing agent: {e}", None
71
- # In the case of an app running as a hugging Face space, this link points toward your codebase ( usefull for others so please keep it public)
72
- agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
73
- print(agent_code)
74
-
75
- # 2. Fetch Questions
76
  print(f"Fetching questions from: {questions_url}")
77
  try:
78
  response = requests.get(questions_url, timeout=15)
@@ -92,42 +89,62 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
92
  except Exception as e:
93
  print(f"An unexpected error occurred fetching questions: {e}")
94
  return f"An unexpected error occurred fetching questions: {e}", None
 
 
 
 
 
 
 
 
 
 
 
95
 
96
  # 3. Run your Agent
97
  results_log = []
98
  answers_payload = []
99
  print(f"Running agent on {len(questions_data)} questions...")
100
- # added limit for testing
 
 
101
  for item in questions_data:
102
  task_id = item.get("task_id")
103
- question_text = item.get("question")
 
 
 
 
 
104
  if not task_id or question_text is None:
105
  print(f"Skipping item with missing task_id or question: {item}")
106
  continue
107
  try:
 
108
  submitted_answer = agent(question_text)
 
109
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
110
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
111
  except Exception as e:
112
- print(f"Error running agent on task {task_id}: {e}")
113
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
114
 
115
- if not answers_payload:
116
- print("Agent did not produce any answers to submit.")
117
- return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
118
 
119
  # 4. Prepare Submission
120
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
121
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
122
  print(status_update)
123
 
124
- # 5. Submit
125
  print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
126
  try:
127
  response = requests.post(submit_url, json=submission_data, timeout=60)
128
  response.raise_for_status()
129
  result_data = response.json()
130
- final_status = (
131
  f"Submission Successful!\n"
132
  f"User: {result_data.get('username')}\n"
133
  f"Overall Score: {result_data.get('score', 'N/A')}% "
@@ -218,4 +235,7 @@ if __name__ == "__main__":
218
  print("-"*(60 + len(" App Starting ")) + "\n")
219
 
220
  print("Launching Gradio Interface for Basic Agent Evaluation...")
221
- demo.launch(debug=True, share=False)
 
 
 
 
3
  import requests
4
  import inspect
5
  import pandas as pd
6
+ from smolagents import CodeAgent, OpenAIServerModel, DuckDuckGoSearchTool, WikipediaSearchTool, HfApiModel, GoogleSearchTool
7
+ from dotenv import find_dotenv, load_dotenv
8
+ from tools import WikipediaSearch, ExcelReader, download_files, get_images, FileReader, AudioTransciber, YouTubeTranscipt, YouTubeVideoUnderstanding
9
+ from pathlib import Path
10
+ from PIL import Image
11
+
12
  # (Keep Constants as is)
13
  # --- Constants ---
14
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
 
17
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
18
  class BasicAgent:
19
  def __init__(self):
20
+ load_dotenv(find_dotenv())
21
+ os.environ["SERPER_API_KEY"] = os.getenv('SERPER_API_KEY')
22
+ model = OpenAIServerModel(model_id="gpt-4o",
23
+ api_key=os.getenv("OPEN_AI_KEY"))
24
+ #model=HfApiModel(api_key=os.getenv('HUGGING_FACE_API_KEY'))
 
 
25
  # Instantiate the agent
26
  self.agent = CodeAgent(
27
+ tools=[
28
+ GoogleSearchTool(provider="serper"),
29
+ #DuckDuckGoSearchTool(),
30
+ WikipediaSearch(), ExcelReader(), FileReader(), AudioTransciber(), YouTubeTranscipt(),
31
+ YouTubeVideoUnderstanding()],
32
  model=model,
33
+ add_base_tools=True,
34
+ additional_authorized_imports=['pandas','numpy', 'io']
35
  )
36
  SYSTEM_PROMPT = """You are a general AI assistant. I will ask you a question. Report your thoughts, and
37
  finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER].
 
40
  If you are asked for a number, don't use comma to write your number neither use units such as $ or
41
  percent sign unless specified otherwise.
42
  If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the
43
+ digits in plain text unless specified otherwise. Never include currency symbols in the response.
44
  If you are asked for a comma separated list, apply the above rules depending of whether the element
45
+ to be put in the list is a number or a string. For question that contain phrases like `what is the number` or
46
+ `what is the highest number` return just the number, e.g., 2.
47
  """
48
  self.agent.prompt_templates["system_prompt"] = self.agent.prompt_templates["system_prompt"] + SYSTEM_PROMPT
49
  def __call__(self, question: str) -> str:
 
52
  print(f"Agent returning answer: {final_answer}")
53
  return final_answer
54
 
55
+ def run_and_submit_all(profile: gr.OAuthProfile | None):
56
  """
57
  Fetches all questions, runs the BasicAgent on them, submits all answers,
58
  and displays the results.
59
  """
60
+ #--- Determine HF Space Runtime URL and Repo URL ---
61
  space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
62
 
63
  if profile:
 
66
  else:
67
  print("User not logged in.")
68
  return "Please Login to Hugging Face with the button.", None
69
+
70
  api_url = DEFAULT_API_URL
71
  questions_url = f"{api_url}/questions"
72
  submit_url = f"{api_url}/submit"
 
 
 
 
 
 
 
 
 
 
 
 
73
  print(f"Fetching questions from: {questions_url}")
74
  try:
75
  response = requests.get(questions_url, timeout=15)
 
89
  except Exception as e:
90
  print(f"An unexpected error occurred fetching questions: {e}")
91
  return f"An unexpected error occurred fetching questions: {e}", None
92
+ # 1. Instantiate Agent ( modify this part to create your agent)
93
+ try:
94
+ agent = BasicAgent()
95
+ except Exception as e:
96
+ print(f"Error instantiating agent: {e}")
97
+ return f"Error initializing agent: {e}", None
98
+ # In the case of an app running as a hugging Face space, this link points toward your codebase ( usefull for others so please keep it public)
99
+ agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
100
+ print(agent_code)
101
+
102
+ # 2. Fetch Questions
103
 
104
  # 3. Run your Agent
105
  results_log = []
106
  answers_payload = []
107
  print(f"Running agent on {len(questions_data)} questions...")
108
+ #questions_data = [i for i in questions_data if i['task_id'] == 'f918266a-b3e0-4914-865d-4faa564f1aef']
109
+ images = []
110
+ #added limit for testing
111
  for item in questions_data:
112
  task_id = item.get("task_id")
113
+ question_text = item.get("question") + 'You can use wikipedia.'
114
+ file_name = item.get('file_name')
115
+ if file_name:
116
+ file_path = download_files(task_id, file_name)
117
+ file_format = file_name.split('.')[-1]
118
+ question_text = question_text + f"This question has an associated file at path: {file_path}. The file is in the {file_format} format"
119
  if not task_id or question_text is None:
120
  print(f"Skipping item with missing task_id or question: {item}")
121
  continue
122
  try:
123
+ print(images)
124
  submitted_answer = agent(question_text)
125
+ print(submitted_answer)
126
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
127
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
128
  except Exception as e:
129
+ print(f"Error running agent on task {task_id}: {e}")
130
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
131
 
132
+ if not answers_payload:
133
+ print("Agent did not produce any answers to submit.")
134
+ return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
135
 
136
  # 4. Prepare Submission
137
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
138
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
139
  print(status_update)
140
 
141
+ 5. Submit
142
  print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
143
  try:
144
  response = requests.post(submit_url, json=submission_data, timeout=60)
145
  response.raise_for_status()
146
  result_data = response.json()
147
+ f = (
148
  f"Submission Successful!\n"
149
  f"User: {result_data.get('username')}\n"
150
  f"Overall Score: {result_data.get('score', 'N/A')}% "
 
235
  print("-"*(60 + len(" App Starting ")) + "\n")
236
 
237
  print("Launching Gradio Interface for Basic Agent Evaluation...")
238
+ demo.launch(debug=True, share=False)
239
+
240
+ if __name__ == "__main__":
241
+ run_and_submit_all()
requirements.txt CHANGED
@@ -2,4 +2,7 @@ gradio
2
  requests
3
  smolagents
4
  smolagents[openai]
5
- wikipedia-api
 
 
 
 
2
  requests
3
  smolagents
4
  smolagents[openai]
5
+ openpyxl
6
+ Wikipedia-API
7
+ llama-index-readers-youtube_transcript
8
+ google-genai
tools.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from smolagents import Tool
2
+ import wikipedia
3
+ from bs4 import BeautifulSoup
4
+ import io
5
+ import pandas as pd
6
+ import requests
7
+ from tabulate import tabulate
8
+ import os
9
+ import tempfile
10
+ from pathlib import Path
11
+ from PIL import Image
12
+ from io import BytesIO
13
+ from dotenv import find_dotenv, load_dotenv
14
+ from openai import OpenAI
15
+ from llama_index.readers.youtube_transcript import YoutubeTranscriptReader
16
+ from google import genai
17
+ from google.genai import types
18
+
19
+ class WikipediaSearch(Tool):
20
+ name = "wikipedia_search"
21
+ description = "Fetches wikipedia pages."
22
+ inputs = {
23
+ "query": {
24
+ "type": "string",
25
+ "description": "Query to be searched on wikipedia"
26
+ }
27
+ }
28
+ output_type = "string"
29
+
30
+ def forward(self, query:str)->str:
31
+ res = wikipedia.page(query)
32
+ bs = BeautifulSoup(res.html(), 'html.parser')
33
+ text_only = bs.get_text()
34
+ return text_only
35
+
36
+ class ExcelReader(Tool):
37
+ name = 'excel_processor'
38
+ description = "excel reading tool, processed files of .xlsx and .xls format."
39
+ inputs = {
40
+
41
+ "file_path": {
42
+ "type": "string",
43
+ "description": "path to the excel file"
44
+ }
45
+ }
46
+ output_type = "string"
47
+
48
+ def forward(self, file_path:str)->str:
49
+ df = pd.read_excel(file_path)
50
+ txt_excel = tabulate(df, headers="keys", tablefmt="github", showindex=False)
51
+ return txt_excel
52
+
53
+ class FileReader(Tool):
54
+ name = 'file_reader'
55
+ description = "reads saved files"
56
+ inputs = {
57
+
58
+ "file_path": {
59
+ "type": "string",
60
+ "description": "path to the file"
61
+ }
62
+ }
63
+ output_type = "string"
64
+
65
+ def forward(self, file_path:str)->str:
66
+ with open(file_path, "r") as file:
67
+ content = file.read()
68
+ return content
69
+
70
+ def download_files(task_id, file_name):
71
+ url = f'https://agents-course-unit4-scoring.hf.space/files/{task_id}'
72
+ response = requests.get(url, timeout=15)
73
+ tmp_dir = Path(tempfile.gettempdir()) / "project_files"
74
+ tmp_dir.mkdir(exist_ok=True)
75
+ filepath = os.path.join(tmp_dir, file_name)
76
+ with open(filepath, "wb") as f:
77
+ f.write(response.content)
78
+
79
+ return filepath
80
+
81
+ def get_images(file_format, file_path):
82
+ if file_format in ['png', 'jpeg', 'jpg']:
83
+ images = [Image.open(file_path).convert("RGB")]
84
+ else:
85
+ images = []
86
+
87
+ return images
88
+
89
+ class AudioTransciber(Tool):
90
+ name = 'audio_transcriber'
91
+ description = "transcribes audio files"
92
+ inputs = {
93
+
94
+ "file_path": {
95
+ "type": "string",
96
+ "description": "path to the file"
97
+ }
98
+ }
99
+ output_type = "string"
100
+
101
+ def forward(self, file_path:str)->str:
102
+ audio = open(file_path, 'rb')
103
+ client = OpenAI(api_key=os.getenv("OPEN_AI_KEY"))
104
+ transcript = client.audio.transcriptions.create(model='whisper-1',
105
+ file=audio)
106
+ return transcript
107
+
108
+ class YouTubeTranscipt(Tool):
109
+ name = 'youtube_transcript'
110
+ description = "a tool that returns a transcript for a youtube video. Youtube videos come from urls containing www.youtube.com"
111
+ inputs = {
112
+
113
+ "url": {
114
+ "type": "string",
115
+ "description": "url to the youtube video, has 'www.youtube.com' in it."
116
+ }
117
+ }
118
+ output_type = "string"
119
+
120
+ def forward(self, url:str)->str:
121
+ loader = YoutubeTranscriptReader()
122
+ documents = loader.load_data(ytlinks=[url])
123
+ transcript = documents[0].text
124
+ return transcript
125
+
126
+ class YouTubeVideoUnderstanding(Tool):
127
+ name = 'youtube_video_understanding'
128
+ description = "a tool that processes summarizes what is happenening in a youtube video. Youtube videos come from urls containing www.youtube.com"
129
+ inputs = {
130
+ "url": {
131
+ "type": "string",
132
+ "description": "url to the youtube video, has 'www.youtube.com' in it."
133
+ },
134
+ "prompt": {
135
+ "type": "string",
136
+ "description": "user prompt about the video content"
137
+
138
+ }
139
+ }
140
+ output_type = "string"
141
+
142
+ def forward(self, url:str, prompt:str)->str:
143
+ load_dotenv(find_dotenv())
144
+ client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
145
+ response = client.models.generate_content(
146
+ model='models/gemini-2.5-flash-preview-04-17',
147
+ contents=types.Content(
148
+ parts=[
149
+ types.Part(
150
+ file_data=types.FileData(file_uri=url)
151
+ ),
152
+ types.Part(text=prompt)
153
+ ]
154
+ )
155
+ )
156
+ return response.text