|
|
|
""" |
|
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_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 |
|
|
|
|
|
multimodal_tools = MultimodalTools() |
|
search_tools = SearchTools() |
|
youtube_tools = YouTubeTools() |
|
|
|
|
|
|
|
|
|
|
|
@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) |
|
|
|
|
|
|
|
|
|
|
|
@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" |
|
|
|
|
|
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" |
|
|
|
|
|
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" |
|
|
|
|
|
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 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" |
|
|
|
|
|
|
|
|
|
|
|
@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) |
|
|
|
|
|
|
|
|
|
|
|
@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 |
|
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'] |
|
|
|
|
|
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') |
|
|
|
@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 = [ |
|
extract_text, |
|
analyze_image_tool, |
|
analyze_audio_tool, |
|
extract_youtube_transcript, |
|
add, |
|
subtract, |
|
multiply, |
|
divide, |
|
search_tool |
|
] |
|
|
|
|
|
EXTENDED_TOOLS = CORE_TOOLS + [ |
|
analyze_excel_tool, |
|
analyze_youtube_frames, |
|
extract_video_slides, |
|
analyze_python_tool, |
|
search_news_tool, |
|
search_wikipedia_tool, |
|
get_wikipedia_page_tool, |
|
wikipedia_summary_tool, |
|
search_academic_tool, |
|
get_youtube_info, |
|
get_youtube_playlist_info, |
|
calculate_expression, |
|
factorial, |
|
square_root, |
|
percentage, |
|
average |
|
] |
|
|
|
|
|
ALL_TOOLS = EXTENDED_TOOLS + [ |
|
power, |
|
absolute_value, |
|
round_number, |
|
min_value, |
|
max_value, |
|
compound_interest, |
|
solve_quadratic |
|
] |
|
|
|
|
|
tools = CORE_TOOLS |
|
|