santimber commited on
Commit
319ed46
·
1 Parent(s): 8ae9f7c
Files changed (3) hide show
  1. app.py +22 -3
  2. requirements.txt +4 -1
  3. tools.py +171 -19
app.py CHANGED
@@ -9,7 +9,17 @@ from langgraph.graph import START, StateGraph
9
  from langgraph.prebuilt import ToolNode, tools_condition
10
  from langgraph.graph.message import add_messages
11
  from typing import TypedDict, Annotated
12
- from tools import image_recognition_tool, download_file_tool, reverse_text_tool, hub_stats_tool, web_search_tool
 
 
 
 
 
 
 
 
 
 
13
 
14
  # (Keep Constants as is)
15
  # --- Constants ---
@@ -17,8 +27,17 @@ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
17
 
18
  # Setting up the llm
19
  llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
20
- tools = [web_search_tool, hub_stats_tool, download_file_tool,
21
- image_recognition_tool, reverse_text_tool]
 
 
 
 
 
 
 
 
 
22
  chat_with_tools = llm.bind_tools(tools)
23
 
24
  # Defining my agent
 
9
  from langgraph.prebuilt import ToolNode, tools_condition
10
  from langgraph.graph.message import add_messages
11
  from typing import TypedDict, Annotated
12
+ from tools import (
13
+ image_recognition_tool,
14
+ download_file_tool,
15
+ reverse_text_tool,
16
+ hub_stats_tool,
17
+ web_search_tool,
18
+ python_execution_tool,
19
+ video_analysis_tool,
20
+ audio_processing_tool,
21
+ file_type_detection_tool
22
+ )
23
 
24
  # (Keep Constants as is)
25
  # --- Constants ---
 
27
 
28
  # Setting up the llm
29
  llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
30
+ tools = [
31
+ web_search_tool,
32
+ hub_stats_tool,
33
+ download_file_tool,
34
+ image_recognition_tool,
35
+ reverse_text_tool,
36
+ python_execution_tool,
37
+ video_analysis_tool,
38
+ audio_processing_tool,
39
+ file_type_detection_tool
40
+ ]
41
  chat_with_tools = llm.bind_tools(tools)
42
 
43
  # Defining my agent
requirements.txt CHANGED
@@ -14,4 +14,7 @@ python-dotenv
14
  duckduckgo-search
15
  pandas
16
  datasets
17
- langchain-huggingface
 
 
 
 
14
  duckduckgo-search
15
  pandas
16
  datasets
17
+ langchain-huggingface
18
+ pathlib
19
+ SpeechRecognition
20
+ librosa
tools.py CHANGED
@@ -24,6 +24,14 @@ from dotenv import load_dotenv
24
  import os
25
  import torch
26
  import base64
 
 
 
 
 
 
 
 
27
 
28
  # DEFINE HUB STAT TOOLS
29
 
@@ -67,7 +75,11 @@ print(pp.pprint(results))
67
 
68
  # REVERSE TOOLS
69
  def ReverseTextTool(text: str) -> str:
70
- return text[::-1]
 
 
 
 
71
 
72
 
73
  reverse_text_tool = Tool(
@@ -84,6 +96,7 @@ print(pp.pprint(results))
84
 
85
 
86
  def download_file(url: str) -> str:
 
87
  try:
88
  response = requests.get(url, timeout=30)
89
  response.raise_for_status()
@@ -95,7 +108,7 @@ def download_file(url: str) -> str:
95
 
96
  with open(save_path, "wb") as f:
97
  f.write(response.content)
98
- return save_path # Return the file path instead of success message
99
  except Exception as e:
100
  return f"Failed to download: {e}"
101
 
@@ -103,20 +116,132 @@ def download_file(url: str) -> str:
103
  download_file_tool = Tool(
104
  name="download_file_tool",
105
  func=download_file,
106
- description="Downloads a file from a given URL."
107
  )
108
 
109
  results = download_file_tool.invoke("https://www.google.com")
110
  print(results)
111
 
112
- # DEFINE IMAGE RECOGNITION TOOLS
113
- vision_llm = ChatOpenAI(model="gpt-4o")
114
 
115
 
116
- def image_recognition(img_path: str) -> str:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
 
118
- all_text = ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  # Read image and encode as base64
121
  with open(img_path, "rb") as image_file:
122
  image_bytes = image_file.read()
@@ -131,7 +256,7 @@ def image_recognition(img_path: str) -> str:
131
  "type": "text",
132
  "text": (
133
  "Describe the image or extract all the text from this image. "
134
- "Return only the description orextracted text, no explanations."
135
  ),
136
  },
137
  {
@@ -146,16 +271,10 @@ def image_recognition(img_path: str) -> str:
146
 
147
  # Call the vision-capable model
148
  response = vision_llm.invoke(message)
 
149
 
150
- # Append extracted text
151
- all_text += response.content + "\n\n"
152
-
153
- return all_text.strip()
154
  except Exception as e:
155
- # A butler should handle errors gracefully
156
- error_msg = f"Error extracting text: {str(e)}"
157
- print(error_msg)
158
- return ""
159
 
160
 
161
  image_recognition_tool = Tool(
@@ -163,9 +282,42 @@ image_recognition_tool = Tool(
163
  func=image_recognition,
164
  description="Analyzes and describes the content of images using AI vision. Use this when you need to understand what's in an image."
165
  )
166
- test_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"
167
 
168
- results = image_recognition_tool.invoke(download_file_tool.invoke(test_url))
169
- print(results)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
 
 
 
 
 
 
 
24
  import os
25
  import torch
26
  import base64
27
+ import subprocess
28
+ import tempfile
29
+ import json
30
+ import re
31
+ from pathlib import Path
32
+
33
+ # Load environment variables
34
+ load_dotenv()
35
 
36
  # DEFINE HUB STAT TOOLS
37
 
 
75
 
76
  # REVERSE TOOLS
77
  def ReverseTextTool(text: str) -> str:
78
+ """Reverses the order of characters in a given text string."""
79
+ try:
80
+ return text[::-1]
81
+ except Exception as e:
82
+ return f"Error reversing text: {str(e)}"
83
 
84
 
85
  reverse_text_tool = Tool(
 
96
 
97
 
98
  def download_file(url: str) -> str:
99
+ """Downloads a file from a given URL and returns the local file path."""
100
  try:
101
  response = requests.get(url, timeout=30)
102
  response.raise_for_status()
 
108
 
109
  with open(save_path, "wb") as f:
110
  f.write(response.content)
111
+ return save_path
112
  except Exception as e:
113
  return f"Failed to download: {e}"
114
 
 
116
  download_file_tool = Tool(
117
  name="download_file_tool",
118
  func=download_file,
119
+ description="Downloads a file from a given URL and returns the local file path."
120
  )
121
 
122
  results = download_file_tool.invoke("https://www.google.com")
123
  print(results)
124
 
125
+ # PYTHON CODE EXECUTION TOOL
 
126
 
127
 
128
+ def execute_python_code(code: str) -> str:
129
+ """Executes Python code and returns the output."""
130
+ try:
131
+ # Create a temporary file to execute the code
132
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
133
+ f.write(code)
134
+ temp_file = f.name
135
+
136
+ # Execute the code
137
+ result = subprocess.run(['python', temp_file],
138
+ capture_output=True, text=True, timeout=30)
139
+
140
+ # Clean up
141
+ os.unlink(temp_file)
142
+
143
+ if result.returncode == 0:
144
+ return f"Output: {result.stdout.strip()}"
145
+ else:
146
+ return f"Error: {result.stderr.strip()}"
147
+ except subprocess.TimeoutExpired:
148
+ return "Error: Code execution timed out"
149
+ except Exception as e:
150
+ return f"Error executing Python code: {str(e)}"
151
+
152
+
153
+ python_execution_tool = Tool(
154
+ name="python_execution_tool",
155
+ func=execute_python_code,
156
+ description="Executes Python code and returns the output. Use this when you need to run Python scripts or calculate values."
157
+ )
158
 
159
+ # VIDEO ANALYSIS TOOL
160
+
161
+
162
+ def analyze_video(video_url: str) -> str:
163
+ """Analyzes video content from YouTube or other video URLs."""
164
+ try:
165
+ # Extract video ID from YouTube URL
166
+ if 'youtube.com' in video_url or 'youtu.be' in video_url:
167
+ # For YouTube videos, we can extract some basic info
168
+ video_id = None
169
+ if 'youtube.com/watch?v=' in video_url:
170
+ video_id = video_url.split('watch?v=')[1].split('&')[0]
171
+ elif 'youtu.be/' in video_url:
172
+ video_id = video_url.split('youtu.be/')[1].split('?')[0]
173
+
174
+ if video_id:
175
+ # Use web search to get video information
176
+ search_result = web_search_tool.func(
177
+ f"youtube video {video_id} title description")
178
+ return f"Video analysis for {video_id}: {search_result}"
179
+ else:
180
+ return "Could not extract video ID from URL"
181
+ else:
182
+ return "Video analysis currently supports YouTube videos only"
183
+ except Exception as e:
184
+ return f"Error analyzing video: {str(e)}"
185
+
186
+
187
+ video_analysis_tool = Tool(
188
+ name="video_analysis_tool",
189
+ func=analyze_video,
190
+ description="Analyzes video content from URLs. Use this when questions involve video content or YouTube links."
191
+ )
192
+
193
+ # AUDIO PROCESSING TOOL
194
+
195
+
196
+ def process_audio(audio_file_path: str) -> str:
197
+ """Processes audio files to extract information."""
198
  try:
199
+ if not os.path.exists(audio_file_path):
200
+ return f"Audio file not found: {audio_file_path}"
201
+
202
+ # For now, return basic file info
203
+ file_size = os.path.getsize(audio_file_path)
204
+ file_extension = Path(audio_file_path).suffix
205
+
206
+ return f"Audio file: {audio_file_path}, Size: {file_size} bytes, Type: {file_extension}. Audio processing requires additional libraries like speech_recognition or librosa."
207
+ except Exception as e:
208
+ return f"Error processing audio: {str(e)}"
209
+
210
+
211
+ audio_processing_tool = Tool(
212
+ name="audio_processing_tool",
213
+ func=process_audio,
214
+ description="Processes audio files to extract information. Use this when questions involve audio files or MP3 content."
215
+ )
216
+
217
+ # ENHANCED IMAGE RECOGNITION TOOLS
218
+
219
+
220
+ def create_vision_llm():
221
+ """Creates a vision-capable LLM with proper error handling."""
222
+ try:
223
+ # Check if OpenAI API key is available
224
+ if not os.getenv("OPENAI_API_KEY"):
225
+ return None, "OpenAI API key not found. Please set OPENAI_API_KEY in your environment variables."
226
+
227
+ vision_llm = ChatOpenAI(model="gpt-4o")
228
+ return vision_llm, None
229
+ except Exception as e:
230
+ return None, f"Error creating vision LLM: {str(e)}"
231
+
232
+
233
+ def image_recognition(img_path: str) -> str:
234
+ """Analyzes and describes the content of images using AI vision."""
235
+ try:
236
+ # Check if file exists
237
+ if not os.path.exists(img_path):
238
+ return f"Error: Image file not found at {img_path}"
239
+
240
+ # Create vision LLM
241
+ vision_llm, error = create_vision_llm()
242
+ if error:
243
+ return error
244
+
245
  # Read image and encode as base64
246
  with open(img_path, "rb") as image_file:
247
  image_bytes = image_file.read()
 
256
  "type": "text",
257
  "text": (
258
  "Describe the image or extract all the text from this image. "
259
+ "Return only the description or extracted text, no explanations."
260
  ),
261
  },
262
  {
 
271
 
272
  # Call the vision-capable model
273
  response = vision_llm.invoke(message)
274
+ return response.content.strip()
275
 
 
 
 
 
276
  except Exception as e:
277
+ return f"Error analyzing image: {str(e)}"
 
 
 
278
 
279
 
280
  image_recognition_tool = Tool(
 
282
  func=image_recognition,
283
  description="Analyzes and describes the content of images using AI vision. Use this when you need to understand what's in an image."
284
  )
 
285
 
286
+ # FILE TYPE DETECTION TOOL
287
+
288
+
289
+ def detect_file_type(file_path: str) -> str:
290
+ """Detects the type of file and provides appropriate handling suggestions."""
291
+ try:
292
+ if not os.path.exists(file_path):
293
+ return f"File not found: {file_path}"
294
+
295
+ file_extension = Path(file_path).suffix.lower()
296
+ file_size = os.path.getsize(file_path)
297
+
298
+ file_types = {
299
+ '.py': 'Python script',
300
+ '.mp3': 'Audio file',
301
+ '.mp4': 'Video file',
302
+ '.jpg': 'Image file',
303
+ '.jpeg': 'Image file',
304
+ '.png': 'Image file',
305
+ '.txt': 'Text file',
306
+ '.pdf': 'PDF document',
307
+ '.doc': 'Word document',
308
+ '.docx': 'Word document',
309
+ '.xls': 'Excel spreadsheet',
310
+ '.xlsx': 'Excel spreadsheet'
311
+ }
312
+
313
+ file_type = file_types.get(file_extension, 'Unknown file type')
314
+ return f"File: {file_path}, Type: {file_type}, Size: {file_size} bytes"
315
+ except Exception as e:
316
+ return f"Error detecting file type: {str(e)}"
317
 
318
 
319
+ file_type_detection_tool = Tool(
320
+ name="file_type_detection_tool",
321
+ func=detect_file_type,
322
+ description="Detects file types and provides information about files. Use this when you need to understand what type of file you're working with."
323
+ )