Budlee commited on
Commit
314fc0f
·
1 Parent(s): 81917a3

First attempt of running code

Browse files
Files changed (5) hide show
  1. .gitignore +2 -0
  2. agent.py +196 -0
  3. app.py +6 -2
  4. models.py +115 -0
  5. requirements.txt +7 -1
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ .venv
2
+ .vscode
agent.py ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from smolagents import (
2
+ CodeAgent,
3
+ InferenceClientModel,
4
+ WebSearchTool,
5
+ VisitWebpageTool,
6
+ WikipediaSearchTool,
7
+ PythonInterpreterTool,
8
+ FinalAnswerTool,
9
+ )
10
+ from models import TaskItem
11
+ from smolagents.monitoring import LogLevel
12
+
13
+ import requests
14
+ import tempfile
15
+ import os
16
+
17
+
18
+ class CodingAgent:
19
+ def __init__(self):
20
+ model = InferenceClientModel(
21
+ model_id="Qwen/Qwen2.5-Coder-32B-Instruct",
22
+ )
23
+ self._c_agent = CodeAgent(
24
+ model=model,
25
+ tools=[PythonInterpreterTool()],
26
+ name="coding_agent",
27
+ description="Executes Python code to solve tasks",
28
+ verbosity_level=LogLevel.INFO,
29
+ max_steps=10,
30
+ # add_base_tools=True,
31
+ additional_authorized_imports=["pandas", "*"],
32
+ )
33
+
34
+ @property
35
+ def agent(self):
36
+ """
37
+ Property that returns the CodeAgent instance
38
+ """
39
+ return self._c_agent
40
+
41
+
42
+ class WebAgent:
43
+ def __init__(self):
44
+ model = InferenceClientModel(
45
+ model_id="Qwen/Qwen2.5-Coder-32B-Instruct",
46
+ )
47
+ self._w_agent = CodeAgent(
48
+ model=model,
49
+ tools=[WebSearchTool(), VisitWebpageTool(), WikipediaSearchTool()],
50
+ name="web_agent",
51
+ description="Browses the web to find information",
52
+ verbosity_level=LogLevel.INFO,
53
+ max_steps=10,
54
+ )
55
+
56
+ @property
57
+ def agent(self):
58
+ """
59
+ Property that returns the CodeAgent instance
60
+ """
61
+ return self._w_agent
62
+
63
+
64
+ class BudleeAgent:
65
+
66
+ # Constructor for SMOL Agent
67
+
68
+ _PROMPT = """
69
+ "I will ask you a question. Report your thoughts step by step. "
70
+ "Finish your answer only with the final answer. In the final answer don't write explanations. "
71
+ "The answer should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. "
72
+ "Avoid units, abbreviations, or articles unless specified. "
73
+ "Pay attention to each sentence in the question and verify the answer against every part. "
74
+ "Try searching more sources if initial results are insufficient.\n"
75
+ "\n"
76
+ "{additional_context}"
77
+ "\n"
78
+ "QUESTION: "
79
+ ""
80
+ "{question}"
81
+ """
82
+
83
+ def __init__(self, api_base_url: str):
84
+ """
85
+ Initialize the BudleeAgent.
86
+ This is where you can set up any necessary configurations or parameters.
87
+ """
88
+ self._api_url = api_base_url
89
+ model = InferenceClientModel(
90
+ max_tokens=4096,
91
+ temperature=0.2,
92
+ model_id="deepseek-ai/DeepSeek-R1", # it is possible that this model may be overloaded
93
+ custom_role_conversions=None,
94
+ )
95
+ agent_web = WebAgent().agent
96
+ agent_coding = CodingAgent().agent
97
+ self._manager_agent = CodeAgent(
98
+ model=model,
99
+ managed_agents=[agent_web, agent_coding],
100
+ tools=[
101
+ FinalAnswerTool(),
102
+ ],
103
+ planning_interval=5,
104
+ verbosity_level=LogLevel.DEBUG,
105
+ # final_answer_checks=[self._check_response],
106
+ max_steps=15,
107
+ )
108
+
109
+ self._manager_agent.visualize()
110
+
111
+ # def _check_response(self, final_answer, agent_memory):
112
+ # """
113
+ # Check the final answer response for validity.
114
+ # This is a placeholder; implement your own checks as needed.
115
+ # """
116
+ # # Example: always return True (no check)
117
+ # return True
118
+
119
+ def answer(self, taskItem: TaskItem) -> str:
120
+ """
121
+ Try to solve the task as an Agent using the information
122
+ """
123
+ print(f"Agent received question (first 50 chars): {taskItem.question[:50]}...")
124
+ additional_context = ""
125
+
126
+ # Check if a file is present by validating the file_name is not empty
127
+
128
+ if taskItem.file_name and taskItem.file_name.strip():
129
+ print(f"Agent received file: {taskItem.file_name}")
130
+ dl_file= self._download_file(taskItem.file_name)
131
+ additional_context = f"The question has some additional context from a file that needed to be downloaded. here is the contents of the file\n FILE_CONTENTS: {dl_file}\n"
132
+
133
+ prompt = self._PROMPT.format(question=taskItem.question, additional_context=additional_context)
134
+ print(f"Agent prompt {prompt}")
135
+ answer = self._manager_agent.run(prompt)
136
+ # check the answer is FinalStep
137
+ # if not isinstance(answer, FinalAnswerStep):
138
+ # raise ValueError("The agent did not return a FinalAnswerTool instance.")
139
+
140
+ # print(f"Agent returning fixed answer: {answer}")
141
+
142
+ return answer # type: ignore
143
+
144
+ def _download_file(self, file_name: str) -> str:
145
+ """
146
+ Download the file from the given task_id and return its contents as a string.
147
+ """
148
+ print(f"Downloading file for task: {file_name}")
149
+
150
+ try:
151
+ # Construct the API URL - assuming file_name is the task_id
152
+ api_url = f"{self._api_url}/files/{file_name}" # Replace with actual base URL
153
+
154
+ # Download the file
155
+ response = requests.get(api_url)
156
+ response.raise_for_status() # Raises an HTTPError for bad responses
157
+
158
+ # Create a temporary file
159
+ with tempfile.NamedTemporaryFile(mode='w+b', delete=False) as temp_file:
160
+ temp_file.write(response.content)
161
+ temp_file_path = temp_file.name
162
+
163
+ try:
164
+ # Try to read as text with UTF-8 encoding first
165
+ with open(temp_file_path, 'r', encoding='utf-8') as f:
166
+ content = f.read()
167
+ except UnicodeDecodeError:
168
+ # If UTF-8 fails, try with latin-1
169
+ try:
170
+ with open(temp_file_path, 'r', encoding='latin-1') as f:
171
+ content = f.read()
172
+ except Exception:
173
+ # If all text encodings fail, return binary info
174
+ with open(temp_file_path, 'rb') as f:
175
+ binary_content = f.read()
176
+ content = f"Binary file content (Size: {len(binary_content)} bytes)"
177
+ finally:
178
+ # Clean up the temporary file
179
+ os.unlink(temp_file_path)
180
+
181
+ print(f"File downloaded and processed successfully for task: {file_name}")
182
+ return content
183
+
184
+ except requests.HTTPError as e:
185
+ if e.response.status_code == 404:
186
+ error_msg = f"No file found for task ID: {file_name}"
187
+ elif e.response.status_code == 403:
188
+ error_msg = f"Access denied for task ID: {file_name}"
189
+ else:
190
+ error_msg = f"HTTP error downloading file for task {file_name}: {e}"
191
+ print(error_msg)
192
+ return error_msg
193
+ except Exception as e:
194
+ error_msg = f"Error downloading/processing file for task {file_name}: {e}"
195
+ print(error_msg)
196
+ return error_msg
app.py CHANGED
@@ -4,9 +4,13 @@ import requests
4
  import inspect
5
  import pandas as pd
6
 
 
 
 
7
  # (Keep Constants as is)
8
  # --- Constants ---
9
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
 
10
 
11
  # --- Basic Agent Definition ---
12
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
@@ -40,7 +44,7 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
40
 
41
  # 1. Instantiate Agent ( modify this part to create your agent)
42
  try:
43
- agent = BasicAgent()
44
  except Exception as e:
45
  print(f"Error instantiating agent: {e}")
46
  return f"Error initializing agent: {e}", None
@@ -80,7 +84,7 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
80
  print(f"Skipping item with missing task_id or question: {item}")
81
  continue
82
  try:
83
- submitted_answer = agent(question_text)
84
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
85
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
86
  except Exception as e:
 
4
  import inspect
5
  import pandas as pd
6
 
7
+ from agent import BudleeAgent
8
+ from models import TaskItem
9
+
10
  # (Keep Constants as is)
11
  # --- Constants ---
12
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
13
+ _DEFAULT_AGENT = BudleeAgent(DEFAULT_API_URL)
14
 
15
  # --- Basic Agent Definition ---
16
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
 
44
 
45
  # 1. Instantiate Agent ( modify this part to create your agent)
46
  try:
47
+ agent = _DEFAULT_AGENT
48
  except Exception as e:
49
  print(f"Error instantiating agent: {e}")
50
  return f"Error initializing agent: {e}", None
 
84
  print(f"Skipping item with missing task_id or question: {item}")
85
  continue
86
  try:
87
+ submitted_answer = agent.answer(taskItem=TaskItem.from_dict(item))
88
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
89
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
90
  except Exception as e:
models.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dataclasses import dataclass
2
+ from typing import Optional, Dict, Any
3
+ import json
4
+
5
+
6
+ @dataclass
7
+ class TaskItem:
8
+ """
9
+ Model representing a task/question item from the evaluation system.
10
+
11
+ Attributes:
12
+ task_id: Unique identifier for the task
13
+ question: The question text to be answered
14
+ level: Difficulty level of the task (default: "1")
15
+ file_name: Associated file name if any (default: empty string)
16
+ """
17
+ task_id: str
18
+ question: str
19
+ level: str = "1"
20
+ file_name: str = ""
21
+
22
+ @classmethod
23
+ def from_dict(cls, data: Dict[str, Any]) -> 'TaskItem':
24
+ """
25
+ Create TaskItem from dictionary/JSON data.
26
+
27
+ Args:
28
+ data: Dictionary containing task data
29
+
30
+ Returns:
31
+ TaskItem instance
32
+
33
+ Raises:
34
+ ValueError: If required fields are missing
35
+ """
36
+ if not data.get("task_id"):
37
+ raise ValueError("task_id is required")
38
+ if not data.get("question"):
39
+ raise ValueError("question is required")
40
+
41
+ return cls(
42
+ task_id=data["task_id"],
43
+ question=data["question"],
44
+ level=data.get("Level", "1"), # Note: JSON uses "Level" not "level"
45
+ file_name=data.get("file_name", "")
46
+ )
47
+
48
+ @classmethod
49
+ def from_json(cls, json_str: str) -> 'TaskItem':
50
+ """
51
+ Create TaskItem from JSON string.
52
+
53
+ Args:
54
+ json_str: JSON string containing task data
55
+
56
+ Returns:
57
+ TaskItem instance
58
+ """
59
+ data = json.loads(json_str)
60
+ return cls.from_dict(data)
61
+
62
+ def to_dict(self) -> Dict[str, Any]:
63
+ """
64
+ Convert TaskItem to dictionary format.
65
+
66
+ Returns:
67
+ Dictionary representation of the task
68
+ """
69
+ return {
70
+ "task_id": self.task_id,
71
+ "question": self.question,
72
+ "Level": self.level, # Maintain original JSON key format
73
+ "file_name": self.file_name
74
+ }
75
+
76
+ def to_json(self) -> str:
77
+ """
78
+ Convert TaskItem to JSON string.
79
+
80
+ Returns:
81
+ JSON string representation of the task
82
+ """
83
+ return json.dumps(self.to_dict(), indent=2)
84
+
85
+ def is_valid(self) -> bool:
86
+ """
87
+ Check if the TaskItem has valid required fields.
88
+
89
+ Returns:
90
+ True if task_id and question are non-empty, False otherwise
91
+ """
92
+ return bool(self.task_id and self.question)
93
+
94
+ def __str__(self) -> str:
95
+ """String representation showing task ID and truncated question."""
96
+ question_preview = self.question[:50] + "..." if len(self.question) > 50 else self.question
97
+ return f"TaskItem(id={self.task_id}, level={self.level}, question='{question_preview}')"
98
+
99
+
100
+ # Example usage and testing
101
+ if __name__ == "__main__":
102
+ # Example JSON data
103
+ sample_json = {
104
+ 'task_id': '8e867cd7-cff9-4e6c-867a-ff5ddc2550be',
105
+ 'question': 'How many studio albums were published by Mercedes Sosa between 2000 and 2009 (included)? You can use the latest 2022 version of english wikipedia.',
106
+ 'Level': '1',
107
+ 'file_name': ''
108
+ }
109
+
110
+ # Create TaskItem from dictionary
111
+ task = TaskItem.from_dict(sample_json)
112
+ print("Created TaskItem:")
113
+ print(task)
114
+ print("\nIs valid:", task.is_valid())
115
+ print("\nBack to dict:", task.to_dict())
requirements.txt CHANGED
@@ -1,2 +1,8 @@
1
  gradio
2
- requests
 
 
 
 
 
 
 
1
  gradio
2
+ requests
3
+ gradio[oauth]
4
+ smolagents
5
+ smolagents[toolkit]
6
+ black
7
+ wikipedia-api
8
+ pandas