CoolFace
Apppublic

Shafagh99/Daily_Headlines_Assistant

sourceHugging Faceupdated 8mo agoView on Hugging Face
0likes
app.py226 linesDownload Raw Back to root
1from smolagents import CodeAgent, DuckDuckGoSearchTool, InferenceClientModel, load_tool, tool2import datetime3import requests4import pytz5import yaml6import gradio as gr7from tools.final_answer import FinalAnswerTool8 9# Below is an example of a tool that does nothing. Amaze us with your creativity !10@tool11def my_custom_tool(arg1: str, arg2: int) -> str:  # it's important to specify the return type12    # Keep this format for the description / args / args description but feel free to modify the tool13    """Fetch and nicely format top headlines from popular news sources for today.14 15    Args:16        arg1: Comma-separated list of sources to include (options: "bbc", "nyt", "guardian", "hn", "all").17              Use "all" or empty string to fetch from all supported sources.18        arg2: Maximum number of headlines per source (must be > 0).19 20    This tool scrapes public RSS feeds (no API key needed) and returns a21    markdown-formatted string grouped by source, with each headline on its own line22    and linked to the original article when available.23    """24    import xml.etree.ElementTree as ET25 26    if arg2 <= 0:27        return "Please provide a positive integer number of headlines per source for arg2."28 29    # Normalize requested sources30    requested = [s.strip().lower() for s in arg1.split(",")] if arg1 else []31    if not requested or "all" in requested:32        requested = ["bbc", "nyt", "guardian", "hn"]33 34    # Supported sources and their RSS URLs35    sources = {36        "bbc": {37            "name": "BBC News",38            "url": "https://feeds.bbci.co.uk/news/rss.xml",39        },40        "nyt": {41            "name": "The New York Times",42            "url": "https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml",43        },44        "guardian": {45            "name": "The Guardian",46            "url": "https://www.theguardian.com/world/rss",47        },48        "hn": {49            "name": "Hacker News (Top)",50            "url": "https://hnrss.org/frontpage",51        },52    }53 54    picked_keys = [k for k in requested if k in sources]55    if not picked_keys:56        return (57            "No valid news sources selected. Valid options: bbc, nyt, guardian, hn, all."58        )59 60    output_sections = []61 62    for key in picked_keys:63        meta = sources[key]64        name = meta["name"]65        url = meta["url"]66 67        try:68            resp = requests.get(url, timeout=8)69            resp.raise_for_status()70            root = ET.fromstring(resp.content)71 72            # RSS structure: channel/item/title/link73            items = []74            for item in root.findall(".//item"):75                title_el = item.find("title")76                link_el = item.find("link")77                if title_el is not None and title_el.text:78                    title = title_el.text.strip()79                    link = link_el.text.strip() if link_el is not None and link_el.text else ""80                    if title:81                        items.append((title, link))82                if len(items) >= arg2:83                    break84 85            if not items:86                output_sections.append(f"### {name}\n\n_(no headlines found)_")87            else:88                lines = []89                for idx, (title, link) in enumerate(items, start=1):90                    if link:91                        lines.append(f"{idx}. [{title}]({link})")92                    else:93                        lines.append(f"{idx}. {title}")94                joined = "\n".join(lines)95                output_sections.append(f"### {name} (top {len(items)})\n\n{joined}")96        except Exception as e:97            output_sections.append(f"### {name}\n\n_Error fetching headlines: {e}_")98 99    header = "## Top headlines from popular news sources\n"100    return header + "\n\n" + "\n\n".join(output_sections)101 102@tool103def get_current_time_in_timezone(timezone: str) -> str:104    """A tool that fetches the current local time in a specified timezone.105    Args:106        timezone: A string representing a valid timezone (e.g., 'America/New_York').107    """108    try:109        # Create timezone object110        tz = pytz.timezone(timezone)111        # Get current time in that timezone112        local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")113        return f"The current local time in {timezone} is: {local_time}"114    except Exception as e:115        return f"Error fetching time for timezone '{timezone}': {str(e)}"116 117 118final_answer = FinalAnswerTool()119 120# 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:121# model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud' 122 123model = InferenceClientModel(124    max_tokens=2096,125    temperature=0.5,126    model_id='Qwen/Qwen2.5-Coder-32B-Instruct',  # it is possible that this model may be overloaded127    custom_role_conversions=None,128)129 130 131# Import tool from Hub132image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)133 134with open("prompts.yaml", 'r') as stream:135    prompt_templates = yaml.safe_load(stream)136    137agent = CodeAgent(138    model=model,139    tools=[final_answer, my_custom_tool, get_current_time_in_timezone, image_generation_tool],  # don't remove final_answer140    max_steps=6,141    verbosity_level=1,142    name=None,143    description=None,144)145 146 147def chat_fn(message, history):148    """Chat handler for Gradio.149 150    If the user is asking for headlines, we bypass the agent and call the151    headlines tool directly so the nicely formatted markdown is returned152    as-is. For other queries, we fall back to the CodeAgent.153    """154    text = (message or "").lower().strip()155 156    # Special handling for capability / "what can you do" questions157    if any(phrase in text for phrase in ["what can you do", "what you can do", "help me", "how can you help"]):158        return (159            "I’m your **Daily Headlines Assistant**.\n\n"160            "- I fetch today’s top headlines from **BBC**, **The New York Times**, "161            "**The Guardian**, and **Hacker News** using live RSS feeds.\n"162            "- I format them into a clean, grouped markdown view with **clickable links**.\n"163            "- I can also tell you the **current time in any timezone** and generate images from text prompts.\n\n"164            "Try asking things like:\n"165            "- \"Show me today’s top 3 headlines from BBC, NYT and Hacker News.\"\n"166            "- \"Give me the top 5 headlines from BBC only.\"\n"167            "- \"What time is it now in America/New_York?\"\n"168        )169    wants_news = any(170        kw in text171        for kw in ["headline", "headlines", "bbc", "nyt", "new york times", "guardian", "hacker news", "hn"]172    )173 174    if wants_news:175        # Simple heuristic: default to all sources and 3 headlines if user176        # does not specify numbers; otherwise, try to extract a small integer.177        import re178 179        match = re.search(r"\b(\d{1,2})\b", text)180        count = int(match.group(1)) if match else 3181        # Map some common names to our source keys182        sources = []183        if "bbc" in text:184            sources.append("bbc")185        if "nyt" in text or "new york times" in text:186            sources.append("nyt")187        if "guardian" in text:188            sources.append("guardian")189        if "hacker news" in text or "hn" in text:190            sources.append("hn")191        # If nothing specific mentioned, use all192        arg1 = ",".join(sources) if sources else "all"193 194        try:195            return my_custom_tool(arg1=arg1, arg2=count)196        except Exception as e:197            return f"Error while fetching headlines: {e}"198 199    # Fallback: use the full agent for non-news tasks200    try:201        result = agent.run(task=message)202    except Exception as e:203        result = f"Error while running the agent: {e}"204    if result is None:205        result = (206            "The agent did not produce a final answer (the upstream model may have "207            "returned an error like 502). Please try again or with a simpler request."208        )209    return str(result)210 211 212demo = gr.ChatInterface(213    fn=chat_fn,214    title="Daily Headlines Assistant",215    description=(216        "Ask for today's top headlines from BBC, The New York Times, The Guardian, "217        "and Hacker News. Results include clickable links and are grouped by source."218    ),219    examples=[220        "Show me today’s top 3 headlines from BBC, NYT and Hacker News.",221        "Give me the top 5 headlines from BBC only.",222        "Fetch today’s main stories from The Guardian and Hacker News.",223    ],224)225 226demo.launch()