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/
|
||||
50
README.md
50
README.md
@@ -1 +1,51 @@
|
||||
# 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