From de45353ab38a85e79d456eaea302b3b88a7e47d6 Mon Sep 17 00:00:00 2001 From: xpander-ai-coding-agent Date: Wed, 6 Aug 2025 20:55:30 +0000 Subject: [PATCH 1/2] Convert ai_news_generator to use CrewAI flows for agentic workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replaced simple Crew implementation with CrewAI Flow architecture - Added @start decorator for research phase (Senior Research Analyst) - Added @listen decorator for writing phase (Content Writer) - Created structured two-phase workflow ensuring proper task sequencing - Updated README with architecture documentation and improved formatting - Fixed title capitalization in README Resolves issue #168: use crewai flow instead of simple crew 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- ai_news_generator/README.md | 24 ++++- ai_news_generator/app.py | 210 ++++++++++++++++++++---------------- 2 files changed, 141 insertions(+), 93 deletions(-) diff --git a/ai_news_generator/README.md b/ai_news_generator/README.md index 6bc3e25b6..545ebfc13 100644 --- a/ai_news_generator/README.md +++ b/ai_news_generator/README.md @@ -1,7 +1,7 @@ -# AI News generator +# AI News Generator -This project leverages CrewAI and Cohere's Command-R:7B model to build an AI news generator! +This project leverages CrewAI Flows and Cohere's Command-R:7B model to build an AI news generator with an agentic workflow! ## Installation and setup @@ -13,9 +13,27 @@ This project leverages CrewAI and Cohere's Command-R:7B model to build an AI new **Install Dependencies**: Ensure you have Python 3.11 or later installed. ```bash - pip install crewai crewai-tools + pip install crewai crewai-tools streamlit python-dotenv ``` +## Architecture + +This application uses CrewAI Flows to create an agentic workflow with two main phases: + +### Phase 1: Research Phase (@start) +- **Agent**: Senior Research Analyst +- **Task**: Conduct comprehensive research on the given topic +- **Tools**: SerperDev (web search) +- **Output**: Structured research brief with citations + +### Phase 2: Writing Phase (@listen) +- **Agent**: Content Writer +- **Task**: Transform research into engaging blog post +- **Input**: Research output from Phase 1 +- **Output**: Polished markdown blog post + +The flow ensures that the writing phase only begins after the research phase completes, creating a structured agentic workflow. + --- ## 📬 Stay Updated with Our Newsletter! diff --git a/ai_news_generator/app.py b/ai_news_generator/app.py index 7fc78e07d..1229c2a11 100644 --- a/ai_news_generator/app.py +++ b/ai_news_generator/app.py @@ -2,6 +2,7 @@ import streamlit as st from crewai import Agent, Task, Crew, LLM from crewai_tools import SerperDevTool +from crewai.flow.flow import Flow, listen, start from dotenv import load_dotenv # Load environment variables @@ -45,102 +46,131 @@ 5. Download the result as a markdown file """) -def generate_content(topic): - llm = LLM( - model="command-r", - temperature=0.7 - ) +class NewsGeneratorFlow(Flow): + def __init__(self, topic): + super().__init__() + self.topic = topic + self.llm = LLM( + model="command-r", + temperature=0.7 + ) + self.search_tool = SerperDevTool(n_results=10) - search_tool = SerperDevTool(n_results=10) - - # First Agent: Senior Research Analyst - senior_research_analyst = Agent( - role="Senior Research Analyst", - goal=f"Research, analyze, and synthesize comprehensive information on {topic} from reliable web sources", - backstory="You're an expert research analyst with advanced web research skills. " - "You excel at finding, analyzing, and synthesizing information from " - "across the internet using search tools. You're skilled at " - "distinguishing reliable sources from unreliable ones, " - "fact-checking, cross-referencing information, and " - "identifying key patterns and insights. You provide " - "well-organized research briefs with proper citations " - "and source verification. Your analysis includes both " - "raw data and interpreted insights, making complex " - "information accessible and actionable.", - allow_delegation=False, - verbose=True, - tools=[search_tool], - llm=llm - ) + @start() + def research_phase(self): + """Phase 1: Research and analyze information on the given topic""" + # Senior Research Analyst Agent + senior_research_analyst = Agent( + role="Senior Research Analyst", + goal=f"Research, analyze, and synthesize comprehensive information on {self.topic} from reliable web sources", + backstory="You're an expert research analyst with advanced web research skills. " + "You excel at finding, analyzing, and synthesizing information from " + "across the internet using search tools. You're skilled at " + "distinguishing reliable sources from unreliable ones, " + "fact-checking, cross-referencing information, and " + "identifying key patterns and insights. You provide " + "well-organized research briefs with proper citations " + "and source verification. Your analysis includes both " + "raw data and interpreted insights, making complex " + "information accessible and actionable.", + allow_delegation=False, + verbose=True, + tools=[self.search_tool], + llm=self.llm + ) - # Second Agent: Content Writer - content_writer = Agent( - role="Content Writer", - goal="Transform research findings into engaging blog posts while maintaining accuracy", - backstory="You're a skilled content writer specialized in creating " - "engaging, accessible content from technical research. " - "You work closely with the Senior Research Analyst and excel at maintaining the perfect " - "balance between informative and entertaining writing, " - "while ensuring all facts and citations from the research " - "are properly incorporated. You have a talent for making " - "complex topics approachable without oversimplifying them.", - allow_delegation=False, - verbose=True, - llm=llm - ) + # Research Task + research_task = Task( + description=(f""" + 1. Conduct comprehensive research on {self.topic} including: + - Recent developments and news + - Key industry trends and innovations + - Expert opinions and analyses + - Statistical data and market insights + 2. Evaluate source credibility and fact-check all information + 3. Organize findings into a structured research brief + 4. Include all relevant citations and sources + """), + expected_output="""A detailed research report containing: + - Executive summary of key findings + - Comprehensive analysis of current trends and developments + - List of verified facts and statistics + - All citations and links to original sources + - Clear categorization of main themes and patterns + Please format with clear sections and bullet points for easy reference.""", + agent=senior_research_analyst + ) - # Research Task - research_task = Task( - description=(""" - 1. Conduct comprehensive research on {topic} including: - - Recent developments and news - - Key industry trends and innovations - - Expert opinions and analyses - - Statistical data and market insights - 2. Evaluate source credibility and fact-check all information - 3. Organize findings into a structured research brief - 4. Include all relevant citations and sources - """), - expected_output="""A detailed research report containing: - - Executive summary of key findings - - Comprehensive analysis of current trends and developments - - List of verified facts and statistics - - All citations and links to original sources - - Clear categorization of main themes and patterns - Please format with clear sections and bullet points for easy reference.""", - agent=senior_research_analyst - ) + # Create and execute research crew + research_crew = Crew( + agents=[senior_research_analyst], + tasks=[research_task], + verbose=True + ) - # Writing Task - writing_task = Task( - description=(""" - Using the research brief provided, create an engaging blog post that: - 1. Transforms technical information into accessible content - 2. Maintains all factual accuracy and citations from the research - 3. Includes: - - Attention-grabbing introduction - - Well-structured body sections with clear headings - - Compelling conclusion - 4. Preserves all source citations in [Source: URL] format - 5. Includes a References section at the end - """), - expected_output="""A polished blog post in markdown format that: - - Engages readers while maintaining accuracy - - Contains properly structured sections - - Includes Inline citations hyperlinked to the original source url - - Presents information in an accessible yet informative way - - Follows proper markdown formatting, use H1 for the title and H3 for the sub-sections""", - agent=content_writer - ) + research_result = research_crew.kickoff(inputs={"topic": self.topic}) + return research_result - # Create Crew - crew = Crew( - agents=[senior_research_analyst, content_writer], - tasks=[research_task, writing_task], - verbose=True - ) + @listen(research_phase) + def writing_phase(self, research_output): + """Phase 2: Transform research into engaging blog post""" + # Content Writer Agent + content_writer = Agent( + role="Content Writer", + goal="Transform research findings into engaging blog posts while maintaining accuracy", + backstory="You're a skilled content writer specialized in creating " + "engaging, accessible content from technical research. " + "You work closely with the Senior Research Analyst and excel at maintaining the perfect " + "balance between informative and entertaining writing, " + "while ensuring all facts and citations from the research " + "are properly incorporated. You have a talent for making " + "complex topics approachable without oversimplifying them.", + allow_delegation=False, + verbose=True, + llm=self.llm + ) + + # Writing Task + writing_task = Task( + description=(f""" + Using the research brief provided about {self.topic}, create an engaging blog post that: + 1. Transforms technical information into accessible content + 2. Maintains all factual accuracy and citations from the research + 3. Includes: + - Attention-grabbing introduction + - Well-structured body sections with clear headings + - Compelling conclusion + 4. Preserves all source citations in [Source: URL] format + 5. Includes a References section at the end + + Research Brief: {research_output} + """), + expected_output="""A polished blog post in markdown format that: + - Engages readers while maintaining accuracy + - Contains properly structured sections + - Includes Inline citations hyperlinked to the original source url + - Presents information in an accessible yet informative way + - Follows proper markdown formatting, use H1 for the title and H3 for the sub-sections""", + agent=content_writer + ) + + # Create and execute writing crew + writing_crew = Crew( + agents=[content_writer], + tasks=[writing_task], + verbose=True + ) - return crew.kickoff(inputs={"topic": topic}) + writing_result = writing_crew.kickoff(inputs={ + "topic": self.topic, + "research_output": research_output + }) + return writing_result + +def generate_content(topic): + """Generate content using CrewAI Flow""" + flow = NewsGeneratorFlow(topic) + return flow.kickoff() # Main content area if generate_button: From fe048c021215d9fc39d5f47a6f7dd2aec9389268 Mon Sep 17 00:00:00 2001 From: xpander-ai-coding-agent Date: Wed, 6 Aug 2025 20:57:15 +0000 Subject: [PATCH 2/2] feat: complete task - 2025-08-06 20:57 --- .../__pycache__/app.cpython-311.pyc | Bin 0 -> 9819 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ai_news_generator/__pycache__/app.cpython-311.pyc diff --git a/ai_news_generator/__pycache__/app.cpython-311.pyc b/ai_news_generator/__pycache__/app.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..89b083749dd6639c1ea905db28bc92d3125095a3 GIT binary patch literal 9819 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