Spaces:
Sleeping
Sleeping
| from smolagents import CodeAgent, DuckDuckGoSearchTool, InferenceClientModel, load_tool, tool | |
| import datetime | |
| import requests | |
| import pytz | |
| import yaml | |
| import gradio as gr | |
| from tools.final_answer import FinalAnswerTool | |
| # Below is an example of a tool that does nothing. Amaze us with your creativity ! | |
| def my_custom_tool(arg1: str, arg2: int) -> str: # it's important to specify the return type | |
| # Keep this format for the description / args / args description but feel free to modify the tool | |
| """Fetch and nicely format top headlines from popular news sources for today. | |
| Args: | |
| arg1: Comma-separated list of sources to include (options: "bbc", "nyt", "guardian", "hn", "all"). | |
| Use "all" or empty string to fetch from all supported sources. | |
| arg2: Maximum number of headlines per source (must be > 0). | |
| This tool scrapes public RSS feeds (no API key needed) and returns a | |
| markdown-formatted string grouped by source, with each headline on its own line | |
| and linked to the original article when available. | |
| """ | |
| import xml.etree.ElementTree as ET | |
| if arg2 <= 0: | |
| return "Please provide a positive integer number of headlines per source for arg2." | |
| # Normalize requested sources | |
| requested = [s.strip().lower() for s in arg1.split(",")] if arg1 else [] | |
| if not requested or "all" in requested: | |
| requested = ["bbc", "nyt", "guardian", "hn"] | |
| # Supported sources and their RSS URLs | |
| sources = { | |
| "bbc": { | |
| "name": "BBC News", | |
| "url": "https://feeds.bbci.co.uk/news/rss.xml", | |
| }, | |
| "nyt": { | |
| "name": "The New York Times", | |
| "url": "https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml", | |
| }, | |
| "guardian": { | |
| "name": "The Guardian", | |
| "url": "https://www.theguardian.com/world/rss", | |
| }, | |
| "hn": { | |
| "name": "Hacker News (Top)", | |
| "url": "https://hnrss.org/frontpage", | |
| }, | |
| } | |
| picked_keys = [k for k in requested if k in sources] | |
| if not picked_keys: | |
| return ( | |
| "No valid news sources selected. Valid options: bbc, nyt, guardian, hn, all." | |
| ) | |
| output_sections = [] | |
| for key in picked_keys: | |
| meta = sources[key] | |
| name = meta["name"] | |
| url = meta["url"] | |
| try: | |
| resp = requests.get(url, timeout=8) | |
| resp.raise_for_status() | |
| root = ET.fromstring(resp.content) | |
| # RSS structure: channel/item/title/link | |
| items = [] | |
| for item in root.findall(".//item"): | |
| title_el = item.find("title") | |
| link_el = item.find("link") | |
| if title_el is not None and title_el.text: | |
| title = title_el.text.strip() | |
| link = link_el.text.strip() if link_el is not None and link_el.text else "" | |
| if title: | |
| items.append((title, link)) | |
| if len(items) >= arg2: | |
| break | |
| if not items: | |
| output_sections.append(f"### {name}\n\n_(no headlines found)_") | |
| else: | |
| lines = [] | |
| for idx, (title, link) in enumerate(items, start=1): | |
| if link: | |
| lines.append(f"{idx}. [{title}]({link})") | |
| else: | |
| lines.append(f"{idx}. {title}") | |
| joined = "\n".join(lines) | |
| output_sections.append(f"### {name} (top {len(items)})\n\n{joined}") | |
| except Exception as e: | |
| output_sections.append(f"### {name}\n\n_Error fetching headlines: {e}_") | |
| header = "## Top headlines from popular news sources\n" | |
| return header + "\n\n" + "\n\n".join(output_sections) | |
| def get_current_time_in_timezone(timezone: str) -> str: | |
| """A tool that fetches the current local time in a specified timezone. | |
| Args: | |
| timezone: A string representing a valid timezone (e.g., 'America/New_York'). | |
| """ | |
| try: | |
| # Create timezone object | |
| tz = pytz.timezone(timezone) | |
| # Get current time in that timezone | |
| local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S") | |
| return f"The current local time in {timezone} is: {local_time}" | |
| except Exception as e: | |
| return f"Error fetching time for timezone '{timezone}': {str(e)}" | |
| final_answer = FinalAnswerTool() | |
| # 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 = InferenceClientModel( | |
| max_tokens=2096, | |
| temperature=0.5, | |
| model_id='Qwen/Qwen2.5-Coder-32B-Instruct', # it is possible that this model may be overloaded | |
| custom_role_conversions=None, | |
| ) | |
| # Import tool from Hub | |
| image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True) | |
| with open("prompts.yaml", 'r') as stream: | |
| prompt_templates = yaml.safe_load(stream) | |
| agent = CodeAgent( | |
| model=model, | |
| tools=[final_answer, my_custom_tool, get_current_time_in_timezone, image_generation_tool], # don't remove final_answer | |
| max_steps=6, | |
| verbosity_level=1, | |
| name=None, | |
| description=None, | |
| ) | |
| def chat_fn(message, history): | |
| """Chat handler for Gradio. | |
| If the user is asking for headlines, we bypass the agent and call the | |
| headlines tool directly so the nicely formatted markdown is returned | |
| as-is. For other queries, we fall back to the CodeAgent. | |
| """ | |
| text = (message or "").lower().strip() | |
| # Special handling for capability / "what can you do" questions | |
| if any(phrase in text for phrase in ["what can you do", "what you can do", "help me", "how can you help"]): | |
| return ( | |
| "I’m your **Daily Headlines Assistant**.\n\n" | |
| "- I fetch today’s top headlines from **BBC**, **The New York Times**, " | |
| "**The Guardian**, and **Hacker News** using live RSS feeds.\n" | |
| "- I format them into a clean, grouped markdown view with **clickable links**.\n" | |
| "- I can also tell you the **current time in any timezone** and generate images from text prompts.\n\n" | |
| "Try asking things like:\n" | |
| "- \"Show me today’s top 3 headlines from BBC, NYT and Hacker News.\"\n" | |
| "- \"Give me the top 5 headlines from BBC only.\"\n" | |
| "- \"What time is it now in America/New_York?\"\n" | |
| ) | |
| wants_news = any( | |
| kw in text | |
| for kw in ["headline", "headlines", "bbc", "nyt", "new york times", "guardian", "hacker news", "hn"] | |
| ) | |
| if wants_news: | |
| # Simple heuristic: default to all sources and 3 headlines if user | |
| # does not specify numbers; otherwise, try to extract a small integer. | |
| import re | |
| match = re.search(r"\b(\d{1,2})\b", text) | |
| count = int(match.group(1)) if match else 3 | |
| # Map some common names to our source keys | |
| sources = [] | |
| if "bbc" in text: | |
| sources.append("bbc") | |
| if "nyt" in text or "new york times" in text: | |
| sources.append("nyt") | |
| if "guardian" in text: | |
| sources.append("guardian") | |
| if "hacker news" in text or "hn" in text: | |
| sources.append("hn") | |
| # If nothing specific mentioned, use all | |
| arg1 = ",".join(sources) if sources else "all" | |
| try: | |
| return my_custom_tool(arg1=arg1, arg2=count) | |
| except Exception as e: | |
| return f"Error while fetching headlines: {e}" | |
| # Fallback: use the full agent for non-news tasks | |
| try: | |
| result = agent.run(task=message) | |
| except Exception as e: | |
| result = f"Error while running the agent: {e}" | |
| if result is None: | |
| result = ( | |
| "The agent did not produce a final answer (the upstream model may have " | |
| "returned an error like 502). Please try again or with a simpler request." | |
| ) | |
| return str(result) | |
| demo = gr.ChatInterface( | |
| fn=chat_fn, | |
| title="Daily Headlines Assistant", | |
| description=( | |
| "Ask for today's top headlines from BBC, The New York Times, The Guardian, " | |
| "and Hacker News. Results include clickable links and are grouped by source." | |
| ), | |
| examples=[ | |
| "Show me today’s top 3 headlines from BBC, NYT and Hacker News.", | |
| "Give me the top 5 headlines from BBC only.", | |
| "Fetch today’s main stories from The Guardian and Hacker News.", | |
| ], | |
| ) | |
| demo.launch() |