├── news_agent ├── __init__.py └── news_agent.py ├── .env ├── .gitignore ├── requirements.txt ├── rxconfig.py ├── README.md └── LICENSE /news_agent/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | OPENAI_BASE_URL=http://localhost:11434/v1 2 | OPENAI_API_KEY=fake-key -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.py[cod] 3 | assets/external/ 4 | *.db 5 | .web 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | reflex==0.6.6.post2 2 | git+https://github.com/openai/swarm.git 3 | duckduckgo-search -------------------------------------------------------------------------------- /rxconfig.py: -------------------------------------------------------------------------------- 1 | import reflex as rx 2 | 3 | 4 | config = rx.Config( 5 | app_name="news_agent", 6 | ) 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AI News Agent using Open AI Swarm and Llama 3.2 running locally 2 | 3 | An intelligent research and writing tool built with Reflex, Open AI Swarm and Ollama that allows users to research a topic and generate a concise, well-structured summary using the advanced AI-powered research and writing agents. 4 | 5 | ## Features 6 | - Perform in-depth research on any topic 7 | - Utilize multiple AI agents for comprehensive information gathering 8 | - Generate structured, markdown-formatted research outputs 9 | - User-friendly web interface 10 | - Real-time processing with async functionality 11 | 12 | ## Installation 13 | 14 | 1. Clone the repository: 15 | ```bash 16 | git clone https://github.com/Sumanth077/news-agent-openai-swarm-ollama.git 17 | cd news-agent 18 | ``` 19 | 20 | 2. Create a virtual environment (optional but recommended): 21 | ```bash 22 | python -m venv venv 23 | source venv/bin/activate # On Windows, use `venv\Scripts\activate` 24 | ``` 25 | 26 | 3. Install the dependencies: 27 | ```bash 28 | pip install -r requirements.txt 29 | ``` 30 | 31 | ## Running the Application 32 | ```bash 33 | reflex run 34 | ``` 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Pynecone, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /news_agent/news_agent.py: -------------------------------------------------------------------------------- 1 | import reflex as rx 2 | from duckduckgo_search import DDGS 3 | from swarm import Swarm, Agent 4 | from datetime import datetime 5 | from dotenv import load_dotenv 6 | import os 7 | 8 | # Load environment variables 9 | load_dotenv() 10 | 11 | # Initialize Swarm and set model 12 | 13 | MODEL = "llama3.2" 14 | client = Swarm() 15 | 16 | # Create specialized agents 17 | search_agent = Agent( 18 | name="News Searcher", 19 | instructions=""" 20 | You are an expert in news discovery. Your role involves: 21 | 1. Identifying the latest and most pertinent news articles on the provided topic. 22 | 2. Ensuring all sources are credible and trustworthy. 23 | 3. Presenting the raw search results in a clear and organized manner. 24 | """, 25 | model=MODEL 26 | ) 27 | 28 | synthesis_agent = Agent( 29 | name="News Synthesizer", 30 | instructions=""" 31 | You are a specialist in news summarization. Your responsibilities include: 32 | 1. Reviewing the provided news articles thoroughly. 33 | 2. Extracting key insights and essential details. 34 | 3. Merging information from various sources into a unified summary. 35 | 4. Crafting a clear and concise overview that is both comprehensive and succinct in a 36 | professional and accessible tone. 37 | 5. Prioritizing factual accuracy and upholding journalistic neutrality. 38 | 6. Provide a synthesis of the main points in 2-3 paragraphs. 39 | """, 40 | model=MODEL 41 | ) 42 | 43 | summary_agent = Agent( 44 | name="News Summarizer", 45 | instructions=""" 46 | You are a skilled news summarizer, blending the precision of AP and Reuters with concise, modern storytelling. 47 | 48 | Your Responsibilities: 49 | 1. Core Details: 50 | - Start with the most critical news development. 51 | - Highlight key players and their actions. 52 | - Include significant data or figures where applicable. 53 | - Explain its immediate relevance and importance. 54 | - Outline potential short-term effects or implications. 55 | 56 | 2. Writing Style: 57 | - Use clear, active language. 58 | - Focus on specifics over generalities. 59 | - Maintain a neutral, fact-based tone. 60 | - Ensure each word adds value. 61 | - Simplify complex terms for broader understanding. 62 | 63 | Deliverable: 64 | 65 | Compose a single, engaging paragraph (250-400 words) structured as follows: 66 | [Main Event] + [Key Details/Data] + [Significance/Next Steps]. 67 | 68 | IMPORTANT NOTE: Deliver the paragraph as news content only, without labels, introductions, or meta-comments. Begin directly with the story. 69 | """, 70 | model=MODEL 71 | ) 72 | 73 | def search_news(topic): 74 | """Search for news articles using DuckDuckGo""" 75 | with DDGS() as ddg: 76 | results = ddg.text(f"{topic} news {datetime.now().strftime('%Y-%m')}", max_results=3) 77 | if results: 78 | news_results = "\n\n".join([ 79 | f"Title: {result['title']}\nURL: {result['href']}\nSummary: {result['body']}" 80 | for result in results 81 | ]) 82 | return news_results 83 | return f"No news found for {topic}." 84 | 85 | class State(rx.State): 86 | """Manage the application state.""" 87 | topic: str = "AI Agents" 88 | raw_news: str = "" 89 | synthesized_news: str = "" 90 | final_summary: str = "" 91 | is_loading: bool = False 92 | error_message: str = "" 93 | 94 | @rx.event(background=True) 95 | async def process_news(self): 96 | """Asynchronous news processing workflow using Swarm agents""" 97 | # Reset previous state 98 | async with self: 99 | 100 | self.is_loading = True 101 | self.error_message = "" 102 | self.raw_news = "" 103 | self.synthesized_news = "" 104 | self.final_summary = "" 105 | 106 | yield 107 | 108 | try: 109 | # Search news using search agent 110 | search_response = client.run( 111 | agent=search_agent, 112 | messages=[{"role": "user", "content": f"Find recent news about {self.topic}"}] 113 | ) 114 | async with self: 115 | self.raw_news = search_response.messages[-1]["content"] 116 | 117 | # Synthesize using synthesis agent 118 | synthesis_response = client.run( 119 | agent=synthesis_agent, 120 | messages=[{"role": "user", "content": f"Synthesize these news articles:\n{self.raw_news}"}] 121 | ) 122 | async with self: 123 | self.synthesized_news = synthesis_response.messages[-1]["content"] 124 | 125 | # Generate summary using summary agent 126 | summary_response = client.run( 127 | agent=summary_agent, 128 | messages=[{"role": "user", "content": f"Summarize this synthesis:\n{self.synthesized_news}"}] 129 | ) 130 | 131 | async with self: 132 | self.final_summary = summary_response.messages[-1]["content"] 133 | self.is_loading = False 134 | 135 | except Exception as e: 136 | 137 | async with self: 138 | self.error_message = f"An error occurred: {str(e)}" 139 | self.is_loading = False 140 | 141 | def update_topic(self, topic: str): 142 | """Update the search topic""" 143 | self.topic = topic 144 | 145 | def news_page() -> rx.Component: 146 | """Render the main news processing page""" 147 | return rx.box( 148 | rx.section( 149 | rx.heading("📰 News Agent", size="8"), 150 | rx.input( 151 | placeholder="Enter news topic", 152 | value=State.topic, 153 | on_change=State.update_topic, 154 | width="300px" 155 | ), 156 | rx.button( 157 | "Process News", 158 | on_click=State.process_news, 159 | color_scheme="blue", 160 | loading=State.is_loading, 161 | width="fit-content", 162 | ), 163 | display="flex", 164 | flex_direction="column", 165 | gap="1rem", 166 | ), 167 | 168 | # Results Section 169 | rx.cond( 170 | State.final_summary != "", 171 | rx.vstack( 172 | rx.heading("📝 News Summary", size="4"), 173 | rx.text(State.final_summary), 174 | rx.button("Copy the Summary", on_click=[rx.set_clipboard(State.final_summary), rx.toast.info("Summary copied")]), 175 | spacing="4", 176 | width="100%" 177 | ) 178 | ), 179 | 180 | spacing="4", 181 | max_width="800px", 182 | margin="auto", 183 | padding="20px" 184 | ) 185 | 186 | app = rx.App( 187 | theme=rx.theme( 188 | appearance="light", 189 | accent_color="blue" 190 | ) 191 | ) 192 | app.add_page(news_page, route="/") 193 | --------------------------------------------------------------------------------