AI_Agents_Course_Submission / tools /langchain_tools.py
omarequalmars
Added wikipedia search
7b71bd5
# tools/langchain_tools.py
"""
LangChain-compatible tool wrappers for our existing tools
Complete integration of multimodal, search, math, and YouTube tools
"""
from langchain_core.tools import tool
from typing import Optional
import os
from dotenv import load_dotenv
# Load environment variables FIRST, before any tool imports
load_dotenv()
from .multimodal_tools import MultimodalTools, analyze_transcript as _analyze_transcript, analyze_excel, analyze_python
from .search_tools import SearchTools
from .math_tools import MathTools
from .youtube_tools import YouTubeTools
from .wikipedia_tools import search_wikipedia, get_wikipedia_page, wikipedia_summary
# Initialize tool instances (now env vars are available)
multimodal_tools = MultimodalTools()
search_tools = SearchTools()
youtube_tools = YouTubeTools()
# =============================================================================
# MULTIMODAL TOOLS
# =============================================================================
@tool
def extract_text(image_path: str) -> str:
"""Extract text from an image using OCR"""
return multimodal_tools.extract_text_from_image(image_path)
@tool
def analyze_image_tool(image_path: str, question: str = "Describe this image in detail") -> str:
"""Analyze an image and answer questions about it"""
return multimodal_tools.analyze_image(image_path, question)
@tool
def analyze_audio_tool(transcript: str, question: str = "Summarize this audio content") -> str:
"""Analyze audio content via transcript"""
return multimodal_tools.analyze_audio_transcript(transcript, question)
@tool
def analyze_excel_tool(file_path: str, question: str) -> str:
"""Analyze Excel or CSV files to answer questions about the data"""
return analyze_excel(file_path, question)
# =============================================================================
# SEARCH TOOLS
# =============================================================================
@tool
def search_tool(query: str, max_results: int = 10) -> str:
"""Search the web for information"""
results = search_tools.search(query, max_results)
if not results:
return "No search results found"
# Format results for the LLM
formatted_results = []
for i, result in enumerate(results, 1):
title = result.get('title', 'No title')
content = result.get('content', 'No content')
url = result.get('url', 'No URL')
formatted_results.append(f"{i}. {title}\n{content[:200]}...\nSource: {url}\n")
return "\n".join(formatted_results)
@tool
def search_news_tool(query: str, max_results: int = 10) -> str:
"""Search for news articles about a topic"""
results = search_tools.search_news(query, max_results)
if not results:
return "No news results found"
# Format results for the LLM
formatted_results = []
for i, result in enumerate(results, 1):
title = result.get('title', 'No title')
content = result.get('content', 'No content')
url = result.get('url', 'No URL')
formatted_results.append(f"{i}. {title}\n{content[:200]}...\nSource: {url}\n")
return "\n".join(formatted_results)
@tool
def search_academic_tool(query: str, max_results: int = 10) -> str:
"""Search for academic research and papers"""
results = search_tools.search_academic(query, max_results)
if not results:
return "No academic results found"
# Format results for the LLM
formatted_results = []
for i, result in enumerate(results, 1):
title = result.get('title', 'No title')
content = result.get('content', 'No content')
url = result.get('url', 'No URL')
formatted_results.append(f"{i}. {title}\n{content[:200]}...\nSource: {url}\n")
return "\n".join(formatted_results)
# =============================================================================
# YOUTUBE TOOLS
# =============================================================================
@tool
def extract_youtube_transcript(url: str, language_code: str = 'en') -> str:
"""Extract transcript/captions from a YouTube video"""
captions = youtube_tools.get_captions(url, language_code)
if captions:
return captions
else:
return "No captions available for this video"
@tool
def get_youtube_info(url: str) -> str:
"""Get information about a YouTube video"""
info = youtube_tools.get_video_info(url)
if info:
return f"Title: {info.get('title', 'Unknown')}\nAuthor: {info.get('author', 'Unknown')}\nDuration: {info.get('length', 0)} seconds\nViews: {info.get('views', 0):,}"
else:
return "Could not retrieve video information"
@tool
def get_youtube_playlist_info(playlist_url: str) -> str:
"""Get information about a YouTube playlist"""
info = youtube_tools.get_playlist_info(playlist_url)
if info:
return f"Playlist: {info.get('title', 'Unknown')}\nVideos: {info.get('video_count', 0)}\nOwner: {info.get('owner', 'Unknown')}"
else:
return "Could not retrieve playlist information"
# =============================================================================
# MATH TOOLS - Basic Operations
# =============================================================================
@tool
def add(a: float, b: float) -> float:
"""Add two numbers"""
return MathTools.add(a, b)
@tool
def subtract(a: float, b: float) -> float:
"""Subtract two numbers"""
return MathTools.subtract(a, b)
@tool
def multiply(a: float, b: float) -> float:
"""Multiply two numbers"""
return MathTools.multiply(a, b)
@tool
def divide(a: float, b: float) -> str:
"""Divide two numbers"""
result = MathTools.divide(a, b)
return str(result)
@tool
def power(base: float, exponent: float) -> float:
"""Calculate base raised to the power of exponent"""
return MathTools.power(base, exponent)
# =============================================================================
# MATH TOOLS - Advanced Operations
# =============================================================================
@tool
def factorial(n: int) -> str:
"""Calculate factorial of a number"""
result = MathTools.factorial(n)
return str(result)
@tool
def square_root(n: float) -> str:
"""Calculate square root of a number"""
result = MathTools.square_root(n)
return str(result)
@tool
def percentage(part: float, whole: float) -> str:
"""Calculate percentage"""
result = MathTools.percentage(part, whole)
return str(result)
@tool
def average(numbers: str) -> str:
"""Calculate average of numbers (provide as comma-separated string)"""
try:
number_list = [float(x.strip()) for x in numbers.split(',')]
result = MathTools.average(number_list)
return str(result)
except Exception as e:
return f"Error parsing numbers: {str(e)}"
@tool
def calculate_expression(expression: str) -> str:
"""Calculate a mathematical expression safely"""
from .math_tools import calculate_expression as calc_expr
return str(calc_expr(expression))
@tool
def absolute_value(n: float) -> float:
"""Calculate absolute value of a number"""
return MathTools.absolute(n)
@tool
def round_number(n: float, decimals: int = 2) -> float:
"""Round number to specified decimal places"""
return MathTools.round_number(n, decimals)
@tool
def min_value(numbers: str) -> str:
"""Find minimum value in a list of numbers (provide as comma-separated string)"""
try:
number_list = [float(x.strip()) for x in numbers.split(',')]
result = MathTools.min_value(number_list)
return str(result)
except Exception as e:
return f"Error parsing numbers: {str(e)}"
@tool
def max_value(numbers: str) -> str:
"""Find maximum value in a list of numbers (provide as comma-separated string)"""
try:
number_list = [float(x.strip()) for x in numbers.split(',')]
result = MathTools.max_value(number_list)
return str(result)
except Exception as e:
return f"Error parsing numbers: {str(e)}"
@tool
def compound_interest(principal: float, rate: float, time: float, compounds_per_year: int = 1) -> str:
"""Calculate compound interest"""
result = MathTools.calculate_compound_interest(principal, rate, time, compounds_per_year)
return str(result)
@tool
def solve_quadratic(a: float, b: float, c: float) -> str:
"""Solve quadratic equation ax² + bx + c = 0"""
result = MathTools.solve_quadratic(a, b, c)
return str(result)
@tool
def analyze_python_tool(file_path: str, question: str = "What is the final output of this code?") -> str:
"""Read and analyze Python code files, can execute code to get results"""
return analyze_python(file_path, question)
# =============================================================================
# TOOL COLLECTIONS FOR EASY IMPORT
# =============================================================================
@tool
def analyze_youtube_frames(url: str, question: str = "Describe what happens in this video") -> str:
"""Extract frames from YouTube video and analyze visual content"""
youtube_tools = YouTubeTools()
return youtube_tools.analyze_video_content(url, question)
@tool
def extract_video_slides(url: str) -> str:
"""Extract and analyze slides from educational YouTube videos"""
youtube_tools = YouTubeTools()
results = youtube_tools.analyze_video_slides(url)
if 'error' in results:
return results['error']
# Format slide analysis for LLM
slide_content = []
for frame in results.get('frames_analyzed', []):
if 'slide' in frame.get('analysis', '').lower():
slide_content.append(f"Slide {frame['frame_number']}: {frame['analysis']}")
if slide_content:
return "\n\n".join(slide_content)
else:
return results.get('analysis_summary', 'No slides detected in video')
# Add Wikipedia tools
@tool
def search_wikipedia_tool(query: str, language: str = 'en') -> str:
"""Search Wikipedia for information about a topic"""
return search_wikipedia(query, language)
@tool
def get_wikipedia_page_tool(page_title: str, language: str = 'en') -> str:
"""Retrieve a specific Wikipedia page by title"""
return get_wikipedia_page(page_title, language)
@tool
def wikipedia_summary_tool(query: str, language: str = 'en') -> str:
"""Get a concise Wikipedia summary about a topic"""
return wikipedia_summary(query, language)
# Core tools (matching original template)
CORE_TOOLS = [
extract_text,
analyze_image_tool,
analyze_audio_tool,
extract_youtube_transcript,
add,
subtract,
multiply,
divide,
search_tool
]
# Extended tools with new Excel functionality
EXTENDED_TOOLS = CORE_TOOLS + [
analyze_excel_tool, # NEW: Excel/CSV analysis
analyze_youtube_frames, # ✅ NEW: Frame extraction and analysis
extract_video_slides, # ✅ NEW: Slide detection
analyze_python_tool,
search_news_tool,
search_wikipedia_tool, # ✅ NEW: Wikipedia search
get_wikipedia_page_tool, # ✅ NEW: Specific Wikipedia pages
wikipedia_summary_tool, # ✅ NEW: Wikipedia summaries
search_academic_tool,
get_youtube_info,
get_youtube_playlist_info,
calculate_expression,
factorial,
square_root,
percentage,
average
]
# All available tools
ALL_TOOLS = EXTENDED_TOOLS + [
power,
absolute_value,
round_number,
min_value,
max_value,
compound_interest,
solve_quadratic
]
# Default export (for backwards compatibility)
tools = CORE_TOOLS