Spaces:
Sleeping
Sleeping
| from smolagents import CodeAgent,DuckDuckGoSearchTool, HfApiModel,load_tool,tool, OpenAIServerModel | |
| import datetime | |
| import requests | |
| import pytz | |
| import yaml | |
| import os | |
| from collections import defaultdict | |
| from tools.final_answer import FinalAnswerTool | |
| from tools.web_search import DuckDuckGoSearchTool | |
| from tools.visit_webpage import VisitWebpageTool | |
| from Gradio_UI import GradioUI | |
| # Below is an example of a tool that does nothing. Amaze us with your creativity ! | |
| #@tool | |
| #def my_custom_tool(arg1:str, arg2:int)-> str: #it's import to specify the return type | |
| # #Keep this format for the description / args / args description but feel free to modify the tool | |
| # """A tool that does nothing yet | |
| # Args: | |
| # arg1: the first argument | |
| # arg2: the second argument | |
| # """ | |
| # return "What magic will you build ?" | |
| def get_pokedex_entry(pokemon_name: str) -> str: | |
| """ | |
| Fetches the English Pokédex entry (flavor text) or dex entry for the given Pokémon. | |
| Args: | |
| pokemon_name: Name or ID of the Pokémon (e.g., 'pikachu'). | |
| Returns: | |
| A string containing the Pokémon's English Pokédex entry or an error message. | |
| """ | |
| # Normalize name/ID and construct URL | |
| name = pokemon_name.strip().lower() | |
| url = f"https://pokeapi.co/api/v2/pokemon-species/{name}/" | |
| # Request data from PokéAPI | |
| response = requests.get(url, timeout=5) | |
| if response.status_code != 200: | |
| return f"Error: Pokémon '{pokemon_name}' not found (HTTP {response.status_code})." | |
| data = response.json() | |
| # Filter for English flavor-text entries | |
| flavor_texts = [ | |
| entry["flavor_text"] | |
| for entry in data.get("flavor_text_entries", []) | |
| if entry["language"]["name"] == "en" | |
| ] | |
| if not flavor_texts: | |
| return f"No English Pokédex entry available for '{pokemon_name}'." | |
| # Clean up the first entry by replacing newlines/form feeds with spaces | |
| entry = flavor_texts[0].replace("\n", " ").replace("\f", " ") | |
| # Capitalize the Pokémon name for presentation | |
| title = pokemon_name.strip().title() | |
| return f"{title}: {entry}" | |
| def get_pokemon_basic_info(pokemon_name: str) -> str: | |
| """ | |
| Fetches basic information about a Pokémon, such as its ID, height, weight, and types. | |
| Args: | |
| pokemon_name: The name or ID of the Pokémon (e.g., 'pikachu'). | |
| Returns: | |
| A string summarizing the Pokémon's ID, height, weight, and types, or an error message. | |
| """ | |
| name = pokemon_name.strip().lower() | |
| url = f"https://pokeapi.co/api/v2/pokemon/{name}/" | |
| response = requests.get(url, timeout=5) | |
| if response.status_code != 200: | |
| return f"Error: Pokémon '{pokemon_name}' not found (HTTP {response.status_code})." | |
| data = response.json() | |
| types = ', '.join([t['type']['name'].title() for t in data.get('types', [])]) | |
| return ( | |
| f"{data['name'].title()} (ID: {data['id']}):\n" | |
| f"Height: {data['height']} Weight: {data['weight']}\n" | |
| f"Types: {types}" | |
| ) | |
| def get_pokemon_abilities(pokemon_name: str) -> str: | |
| """ | |
| Retrieves a list of abilities for a given Pokémon, distinguishing between normal and hidden abilities. | |
| Args: | |
| pokemon_name: The name or ID of the Pokémon. | |
| Returns: | |
| A string listing the Pokémon's abilities, labeled as Normal or Hidden, or an error message. | |
| """ | |
| name = pokemon_name.strip().lower() | |
| url = f"https://pokeapi.co/api/v2/pokemon/{name}/" | |
| response = requests.get(url, timeout=5) | |
| if response.status_code != 200: | |
| return f"Error: Pokémon '{pokemon_name}' not found (HTTP {response.status_code})." | |
| data = response.json() | |
| abilities = [] | |
| for ability_info in data.get('abilities', []): | |
| ability_name = ability_info['ability']['name'].replace('-', ' ').title() | |
| label = "Hidden" if ability_info.get('is_hidden', False) else "Normal" | |
| abilities.append(f"{ability_name} ({label})") | |
| if not abilities: | |
| return f"No abilities found for '{pokemon_name}'." | |
| return f"{pokemon_name.title()}'s abilities:\n" + "\n".join(abilities) | |
| def get_pokemon_base_stats(pokemon_name: str) -> str: | |
| """ | |
| Fetches the base stats (HP, Attack, Defense, etc.) of a Pokémon. | |
| Args: | |
| pokemon_name: The name or ID of the Pokémon. | |
| Returns: | |
| A string summarizing the Pokémon's base stats or an error message. | |
| """ | |
| name = pokemon_name.strip().lower() | |
| url = f"https://pokeapi.co/api/v2/pokemon/{name}/" | |
| response = requests.get(url, timeout=5) | |
| if response.status_code != 200: | |
| return f"Error: Pokémon '{pokemon_name}' not found (HTTP {response.status_code})." | |
| data = response.json() | |
| stats = {s['stat']['name'].replace('-', ' ').title(): s['base_stat'] for s in data.get('stats', [])} | |
| if not stats: | |
| return f"No base stats found for '{pokemon_name}'." | |
| stats_str = ', '.join([f"{k}: {v}" for k, v in stats.items()]) | |
| return f"{pokemon_name.title()}'s base stats: {stats_str}" | |
| def get_pokemon_evolutions(pokemon_name: str) -> str: | |
| """ | |
| Retrieves the evolution chain for a given Pokémon. | |
| Args: | |
| pokemon_name: The name or ID of the Pokémon. | |
| Returns: | |
| A string listing the evolution chain or an error message. | |
| """ | |
| # Step 1: Get species info to find evolution chain URL | |
| species_url = f"https://pokeapi.co/api/v2/pokemon-species/{pokemon_name.strip().lower()}/" | |
| species_response = requests.get(species_url, timeout=5) | |
| if species_response.status_code != 200: | |
| return f"Error: Pokémon '{pokemon_name}' not found (HTTP {species_response.status_code})." | |
| species_data = species_response.json() | |
| evo_chain_url = species_data.get('evolution_chain', {}).get('url') | |
| if not evo_chain_url: | |
| return f"No evolution chain found for '{pokemon_name}'." | |
| # Step 2: Get evolution chain data | |
| evo_response = requests.get(evo_chain_url, timeout=5) | |
| if evo_response.status_code != 200: | |
| return f"Error fetching evolution chain (HTTP {evo_response.status_code})." | |
| evo_data = evo_response.json() | |
| # Recursive function to extract evolution names | |
| def extract_chain(chain): | |
| names = [chain['species']['name'].title()] | |
| for evo in chain.get('evolves_to', []): | |
| names.extend(extract_chain(evo)) | |
| return names | |
| evo_names = extract_chain(evo_data['chain']) | |
| return f"Evolution chain: {' → '.join(evo_names)}" | |
| def get_pokemon_moves_grouped(pokemon_name: str) -> str: | |
| """ | |
| Lists all moves a Pokémon can learn, grouped by move name, showing the minimum level (if applicable), | |
| all learning methods, and all game versions. Egg moves are listed separately with their versions. | |
| Args: | |
| pokemon_name: The name or ID of the Pokémon. | |
| Returns: | |
| A string listing the Pokémon's moves, grouped by name, with levels, methods, and versions, or an error message. | |
| """ | |
| name = pokemon_name.strip().lower() | |
| url = f"https://pokeapi.co/api/v2/pokemon/{name}/" | |
| response = requests.get(url, timeout=5) | |
| if response.status_code != 200: | |
| return f"Error: Pokémon '{pokemon_name}' not found (HTTP {response.status_code})." | |
| data = response.json() | |
| moves_dict = defaultdict(lambda: {'level': None, 'versions': set(), 'methods': set()}) | |
| egg_moves_dict = defaultdict(set) | |
| for move in data.get('moves', []): | |
| move_name = move['move']['name'].replace('-', ' ').title() | |
| for detail in move.get('version_group_details', []): | |
| method = detail['move_learn_method']['name'].replace('-', ' ').title() | |
| version = detail['version_group']['name'].replace('-', ' ').title() | |
| level = detail['level_learned_at'] | |
| if method == "Egg": | |
| egg_moves_dict[move_name].add(version) | |
| else: | |
| moves_dict[move_name]['methods'].add(method) | |
| moves_dict[move_name]['versions'].add(version) | |
| # For level-up moves, keep the minimum level learned | |
| if method == "Level Up": | |
| if moves_dict[move_name]['level'] is None or level < moves_dict[move_name]['level']: | |
| moves_dict[move_name]['level'] = level | |
| # Prepare moves output | |
| moves_lines = [] | |
| for move_name, info in sorted(moves_dict.items()): | |
| versions_str = ', '.join(sorted(info['versions'])) | |
| methods_str = ', '.join(sorted(info['methods'])) | |
| if info['level'] is not None: | |
| moves_lines.append(f"{move_name} (Level {info['level']}, Versions: {versions_str})") | |
| else: | |
| moves_lines.append(f"{move_name} (Methods: {methods_str}, Versions: {versions_str})") | |
| # Prepare egg moves output | |
| egg_lines = [] | |
| for move_name, versions in sorted(egg_moves_dict.items()): | |
| versions_str = ', '.join(sorted(versions)) | |
| egg_lines.append(f"{move_name} (Egg Move in: {versions_str})") | |
| # Limit output for readability | |
| moves_preview = '\n'.join(moves_lines[:20]) | |
| more_moves = f"\n...and {len(moves_lines)-20} more moves." if len(moves_lines) > 20 else "" | |
| egg_moves_output = '\n'.join(egg_lines) if egg_lines else 'None' | |
| return ( | |
| f"{pokemon_name.title()} can learn these moves grouped by name with versions and levels:\n" | |
| f"{moves_preview}{more_moves}\n\n" | |
| f"Egg moves:\n{egg_moves_output}" | |
| ) | |
| final_answer = FinalAnswerTool() | |
| #search_tool = DuckDuckGoSearchTool() | |
| #webpage_tool = VisitWebpageTool() | |
| # If the agent does not answer, the model is overloaded, please use another model or the following Hugging Face Endpoint that also contains qwen2.5 coder: | |
| # model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud' | |
| #model = OpenAIServerModel( | |
| # model_id="deepseek/deepseek-r1-0528-qwen3-8b:free", | |
| # api_base="https://openrouter.ai/api/v1", # Leave this blank to query OpenAI servers. | |
| # api_key=os.environ["OPENROUTER_API_KEY"], # Switch to the API key for the server you're targeting. | |
| # | |
| #) | |
| model = OpenAIServerModel( | |
| model_id="meta-llama/Llama-3.3-70B-Instruct-Turbo-Free", | |
| #model_id="meta-llama/Llama-Vision-Free", | |
| api_base="https://api.together.xyz/v1/", # Leave this blank to query OpenAI servers. | |
| api_key=os.environ["TOGETHER_API_KEY"], # Switch to the API key for the server you're targeting. | |
| ) | |
| with open("prompts.yaml", 'r') as stream: | |
| prompt_templates = yaml.safe_load(stream) | |
| agent = CodeAgent( | |
| model=model, | |
| tools=[final_answer,get_pokedex_entry,get_pokemon_basic_info,get_pokemon_abilities,get_pokemon_base_stats,get_pokemon_evolutions,get_pokemon_moves_grouped], ## add your tools here (don't remove final answer) | |
| max_steps=6, | |
| verbosity_level=2, | |
| grammar=None, | |
| planning_interval=None, | |
| name=None, | |
| description=None, | |
| prompt_templates=prompt_templates | |
| ) | |
| GradioUI(agent).launch() |