generated from kyegomez/Python-Package-Template
-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Your Name
committed
Sep 23, 2024
1 parent
15454b3
commit aacda07
Showing
11 changed files
with
890 additions
and
11 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") |
Oops, something went wrong.