Spaces:
Sleeping
Sleeping
| from tavily import TavilyClient | |
| from langchain_core.prompts import ChatPromptTemplate | |
| import os | |
| class AINewsNode: | |
| def __init__(self, llm): | |
| """ | |
| Initializes the AI News Node. | |
| This class handles fetching and summarizing recent AI-related news | |
| using Tavily (a web search API) and an LLM (language model such as Groq). | |
| Args: | |
| llm: The language model used for generating summaries. | |
| """ | |
| # Create an instance of Tavily client to perform news searches | |
| self.tavily = TavilyClient() | |
| # Store the LLM (used later for summarization) | |
| self.llm = llm | |
| # A dictionary to store intermediate data such as frequency, fetched news, and summaries | |
| self.state = {} | |
| # ---------------------------------------------------------------------- | |
| def fetch_news(self, state: dict) -> dict: | |
| """ | |
| Fetch AI-related news articles using the Tavily API. | |
| Args: | |
| state (dict): The current graph state, expected to include | |
| 'messages' containing the news frequency (e.g., daily, weekly, monthly). | |
| Returns: | |
| dict: Updated state with 'news_data' containing the fetched news articles. | |
| """ | |
| # Extract frequency from user input (e.g., "daily", "weekly", etc.) | |
| frequency = state['messages'][0].content.lower() | |
| self.state['frequency'] = frequency | |
| # Mapping for Tavily's time range codes and days | |
| time_range_map = {'daily': 'd', 'weekly': 'w', 'monthly': 'm', 'year': 'y'} | |
| days_map = {'daily': 1, 'weekly': 7, 'monthly': 30, 'year': 366} | |
| # Perform a Tavily API search for the latest AI news | |
| response = self.tavily.search( | |
| query="Top Artificial Intelligence (AI) technology news globally", | |
| topic="news", | |
| time_range=time_range_map[frequency], # How far back to look | |
| include_answer="advanced", # Request detailed information | |
| max_results=20, # Limit number of news items | |
| days=days_map[frequency], # Number of days to consider | |
| # include_domains=["techcrunch.com", "venturebeat.com/ai", ...] # (Optional) restrict sources | |
| ) | |
| # Store the fetched results in the state dictionary | |
| state['news_data'] = response.get('results', []) | |
| self.state['news_data'] = state['news_data'] | |
| return state | |
| # ---------------------------------------------------------------------- | |
| def summarize_news(self, state: dict) -> dict: | |
| """ | |
| Summarize the fetched AI news articles using the provided LLM. | |
| Args: | |
| state (dict): The current graph state containing 'news_data'. | |
| Returns: | |
| dict: Updated state with 'summary' containing the summarized news in markdown format. | |
| """ | |
| # Get the list of fetched news articles | |
| news_items = self.state['news_data'] | |
| # Define how the summary should be formatted (markdown structure) | |
| prompt_template = ChatPromptTemplate.from_messages([ | |
| ("system", """Summarize AI news articles into markdown format. For each item include: | |
| - Date in **YYYY-MM-DD** format (IST timezone) | |
| - A concise summary of the news | |
| - Sorted by latest date first | |
| - Include the source URL as a link | |
| Use this format: | |
| ### [Date] | |
| - [Summary](URL)"""), | |
| ("user", "Articles:\n{articles}") | |
| ]) | |
| # Convert each article into a formatted string with content, URL, and publication date | |
| articles_str = "\n\n".join([ | |
| f"Content: {item.get('content', '')}\nURL: {item.get('url', '')}\nDate: {item.get('published_date', '')}" | |
| for item in news_items | |
| ]) | |
| # Ask the LLM to generate a markdown summary from the provided articles | |
| response = self.llm.invoke(prompt_template.format(articles=articles_str)) | |
| # Save the summary to the state | |
| state['summary'] = response.content | |
| self.state['summary'] = state['summary'] | |
| return self.state | |
| # ---------------------------------------------------------------------- | |
| def save_result(self, state): | |
| """ | |
| Save the summarized AI news to a markdown (.md) file. | |
| Args: | |
| state (dict): The current graph state (contains 'frequency' and 'summary'). | |
| Returns: | |
| dict: Updated state with 'filename' indicating where the summary file was saved. | |
| """ | |
| # Retrieve frequency and summary content from the state | |
| frequency = self.state['frequency'] | |
| summary = self.state['summary'] | |
| # Define output file path (e.g., ./AINews/daily_summary.md) | |
| filename = f"./AINews/{frequency}_summary.md" | |
| os.makedirs(os.path.dirname(filename), exist_ok=True) | |
| # Write the summary content to a markdown file | |
| with open(filename, 'w') as f: | |
| f.write(f"# {frequency.capitalize()} AI News Summary\n\n") | |
| f.write(summary) | |
| # Save filename in the state for reference | |
| self.state['filename'] = filename | |
| return self.state | |