from smolagents import CodeAgent,DuckDuckGoSearchTool, LiteLLMModel,load_tool,tool import datetime import requests import pytz import yaml from tools.final_answer import FinalAnswerTool from Gradio_UI import GradioUI import os #retreive your secret api key for LiteLLMModel import asyncio import lyricsgenius import re from litellm import completion from bs4 import BeautifulSoup import gradio as gr # Retrieve your "secret" google api key named GEMINI_API_KEY for LiteLLMModel os.environ["GEMINI_API_KEY"] = os.getenv('GEMINI_API_KEY') YOUTUBE_API_KEY = os.getenv("YOUTUBE_API_KEY") # Get YouTube API Key GOOGLE_TRANSLATE_API_KEY = os.getenv("GOOGLE_TRANSLATE_API_KEY") # GENIUS_ACCESS_TOKEN = os.getenv("GENIUS_API_KEY") MUSIXMATCH_API_KEY = os.getenv("MUSIXMATCH_API_KEY") # Set your API key def get_song_metadata_with_ai(youtube_title): """Ask the AI model to extract the song title and artist, and return them as a tuple.""" prompt = f"Extract the song name and artist from this video title: '{youtube_title}'. Return in this format: SONG - ARTIST" response = completion(model="gemini/gemini-2.0-flash", messages=[{"role": "user", "content": prompt}]) try: metadata_string = response.choices[0].message.content.strip() except (AttributeError, KeyError, IndexError): try: metadata_string = response['choices'][0]['message']['content'].strip() except (AttributeError, KeyError, IndexError): return (None, None) # Return a tuple of (None, None) on error # Split the string into song and artist parts = metadata_string.split(" - ") if len(parts) == 2: song, artist = parts[0].strip(), parts[1].strip() return (song, artist) # Return as a tuple else: # Handle cases where the format isn't "SONG - ARTIST" return (None, None) def fetch_lyrics_ai(song_title, artist): """Returns lyrics using Gemini API.""" prompt = f"Tell me the lyrics of the the song '{song_title}' by {artist}. Return only the lyrics, nothing else" response = completion(model="gemini/gemini-2.0-flash", messages=[{"role": "user", "content": prompt}]) try: lyrics = response.choices[0].message.content.strip() return lyrics except (AttributeError, KeyError, IndexError): try: lyrics = response['choices'][0]['message']['content'].strip() return lyrics except (AttributeError, KeyError, IndexError): return (None, None) # Return a tuple of (None, None) on error import requests def detect_language(text): """Detects the language of the text using Google Cloud Translation API.""" url = "https://translation.googleapis.com/language/translate/v2/detect" params = { "q": text, "key": GOOGLE_TRANSLATE_API_KEY } response = requests.post(url, params=params) result = response.json() try: # Ensure proper response format if "data" in result and "detections" in result["data"]: detections = result["data"]["detections"] # Check if detections is a list and contains at least one element if isinstance(detections, list) and len(detections) > 0 and isinstance(detections[0], list): detected_language_code = detections[0][0]["language"] return detected_language_code else: print(f"❌ Unexpected response format from Language Detection API: {result}") return None except (IndexError, TypeError, KeyError) as e: print(f"❌ Error processing response from Language Detection API: {e}, Response: {result}") return None def translate_text(text): """Translates text using Google Cloud Translation API""" print(f"Attempting to translate text: '{text}'") # ADDED: Print input text url = f"https://translation.googleapis.com/language/translate/v2" source_language = detect_language(text) print(source_language) params = { "q": text, "source": source_language, "target": "en", "format": "text", "key": GOOGLE_TRANSLATE_API_KEY } response = requests.post(url, params=params) print(f"Translation API Response Status Code: {response.status_code}") # ADDED: Print status code result = response.json() if "data" in result: return result["data"]["translations"][0]["translatedText"] else: print(f"❌ Error Response from Translation API: {result}") # ADDED: Print full error response return "❌ Error: Translation failed." # Initialize Translator @tool def song_meaning_tool(youtube_link: str) -> str: """ Extracts the lyrics of a song from a YouTube link, translates them to English, and provides the meaning of the song. Args: youtube_link: The URL of the YouTube song video. Returns: A summary of the song's meaning in English. """ try: # Extract Video ID from YouTube URL video_id = youtube_link.split("v=")[-1].split("&")[0] # Use YouTube API to get video details api_url = f"https://www.googleapis.com/youtube/v3/videos?part=snippet&id={video_id}&key={YOUTUBE_API_KEY}" response = requests.get(api_url) data = response.json() if "items" not in data or not data["items"]: return "❌ Error: Unable to retrieve song details. Check the YouTube link." # Get metadata # Extract raw YouTube title youtube_title = data["items"][0]["snippet"]["title"] # ✅ Use AI to extract the actual song title and artist song_title, artist = get_song_metadata_with_ai(youtube_title) if not song_title or not artist: return f"❌ Error: AI could not determine the song title and artist from '{youtube_title}'" print(f"🎵 AI Identified: {song_title} by {artist}") # Search for lyrics lyrics = fetch_lyrics_ai(song_title, artist) if "❌ Error" in lyrics: return f"{lyrics}\n\n⚠️ Could not find lyrics: **{song_title}**" print(f"Lyrics before translation: '{lyrics}'") # ADDED: Print lyrics # Translate to English translated_lyrics = translate_text(lyrics) # Summarize the song meaning summary_prompt = f"You are an expert in songs and their meanings. Mention the {song_title}' and summarize the meaning of the song in the desired length asked from the user. If no length is asked, give the answer in a few paragraphs with key themes in bullets:\n\n{translated_lyrics}" response = completion(model="gemini/gemini-2.0-flash", messages=[{"role": "user", "content": summary_prompt}]) try: song_meaning = response.choices[0].message.content.strip() return song_meaning except (AttributeError, KeyError, IndexError): try: song_meaning = response['choices'][0]['message']['content'].strip() return song_meaning except (AttributeError, KeyError, IndexError): return (None, None) # Return a tuple of (None, None) on error except Exception as e: return f"Error finding meaning of your song." final_answer = FinalAnswerTool() model = LiteLLMModel(model_id="gemini/gemini-2.0-flash") with open("prompts.yaml", 'r') as stream: prompt_templates = yaml.safe_load(stream) agent = CodeAgent( model=model, tools=[final_answer, song_meaning_tool], ## add your tools here (don't remove final answer) max_steps=6, verbosity_level=1, grammar=None, planning_interval=None, name=None, description=None, prompt_templates=prompt_templates ) GradioUI(agent).launch()