fmarky commited on
Commit
0f6314c
·
1 Parent(s): d1b66f5

fix: last preparations for meetup/devfest

Browse files
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Final Assignment Agents Course LangGraph
3
  emoji: 🕵🏻‍♂️
4
  colorFrom: indigo
5
  colorTo: indigo
@@ -11,7 +11,7 @@ hf_oauth: true
11
  hf_oauth_expiration_minutes: 480
12
  ---
13
 
14
- # 🕵🏻‍♂️ Final Assignment Agents Course
15
 
16
  LangGraph-powered agent with web search capabilities and tool integration.
17
 
 
1
  ---
2
+ title: GAÏA Agent LangGraph
3
  emoji: 🕵🏻‍♂️
4
  colorFrom: indigo
5
  colorTo: indigo
 
11
  hf_oauth_expiration_minutes: 480
12
  ---
13
 
14
+ # 🕵🏻‍♂️ GAÏA Agent
15
 
16
  LangGraph-powered agent with web search capabilities and tool integration.
17
 
agents/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- """Agents package for the Final Assignment Agents Course."""
2
 
3
  from agents.assistant_agent import AwesomeAgent
4
 
 
1
+ """Agents package for the GAÏA Agent."""
2
 
3
  from agents.assistant_agent import AwesomeAgent
4
 
agents/assistant_agent.py CHANGED
@@ -88,7 +88,7 @@ WEB & SEARCH:
88
  CALCULATIONS:
89
  - calculator: Basic arithmetic (+, -, *, /)
90
  - advanced_math: Advanced math functions (sqrt, log, trig)
91
- - python_repl: Execute Python code for complex computations (use carefully)
92
 
93
  TEXT PROCESSING:
94
  - reverse_text: Reverse text character by character
@@ -156,8 +156,9 @@ def build_langgraph(
156
  file = state["input_file"]
157
  sys_msg = SystemMessage(
158
  content=f"""
159
- You are a LLM agent. You will be given a question.
160
- Your task it to answer the question using the tools you have access to.
 
161
  take time to analyse the steps to answer the question.
162
 
163
  # Input File
@@ -183,12 +184,13 @@ def build_langgraph(
183
 
184
  Here is the question: {state.get(state["messages"][0].content)}
185
 
186
- Summarize the answer with the following rules:
187
- - YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings.
188
- - If the question asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. Write numbers using digits.
189
- - If the question asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise.
190
  - If the question 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.
191
 
 
192
  Here is the content to format:
193
  """
194
  )
 
88
  CALCULATIONS:
89
  - calculator: Basic arithmetic (+, -, *, /)
90
  - advanced_math: Advanced math functions (sqrt, log, trig)
91
+ - python_repl: Execute Python code from path to file (use carefully)
92
 
93
  TEXT PROCESSING:
94
  - reverse_text: Reverse text character by character
 
156
  file = state["input_file"]
157
  sys_msg = SystemMessage(
158
  content=f"""
159
+ You are a LLM agent.
160
+ You will be given a question.
161
+ Your task it to answer the question using the tools.
162
  take time to analyse the steps to answer the question.
163
 
164
  # Input File
 
184
 
185
  Here is the question: {state.get(state["messages"][0].content)}
186
 
187
+ Format the answer with the following rules:
188
+ - YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings.
189
+ - If the question asked for a number, write only the number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. Write numbers using digits.
190
+ - If the question asked for a string, don't use articles, no abbreviations (e.g: write "Saint" rather than "St."), and write the digits in plain text unless specified otherwise.
191
  - If the question 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.
192
 
193
+ WRITE ONLY THE ANSWER, no sentence, no explanation, no context
194
  Here is the content to format:
195
  """
196
  )
agents/assistant_tools.py CHANGED
@@ -23,7 +23,6 @@ from langchain_google_genai import ChatGoogleGenerativeAI
23
  # ---
24
 
25
  from langchain_community.tools import ShellTool
26
- from langchain_experimental.tools import PythonREPLTool
27
  from langchain_community.document_loaders import AssemblyAIAudioTranscriptLoader
28
  from langchain_community.document_loaders.assemblyai import TranscriptFormat
29
 
@@ -202,6 +201,53 @@ def transcribe_mp3(
202
  return f"Transcription error: {str(e)}"
203
 
204
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  def build_tools():
206
  """
207
  Initialize and return a list of built-in and custom LangChain tools.
@@ -212,16 +258,6 @@ def build_tools():
212
 
213
  # Initialize built-in LangChain tools
214
 
215
- # SECURITY: Python REPL Tool
216
- # Should implement:
217
- # - Use RestrictedPython library to restrict dangerous operations
218
- # - Block dangerous built-ins: __import__, eval, exec, open, file operations
219
- # - Block system calls: os.system, subprocess, sys.exit
220
- # - Block network access: socket, urllib, requests
221
- # - Allow only safe modules: math, json, datetime, collections, etc.
222
- # - AST-based validation before execution to catch dangerous patterns
223
- python_repl = PythonREPLTool()
224
-
225
  # SECURITY: Shell Tool
226
  # Should implement:
227
  # - Command whitelist: Only allow safe commands (ls, cat, grep, find, etc.)
@@ -239,11 +275,11 @@ def build_tools():
239
  # Combine built-in tools with custom tools
240
  all_tools = [
241
  # Built-in LangChain tools
242
- python_repl,
243
  shell_tool,
244
  # Web search subagent (replaces individual web/search tools for isolated context)
245
  web_search_agent,
246
  # Custom tools for specialized tasks
 
247
  read_excel_file,
248
  get_youtube_transcript_tool,
249
  get_youtube_title_description,
 
23
  # ---
24
 
25
  from langchain_community.tools import ShellTool
 
26
  from langchain_community.document_loaders import AssemblyAIAudioTranscriptLoader
27
  from langchain_community.document_loaders.assemblyai import TranscriptFormat
28
 
 
201
  return f"Transcription error: {str(e)}"
202
 
203
 
204
+ @tool
205
+ def execute_python_file(file_path: str) -> str:
206
+ """
207
+ Execute Python code from the provided file path and return its stdout/stderr output.
208
+ """
209
+ import subprocess
210
+ import sys
211
+
212
+ if not isinstance(file_path, str) or not file_path.strip():
213
+ return "Error: file_path must be a non-empty string."
214
+
215
+ file_path = file_path.strip()
216
+
217
+ if not os.path.isfile(file_path):
218
+ return f"Error: file not found at '{file_path}'."
219
+
220
+ if not file_path.endswith(".py"):
221
+ return "Error: only '.py' files are supported."
222
+
223
+ try:
224
+ with open(file_path, "r", encoding="utf-8") as f:
225
+ f.read()
226
+ except Exception as e:
227
+ return f"Error reading file: {str(e)}"
228
+
229
+ try:
230
+ completed = subprocess.run(
231
+ [sys.executable, file_path],
232
+ capture_output=True,
233
+ text=True,
234
+ check=False,
235
+ )
236
+ except Exception as e:
237
+ return f"Execution error: {str(e)}"
238
+
239
+ stdout_content = (completed.stdout or "").strip()
240
+ stderr_content = (completed.stderr or "").strip()
241
+
242
+ if stdout_content and stderr_content:
243
+ return f"STDOUT:\n{stdout_content}\n\nSTDERR:\n{stderr_content}"
244
+ if stdout_content:
245
+ return stdout_content
246
+ if stderr_content:
247
+ return f"STDERR:\n{stderr_content}"
248
+ return "Execution completed with no output."
249
+
250
+
251
  def build_tools():
252
  """
253
  Initialize and return a list of built-in and custom LangChain tools.
 
258
 
259
  # Initialize built-in LangChain tools
260
 
 
 
 
 
 
 
 
 
 
 
261
  # SECURITY: Shell Tool
262
  # Should implement:
263
  # - Command whitelist: Only allow safe commands (ls, cat, grep, find, etc.)
 
275
  # Combine built-in tools with custom tools
276
  all_tools = [
277
  # Built-in LangChain tools
 
278
  shell_tool,
279
  # Web search subagent (replaces individual web/search tools for isolated context)
280
  web_search_agent,
281
  # Custom tools for specialized tasks
282
+ execute_python_file,
283
  read_excel_file,
284
  get_youtube_transcript_tool,
285
  get_youtube_title_description,
app.py CHANGED
@@ -114,7 +114,7 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
114
  # TODO: REMOVE THIS PART - AVOID ASKING 50 QUESTIONS
115
  # questions_data = questions_data[:5] # the top 5
116
  # questions_data = [questions_data[18]] # the 19th question
117
- keep = {1, 3, 7, 11, 12, 16}
118
  questions_data[:] = [x for i, x in enumerate(questions_data, start=1) if i in keep]
119
  ############################################################################################################
120
 
@@ -183,7 +183,7 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
183
  f"User: {result_data.get('username')}\n"
184
  # f"Overall Score: {result_data.get('score', 'N/A')}% "
185
  f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
186
- f"Message: {result_data.get('message', 'No message received.')}"
187
  )
188
  print("Submission successful.")
189
  results_df = pd.DataFrame(results_log)
 
114
  # TODO: REMOVE THIS PART - AVOID ASKING 50 QUESTIONS
115
  # questions_data = questions_data[:5] # the top 5
116
  # questions_data = [questions_data[18]] # the 19th question
117
+ keep = {1, 3, 7, 12, 16}
118
  questions_data[:] = [x for i, x in enumerate(questions_data, start=1) if i in keep]
119
  ############################################################################################################
120
 
 
183
  f"User: {result_data.get('username')}\n"
184
  # f"Overall Score: {result_data.get('score', 'N/A')}% "
185
  f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
186
+ # f"Message: {result_data.get('message', 'No message received.')}"
187
  )
188
  print("Submission successful.")
189
  results_df = pd.DataFrame(results_log)
pyproject.toml CHANGED
@@ -1,7 +1,7 @@
1
  [project]
2
  name = "final-assignment-agents-course"
3
  version = "0.1.0"
4
- description = "Final assignment Hugging Face agents course"
5
  readme = "README.md"
6
  requires-python = "==3.10.*"
7
  dependencies = [
 
1
  [project]
2
  name = "final-assignment-agents-course"
3
  version = "0.1.0"
4
+ description = "GAÏA Agent LangGraphHugging Face agents course"
5
  readme = "README.md"
6
  requires-python = "==3.10.*"
7
  dependencies = [