Tingusto commited on
Commit
37f56f9
·
1 Parent(s): 2247153

Add SerpAPI search functionality, audio transcription, Excel analysis, and OCR tools to agent.py. Update requirements.txt to include new dependencies.

Browse files
Files changed (3) hide show
  1. agent.py +84 -95
  2. metadata.jsonl +0 -0
  3. requirements.txt +4 -0
agent.py CHANGED
@@ -12,9 +12,18 @@ import requests
12
  from bs4 import BeautifulSoup
13
  import urllib.parse
14
  import re
 
 
 
 
 
 
 
15
 
16
  load_dotenv()
17
 
 
 
18
  @tool
19
  def wiki_search(query: str) -> str:
20
  """Search Wikipedia for information.
@@ -33,37 +42,30 @@ def wiki_search(query: str) -> str:
33
  return f"Error searching Wikipedia: {str(e)}"
34
 
35
  @tool
36
- def web_search(query: str) -> str:
37
- """Search the web using DuckDuckGo.
38
 
39
  Args:
40
  query: The search query."""
41
  try:
42
- encoded_query = urllib.parse.quote(query)
43
- url = f"https://html.duckduckgo.com/html/?q={encoded_query}"
44
-
45
- headers = {
46
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
 
 
 
47
  }
48
-
49
- response = requests.get(url, headers=headers)
50
  response.raise_for_status()
51
-
52
- soup = BeautifulSoup(response.text, 'html.parser')
53
-
54
  results = []
55
- for result in soup.find_all('div', class_='result__body'):
56
- title = result.find('h2', class_='result__title')
57
- snippet = result.find('a', class_='result__snippet')
58
-
59
- if title and snippet:
60
- results.append(f"Title: {title.get_text()}\nSnippet: {snippet.get_text()}")
61
-
62
- if len(results) >= 3:
63
- break
64
-
65
  return {"web_results": "\n\n".join(results) if results else "No results found"}
66
-
67
  except Exception as e:
68
  return f"Error searching web: {str(e)}"
69
 
@@ -92,87 +94,71 @@ def reverse_text(text: str) -> str:
92
  text: The text to reverse."""
93
  return text[::-1]
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  @tool
96
  def analyze_youtube_video(video_url: str) -> str:
97
- """Analyze a YouTube video for specific information.
98
 
99
  Args:
100
  video_url: The URL of the YouTube video."""
101
  try:
102
- # Extract video ID from URL
103
- video_id = re.search(r'(?:v=|\/)([0-9A-Za-z_-]{11}).*', video_url)
104
- if not video_id:
105
- return "Invalid YouTube URL"
106
-
107
- video_id = video_id.group(1)
108
-
109
- # Use YouTube API or web search to get video information
110
- encoded_query = urllib.parse.quote(f"youtube video {video_id} transcript description")
111
- url = f"https://html.duckduckgo.com/html/?q={encoded_query}"
112
-
113
- headers = {
114
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
115
- }
116
-
117
- response = requests.get(url, headers=headers)
118
- response.raise_for_status()
119
-
120
- soup = BeautifulSoup(response.text, 'html.parser')
121
-
122
- results = []
123
- for result in soup.find_all('div', class_='result__body'):
124
- title = result.find('h2', class_='result__title')
125
- snippet = result.find('a', class_='result__snippet')
126
-
127
- if title and snippet:
128
- results.append(f"Title: {title.get_text()}\nSnippet: {snippet.get_text()}")
129
-
130
- if len(results) >= 3:
131
- break
132
-
133
- return {"video_results": "\n\n".join(results) if results else "No results found"}
134
-
135
  except Exception as e:
136
  return f"Error analyzing YouTube video: {str(e)}"
137
 
138
  # System prompt
139
- system_prompt = """You are a highly accurate question-answering assistant. Your task is to provide precise, direct answers to questions.
140
-
141
- Key Rules:
142
- 1. Answer Format:
143
- - For numbers: Provide only the number without units, commas, or formatting
144
- - For text: Use minimal words, no articles or abbreviations
145
- - For lists: Use comma-separated values without additional formatting
146
- - For dates: Use YYYY-MM-DD format unless specified otherwise
147
- - For names: Use full names without titles or honorifics
148
- - For country codes: Use official IOC codes (3 letters)
149
- - For chess moves: Use standard algebraic notation
150
- - For currency: Use numbers only, no symbols
151
-
152
- 2. Answer Guidelines:
153
- - Be extremely precise and direct
154
- - Do not include any explanatory text
155
- - Do not use phrases like "FINAL ANSWER" or any markers
156
- - Do not include units unless explicitly requested
157
- - Do not use abbreviations unless they are standard (e.g., DNA, RNA)
158
- - For multiple choice: Provide only the letter or number of the correct answer
159
- - For reversed text: Provide the answer in normal text
160
- - For file-based questions: Focus on the specific information requested
161
-
162
- 3. Error Handling:
163
- - If uncertain, provide the most likely answer based on available information
164
- - If completely unsure, provide a reasonable default rather than an error message
165
- - For file processing errors, indicate the specific issue
166
-
167
- 4. Special Cases:
168
- - For mathematical questions: Provide the exact numerical result
169
- - For historical dates: Use the most widely accepted date
170
- - For scientific terms: Use the standard scientific notation
171
- - For geographical locations: Use official names without abbreviations
172
- - For audio/video questions: Focus on the specific detail requested
173
- - For reversed text: Use the reverse_text tool to decode
174
- - For YouTube videos: Use the analyze_youtube_video tool to get information
175
- - For chess positions: Provide the move in standard algebraic notation"""
176
 
177
  # System message
178
  sys_msg = SystemMessage(content=system_prompt)
@@ -180,9 +166,12 @@ sys_msg = SystemMessage(content=system_prompt)
180
  # Tools list
181
  tools = [
182
  wiki_search,
183
- web_search,
184
  arxiv_search,
185
  reverse_text,
 
 
 
186
  analyze_youtube_video,
187
  ]
188
 
 
12
  from bs4 import BeautifulSoup
13
  import urllib.parse
14
  import re
15
+ import pandas as pd
16
+ import pytesseract
17
+ from PIL import Image
18
+ import whisper
19
+ import yt_dlp
20
+ import tempfile
21
+ import subprocess
22
 
23
  load_dotenv()
24
 
25
+ SERPAPI_API_KEY = os.getenv("SERPAPI_API_KEY")
26
+
27
  @tool
28
  def wiki_search(query: str) -> str:
29
  """Search Wikipedia for information.
 
42
  return f"Error searching Wikipedia: {str(e)}"
43
 
44
  @tool
45
+ def serpapi_search(query: str) -> str:
46
+ """Search the web using SerpAPI (Google Custom Search).
47
 
48
  Args:
49
  query: The search query."""
50
  try:
51
+ if not SERPAPI_API_KEY:
52
+ return "SerpAPI key not set"
53
+ params = {
54
+ "q": query,
55
+ "api_key": SERPAPI_API_KEY,
56
+ "engine": "google",
57
+ "num": 3,
58
+ "hl": "en"
59
  }
60
+ response = requests.get("https://serpapi.com/search", params=params)
 
61
  response.raise_for_status()
62
+ data = response.json()
 
 
63
  results = []
64
+ for r in data.get("organic_results", [])[:3]:
65
+ title = r.get("title", "")
66
+ snippet = r.get("snippet", "")
67
+ results.append(f"Title: {title}\nSnippet: {snippet}")
 
 
 
 
 
 
68
  return {"web_results": "\n\n".join(results) if results else "No results found"}
 
69
  except Exception as e:
70
  return f"Error searching web: {str(e)}"
71
 
 
94
  text: The text to reverse."""
95
  return text[::-1]
96
 
97
+ @tool
98
+ def transcribe_audio(file_path: str) -> str:
99
+ """Transcribe an audio file using Whisper.
100
+
101
+ Args:
102
+ file_path: Path to the audio file."""
103
+ try:
104
+ model = whisper.load_model("base")
105
+ result = model.transcribe(file_path)
106
+ return result["text"]
107
+ except Exception as e:
108
+ return f"Error transcribing audio: {str(e)}"
109
+
110
+ @tool
111
+ def analyze_excel(file_path: str, column: str = None) -> str:
112
+ """Analyze an Excel file and return the sum of a column or all data.
113
+
114
+ Args:
115
+ file_path: Path to the Excel file.
116
+ column: Optional column to sum."""
117
+ try:
118
+ df = pd.read_excel(file_path)
119
+ if column and column in df.columns:
120
+ return str(df[column].sum())
121
+ return df.to_csv(index=False)
122
+ except Exception as e:
123
+ return f"Error analyzing Excel: {str(e)}"
124
+
125
+ @tool
126
+ def ocr_image(file_path: str) -> str:
127
+ """Extract text from an image using OCR.
128
+
129
+ Args:
130
+ file_path: Path to the image file."""
131
+ try:
132
+ img = Image.open(file_path)
133
+ text = pytesseract.image_to_string(img)
134
+ return text
135
+ except Exception as e:
136
+ return f"Error extracting text from image: {str(e)}"
137
+
138
  @tool
139
  def analyze_youtube_video(video_url: str) -> str:
140
+ """Download and transcribe a YouTube video using yt-dlp and Whisper.
141
 
142
  Args:
143
  video_url: The URL of the YouTube video."""
144
  try:
145
+ with tempfile.TemporaryDirectory() as tmpdir:
146
+ ydl_opts = {
147
+ 'format': 'bestaudio/best',
148
+ 'outtmpl': f'{tmpdir}/%(id)s.%(ext)s',
149
+ 'quiet': True,
150
+ }
151
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
152
+ info = ydl.extract_info(video_url, download=True)
153
+ audio_path = ydl.prepare_filename(info)
154
+ model = whisper.load_model("base")
155
+ result = model.transcribe(audio_path)
156
+ return result["text"][:2000] # Limite la sortie
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  except Exception as e:
158
  return f"Error analyzing YouTube video: {str(e)}"
159
 
160
  # System prompt
161
+ system_prompt = """You are a highly accurate question-answering assistant. Your answers must be:\n- Direct, with no extra words or explanations.\n- Formatted exactly as requested (numbers only, comma-separated lists, etc.).\n- If the question involves a file, extract only the requested information.\n- If the question is about a video, audio, or image, use the appropriate tool to extract the answer.\n- If you are unsure, provide the most likely answer in the correct format.\n- Never add units, explanations, or formatting unless explicitly requested.\n"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
  # System message
164
  sys_msg = SystemMessage(content=system_prompt)
 
166
  # Tools list
167
  tools = [
168
  wiki_search,
169
+ serpapi_search,
170
  arxiv_search,
171
  reverse_text,
172
+ transcribe_audio,
173
+ analyze_excel,
174
+ ocr_image,
175
  analyze_youtube_video,
176
  ]
177
 
metadata.jsonl ADDED
The diff for this file is too large to render. See raw diff
 
requirements.txt CHANGED
@@ -15,3 +15,7 @@ langgraph==0.4.1
15
  langgraph-checkpoint==2.0.24
16
  langgraph-prebuilt==0.1.8
17
  langgraph-sdk==0.1.63
 
 
 
 
 
15
  langgraph-checkpoint==2.0.24
16
  langgraph-prebuilt==0.1.8
17
  langgraph-sdk==0.1.63
18
+ whisper
19
+ pytesseract
20
+ pillow
21
+ yt-dlp