Spaces:
Sleeping
Sleeping
Download app.py from stevafernandes/crew: direct link, hf CLI and curl.
- Browser
- Download file 5.17 kB
-
https://huggingface.co/spaces/stevafernandes/crew/resolve/main/app.py
- Command line
-
hf download hf://spaces/stevafernandes/crew/app.py
-
curl -L -o app.py https://huggingface.co/spaces/stevafernandes/crew/resolve/main/app.py
5.17 kB
| """Create agents to research and write an article. | |
| Planner -> Writer -> Editor, executed sequentially. | |
| Needs only GEMINI_API_KEY (in .env locally, or as a Space secret on Hugging Face). | |
| Run: python app.py | |
| """ | |
| import os | |
| import gradio as gr | |
| from dotenv import load_dotenv | |
| from crewai import Agent, Task, Crew, LLM | |
| load_dotenv() | |
| if not (os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY")): | |
| raise SystemExit("Missing GEMINI_API_KEY. Add it to .env locally, " | |
| "or as a secret in your Hugging Face Space settings.") | |
| # CrewAI picks the provider from the prefix before the slash. | |
| # The key is read automatically from GEMINI_API_KEY (or GOOGLE_API_KEY). | |
| gemini_llm = LLM(model=os.getenv("GEMINI_MODEL", "gemini/gemini-3.8-flash")) | |
| # Default topic shown in the text box. | |
| TOPIC = "Artificial Intelligence" | |
| planner = Agent( | |
| role="Content Planner", | |
| goal="Plan engaging and factually accurate content on {topic}", | |
| backstory="You're working on planning a blog article " | |
| "about the topic: {topic}. " | |
| "You collect information that helps the " | |
| "audience learn something " | |
| "and make informed decisions. " | |
| "Your work is the basis for " | |
| "the Content Writer to write an article on this topic.", | |
| llm=gemini_llm, | |
| allow_delegation=False, | |
| verbose=True, | |
| ) | |
| writer = Agent( | |
| role="Content Writer", | |
| goal="Write insightful and factually accurate " | |
| "opinion piece about the topic: {topic}", | |
| backstory="You're working on writing " | |
| "a new opinion piece about the topic: {topic}. " | |
| "You base your writing on the work of " | |
| "the Content Planner, who provides an outline " | |
| "and relevant context about the topic. " | |
| "You follow the main objectives and " | |
| "direction of the outline, " | |
| "as provided by the Content Planner. " | |
| "You also provide objective and impartial insights " | |
| "and back them up with information " | |
| "provided by the Content Planner. " | |
| "You acknowledge in your opinion piece " | |
| "when your statements are opinions " | |
| "as opposed to objective statements.", | |
| llm=gemini_llm, | |
| allow_delegation=False, | |
| verbose=True, | |
| ) | |
| editor = Agent( | |
| role="Editor", | |
| goal="Edit a given blog post to align with " | |
| "the writing style of the organization.", | |
| backstory="You are an editor who receives a blog post " | |
| "from the Content Writer. " | |
| "Your goal is to review the blog post " | |
| "to ensure that it follows journalistic best practices, " | |
| "provides balanced viewpoints " | |
| "when providing opinions or assertions, " | |
| "and also avoids major controversial topics " | |
| "or opinions when possible.", | |
| llm=gemini_llm, | |
| allow_delegation=False, | |
| verbose=True, | |
| ) | |
| plan = Task( | |
| description=( | |
| "1. Prioritize the latest trends, key players, " | |
| "and noteworthy news on {topic}.\n" | |
| "2. Identify the target audience, considering " | |
| "their interests and pain points.\n" | |
| "3. Develop a detailed content outline including " | |
| "an introduction, key points, and a call to action.\n" | |
| "4. Include SEO keywords and relevant data or sources." | |
| ), | |
| expected_output="A comprehensive content plan document " | |
| "with an outline, audience analysis, " | |
| "SEO keywords, and resources.", | |
| agent=planner, | |
| ) | |
| write = Task( | |
| description=( | |
| "1. Use the content plan to craft a compelling " | |
| "blog post on {topic}.\n" | |
| "2. Incorporate SEO keywords naturally.\n" | |
| "3. Sections and subtitles are properly named " | |
| "in an engaging manner.\n" | |
| "4. Ensure the post is structured with an " | |
| "engaging introduction, insightful body, " | |
| "and a summarizing conclusion.\n" | |
| "5. Proofread for grammatical errors and " | |
| "alignment with the brand's voice." | |
| ), | |
| expected_output="A well-written blog post " | |
| "in markdown format, ready for publication, " | |
| "each section should have 2 or 3 paragraphs.", | |
| agent=writer, | |
| ) | |
| edit = Task( | |
| description="Proofread the given blog post for " | |
| "grammatical errors and " | |
| "alignment with the brand's voice.", | |
| expected_output="A well-written blog post in markdown format, " | |
| "ready for publication, " | |
| "each section should have 2 or 3 paragraphs.", | |
| agent=editor, | |
| ) | |
| crew = Crew( | |
| agents=[planner, writer, editor], | |
| tasks=[plan, write, edit], | |
| verbose=True, | |
| ) | |
| # --- Hugging Face Space UI (the only real addition) --- | |
| def write_article(topic): | |
| return crew.kickoff(inputs={"topic": topic}).raw | |
| demo = gr.Interface( | |
| fn=write_article, | |
| inputs=gr.Textbox(label="Topic", value=TOPIC), | |
| outputs=gr.Markdown(), | |
| title="Research & Write an Article", | |
| submit_btn="Write article", | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |