Skip to content

Commit

Permalink
Clean up pipeline (#1187)
Browse files Browse the repository at this point in the history
* Clean up pipeline

* Make versioning dynamic in templates

* fix .env issues when openai is trying to use invalid keys

* Fix type checker issue in pipeline

* Fix tests.
  • Loading branch information
bhancockio authored Aug 16, 2024
1 parent dbf2570 commit 3451b6f
Show file tree
Hide file tree
Showing 10 changed files with 210 additions and 108 deletions.
136 changes: 136 additions & 0 deletions docs/getting-started/Create-a-New-CrewAI-Pipeline-Template-Method.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Creating a CrewAI Pipeline Project

Welcome to the comprehensive guide for creating a new CrewAI pipeline project. This document will walk you through the steps to create, customize, and run your CrewAI pipeline project, ensuring you have everything you need to get started.

To learn more about CrewAI pipelines, visit the [CrewAI documentation](https://docs.crewai.com/core-concepts/Pipeline/).

## Prerequisites

Before getting started with CrewAI pipelines, make sure that you have installed CrewAI via pip:

```shell
$ pip install crewai crewai-tools
```

The same prerequisites for virtual environments and Code IDEs apply as in regular CrewAI projects.

## Creating a New Pipeline Project

To create a new CrewAI pipeline project, you have two options:

1. For a basic pipeline template:

```shell
$ crewai create pipeline <project_name>
```

2. For a pipeline example that includes a router:

```shell
$ crewai create pipeline --router <project_name>
```

These commands will create a new project folder with the following structure:

```
<project_name>/
├── README.md
├── poetry.lock
├── pyproject.toml
├── src/
│ └── <project_name>/
│ ├── __init__.py
│ ├── main.py
│ ├── crews/
│ │ ├── crew1/
│ │ │ ├── crew1.py
│ │ │ └── config/
│ │ │ ├── agents.yaml
│ │ │ └── tasks.yaml
│ │ ├── crew2/
│ │ │ ├── crew2.py
│ │ │ └── config/
│ │ │ ├── agents.yaml
│ │ │ └── tasks.yaml
│ ├── pipelines/
│ │ ├── __init__.py
│ │ ├── pipeline1.py
│ │ └── pipeline2.py
│ └── tools/
│ ├── __init__.py
│ └── custom_tool.py
└── tests/
```

## Customizing Your Pipeline Project

To customize your pipeline project, you can:

1. Modify the crew files in `src/<project_name>/crews/` to define your agents and tasks for each crew.
2. Modify the pipeline files in `src/<project_name>/pipelines/` to define your pipeline structure.
3. Modify `src/<project_name>/main.py` to set up and run your pipelines.
4. Add your environment variables into the `.env` file.

### Example: Defining a Pipeline

Here's an example of how to define a pipeline in `src/<project_name>/pipelines/normal_pipeline.py`:

```python
from crewai import Pipeline
from crewai.project import PipelineBase
from ..crews.normal_crew import NormalCrew

@PipelineBase
class NormalPipeline:
def __init__(self):
# Initialize crews
self.normal_crew = NormalCrew().crew()

def create_pipeline(self):
return Pipeline(
stages=[
self.normal_crew
]
)

async def kickoff(self, inputs):
pipeline = self.create_pipeline()
results = await pipeline.kickoff(inputs)
return results
```

### Annotations

The main annotation you'll use for pipelines is `@PipelineBase`. This annotation is used to decorate your pipeline classes, similar to how `@CrewBase` is used for crews.

## Installing Dependencies

To install the dependencies for your project, use Poetry:

```shell
$ cd <project_name>
$ poetry lock
$ poetry install
```

## Running Your Pipeline Project

To run your pipeline project, use the following command:

```shell
$ crewai run
```

or

```shell
$ poetry run <project_name>
```

This will initialize your pipeline and begin task execution as defined in your `main.py` file.

## Deploying Your Pipeline Project

Pipelines can be deployed in the same way as regular CrewAI projects. The easiest way is through [CrewAI+](https://www.crewai.com/crewaiplus), where you can deploy your pipeline in a few clicks.

Remember, when working with pipelines, you're orchestrating multiple crews to work together in a sequence or parallel fashion. This allows for more complex workflows and information processing tasks.
15 changes: 11 additions & 4 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@ Cutting-edge framework for orchestrating role-playing, autonomous AI agents. By
<div style="width:25%">
<h2>Getting Started</h2>
<ul>
<li><a href='./getting-started/Installing-CrewAI'>
<li>
<a href='./getting-started/Installing-CrewAI'>
Installing CrewAI
</a>
</a>
</li>
<li><a href='./getting-started/Start-a-New-CrewAI-Project-Template-Method'>
<li>
<a href='./getting-started/Start-a-New-CrewAI-Project-Template-Method'>
Start a New CrewAI Project: Template Method
</a>
</a>
</li>
<li>
<a href='./getting-started/Create-a-New-CrewAI-Pipeline-Template-Method'>
Create a New CrewAI Pipeline: Template Method
</a>
</li>
</ul>
</div>
Expand Down
18 changes: 5 additions & 13 deletions src/crewai/agents/executor.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
import threading
import time
from typing import Any, Dict, Iterator, List, Literal, Optional, Tuple, Union
import click


import click
from langchain.agents import AgentExecutor
from langchain.agents.agent import ExceptionTool
from langchain.callbacks.manager import CallbackManagerForChainRun
from langchain.chains.summarize import load_summarize_chain
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_core.agents import AgentAction, AgentFinish, AgentStep
from langchain_core.exceptions import OutputParserException
from langchain_core.tools import BaseTool
from langchain_core.utils.input import get_color_mapping
from pydantic import InstanceOf

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains.summarize import load_summarize_chain

from crewai.agents.agent_builder.base_agent_executor_mixin import CrewAgentExecutorMixin
from crewai.agents.tools_handler import ToolsHandler


from crewai.tools.tool_usage import ToolUsage, ToolUsageErrorException
from crewai.utilities import I18N
from crewai.utilities.constants import TRAINING_DATA_FILE
from crewai.utilities.exceptions.context_window_exceeding_exception import (
LLMContextLengthExceededException,
)
from crewai.utilities.training_handler import CrewTrainingHandler
from crewai.utilities.logger import Logger
from crewai.utilities.training_handler import CrewTrainingHandler


class CrewAgentExecutor(AgentExecutor, CrewAgentExecutorMixin):
Expand Down Expand Up @@ -213,11 +209,7 @@ def _iter_next_step(
yield step
return

yield AgentStep(
action=AgentAction("_Exception", str(e), str(e)),
observation=str(e),
)
return
raise e

# If the tool chosen is the finishing tool, then we end and return.
if isinstance(output, AgentFinish):
Expand Down
3 changes: 2 additions & 1 deletion src/crewai/cli/templates/crew/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ authors = ["Your Name <you@example.com>"]

[tool.poetry.dependencies]
python = ">=3.10,<=3.13"
crewai = { extras = ["tools"], version = "^0.51.0" }
crewai = { extras = ["tools"], version = ">=0.51.0,<1.0.0" }


[tool.poetry.scripts]
{{folder_name}} = "{{folder_name}}.main:run"
Expand Down
4 changes: 4 additions & 0 deletions src/crewai/cli/templates/pipeline/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ pip install poetry
Next, navigate to your project directory and install the dependencies:

1. First lock the dependencies and then install them:

```bash
poetry lock
```

```bash
poetry install
```

### Customizing

**Add your `OPENAI_API_KEY` into the `.env` file**
Expand Down Expand Up @@ -49,6 +52,7 @@ The {{name}} Crew is composed of multiple AI agents, each with unique roles, goa
## 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)
Expand Down
2 changes: 1 addition & 1 deletion src/crewai/cli/templates/pipeline/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors = ["Your Name <you@example.com>"]

[tool.poetry.dependencies]
python = ">=3.10,<=3.13"
crewai = { extras = ["tools"], version = "^0.51.0" }
crewai = { extras = ["tools"], version = ">=0.51.0,<1.0.0" }
asyncio = "*"

[tool.poetry.scripts]
Expand Down
3 changes: 2 additions & 1 deletion src/crewai/cli/templates/pipeline_router/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ authors = ["Your Name <you@example.com>"]

[tool.poetry.dependencies]
python = ">=3.10,<=3.13"
crewai = { extras = ["tools"], version = "^0.51.0" }
crewai = { extras = ["tools"], version = ">=0.51.0,<1.0.0" }


[tool.poetry.scripts]
{{folder_name}} = "{{folder_name}}.main:main"
Expand Down
35 changes: 13 additions & 22 deletions src/crewai/project/crew_base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import inspect
import os
from pathlib import Path
from typing import Any, Callable, Dict

Expand All @@ -15,42 +14,34 @@ class WrappedClass(cls):
model_config = ConfigDict(arbitrary_types_allowed=True)
is_crew_class: bool = True # type: ignore

base_directory = None
for frame_info in inspect.stack():
if "site-packages" not in frame_info.filename:
base_directory = Path(frame_info.filename).parent.resolve()
break
# Get the directory of the class being decorated
base_directory = Path(inspect.getfile(cls)).parent

original_agents_config_path = getattr(
cls, "agents_config", "config/agents.yaml"
)

original_tasks_config_path = getattr(cls, "tasks_config", "config/tasks.yaml")

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

if self.base_directory is None:
raise Exception(
"Unable to dynamically determine the project's base directory, you must run it from the project's root directory."
)
agents_config_path = self.base_directory / self.original_agents_config_path
tasks_config_path = self.base_directory / self.original_tasks_config_path

self.agents_config = self.load_yaml(
os.path.join(self.base_directory, self.original_agents_config_path)
)

self.tasks_config = self.load_yaml(
os.path.join(self.base_directory, self.original_tasks_config_path)
)
self.agents_config = self.load_yaml(agents_config_path)
self.tasks_config = self.load_yaml(tasks_config_path)

self.map_all_agent_variables()
self.map_all_task_variables()

@staticmethod
def load_yaml(config_path: str):
with open(config_path, "r") as file:
# parsedContent = YamlParser.parse(file) # type: ignore # Argument 1 to "parse" has incompatible type "TextIOWrapper"; expected "YamlParser"
return yaml.safe_load(file)
def load_yaml(config_path: Path):
try:
with open(config_path, "r") as file:
return yaml.safe_load(file)
except FileNotFoundError:
print(f"File not found: {config_path}")
raise

def _get_all_functions(self):
return {
Expand Down
2 changes: 1 addition & 1 deletion src/crewai/project/pipeline_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
def PipelineBase(cls):
class WrappedClass(cls):
model_config = ConfigDict(arbitrary_types_allowed=True)
is_pipeline_class: bool = True
is_pipeline_class: bool = True # type: ignore

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand Down
Loading

0 comments on commit 3451b6f

Please sign in to comment.