Skip to content

Commit

Permalink
Merge pull request #1519 from crewAIInc/feat/improve-tooling-docs
Browse files Browse the repository at this point in the history
Improve tooling and flow docs
  • Loading branch information
tonykipkemboi authored Oct 29, 2024
2 parents 26afee9 + 276cb7b commit 240527d
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 4 deletions.
109 changes: 106 additions & 3 deletions docs/concepts/flows.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -599,13 +599,114 @@ The generated plot will display nodes representing the tasks in your flow, with

By visualizing your flows, you can gain a clearer understanding of the workflow's structure, making it easier to debug, optimize, and communicate your AI processes to others.

### Conclusion

Plotting your flows is a powerful feature of CrewAI that enhances your ability to design and manage complex AI workflows. Whether you choose to use the `plot()` method or the command line, generating plots will provide you with a visual representation of your workflows, aiding in both development and presentation.
## Advanced

In this section, we explore more complex use cases of CrewAI Flows, starting with a self-evaluation loop. This pattern is crucial for developing AI systems that can iteratively improve their outputs through feedback.

### 1) Self-Evaluation Loop

The self-evaluation loop is a powerful pattern that allows AI workflows to automatically assess and refine their outputs. This example demonstrates how to set up a flow that generates content, evaluates it, and iterates based on feedback until the desired quality is achieved.

#### Overview

The self-evaluation loop involves two main Crews:

1. **ShakespeareanXPostCrew**: Generates a Shakespearean-style post on a given topic.
2. **XPostReviewCrew**: Evaluates the generated post, providing feedback on its validity and quality.

The process iterates until the post meets the criteria or a maximum retry limit is reached. This approach ensures high-quality outputs through iterative refinement.

#### Importance

This pattern is essential for building robust AI systems that can adapt and improve over time. By automating the evaluation and feedback loop, developers can ensure that their AI workflows produce reliable and high-quality results.

#### Main Code Highlights

Below is the `main.py` file for the self-evaluation loop flow:

```python
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)
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()
```

#### Code Highlights

- **Retry Mechanism**: The flow uses a retry mechanism to regenerate the post if it doesn't meet the criteria, up to a maximum of three retries.
- **Feedback Loop**: Feedback from the `XPostReviewCrew` is used to refine the post iteratively.
- **State Management**: The flow maintains state using a Pydantic model, ensuring type safety and clarity.

For a complete example and further details, please refer to the [Self Evaluation Loop Flow repository](https://github.com/crewAIInc/crewAI-examples/tree/main/self_evaluation_loop_flow).


## Next Steps

If you're interested in exploring additional examples of flows, we have a variety of recommendations in our examples repository. Here are four specific flow examples, each showcasing unique use cases to help you match your current problem type to a specific example:
If you're interested in exploring additional examples of flows, we have a variety of recommendations in our examples repository. Here are five specific flow examples, each showcasing unique use cases to help you match your current problem type to a specific example:

1. **Email Auto Responder Flow**: This example demonstrates an infinite loop where a background job continually runs to automate email responses. It's a great use case for tasks that need to be performed repeatedly without manual intervention. [View Example](https://github.com/crewAIInc/crewAI-examples/tree/main/email_auto_responder_flow)

Expand All @@ -615,6 +716,8 @@ If you're interested in exploring additional examples of flows, we have a variet

4. **Meeting Assistant Flow**: This flow demonstrates how to broadcast one event to trigger multiple follow-up actions. For instance, after a meeting is completed, the flow can update a Trello board, send a Slack message, and save the results. It's a great example of handling multiple outcomes from a single event, making it ideal for comprehensive task management and notification systems. [View Example](https://github.com/crewAIInc/crewAI-examples/tree/main/meeting_assistant_flow)

5. **Self Evaluation Loop Flow**: This flow demonstrates a self-evaluation loop where AI workflows automatically assess and refine their outputs through feedback. It involves generating content, evaluating it, and iterating until the desired quality is achieved. This pattern is crucial for developing robust AI systems that can adapt and improve over time. [View Example](https://github.com/crewAIInc/crewAI-examples/tree/main/self_evaluation_loop_flow)

By exploring these examples, you can gain insights into how to leverage CrewAI Flows for various use cases, from automating repetitive tasks to managing complex, multi-step processes with dynamic decision-making and human feedback.

Also, check out our YouTube video on how to use flows in CrewAI below!
Expand Down
9 changes: 8 additions & 1 deletion docs/how-to/create-custom-tools.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,21 @@ pip install 'crewai[tools]'

### Subclassing `BaseTool`

To create a personalized tool, inherit from `BaseTool` and define the necessary attributes and the `_run` method.
To create a personalized tool, inherit from `BaseTool` and define the necessary attributes, including the `args_schema` for input validation, and the `_run` method.

```python Code
from typing import Type
from crewai_tools import BaseTool
from pydantic import BaseModel, Field

class MyToolInput(BaseModel):
"""Input schema for MyCustomTool."""
argument: str = Field(..., description="Description of the argument.")

class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = "What this tool does. It's vital for effective utilization."
args_schema: Type[BaseModel] = MyToolInput

def _run(self, argument: str) -> str:
# Your tool's logic here
Expand Down
6 changes: 6 additions & 0 deletions src/crewai/cli/templates/crew/tools/custom_tool.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
from typing import Type
from crewai_tools import BaseTool
from pydantic import BaseModel, Field

class MyCustomToolInput(BaseModel):
"""Input schema for MyCustomTool."""
argument: str = Field(..., description="Description of the argument.")

class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = (
"Clear description for what this tool is useful for, you agent will need this information to use it."
)
args_schema: Type[BaseModel] = MyCustomToolInput

def _run(self, argument: str) -> str:
# Implementation goes here
Expand Down
10 changes: 10 additions & 0 deletions src/crewai/cli/templates/flow/tools/custom_tool.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
from typing import Type

from crewai_tools import BaseTool
from pydantic import BaseModel, Field


class MyCustomToolInput(BaseModel):
"""Input schema for MyCustomTool."""

argument: str = Field(..., description="Description of the argument.")


class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = (
"Clear description for what this tool is useful for, you agent will need this information to use it."
)
args_schema: Type[BaseModel] = MyCustomToolInput

def _run(self, argument: str) -> str:
# Implementation goes here
Expand Down
6 changes: 6 additions & 0 deletions src/crewai/cli/templates/pipeline/tools/custom_tool.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
from typing import Type
from crewai_tools import BaseTool
from pydantic import BaseModel, Field

class MyCustomToolInput(BaseModel):
"""Input schema for MyCustomTool."""
argument: str = Field(..., description="Description of the argument.")

class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = (
"Clear description for what this tool is useful for, you agent will need this information to use it."
)
args_schema: Type[BaseModel] = MyCustomToolInput

def _run(self, argument: str) -> str:
# Implementation goes here
Expand Down
6 changes: 6 additions & 0 deletions src/crewai/cli/templates/pipeline_router/tools/custom_tool.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
from typing import Type
from crewai_tools import BaseTool
from pydantic import BaseModel, Field

class MyCustomToolInput(BaseModel):
"""Input schema for MyCustomTool."""
argument: str = Field(..., description="Description of the argument.")

class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = (
"Clear description for what this tool is useful for, you agent will need this information to use it."
)
args_schema: Type[BaseModel] = MyCustomToolInput

def _run(self, argument: str) -> str:
# Implementation goes here
Expand Down

0 comments on commit 240527d

Please sign in to comment.