h2oaimichalmarszalek commited on
Commit
d3b823a
·
1 Parent(s): 3469f37
Files changed (7) hide show
  1. .gitignore +1 -0
  2. agent.py +7 -4
  3. app.py +29 -4
  4. local_development.py +2 -0
  5. requirements.txt +6 -1
  6. tools/utils.py +8 -6
  7. tools/web.py +51 -0
.gitignore CHANGED
@@ -1 +1,2 @@
1
  __pycache__
 
 
1
  __pycache__
2
+ answears.json
agent.py CHANGED
@@ -2,10 +2,11 @@ import os
2
 
3
  from pathlib import Path
4
  from typing import Optional
5
- from smolagents import CodeAgent, PythonInterpreterTool, DuckDuckGoSearchTool, Tool
6
  from tools.utils import reverse_string, process_excel_file, is_text_file, execute_python_file, get_ingredients
7
  from tools.youtube import load_youtube
8
  from tools.audio import transcribe_audio
 
9
 
10
  # from langchain.agents import load_tools
11
 
@@ -18,9 +19,11 @@ class BasicAgent:
18
  def __init__(self, model):
19
  self._model = model
20
  self._agent = CodeAgent(
21
- tools=[PythonInterpreterTool(), DuckDuckGoSearchTool(), reverse_string, process_excel_file, is_text_file, load_youtube, execute_python_file, transcribe_audio, get_ingredients],
22
- additional_authorized_imports=['random', 'time', 'itertools', 'pandas'],
23
- model=model
 
 
24
  )
25
  print("BasicAgent initialized.")
26
 
 
2
 
3
  from pathlib import Path
4
  from typing import Optional
5
+ from smolagents import CodeAgent, PythonInterpreterTool, WikipediaSearchTool, VisitWebpageTool, FinalAnswerTool
6
  from tools.utils import reverse_string, process_excel_file, is_text_file, execute_python_file, get_ingredients
7
  from tools.youtube import load_youtube
8
  from tools.audio import transcribe_audio
9
+ from tools.web import optimized_web_search
10
 
11
  # from langchain.agents import load_tools
12
 
 
19
  def __init__(self, model):
20
  self._model = model
21
  self._agent = CodeAgent(
22
+ tools=[PythonInterpreterTool(), WikipediaSearchTool(), VisitWebpageTool(), FinalAnswerTool(),optimized_web_search, reverse_string, process_excel_file, is_text_file, load_youtube, execute_python_file, transcribe_audio, get_ingredients],
23
+ additional_authorized_imports=['*', 'subprocess','markdownify', 'chess', 'random', 'time', 'itertools', 'pandas', 'webbrowser', 'requests', 'beautifulsoup4', 'csv', 'openpyxl', 'json', 'yaml'],
24
+ model=model,
25
+ add_base_tools=True,
26
+ max_steps=10
27
  )
28
  print("BasicAgent initialized.")
29
 
app.py CHANGED
@@ -1,16 +1,31 @@
1
  import os
 
2
  import gradio as gr
3
  import requests
4
  import inspect
5
  import pandas as pd
 
6
 
7
  from agent import BasicAgent
 
 
8
 
9
  # (Keep Constants as is)
10
  # --- Constants ---
11
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
12
 
13
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  def run_and_submit_all( profile: gr.OAuthProfile | None):
16
  """
@@ -33,7 +48,11 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
33
 
34
  # 1. Instantiate Agent ( modify this part to create your agent)
35
  try:
36
- agent = BasicAgent()
 
 
 
 
37
  except Exception as e:
38
  print(f"Error instantiating agent: {e}")
39
  return f"Error initializing agent: {e}", None
@@ -65,15 +84,22 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
65
  # 3. Run your Agent
66
  results_log = []
67
  answers_payload = []
 
68
  print(f"Running agent on {len(questions_data)} questions...")
69
  for item in questions_data:
70
  task_id = item.get("task_id")
 
71
  question_text = item.get("question")
72
  if not task_id or question_text is None:
73
  print(f"Skipping item with missing task_id or question: {item}")
74
  continue
75
  try:
76
- submitted_answer = agent(question_text)
 
 
 
 
 
77
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
78
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
79
  except Exception as e:
@@ -92,8 +118,7 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
92
  # 5. Submit
93
  print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
94
  try:
95
- response = requests.post(submit_url, json=submission_data, timeout=60)
96
- response.raise_for_status()
97
  result_data = response.json()
98
  final_status = (
99
  f"Submission Successful!\n"
 
1
  import os
2
+ import json
3
  import gradio as gr
4
  import requests
5
  import inspect
6
  import pandas as pd
7
+ import backoff
8
 
9
  from agent import BasicAgent
10
+ from smolagents import LiteLLMModel
11
+ from tools.utils import download_file
12
 
13
  # (Keep Constants as is)
14
  # --- Constants ---
15
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
16
 
17
 
18
+ @backoff.on_exception(backoff.expo, Exception, max_tries=8, max_time=60)
19
+ def submit(submit_url: str, submission_data):
20
+ try:
21
+ with open('answears.log', 'w') as s:
22
+ s.write(json.dumps(submission_data))
23
+ except:
24
+ pass
25
+
26
+ response = requests.post(submit_url, json=submission_data, timeout=60)
27
+ response.raise_for_status()
28
+ return response
29
 
30
  def run_and_submit_all( profile: gr.OAuthProfile | None):
31
  """
 
48
 
49
  # 1. Instantiate Agent ( modify this part to create your agent)
50
  try:
51
+ model = LiteLLMModel(
52
+ model_id="ollama/qwen2.5:7b",
53
+ api_base="http://localhost:11434"
54
+ )
55
+ agent = BasicAgent(model)
56
  except Exception as e:
57
  print(f"Error instantiating agent: {e}")
58
  return f"Error initializing agent: {e}", None
 
84
  # 3. Run your Agent
85
  results_log = []
86
  answers_payload = []
87
+ file_path = None
88
  print(f"Running agent on {len(questions_data)} questions...")
89
  for item in questions_data:
90
  task_id = item.get("task_id")
91
+ file_name = item.get('file_name')
92
  question_text = item.get("question")
93
  if not task_id or question_text is None:
94
  print(f"Skipping item with missing task_id or question: {item}")
95
  continue
96
  try:
97
+ if file_name:
98
+ task_id = item.get('task_id')
99
+ file_path = download_file(f'{DEFAULT_API_URL}/files/{task_id}', file_name)
100
+ else:
101
+ file_path = None
102
+ submitted_answer = str(agent(question_text, file_path))
103
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
104
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
105
  except Exception as e:
 
118
  # 5. Submit
119
  print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
120
  try:
121
+ response = submit(submit_url, submission_data)
 
122
  result_data = response.json()
123
  final_status = (
124
  f"Submission Successful!\n"
local_development.py CHANGED
@@ -31,6 +31,8 @@ if __name__ == '__main__':
31
  if file_name:
32
  task_id = question.get('task_id')
33
  file_path = download_file(f'{base_url}/files/{task_id}', file_name)
 
 
34
 
35
 
36
  model = LiteLLMModel(
 
31
  if file_name:
32
  task_id = question.get('task_id')
33
  file_path = download_file(f'{base_url}/files/{task_id}', file_name)
34
+ else:
35
+ file_path = None
36
 
37
 
38
  model = LiteLLMModel(
requirements.txt CHANGED
@@ -1,4 +1,5 @@
1
  gradio
 
2
  requests
3
  smolagents
4
  smolagents[litellm]
@@ -11,4 +12,8 @@ langchain
11
  langchain-community
12
  backoff
13
  SpeechRecognition
14
- pydub
 
 
 
 
 
1
  gradio
2
+ gradio[oauth]
3
  requests
4
  smolagents
5
  smolagents[litellm]
 
12
  langchain-community
13
  backoff
14
  SpeechRecognition
15
+ pydub
16
+ wikipedia-api
17
+ beautifulsoup4
18
+ chess
19
+ markdownify
tools/utils.py CHANGED
@@ -114,7 +114,7 @@ def is_text_file(file_path: str) -> bool:
114
 
115
 
116
  @tool
117
- def execute_python_file(file_path: str) -> Union[str|float]:
118
  """
119
  Execute a Python code from file_path in a separate process and return its output as a numeric value.
120
 
@@ -125,7 +125,7 @@ def execute_python_file(file_path: str) -> Union[str|float]:
125
  file_path (str): Path to the Python file to execute.
126
 
127
  Returns:
128
- Union[str|float]: The output from the executed script, or an error message if execution failed. If output is numeric return float in the other case returns str.
129
 
130
  Raises:
131
  None: All exceptions are handled internally and returned as error strings.
@@ -153,7 +153,7 @@ def execute_python_file(file_path: str) -> Union[str|float]:
153
  [sys.executable, file_path],
154
  capture_output=True,
155
  text=True,
156
- timeout=60 # 60 seconds timeout
157
  )
158
 
159
  # If there's stderr output, include it in the result
@@ -163,9 +163,11 @@ def execute_python_file(file_path: str) -> Union[str|float]:
163
  # Include stderr even if return code is 0 (warnings, etc.)
164
  return f"{result.stdout.strip()}\nWarnings/Info: {result.stderr.strip()}"
165
  else:
166
- try:
167
- return float(result.stdout.strip())
168
- except:
 
 
169
  return result.stdout.strip() if result.stdout.strip() else "Script executed successfully with no output"
170
 
171
  except subprocess.TimeoutExpired:
 
114
 
115
 
116
  @tool
117
+ def execute_python_file(file_path: str) -> str:
118
  """
119
  Execute a Python code from file_path in a separate process and return its output as a numeric value.
120
 
 
125
  file_path (str): Path to the Python file to execute.
126
 
127
  Returns:
128
+ str: The output from the executed script, or an error message if execution failed.
129
 
130
  Raises:
131
  None: All exceptions are handled internally and returned as error strings.
 
153
  [sys.executable, file_path],
154
  capture_output=True,
155
  text=True,
156
+ timeout=180 # 180 seconds timeout
157
  )
158
 
159
  # If there's stderr output, include it in the result
 
163
  # Include stderr even if return code is 0 (warnings, etc.)
164
  return f"{result.stdout.strip()}\nWarnings/Info: {result.stderr.strip()}"
165
  else:
166
+ for i in result.stdout.strip().split():
167
+ try:
168
+ return str(int(i.strip()))
169
+ except:
170
+ pass
171
  return result.stdout.strip() if result.stdout.strip() else "Script executed successfully with no output"
172
 
173
  except subprocess.TimeoutExpired:
tools/web.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ from smolagents import DuckDuckGoSearchTool
3
+ from smolagents import tool
4
+
5
+ @tool
6
+ def optimized_web_search(
7
+ search_query: str, important_words: list, batch_size: int = 500
8
+ ) -> str:
9
+ """A tool that performs a web search and filters the results to only include content chunks that contain important keywords.
10
+ Args:
11
+ search_query: The search query to use (e.g., 'Beatles albums Wikipedia')
12
+ important_words: List of important keywords to filter by (e.g., ['Abbey Road', 'Let It Be', '1970'])
13
+ batch_size: The size of content chunks to process (default: 500 characters)
14
+ """
15
+ try:
16
+ # Perform the search using DuckDuckGoSearchTool
17
+ search_tool = DuckDuckGoSearchTool()
18
+ time.sleep(10)
19
+ search_results = search_tool.forward(search_query)
20
+ # Check if search_results is empty or None
21
+ if not search_results or len(search_results) == 0:
22
+ return "No search results found."
23
+
24
+ # If search_results is a dictionary, extract the content
25
+ if isinstance(search_results, list):
26
+ all_content = " ".join(
27
+ [result.get("content", "") for result in search_results]
28
+ )
29
+ else:
30
+ all_content = search_results
31
+
32
+
33
+ batches = []
34
+ for i in range(0, len(all_content), batch_size):
35
+ batches.append(all_content[i : i + batch_size])
36
+
37
+ # Filter batches
38
+ filtered_batches = []
39
+ for batch in batches:
40
+ if any(word.lower() in batch.lower() for word in important_words):
41
+ filtered_batches.append(batch)
42
+
43
+ filtered_content = "\n\n".join(filtered_batches)
44
+
45
+ if not filtered_content:
46
+ return f"No content containing the important words {important_words} was found in the search results."
47
+
48
+ return filtered_content
49
+
50
+ except Exception as e:
51
+ return f"Error during optimized web search: {str(e)}"