# 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 # 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 # ============================================================================= # 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_python_tool, search_news_tool, 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