v1 of self evaluation loop with flows working

This commit is contained in:
Brandon Hancock
2024-10-28 10:59:19 -05:00
parent 156b29003e
commit 71f0f20a18
22 changed files with 4815 additions and 88 deletions

View File

@@ -1,23 +1,26 @@
[tool.poetry]
[project]
name = "email_auto_responder_flow"
version = "0.1.0"
description = "email_auto_responder_flow using crewAI"
authors = ["Your Name <you@example.com>"]
authors = [
{ name = "Your Name", email = "you@example.com" },
]
requires-python = ">=3.10,<=3.13"
dependencies = [
"crewai[tools]>=0.76.2,<1.0.0",
"asyncio*",
"langchain-tools>=0.1.34",
"crewai-tools>=0.12.0",
"google-auth-oauthlib>=1.2.1",
"google-api-python-client>=2.145.0",
]
[tool.poetry.dependencies]
python = ">=3.10,<=3.13"
crewai = { extras = ["tools"], version = ">=0.67.1,<1.0.0" }
asyncio = "*"
langchain-tools = "^0.1.34"
crewai-tools = "^0.12.0"
google-auth-oauthlib = "^1.2.1"
google-api-python-client = "^2.145.0"
[tool.poetry.scripts]
email_auto_responder_flow = "email_auto_responder_flow.main:main"
run_flow = "email_auto_responder_flow.main:main"
plot_flow = "email_auto_responder_flow.main:plot"
[project.scripts]
kickoff = "email_auto_responder_flow.main:kickoff"
plot = "email_auto_responder_flow.main:plot"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
requires = [
"hatchling",
]
build-backend = "hatchling.build"

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python
import asyncio
import time
from typing import List
@@ -45,7 +44,7 @@ class EmailAutoResponderFlow(Flow[AutoResponderState]):
time.sleep(180)
async def run_flow():
def kickoff():
"""
Run the flow.
"""
@@ -53,7 +52,7 @@ async def run_flow():
email_auto_response_flow.kickoff()
async def plot_flow():
def plot_flow():
"""
Plot the flow.
"""
@@ -61,13 +60,5 @@ async def plot_flow():
email_auto_response_flow.plot()
def main():
asyncio.run(run_flow())
def plot():
asyncio.run(plot_flow())
if __name__ == "__main__":
main()
kickoff()

View File

@@ -1,20 +1,23 @@
[tool.poetry]
[project]
name = "meeting_assistant_flow"
version = "0.1.0"
description = "meeting_assistant_flow using crewAI"
authors = ["Your Name <you@example.com>"]
authors = [
{ name = "Your Name", email = "you@example.com" },
]
requires-python = ">=3.10,<=3.13"
dependencies = [
"crewai[tools]>=0.76.2,<1.0.0",
"asyncio*",
"slack-sdk>=3.33.1",
]
[tool.poetry.dependencies]
python = ">=3.10,<=3.13"
crewai = { extras = ["tools"], version = ">=0.67.1,<1.0.0" }
asyncio = "*"
slack-sdk = "^3.33.1"
[tool.poetry.scripts]
meeting_assistant_flow = "meeting_assistant_flow.main:main"
run_flow = "meeting_assistant_flow.main:main"
plot_flow = "meeting_assistant_flow.main:plot"
[project.scripts]
kickoff = "meeting_assistant_flow.main:kickoff"
plot = "meeting_assistant_flow.main:plot"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
requires = [
"hatchling",
]
build-backend = "hatchling.build"

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python
import asyncio
import csv
import os
from typing import List
@@ -67,7 +66,7 @@ class MeetingFlow(Flow[MeetingState]):
send_message_to_channel(message)
async def run_flow():
def kickoff():
"""
Run the flow.
"""
@@ -75,7 +74,7 @@ async def run_flow():
meeting_flow.kickoff()
async def plot_flow():
def plot():
"""
Plot the flow.
"""
@@ -83,13 +82,5 @@ async def plot_flow():
meeting_flow.plot()
def main():
asyncio.run(run_flow())
def plot():
asyncio.run(plot_flow())
if __name__ == "__main__":
main()
kickoff()

3
self_evalulation_loop_flow/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.env
__pycache__/
lib/

View File

@@ -0,0 +1,56 @@
# {{crew_name}} Crew
Welcome to the {{crew_name}} Crew project, powered by [crewAI](https://crewai.com). This template is designed to help you set up a multi-agent AI system with ease, leveraging the powerful and flexible framework provided by crewAI. Our goal is to enable your agents to collaborate effectively on complex tasks, maximizing their collective intelligence and capabilities.
## Installation
Ensure you have Python >=3.10 <=3.13 installed on your system. This project uses [UV](https://docs.astral.sh/uv/) for dependency management and package handling, offering a seamless setup and execution experience.
First, if you haven't already, install uv:
```bash
pip install uv
```
Next, navigate to your project directory and install the dependencies:
(Optional) Lock the dependencies and install them by using the CLI command:
```bash
crewai install
```
### Customizing
**Add your `OPENAI_API_KEY` into the `.env` file**
- Modify `src/flow_self_evalulation_loop/config/agents.yaml` to define your agents
- Modify `src/flow_self_evalulation_loop/config/tasks.yaml` to define your tasks
- Modify `src/flow_self_evalulation_loop/crew.py` to add your own logic, tools and specific args
- Modify `src/flow_self_evalulation_loop/main.py` to add custom inputs for your agents and tasks
## Running the Project
To kickstart your crew of AI agents and begin task execution, run this from the root folder of your project:
```bash
crewai run
```
This command initializes the flow-self-evalulation-loop Crew, assembling the agents and assigning them tasks as defined in your configuration.
This example, unmodified, will run the create a `report.md` file with the output of a research on LLMs in the root folder.
## Understanding Your Crew
The flow-self-evalulation-loop Crew is composed of multiple AI agents, each with unique roles, goals, and tools. These agents collaborate on a series of tasks, defined in `config/tasks.yaml`, leveraging their collective skills to achieve complex objectives. The `config/agents.yaml` file outlines the capabilities and configurations of each agent in your crew.
## Support
For support, questions, or feedback regarding the {{crew_name}} Crew or crewAI.
- Visit our [documentation](https://docs.crewai.com)
- Reach out to us through our [GitHub repository](https://github.com/joaomdmoura/crewai)
- [Join our Discord](https://discord.com/invite/X4JWnZnxPb)
- [Chat with our docs](https://chatg.pt/DWjSBZn)
Let's create wonders together with the power and simplicity of crewAI.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,17 @@
[project]
name = "self_evaluation_loop_flow"
version = "0.1.0"
description = "self-evalulation-loop-flow using crewAI"
authors = [{ name = "Your Name", email = "you@example.com" }]
requires-python = ">=3.10,<=3.13"
dependencies = [
"crewai[tools]>=0.76.2,<1.0.0",
]
[project.scripts]
kickoff = "self_evaluation_loop_flow.main:kickoff"
plot = "self_evaluation_loop_flow.main:plot"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

View File

@@ -0,0 +1,10 @@
shakespearean_bard:
role: >
Shakespearean Bard
goal: >
Craft sarcastic and playful hot takes in the style of Shakespeare.
Ensure that all responses fit within 280 characters and contain no emojis.
backstory: >
Thou art a witty bard, renowned for turning the mundane into the
magnificent with thy playful jests and biting sarcasm. Armed with wit and
wisdom, thou dost revel in the creation of humorous quips most pleasing to the ear.

View File

@@ -0,0 +1,12 @@
write_x_post:
description: >
Given the topic '{topic}', compose a humorous hot take in the style of Shakespeare.
The tone should be sarcastic and playful. The final short form social media post
must be over 200 characters and not exceed 280 characters, and emojis are strictly forbidden.
Please incorporate the following feedback if present:
{feedback}
expected_output: >
A witty, Shakespearean hot take between 200 and 280 characters [Inclusive].
agent: shakespearean_bard

View File

@@ -0,0 +1,34 @@
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from self_evaluation_loop_flow.tools.CharacterCounterTool import CharacterCounterTool
@CrewBase
class ShakespeareanXPostCrew:
"""Shakespearean X Post Crew"""
agents_config = "config/agents.yaml"
tasks_config = "config/tasks.yaml"
@agent
def shakespearean_bard(self) -> Agent:
return Agent(
config=self.agents_config["shakespearean_bard"],
tools=[CharacterCounterTool()],
)
@task
def write_x_post(self) -> Task:
return Task(
config=self.tasks_config["write_x_post"],
)
@crew
def crew(self) -> Crew:
"""Creates the Shakespearean X Post Crew"""
return Crew(
agents=self.agents, # Automatically created by the @agent decorator
tasks=self.tasks, # Automatically created by the @task decorator
process=Process.sequential,
verbose=True,
)

View File

@@ -0,0 +1,10 @@
x_post_verifier:
role: >
X Post Verifier
goal: >
Ensure that any X post meets the strict guidelines:
it must be under 280 characters, contain no emojis, and be free of additional commentary.
backstory: >
You are a careful reviewer, skilled at understanding the core message of a post.
Your job is to maintain the clarity and brevity of the post by ensuring it contains no emojis,
unnecessary commentary, or excessive verbosity.

View File

@@ -0,0 +1,30 @@
verify_x_post:
description: >
Verify that the given X post meets the following criteria:
- It is between 200 and 280 characters inclusive.
- It contains no emojis.
- It contains only the post itself, without additional commentary.
The post should follow the 1-3-1 rule:
- 1 bold statement to hook the reader
- 3 lines of supporting information
- 1 sentence to summarize the post
Additionally, if you believe there are any issues with the post
or ways it could be improved, such as the structure of the post,
rhythm, word choice, please provide feedback.
If any of the criteria are not met, the post is considered invalid.
Provide actionable changes about what is wrong and what actions
need to be taken to fix the post.
Your final response must include:
- Valid: True/False
- Feedback: Provide commentary if the post fails any of the criteria.
X Post to Verify:
{x_post}
expected_output: >
Pass: True/False
Feedback: Commentary here if failed.
agent: x_post_verifier

View File

@@ -0,0 +1,43 @@
from typing import Optional
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from pydantic import BaseModel
from self_evaluation_loop_flow.tools.CharacterCounterTool import CharacterCounterTool
class XPostVerification(BaseModel):
valid: bool
feedback: Optional[str]
@CrewBase
class XPostReviewCrew:
"""X Post Review Crew"""
agents_config = "config/agents.yaml"
tasks_config = "config/tasks.yaml"
@agent
def x_post_verifier(self) -> Agent:
return Agent(
config=self.agents_config["x_post_verifier"],
tools=[CharacterCounterTool()],
)
@task
def verify_x_post(self) -> Task:
return Task(
config=self.tasks_config["verify_x_post"],
output_pydantic=XPostVerification,
)
@crew
def crew(self) -> Crew:
"""Creates the X Post Review Crew"""
return Crew(
agents=self.agents,
tasks=self.tasks,
process=Process.sequential,
verbose=True,
)

View File

@@ -0,0 +1,81 @@
from typing import Optional
from crewai.flow.flow import Flow, listen, router, start
from pydantic import BaseModel
from self_evaluation_loop_flow.crews.shakespeare_crew.shakespeare_crew import (
ShakespeareanXPostCrew,
)
from self_evaluation_loop_flow.crews.x_post_review_crew.x_post_review_crew import (
XPostReviewCrew,
)
class ShakespeareXPostFlowState(BaseModel):
x_post: str = ""
feedback: Optional[str] = None
valid: bool = False
retry_count: int = 0
class ShakespeareXPostFlow(Flow[ShakespeareXPostFlowState]):
@start("retry")
def generate_shakespeare_x_post(self):
print("Generating Shakespearean X post")
topic = "Flying cars"
result = (
ShakespeareanXPostCrew()
.crew()
.kickoff(inputs={"topic": topic, "feedback": self.state.feedback})
)
print("X post generated", result.raw)
self.state.x_post = result.raw
@router(generate_shakespeare_x_post)
def evaluate_x_post(self):
if self.state.retry_count > 3:
return "max_retry_exceeded"
result = XPostReviewCrew().crew().kickoff(inputs={"x_post": self.state.x_post})
self.state.valid = result["valid"]
self.state.feedback = result["feedback"]
print("valid", self.state.valid)
print("feedback", self.state.feedback)
self.state.retry_count += 1
if self.state.valid:
return "complete"
return "retry"
@listen("complete")
def save_result(self):
print("X post is valid")
print("X post:", self.state.x_post)
# Save the valid X post to a file
with open("x_post.txt", "w") as file:
file.write(self.state.x_post)
@listen("max_retry_exceeded")
def max_retry_exceeded_exit(self):
print("Max retry count exceeded")
print("X post:", self.state.x_post)
print("Feedback:", self.state.feedback)
def kickoff():
shakespeare_flow = ShakespeareXPostFlow()
shakespeare_flow.kickoff()
def plot():
shakespeare_flow = ShakespeareXPostFlow()
shakespeare_flow.plot()
if __name__ == "__main__":
kickoff()

View File

@@ -0,0 +1,20 @@
from typing import Type
from crewai_tools import BaseTool
from pydantic import BaseModel, Field
class CharacterCounterInput(BaseModel):
"""Input schema for CharacterCounterTool."""
text: str = Field(..., description="The string to count characters in.")
class CharacterCounterTool(BaseTool):
name: str = "Character Counter Tool"
description: str = "Counts the number of characters in a given string."
args_schema: Type[BaseModel] = CharacterCounterInput
def _run(self, text: str) -> str:
character_count = len(text)
return f"The input string has {character_count} characters."

4232
self_evalulation_loop_flow/uv.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,22 @@
[tool.poetry]
[project]
name = "write_a_book_with_flows"
version = "0.1.0"
description = "write_a_book_with_flows using crewAI"
authors = ["Your Name <you@example.com>"]
authors = [
{ name = "Your Name", email = "you@example.com" },
]
requires-python = ">=3.10,<=3.13"
dependencies = [
"crewai[tools]>=0.76.2,<1.0.0",
"asyncio*",
]
[tool.poetry.dependencies]
python = ">=3.10,<=3.13"
crewai = { extras = ["tools"], version = ">=0.67.1,<1.0.0" }
asyncio = "*"
[tool.poetry.scripts]
write_a_book_with_flows = "write_a_book_with_flows.main:main"
run_flow = "write_a_book_with_flows.main:main"
plot_flow = "write_a_book_with_flows.main:plot"
[project.scripts]
kickoff = "write_a_book_with_flows.main:kickoff"
plot = "write_a_book_with_flows.main:plot"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
requires = [
"hatchling",
]
build-backend = "hatchling.build"

View File

@@ -115,29 +115,15 @@ class BookFlow(Flow[BookState]):
return book_content
async def run_flow():
"""
Run the flow.
"""
book_flow = BookFlow()
await book_flow.kickoff()
async def plot_flow():
"""
Plot the flow.
"""
book_flow = BookFlow()
await book_flow.plot()
def main():
asyncio.run(run_flow())
def kickoff():
poem_flow = BookFlow()
poem_flow.kickoff()
def plot():
asyncio.run(plot_flow())
poem_flow = BookFlow()
poem_flow.plot()
if __name__ == "__main__":
main()
kickoff()