Skip to content

Commit

Permalink
[FUCNTIONAL]
Browse files Browse the repository at this point in the history
  • Loading branch information
Your Name committed Sep 23, 2024
1 parent 15454b3 commit aacda07
Show file tree
Hide file tree
Showing 11 changed files with 890 additions and 11 deletions.
151 changes: 151 additions & 0 deletions agent_workspace/News-Agent-V1_state.json

Large diffs are not rendered by default.

Empty file added agent_workspace/error.txt
Empty file.
51 changes: 51 additions & 0 deletions example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import os

from dotenv import load_dotenv
from swarm_models import OpenAIChat
from swarms import Agent

from news_agent.main import NewsAgent

load_dotenv()

# Get the OpenAI API key from the environment variable
api_key = os.getenv("OPENAI_API_KEY")

# Create an instance of the OpenAIChat class
model = OpenAIChat(
openai_api_key=api_key, model_name="gpt-4o-mini", temperature=0.1
)

# Initialize the agent
agent = Agent(
agent_name="News-Agent-V1",
# system_prompt=FINANCIAL_AGENT_SYS_PROMPT,
llm=model,
max_loops=1,
autosave=True,
dashboard=False,
verbose=True,
dynamic_temperature_enabled=True,
saved_state_path="news_agent.json",
user_name="swarms_corp",
retry_attempts=1,
context_length=200000,
return_step_meta=False,
# output_type="json",
)

# Agent
agent = NewsAgent(
agent_name="news-agent-v1",
agent=agent,
newsapi_api_key=os.getenv("NEWSAPI_API_KEY"),
system_prompt=None,
return_json=True,
# start_date="2024-08-01",
# end_date="2024-08-10"
)


# Run the agent
# agent.run(["multi-agent collaboration"])
agent.run_concurrently(["Swarm Multi-Agent", "AGI"])
183 changes: 183 additions & 0 deletions news_agent/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import os
import time
import uuid
from concurrent.futures import ThreadPoolExecutor
from typing import List, Optional, Any
from news_agent.prompts import NEWS_SYS_PROMPT
from pydantic import BaseModel, Field
from swarms import Agent, create_file_in_folder

from news_agent.tool import fetch_stock_news


class InputLog(BaseModel):
id: Optional[str] = Field(
default=str(uuid.uuid4()),
description="Unique identifier for the input log",
)
query: Optional[str]
start_date: Optional[Any]
end_date: Optional[Any]
return_json: Optional[bool]
max_articles: Optional[int] = 5
time_stamp: Optional[str] = Field(
default=time.strftime("%Y-%m-%d %H:%M:%S"),
description="Timestamp of the input log",
)


class OutputLogSummaries(BaseModel):
id: Optional[str] = Field(
default=str(uuid.uuid4()),
description="Unique identifier for the output log summary",
)
articles: Optional[Any] # Accept list of dictionaries
summary: Optional[str]
time_stamp: Optional[str] = Field(
default=time.strftime("%Y-%m-%d %H:%M:%S"),
description="Timestamp of the output log summary",
)


class OutputLog(BaseModel):
id: Optional[str] = Field(
default=str(uuid.uuid4()),
description="Unique identifier for the output log",
)
input_log: Optional[InputLog]
output_logs: Optional[List[OutputLogSummaries]] = Field(
..., description=None
)
time_stamp: Optional[str] = Field(
default=time.strftime("%Y-%m-%d %H:%M:%S"),
description="Timestamp of the output log",
)


def check_newsapi() -> str:
try:
key = os.getenv("NEWSAPI_API_KEY")
return key
except Exception:
return None


class NewsAgent(Agent):
"""
A specialized agent for fetching and processing news articles based on given tasks.
It utilizes the News API to fetch articles and a language model to generate summaries.
"""

def __init__(
self,
agent_name: str = "news_agent_v1",
newsapi_api_key: str = None,
system_prompt: str = None,
agent: Agent = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
return_json: bool = False,
max_articles: int = 5,
autosave: bool = False,
):
"""
Initializes the NewsAgent with the necessary parameters.
Args:
agent_name (str): The name of the agent.
newsapi_api_key (str, optional): The API key for News API. Defaults to None.
system_prompt (str, optional): The system prompt for the language model. Defaults to None.
llm (BaseLLM, optional): The language model to use for summarization. Defaults to None.
agent (Agent, optional): The base agent to inherit from. Defaults to None.
start_date (Optional[str], optional): The start date for the news query in 'YYYY-MM-DD' format. Defaults to None.
end_date (Optional[str], optional): The end date for the news query in 'YYYY-MM-DD' format. Defaults to None.
return_json (bool, optional): If True, return the result as a JSON object, otherwise return a formatted string. Defaults to False.
max_articles (int, optional): The maximum number of articles to fetch. Defaults to 5.
"""
self.agent_name = agent_name
self.system_prompt = system_prompt
self.newsapi_api_key = newsapi_api_key
self.start_date = start_date
self.end_date = end_date
self.return_json = return_json
self.max_articles = max_articles
self.agent = agent
self.autosave = autosave

self.output_log = OutputLog(
input_log=InputLog(
query="",
start_date=start_date,
end_date=end_date,
return_json=return_json,
max_articles=max_articles,
),
output_logs=[],
)

# Transition the sys prompt of the agent
self.agent.system_prompt = NEWS_SYS_PROMPT

def run(self, tasks: List[str], *args, **kwargs):
"""
Runs the news fetching and summarization process sequentially for each task.
Args:
tasks (List[str]): A list of tasks or queries to process.
Returns:
Union[str, dict]: The output of the process, either a formatted string or a JSON object depending on the return_json parameter.
"""
for task in tasks:
self.output_log.input_log.query = task

string_query, data_dict = fetch_stock_news(
task,
self.newsapi_api_key,
self.start_date,
self.end_date,
max_articles=self.max_articles,
)
print(type(data_dict))

summary = self.agent.run(string_query)

output_log_indi = OutputLogSummaries(
articles=data_dict,
summary=summary,
)

self.output_log.output_logs.append(output_log_indi)

# Save the log
create_file_in_folder(
"news_agent_runs",
f"news_agent_run_id:{self.output_log.id}.json",
self.output_log.model_dump_json(indent=4),
)

if self.return_json is True:
return self.output_log.model_dump_json(indent=4)

else:
return summary

def run_concurrently(self, tasks: List[str]) -> str:
"""
Runs the news fetching and summarization process concurrently for each task.
Args:
tasks (List[str]): A list of tasks or queries to process.
Returns:
str: The output of the process as a JSON object.
"""
with ThreadPoolExecutor() as executor:
futures = {
executor.submit(self.run, [task]): task
for task in tasks
}
for future in futures:
future.result() # Wait for all tasks to complete

return self.output_log.model_dump_json(indent=4)
56 changes: 56 additions & 0 deletions news_agent/prompts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
NEWS_SYS_PROMPT = """
### **System Prompt: News Article Summarization Agent**
#### **Objective:**
You are an advanced LLM agent specialized in summarizing news articles for enterprise use. Your goal is to provide concise, informative, and strategic summaries that highlight key points, context, and potential implications for decision-makers.
Always reference the authors and the URL links associated with each article.
---
### **Instructions:**
1. **Understand the context first**:
- **Step 1**: Read the entire news article carefully, ensuring that you comprehend the subject matter and context.
- **Step 2**: Identify the main topic, key events, participants (individuals or organizations), and any significant quotes, data, or statistics.
- **Step 3**: Capture the overall tone (e.g., positive, neutral, negative) and the impact of the news (e.g., market, social, economic, political).
2. **Identify key information**:
- **Step 4**: Extract the five W’s:
- **Who**: Identify key people or organizations involved.
- **What**: Outline the main event or issue.
- **Where**: Indicate the location if relevant.
- **When**: Mention the timing or date of the event.
- **Why**: Summarize the reason or cause behind the event.
- **Step 5**: Note any important outcomes or potential future developments mentioned in the article.
3. **Summarize strategically**:
- **Step 6**: Write a summary in no more than 3-5 sentences for quick decision-making:
- **Introduction**: Start with a one-sentence overview of the topic.
- **Core facts**: Provide 2-3 sentences detailing the most important facts (i.e., key actors, events, and outcomes).
- **Implications**: End with a strategic insight on the impact of this news on the relevant industry, market, or business domain (e.g., “This could lead to…”).
- **Step 7**: Prioritize clarity, conciseness, and relevance to enterprise use (e.g., focus on market impacts, regulations, or leadership changes that affect business strategy).
4. **Tailor for the audience**:
- **Step 8**: Consider who will be reading the summary. If they are executives, focus more on high-level, strategic insights (e.g., business risks, opportunities). If they are analysts, include more granular details (e.g., specific data points, financial impact).
---
### **What NOT to Do:**
1. **Do NOT repeat the article verbatim**:
- Avoid copying long phrases or entire sentences from the article. Use your own words to provide a fresh and concise summary.
2. **Do NOT provide excessive details**:
- Do not include unnecessary information such as minor details, unimportant background, or excessive historical context unless relevant to understanding the current event.
3. **Do NOT add personal opinions or bias**:
- Stay neutral. Do not speculate or introduce your own interpretations of the event.
4. **Do NOT ignore critical data**:
- Always include important numerical data, quotes, or facts that are central to the story.
5. **Do NOT provide a purely factual summary without strategic insight**:
- Go beyond just facts. Provide a short strategic insight on how the news might impact industries, businesses, or global markets.
"""
105 changes: 105 additions & 0 deletions news_agent/tool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
from newsapi import NewsApiClient
from typing import Optional, Dict, Union, List


def fetch_stock_news(
query: str,
newsapi_api_key: str,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
max_articles: int = 5,
return_json: bool = False,
) -> Union[Dict[str, Union[str, List[Dict[str, str]]]], str]:
"""
Fetches stock news for a query within a specified date range using NewsApiClient.
Args:
query (str): The query name or stock symbol to query news for.
newsapi_api_key (str): Your API key for News API.
start_date (Optional[str]): The start date for the news query in 'YYYY-MM-DD' format (default: None).
end_date (Optional[str]): The end date for the news query in 'YYYY-MM-DD' format (default: None).
max_articles (int): The maximum number of articles to retrieve (default: 5).
return_json (bool): If True, return the result as a JSON object, otherwise return a formatted string (default: False).
Returns:
Union[Dict[str, Union[str, List[Dict[str, str]]]], str]:
A JSON object (if return_json=True) containing articles and metadata, or a formatted string of the news articles.
"""

# Initialize the NewsApiClient with the provided API key
newsapi = NewsApiClient(api_key=newsapi_api_key)

# Fetch news articles using NewsApiClient
articles_data = newsapi.get_everything(
q=query,
from_param=start_date,
to=end_date,
language="en",
sort_by="relevancy",
page_size=max_articles,
)

if articles_data["status"] != "ok":
raise ValueError("Failed to fetch news data from API")

# Extract articles
articles = articles_data.get("articles", [])

if not articles:
return "No articles found for the given query and date range."

# Process each article and return metadata
def process_article(article: Dict[str, str]) -> Dict[str, str]:
"""
Process an article and return metadata.
"""
return {
"title": article.get("title", "No Title"),
"description": article.get(
"description", "No Description"
),
"url": article.get("url", "No URL"),
"published_at": article.get("publishedAt", "No Date"),
"source": article.get("source", {}).get(
"name", "Unknown Source"
),
}

# Process all articles
processed_articles = [
process_article(article) for article in articles
]

# Create formatted string of articles and metadata
formatted_result = f"News Articles for {query}:\n\n"
for idx, article in enumerate(processed_articles, 1):
title = article.get("title", "No Title")
description = article.get("description", "No Description")
url = article.get("url", "No URL")
published_at = article.get("published_at", "No Date")
source = article.get("source", "Unknown Source")

formatted_result += (
f"\nArticle {idx}:\n"
f"Title: {title}\n"
f"Description: {description}\n"
f"URL: {url}\n"
f"Published At: {published_at}\n"
f"Source: {source}\n"
"\n"
)

# If return_json is true, return the raw JSON data with the formatted string
data = {
"query": query,
"start_date": start_date,
"end_date": end_date,
"formatted_result": formatted_result,
"articles": processed_articles,
}

return formatted_result, data


# # Example
# out = fetch_stock_news("Swarms")
Loading

0 comments on commit aacda07

Please sign in to comment.