gaia-agent / tools.py
Daniel Amendoeira
Update tools.py
406ca82 verified
from langchain_core.tools import tool
import datetime
import requests
import openai
import os
import tempfile
import pandas as pd
from urllib.parse import urlparse, parse_qs
from openai import OpenAI
from youtube_transcript_api import YouTubeTranscriptApi
from youtube_transcript_api._errors import TranscriptsDisabled, NoTranscriptFound, VideoUnavailable
from pytube import extract
from openai import OpenAI
from bs4 import BeautifulSoup
from io import BytesIO
from PyPDF2 import PdfReader
@tool
def add(a: float, b: float) -> float:
""" Adds two numbers.
Args:
a (float): first number
b (float): second number
"""
return a + b
@tool
def subtract(a: float, b: float) -> int:
""" Subtracts two numbers.
Args:
a (float): first number
b (float): second number
"""
return a - b
@tool
def multiply(a: float, b: float) -> float:
""" Multiplies two numbers.
Args:
a (float): first number
b (float): second number
"""
return a * b
@tool
def divide(a: float, b: float) -> float:
""" Divides two numbers.
Args:
a (float): first number
b (float): second number
"""
if b == 0:
raise ValueError("Cannot divide by zero.")
return a / b
@tool
def power(a: float, b: float) -> float:
""" Calculates the power of two numbers.
Args:
a (float): first number
b (float): second number
"""
return a**b
calculator_basic = [add, subtract, multiply, divide, power]
@tool
def current_date(_) -> str :
""" Returns the current date in YYYY-MM-DD format """
return datetime.datetime.now().strftime("%Y-%m-%d")
@tool
def day_of_week(_) -> str :
""" Returns the current day of the week (e.g., Monday, Tuesday) """
return datetime.datetime.now().strftime("%A")
@tool
def days_until(date_str: str) -> str :
""" Returns the number of days from today until a given date (input format: YYYY-MM-DD) """
try:
future_date = datetime.datetime.strptime(date_str, "%Y-%m-%d").date()
today = datetime.date.today()
delta_days = (future_date - today).days
return f"{delta_days} days until {date_str}"
except Exception as e:
return f"Error parsing date: {str(e)}"
datetime_tools = [current_date, day_of_week, days_until]
@tool
def transcribe_audio(audio_file: str, file_extension: str) -> str:
""" Transcribes an audio file to text
Args:
audio_file (str): local file path to the audio file (.mp3, .m4a, etc.)
file_extension (str): file extension of the audio, e.g. mp3
Returns:
str: The transcribed text from the audio.
"""
try:
response = requests.get(audio_file) # download the audio_file
response.raise_for_status() # check if the http request was successful
# clean file extension and save to disk
file_extension = file_extension.replace('.','')
filename = f'tmp.{file_extension}'
with open(filename, 'wb') as file: # opens a new file for writing with a name like, e.g. tmp.mp3
file.write(response.content) # write(w) the binary(b) contents (audio file) to disk
# transcribe audio with OpenAI Whisper
client = OpenAI()
# read(r) the audio file from disk in binary(b) mode "rb"; the "with" block ensures the file is automatically closed afterward
with open(filename, "rb") as audio_content:
transcription = client.audio.transcriptions.create(
model="whisper-1",
file=audio_content
)
return transcription.text
except Exception as e:
return f"transcribe_audio failed: {e}"
@tool
def transcribe_youtube(youtube_url: str) -> str:
""" Transcribes a YouTube video
Args:
youtube_url (str): youtube video's url
Returns:
str: The transcribed text from the video.
"""
try:
query = urlparse(youtube_url).query
video_id = parse_qs(query)['v'][0]
except Exception:
return "invalid YouTube URL"
try:
transcript_list = YouTubeTranscriptApi.list_transcripts(video_id)
transcript = transcript_list.find_transcript(['en']).fetch()
# keep only text
text = '\n'.join([t['text'] for t in transcript])
return text
except (TranscriptsDisabled, NoTranscriptFound, VideoUnavailable) as e:
return f"transcript unavailable: {str(e)}"
except Exception as e:
return f"transcribe_youtube failed: {e}"
@tool
def query_image(query: str, image_url: str) -> str:
""" Ask anything about an image using a Vision Language Model
Args:
query (str): the query about the image, e.g. how many animals are on the image?
image_url (str): the image's URL
"""
try:
client = OpenAI()
response = client.responses.create(
model="gpt-4o-mini",
input=[
{
"role": "user",
"content": [
{"type": "input_text", "text": query},
{"type": "input_image","image_url": image_url},
],
}
],
)
return response.output_text
except Exception as e:
return f"query_image failed: {e}"
@tool
def webpage_content(url: str) -> str:
""" Fetch text from a webpage or PDF file.
Args:
url (str): The URL of the webpage to fetch.
Returns:
str: Extracted text.
"""
try:
response = requests.get(url)
response.raise_for_status()
content_type = response.headers.get("Content-Type", "")
# PDF file
if "pdf" in content_type:
pdf_content = BytesIO(response.content)
reader = PdfReader(pdf_content)
return "\n".join(page.extract_text() or "" for page in reader.pages)
# HTML file
soup = BeautifulSoup(response.text, "html.parser")
body = soup.body
return body.get_text(separator="\n", strip=True) if body else soup.get_text(strip=True)
except Exception as e:
return f"webpage_content failed: {e}"
@tool
def read_excel(file_url: str) -> str:
""" Reads an Excel file from a URL and returns the content as CSV text.
Args:
file_url (str): URL to the Excel file (.xlsx, .xls)
Returns:
str: Content of the Excel file as CSV text.
"""
try:
response = requests.get(file_url)
response.raise_for_status()
excel_content = BytesIO(response.content)
df = pd.read_excel(excel_content)
return df.to_csv(index=False) # convert dataframe to CSV string for easy processing
except Exception as e:
return f"read_excel failed: {str(e)}"