mirror of
https://github.com/crewAIInc/crewAI.git
synced 2025-12-16 04:18:35 +00:00
first stab at early concepts
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.DS_Store
|
||||||
|
.pytest_cache
|
||||||
|
__pycache__
|
||||||
|
dist/
|
||||||
52
README.md
52
README.md
@@ -1 +1,51 @@
|
|||||||
# CrewAI
|
# CrewAI
|
||||||
|
|
||||||
|
## Virtual Env
|
||||||
|
```bash
|
||||||
|
poetry shell
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running Tests
|
||||||
|
```bash
|
||||||
|
poetry run pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Packaging
|
||||||
|
```bash
|
||||||
|
poetry build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Installing Locally
|
||||||
|
```bash
|
||||||
|
pip install dist/*.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
# CrewAI
|
||||||
|
|
||||||
|
## Why?
|
||||||
|
|
||||||
|
## How?
|
||||||
|
|
||||||
|
## What is it?
|
||||||
|
Convention?
|
||||||
|
|
||||||
|
Convention of Roles
|
||||||
|
Convention over Tools
|
||||||
|
Convention over interactions (In what ways agents interact, how flexible, conversation patterns, where these happen [in a room, in isolation])
|
||||||
|
Convention over degree of guidance
|
||||||
|
|
||||||
|
You must be able to bring any tools <- Convention over tools
|
||||||
|
|
||||||
|
How does it compare to autogen?
|
||||||
|
|
||||||
|
Autogen is good to create conversational agents, these agents can then work
|
||||||
|
together autonomously, but there is no concepts of process, a process would need
|
||||||
|
to be programatically added.
|
||||||
|
|
||||||
|
ChatDev brings the idea of processes to the AI Agents but it's stiff and it's
|
||||||
|
customizations are not meant to be deployed at production settings
|
||||||
|
|
||||||
|
CrewAI is a python library that provide modules to build crews of AI Agents tha
|
||||||
|
|
||||||
|
What is the interface to interact with CrewAI?
|
||||||
0
__init__.py
Normal file
0
__init__.py
Normal file
2
crewai/__init__.py
Normal file
2
crewai/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
from .crew import Crew
|
||||||
|
from .agent import Agent
|
||||||
48
crewai/agent.py
Normal file
48
crewai/agent.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
"""Generic agent."""
|
||||||
|
|
||||||
|
from typing import List, Any
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
from langchain.tools import Tool
|
||||||
|
from langchain.agents import AgentExecutor
|
||||||
|
from langchain.chat_models import ChatOpenAI as OpenAI
|
||||||
|
from langchain.tools.render import render_text_description
|
||||||
|
from langchain.agents.format_scratchpad import format_log_to_str
|
||||||
|
from langchain.agents.output_parsers import ReActSingleInputOutputParser
|
||||||
|
|
||||||
|
from .prompts import AGENT_EXECUTION_PROMPT
|
||||||
|
|
||||||
|
class Agent(BaseModel):
|
||||||
|
role: str = Field(description="Role of the agent")
|
||||||
|
goal: str = Field(description="Objective of the agent")
|
||||||
|
backstory: str = Field(description="Backstory of the agent")
|
||||||
|
tools: List[Tool] = Field(description="Tools at agents disposal")
|
||||||
|
llm: str = Field(description="LLM of the agent", default=OpenAI(
|
||||||
|
temperature=0.7,
|
||||||
|
model="gpt-4",
|
||||||
|
verbose=True
|
||||||
|
))
|
||||||
|
|
||||||
|
def execute(self, task: str) -> str:
|
||||||
|
prompt = AGENT_EXECUTION_PROMPT.partial(
|
||||||
|
tools=render_text_description(self.tools),
|
||||||
|
tool_names=self.__tools_names(),
|
||||||
|
backstory=self.backstory,
|
||||||
|
role=self.role,
|
||||||
|
goal=self.goal,
|
||||||
|
)
|
||||||
|
return self.__run(task, prompt, self.tools)
|
||||||
|
|
||||||
|
def __run(self, input: str, prompt: str, tools: List[Tool]) -> str:
|
||||||
|
chat_with_bind = self.llm.bind(stop=["\nObservation"])
|
||||||
|
agent = {
|
||||||
|
"input": lambda x: x["input"],
|
||||||
|
"agent_scratchpad": lambda x: format_log_to_str(x['intermediate_steps'])
|
||||||
|
} | prompt | chat_with_bind | ReActSingleInputOutputParser()
|
||||||
|
|
||||||
|
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True)
|
||||||
|
return agent_executor.invoke({"input": input})['output']
|
||||||
|
|
||||||
|
def __tools_names(self) -> str:
|
||||||
|
return ", ".join([t.name for t in self.tools])
|
||||||
|
|
||||||
7
crewai/crew.py
Normal file
7
crewai/crew.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
"""Crew of agents."""
|
||||||
|
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
class Crew(BaseModel):
|
||||||
|
description: str = Field(description="Description and of the crew being created.")
|
||||||
|
goal: str = Field(description="Objective of the crew being created.")
|
||||||
39
crewai/prompts.py
Normal file
39
crewai/prompts.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
"""Prompts for generic agent."""
|
||||||
|
|
||||||
|
from langchain.prompts import PromptTemplate
|
||||||
|
|
||||||
|
AGENT_EXECUTION_PROMPT = PromptTemplate.from_template(
|
||||||
|
"""You are {role}.
|
||||||
|
{backstory}
|
||||||
|
|
||||||
|
Your main goal is: {goal}
|
||||||
|
|
||||||
|
TOOLS:
|
||||||
|
------
|
||||||
|
|
||||||
|
You have access to the following tools:
|
||||||
|
|
||||||
|
{tools}
|
||||||
|
|
||||||
|
To use a tool, please use the following format:
|
||||||
|
|
||||||
|
```
|
||||||
|
Thought: Do I need to use a tool? Yes
|
||||||
|
Action: the action to take, should be one of [{tool_names}]
|
||||||
|
Action Input: the input to the action
|
||||||
|
Observation: the result of the action
|
||||||
|
```
|
||||||
|
|
||||||
|
When you have a response for your task, or if you do not need to use a tool, you MUST use the format:
|
||||||
|
|
||||||
|
```
|
||||||
|
Thought: Do I need to use a tool? No
|
||||||
|
Final Answer: [your response here]
|
||||||
|
```
|
||||||
|
|
||||||
|
Begin!
|
||||||
|
|
||||||
|
Current Task: {input}
|
||||||
|
{agent_scratchpad}
|
||||||
|
"""
|
||||||
|
)
|
||||||
1409
poetry.lock
generated
Normal file
1409
poetry.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
20
pyproject.toml
Normal file
20
pyproject.toml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[tool.poetry]
|
||||||
|
name = "crewai"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = ""
|
||||||
|
authors = ["Joao Moura <joaomdmoura@gmail.com>"]
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
|
[tool.poetry.dependencies]
|
||||||
|
python = ">=3.8.1,<4.0"
|
||||||
|
pydantic = "^2.4.2"
|
||||||
|
langchain = "^0.0.314"
|
||||||
|
openai = "^0.28.1"
|
||||||
|
|
||||||
|
[tool.poetry.group.test.dependencies]
|
||||||
|
pytest = "^7.4"
|
||||||
|
pytest-vcr = "^1.0.2"
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["poetry-core"]
|
||||||
|
build-backend = "poetry.core.masonry.api"
|
||||||
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
46
tests/agent_test.py
Normal file
46
tests/agent_test.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
"""Test Agent creation and execution basic functionality."""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from langchain.chat_models import ChatOpenAI as OpenAI
|
||||||
|
|
||||||
|
from ..crewai import Agent
|
||||||
|
from ..crewai import prompts
|
||||||
|
|
||||||
|
def test_agent_creation():
|
||||||
|
agent = Agent(
|
||||||
|
role="test role",
|
||||||
|
goal="test goal",
|
||||||
|
backstory="test backstory",
|
||||||
|
tools=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert agent.role == "test role"
|
||||||
|
assert agent.goal == "test goal"
|
||||||
|
assert agent.backstory == "test backstory"
|
||||||
|
assert agent.tools == []
|
||||||
|
|
||||||
|
def test_agent_default_value():
|
||||||
|
agent = Agent(
|
||||||
|
role="test role",
|
||||||
|
goal="test goal",
|
||||||
|
backstory="test backstory",
|
||||||
|
tools=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(agent.llm, OpenAI)
|
||||||
|
assert agent.llm.model_name == "gpt-4"
|
||||||
|
assert agent.llm.temperature == 0.7
|
||||||
|
assert agent.llm.verbose == True
|
||||||
|
|
||||||
|
@pytest.mark.vcr()
|
||||||
|
def test_agent_execution():
|
||||||
|
agent = Agent(
|
||||||
|
role="test role",
|
||||||
|
goal="test goal",
|
||||||
|
backstory="test backstory",
|
||||||
|
tools=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
output = agent.execute("How much is 1 + 1?")
|
||||||
|
assert output == "2"
|
||||||
94
tests/cassettes/test_agent_execution.yaml
Normal file
94
tests/cassettes/test_agent_execution.yaml
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
interactions:
|
||||||
|
- request:
|
||||||
|
body: '{"messages": [{"role": "user", "content": "You are test role.\ntest backstory\n\nYour
|
||||||
|
main goal is: test goal\n\nTOOLS:\n------\n\nYou have access to the following
|
||||||
|
tools:\n\n\n\nTo use a tool, please use the following format:\n\n```\nThought:
|
||||||
|
Do I need to use a tool? Yes\nAction: the action to take, should be one of []\nAction
|
||||||
|
Input: the input to the action\nObservation: the result of the action\n```\n\nWhen
|
||||||
|
you have a response for your task, or if you do not need to use a tool, you
|
||||||
|
MUST use the format:\n\n```\nThought: Do I need to use a tool? No\nFinal Answer:
|
||||||
|
[your response here]\n```\n\nBegin!\n\nCurrent Task: How much is 1 + 1?\n\n"}],
|
||||||
|
"model": "gpt-4", "max_tokens": null, "stream": false, "n": 1, "temperature":
|
||||||
|
0.7, "stop": ["\nObservation"]}'
|
||||||
|
headers:
|
||||||
|
Accept:
|
||||||
|
- '*/*'
|
||||||
|
Accept-Encoding:
|
||||||
|
- gzip, deflate
|
||||||
|
Authorization:
|
||||||
|
- Bearer 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
|
||||||
|
Connection:
|
||||||
|
- keep-alive
|
||||||
|
Content-Length:
|
||||||
|
- '758'
|
||||||
|
Content-Type:
|
||||||
|
- application/json
|
||||||
|
User-Agent:
|
||||||
|
- OpenAI/v1 PythonBindings/0.28.1
|
||||||
|
X-OpenAI-Client-User-Agent:
|
||||||
|
- '{"bindings_version": "0.28.1", "httplib": "requests", "lang": "python", "lang_version":
|
||||||
|
"3.9.7", "platform": "macOS-10.16-x86_64-i386-64bit", "publisher": "openai",
|
||||||
|
"uname": "Darwin 22.4.0 Darwin Kernel Version 22.4.0: Mon Mar 6 21:00:17
|
||||||
|
PST 2023; root:xnu-8796.101.5~3/RELEASE_X86_64 x86_64"}'
|
||||||
|
method: POST
|
||||||
|
uri: https://api.openai.com/v1/chat/completions
|
||||||
|
response:
|
||||||
|
body:
|
||||||
|
string: !!binary |
|
||||||
|
H4sIAAAAAAAAA1SQS0/DMBCE7/kVqz23KGmbkOaCgCoSHCohcQNUGWdJXBxviLfipf535PTJxYf5
|
||||||
|
dsaz+xsBoKmwANSNEt12dpyXORuh2U/9vUiXDzflVOLSre8/ktssx1Fw8OuatBxcF5rbzpIYdjus
|
||||||
|
e1JCITXJ5nmWzNN4NoCWK7LBVncyno3jLJnuHQ0bTR4LeIoAAH6HN3RzFX1hAfHooLTkvaoJi+MQ
|
||||||
|
APZsg4LKe+NFOcHRCWp2Qm6o+9jwpm6kgAXDHTiiCoRh4wkUCLO9giU/u9I4ZeHa+U/qC5jgPmp7
|
||||||
|
7PBmnPHNqifl2YVcL9ztxrYRwMuw0+ZfTex6bjtZCb+TC4smabrLw9P5zujlHgqLsuf6JAqfbKM/
|
||||||
|
AAAA//8DAD/1vhO7AQAA
|
||||||
|
headers:
|
||||||
|
CF-Cache-Status:
|
||||||
|
- DYNAMIC
|
||||||
|
CF-RAY:
|
||||||
|
- 81def25b4addf8f1-NVT
|
||||||
|
Cache-Control:
|
||||||
|
- no-cache, must-revalidate
|
||||||
|
Connection:
|
||||||
|
- keep-alive
|
||||||
|
Content-Encoding:
|
||||||
|
- gzip
|
||||||
|
Content-Type:
|
||||||
|
- application/json
|
||||||
|
Date:
|
||||||
|
- Sun, 29 Oct 2023 22:45:05 GMT
|
||||||
|
Server:
|
||||||
|
- cloudflare
|
||||||
|
Transfer-Encoding:
|
||||||
|
- chunked
|
||||||
|
access-control-allow-origin:
|
||||||
|
- '*'
|
||||||
|
alt-svc:
|
||||||
|
- h3=":443"; ma=86400
|
||||||
|
openai-model:
|
||||||
|
- gpt-4-0613
|
||||||
|
openai-organization:
|
||||||
|
- clearbit-2
|
||||||
|
openai-processing-ms:
|
||||||
|
- '950'
|
||||||
|
openai-version:
|
||||||
|
- '2020-10-01'
|
||||||
|
strict-transport-security:
|
||||||
|
- max-age=15724800; includeSubDomains
|
||||||
|
x-ratelimit-limit-requests:
|
||||||
|
- '100'
|
||||||
|
x-ratelimit-limit-tokens:
|
||||||
|
- '150000'
|
||||||
|
x-ratelimit-remaining-requests:
|
||||||
|
- '99'
|
||||||
|
x-ratelimit-remaining-tokens:
|
||||||
|
- '149840'
|
||||||
|
x-ratelimit-reset-requests:
|
||||||
|
- 600ms
|
||||||
|
x-ratelimit-reset-tokens:
|
||||||
|
- 64ms
|
||||||
|
x-request-id:
|
||||||
|
- b6484701bea444a976e49f353baf7be5
|
||||||
|
status:
|
||||||
|
code: 200
|
||||||
|
message: OK
|
||||||
|
version: 1
|
||||||
Reference in New Issue
Block a user