mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-07 07:08:31 +00:00
Merge pull request #15 from greysonlalonde/gl/devops/ci-code-formatting-enhancements
Update Python to 3.9, Add Code Quality Tools, & Update Lockfile
This commit is contained in:
21
.pre-commit-config.yaml
Normal file
21
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
repos:
|
||||
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: 23.12.1
|
||||
hooks:
|
||||
- id: black
|
||||
language_version: python3.11
|
||||
files: \.(py)$
|
||||
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.13.2
|
||||
hooks:
|
||||
- id: isort
|
||||
name: isort (python)
|
||||
args: ["--profile", "black", "--filter-files"]
|
||||
|
||||
- repo: https://github.com/PyCQA/autoflake
|
||||
rev: v2.2.1
|
||||
hooks:
|
||||
- id: autoflake
|
||||
args: ['--in-place', '--remove-all-unused-imports', '--remove-unused-variables', '--ignore-init-module-imports']
|
||||
@@ -144,6 +144,12 @@ poetry install
|
||||
poetry shell
|
||||
```
|
||||
|
||||
### Pre-commit hooks
|
||||
|
||||
```bash
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
```bash
|
||||
poetry run pytest
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from .task import Task
|
||||
from .crew import Crew
|
||||
from .agent import Agent
|
||||
from .process import Process
|
||||
from .crew import Crew
|
||||
from .process import Process
|
||||
from .task import Task
|
||||
|
||||
204
crewai/agent.py
204
crewai/agent.py
@@ -1,128 +1,120 @@
|
||||
"""Generic agent."""
|
||||
|
||||
from typing import List, Any, Optional
|
||||
from pydantic.v1 import BaseModel, PrivateAttr, Field, root_validator
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from langchain.agents import AgentExecutor
|
||||
from langchain.chat_models import ChatOpenAI
|
||||
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 langchain.chat_models import ChatOpenAI
|
||||
from langchain.memory import ConversationSummaryMemory
|
||||
from langchain.tools.render import render_text_description
|
||||
from pydantic.v1 import BaseModel, Field, PrivateAttr, root_validator
|
||||
|
||||
from .prompts import Prompts
|
||||
|
||||
|
||||
class Agent(BaseModel):
|
||||
"""
|
||||
Represents an agent in a system.
|
||||
"""
|
||||
Represents an agent in a system.
|
||||
|
||||
Each agent has a role, a goal, a backstory, and an optional language model (llm).
|
||||
The agent can also have memory, can operate in verbose mode, and can delegate tasks to other agents.
|
||||
Each agent has a role, a goal, a backstory, and an optional language model (llm).
|
||||
The agent can also have memory, can operate in verbose mode, and can delegate tasks to other agents.
|
||||
|
||||
Attributes:
|
||||
agent_executor: An instance of the AgentExecutor class.
|
||||
role: The role of the agent.
|
||||
goal: The objective of the agent.
|
||||
backstory: The backstory of the agent.
|
||||
llm: The language model that will run the agent.
|
||||
memory: Whether the agent should have memory or not.
|
||||
verbose: Whether the agent execution should be in verbose mode.
|
||||
allow_delegation: Whether the agent is allowed to delegate tasks to other agents.
|
||||
"""
|
||||
agent_executor: AgentExecutor = None
|
||||
role: str = Field(description="Role of the agent")
|
||||
goal: str = Field(description="Objective of the agent")
|
||||
backstory: str = Field(description="Backstory of the agent")
|
||||
llm: Optional[Any] = Field(description="LLM that will run the agent")
|
||||
memory: bool = Field(
|
||||
description="Whether the agent should have memory or not",
|
||||
default=True
|
||||
)
|
||||
verbose: bool = Field(
|
||||
description="Verbose mode for the Agent Execution",
|
||||
default=False
|
||||
)
|
||||
allow_delegation: bool = Field(
|
||||
description="Allow delegation of tasks to agents",
|
||||
default=True
|
||||
)
|
||||
tools: List[Any] = Field(
|
||||
description="Tools at agents disposal",
|
||||
default=[]
|
||||
)
|
||||
_task_calls: List[Any] = PrivateAttr()
|
||||
Attributes:
|
||||
agent_executor: An instance of the AgentExecutor class.
|
||||
role: The role of the agent.
|
||||
goal: The objective of the agent.
|
||||
backstory: The backstory of the agent.
|
||||
llm: The language model that will run the agent.
|
||||
memory: Whether the agent should have memory or not.
|
||||
verbose: Whether the agent execution should be in verbose mode.
|
||||
allow_delegation: Whether the agent is allowed to delegate tasks to other agents.
|
||||
"""
|
||||
|
||||
@root_validator(pre=True)
|
||||
def check_llm(_cls, values):
|
||||
if not values.get('llm'):
|
||||
values['llm'] = ChatOpenAI(
|
||||
temperature=0.7,
|
||||
model_name="gpt-4"
|
||||
)
|
||||
return values
|
||||
agent_executor: AgentExecutor = None
|
||||
role: str = Field(description="Role of the agent")
|
||||
goal: str = Field(description="Objective of the agent")
|
||||
backstory: str = Field(description="Backstory of the agent")
|
||||
llm: Optional[Any] = Field(description="LLM that will run the agent")
|
||||
memory: bool = Field(
|
||||
description="Whether the agent should have memory or not", default=True
|
||||
)
|
||||
verbose: bool = Field(
|
||||
description="Verbose mode for the Agent Execution", default=False
|
||||
)
|
||||
allow_delegation: bool = Field(
|
||||
description="Allow delegation of tasks to agents", default=True
|
||||
)
|
||||
tools: List[Any] = Field(description="Tools at agents disposal", default=[])
|
||||
_task_calls: List[Any] = PrivateAttr()
|
||||
|
||||
def __init__(self, **data):
|
||||
super().__init__(**data)
|
||||
agent_args = {
|
||||
"input": lambda x: x["input"],
|
||||
"tools": lambda x: x["tools"],
|
||||
"tool_names": lambda x: x["tool_names"],
|
||||
"agent_scratchpad": lambda x: format_log_to_str(x['intermediate_steps']),
|
||||
}
|
||||
executor_args = {
|
||||
"tools": self.tools,
|
||||
"verbose": self.verbose,
|
||||
"handle_parsing_errors": True,
|
||||
}
|
||||
@root_validator(pre=True)
|
||||
def check_llm(_cls, values):
|
||||
if not values.get("llm"):
|
||||
values["llm"] = ChatOpenAI(temperature=0.7, model_name="gpt-4")
|
||||
return values
|
||||
|
||||
if self.memory:
|
||||
summary_memory = ConversationSummaryMemory(
|
||||
llm=self.llm,
|
||||
memory_key='chat_history',
|
||||
input_key="input"
|
||||
)
|
||||
executor_args['memory'] = summary_memory
|
||||
agent_args['chat_history'] = lambda x: x["chat_history"]
|
||||
prompt = Prompts.TASK_EXECUTION_WITH_MEMORY_PROMPT
|
||||
else:
|
||||
prompt = Prompts.TASK_EXECUTION_PROMPT
|
||||
def __init__(self, **data):
|
||||
super().__init__(**data)
|
||||
agent_args = {
|
||||
"input": lambda x: x["input"],
|
||||
"tools": lambda x: x["tools"],
|
||||
"tool_names": lambda x: x["tool_names"],
|
||||
"agent_scratchpad": lambda x: format_log_to_str(x["intermediate_steps"]),
|
||||
}
|
||||
executor_args = {
|
||||
"tools": self.tools,
|
||||
"verbose": self.verbose,
|
||||
"handle_parsing_errors": True,
|
||||
}
|
||||
|
||||
execution_prompt = prompt.partial(
|
||||
goal=self.goal,
|
||||
role=self.role,
|
||||
backstory=self.backstory,
|
||||
)
|
||||
if self.memory:
|
||||
summary_memory = ConversationSummaryMemory(
|
||||
llm=self.llm, memory_key="chat_history", input_key="input"
|
||||
)
|
||||
executor_args["memory"] = summary_memory
|
||||
agent_args["chat_history"] = lambda x: x["chat_history"]
|
||||
prompt = Prompts.TASK_EXECUTION_WITH_MEMORY_PROMPT
|
||||
else:
|
||||
prompt = Prompts.TASK_EXECUTION_PROMPT
|
||||
|
||||
bind = self.llm.bind(stop=["\nObservation"])
|
||||
inner_agent = agent_args | execution_prompt | bind | ReActSingleInputOutputParser()
|
||||
execution_prompt = prompt.partial(
|
||||
goal=self.goal,
|
||||
role=self.role,
|
||||
backstory=self.backstory,
|
||||
)
|
||||
|
||||
self.agent_executor = AgentExecutor(
|
||||
agent=inner_agent,
|
||||
**executor_args
|
||||
)
|
||||
bind = self.llm.bind(stop=["\nObservation"])
|
||||
inner_agent = (
|
||||
agent_args | execution_prompt | bind | ReActSingleInputOutputParser()
|
||||
)
|
||||
|
||||
def execute_task(self, task: str, context: str = None, tools: List[Any] = None) -> str:
|
||||
"""
|
||||
Execute a task with the agent.
|
||||
Parameters:
|
||||
task (str): Task to execute
|
||||
Returns:
|
||||
output (str): Output of the agent
|
||||
"""
|
||||
if context:
|
||||
task = "\n".join([
|
||||
task,
|
||||
"\nThis is the context you are working with:",
|
||||
context
|
||||
])
|
||||
self.agent_executor = AgentExecutor(agent=inner_agent, **executor_args)
|
||||
|
||||
tools = tools or self.tools
|
||||
self.agent_executor.tools = tools
|
||||
return self.agent_executor.invoke({
|
||||
"input": task,
|
||||
"tool_names": self.__tools_names(tools),
|
||||
"tools": render_text_description(tools),
|
||||
})['output']
|
||||
def execute_task(
|
||||
self, task: str, context: str = None, tools: List[Any] = None
|
||||
) -> str:
|
||||
"""
|
||||
Execute a task with the agent.
|
||||
Parameters:
|
||||
task (str): Task to execute
|
||||
Returns:
|
||||
output (str): Output of the agent
|
||||
"""
|
||||
if context:
|
||||
task = "\n".join(
|
||||
[task, "\nThis is the context you are working with:", context]
|
||||
)
|
||||
|
||||
def __tools_names(self, tools) -> str:
|
||||
return ", ".join([t.name for t in tools])
|
||||
tools = tools or self.tools
|
||||
self.agent_executor.tools = tools
|
||||
return self.agent_executor.invoke(
|
||||
{
|
||||
"input": task,
|
||||
"tool_names": self.__tools_names(tools),
|
||||
"tools": render_text_description(tools),
|
||||
}
|
||||
)["output"]
|
||||
|
||||
def __tools_names(self, tools) -> str:
|
||||
return ", ".join([t.name for t in tools])
|
||||
|
||||
147
crewai/crew.py
147
crewai/crew.py
@@ -1,89 +1,88 @@
|
||||
import json
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic.v1 import BaseModel, Field, Json, root_validator
|
||||
|
||||
from .process import Process
|
||||
from .agent import Agent
|
||||
from .process import Process
|
||||
from .task import Task
|
||||
from .tools.agent_tools import AgentTools
|
||||
|
||||
|
||||
class Crew(BaseModel):
|
||||
"""
|
||||
Class that represents a group of agents, how they should work together and
|
||||
their tasks.
|
||||
"""
|
||||
tasks: Optional[List[Task]] = Field(description="List of tasks")
|
||||
agents: Optional[List[Agent]] = Field(description="List of agents in this crew.")
|
||||
process: Process = Field(
|
||||
description="Process that the crew will follow.",
|
||||
default=Process.sequential
|
||||
)
|
||||
verbose: bool = Field(
|
||||
description="Verbose mode for the Agent Execution",
|
||||
default=False
|
||||
)
|
||||
config: Optional[Json] = Field(
|
||||
description="Configuration of the crew.",
|
||||
default=None
|
||||
)
|
||||
"""
|
||||
Class that represents a group of agents, how they should work together and
|
||||
their tasks.
|
||||
"""
|
||||
|
||||
@root_validator(pre=True)
|
||||
def check_config(_cls, values):
|
||||
if (
|
||||
not values.get('config')
|
||||
and (
|
||||
not values.get('agents') and not values.get('tasks')
|
||||
)
|
||||
):
|
||||
raise ValueError('Either agents and task need to be set or config.')
|
||||
|
||||
if values.get('config'):
|
||||
config = json.loads(values.get('config'))
|
||||
if not config.get('agents') or not config.get('tasks'):
|
||||
raise ValueError('Config should have agents and tasks.')
|
||||
|
||||
values['agents'] = [Agent(**agent) for agent in config['agents']]
|
||||
|
||||
tasks = []
|
||||
for task in config['tasks']:
|
||||
task_agent = [agt for agt in values['agents'] if agt.role == task['agent']][0]
|
||||
del task['agent']
|
||||
tasks.append(Task(**task, agent=task_agent))
|
||||
|
||||
values['tasks'] = tasks
|
||||
return values
|
||||
tasks: Optional[List[Task]] = Field(description="List of tasks")
|
||||
agents: Optional[List[Agent]] = Field(description="List of agents in this crew.")
|
||||
process: Process = Field(
|
||||
description="Process that the crew will follow.", default=Process.sequential
|
||||
)
|
||||
verbose: bool = Field(
|
||||
description="Verbose mode for the Agent Execution", default=False
|
||||
)
|
||||
config: Optional[Json] = Field(
|
||||
description="Configuration of the crew.", default=None
|
||||
)
|
||||
|
||||
def kickoff(self) -> str:
|
||||
"""
|
||||
Kickoff the crew to work on it's tasks.
|
||||
Returns:
|
||||
output (List[str]): Output of the crew for each task.
|
||||
"""
|
||||
if self.process == Process.sequential:
|
||||
return self.__sequential_loop()
|
||||
@root_validator(pre=True)
|
||||
def check_config(_cls, values):
|
||||
if not values.get("config") and (
|
||||
not values.get("agents") and not values.get("tasks")
|
||||
):
|
||||
raise ValueError("Either agents and task need to be set or config.")
|
||||
|
||||
def __sequential_loop(self) -> str:
|
||||
"""
|
||||
Loop that executes the sequential process.
|
||||
Returns:
|
||||
output (str): Output of the crew.
|
||||
"""
|
||||
task_outcome = None
|
||||
for task in self.tasks:
|
||||
# Add delegation tools to the task if the agent allows it
|
||||
if task.agent.allow_delegation:
|
||||
tools = AgentTools(agents=self.agents).tools()
|
||||
task.tools += tools
|
||||
if values.get("config"):
|
||||
config = json.loads(values.get("config"))
|
||||
if not config.get("agents") or not config.get("tasks"):
|
||||
raise ValueError("Config should have agents and tasks.")
|
||||
|
||||
self.__log(f"\nWorking Agent: {task.agent.role}")
|
||||
self.__log(f"Starting Task: {task.description} ...")
|
||||
values["agents"] = [Agent(**agent) for agent in config["agents"]]
|
||||
|
||||
task_outcome = task.execute(task_outcome)
|
||||
tasks = []
|
||||
for task in config["tasks"]:
|
||||
task_agent = [
|
||||
agt for agt in values["agents"] if agt.role == task["agent"]
|
||||
][0]
|
||||
del task["agent"]
|
||||
tasks.append(Task(**task, agent=task_agent))
|
||||
|
||||
self.__log(f"Task output: {task_outcome}")
|
||||
|
||||
return task_outcome
|
||||
|
||||
def __log(self, message):
|
||||
if self.verbose:
|
||||
print(message)
|
||||
values["tasks"] = tasks
|
||||
return values
|
||||
|
||||
def kickoff(self) -> str:
|
||||
"""
|
||||
Kickoff the crew to work on it's tasks.
|
||||
Returns:
|
||||
output (List[str]): Output of the crew for each task.
|
||||
"""
|
||||
if self.process == Process.sequential:
|
||||
return self.__sequential_loop()
|
||||
|
||||
def __sequential_loop(self) -> str:
|
||||
"""
|
||||
Loop that executes the sequential process.
|
||||
Returns:
|
||||
output (str): Output of the crew.
|
||||
"""
|
||||
task_outcome = None
|
||||
for task in self.tasks:
|
||||
# Add delegation tools to the task if the agent allows it
|
||||
if task.agent.allow_delegation:
|
||||
tools = AgentTools(agents=self.agents).tools()
|
||||
task.tools += tools
|
||||
|
||||
self.__log(f"\nWorking Agent: {task.agent.role}")
|
||||
self.__log(f"Starting Task: {task.description} ...")
|
||||
|
||||
task_outcome = task.execute(task_outcome)
|
||||
|
||||
self.__log(f"Task output: {task_outcome}")
|
||||
|
||||
return task_outcome
|
||||
|
||||
def __log(self, message):
|
||||
if self.verbose:
|
||||
print(message)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class Process(str, Enum):
|
||||
"""
|
||||
Class representing the different processes that can be used to tackle tasks
|
||||
"""
|
||||
sequential = 'sequential'
|
||||
# TODO: consensual = 'consensual'
|
||||
# TODO: hierarchical = 'hierarchical'
|
||||
"""
|
||||
Class representing the different processes that can be used to tackle tasks
|
||||
"""
|
||||
|
||||
sequential = "sequential"
|
||||
# TODO: consensual = 'consensual'
|
||||
# TODO: hierarchical = 'hierarchical'
|
||||
|
||||
@@ -2,32 +2,41 @@
|
||||
|
||||
from textwrap import dedent
|
||||
from typing import ClassVar
|
||||
from pydantic.v1 import BaseModel
|
||||
|
||||
from langchain.prompts import PromptTemplate
|
||||
from pydantic.v1 import BaseModel
|
||||
|
||||
|
||||
class Prompts(BaseModel):
|
||||
"""Prompts for generic agent."""
|
||||
"""Prompts for generic agent."""
|
||||
|
||||
TASK_SLICE: ClassVar[str] = dedent("""\
|
||||
TASK_SLICE: ClassVar[str] = dedent(
|
||||
"""\
|
||||
Begin! This is VERY important to you, your job depends on it!
|
||||
|
||||
Current Task: {input}
|
||||
{agent_scratchpad}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
MEMORY_SLICE: ClassVar[str] = dedent("""\
|
||||
MEMORY_SLICE: ClassVar[str] = dedent(
|
||||
"""\
|
||||
This is the summary of your work so far:
|
||||
{chat_history}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
ROLE_PLAYING_SLICE: ClassVar[str] = dedent("""\
|
||||
ROLE_PLAYING_SLICE: ClassVar[str] = dedent(
|
||||
"""\
|
||||
You are {role}.
|
||||
{backstory}
|
||||
|
||||
Your personal goal is: {goal}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
TOOLS_SLICE: ClassVar[str] = dedent("""\
|
||||
TOOLS_SLICE: ClassVar[str] = dedent(
|
||||
"""\
|
||||
|
||||
TOOLS:
|
||||
------
|
||||
@@ -50,9 +59,11 @@ class Prompts(BaseModel):
|
||||
Thought: Do I need to use a tool? No
|
||||
Final Answer: [your response here]
|
||||
```
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
VOTING_SLICE: ClassVar[str] = dedent("""\
|
||||
VOTING_SLICE: ClassVar[str] = dedent(
|
||||
"""\
|
||||
You are working on a crew with your co-workers and need to decide who will execute the task.
|
||||
|
||||
These are your format instructions:
|
||||
@@ -60,16 +71,17 @@ class Prompts(BaseModel):
|
||||
|
||||
These are your co-workers and their roles:
|
||||
{coworkers}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
TASK_EXECUTION_WITH_MEMORY_PROMPT: ClassVar[str] = PromptTemplate.from_template(
|
||||
ROLE_PLAYING_SLICE + TOOLS_SLICE + MEMORY_SLICE + TASK_SLICE
|
||||
)
|
||||
TASK_EXECUTION_WITH_MEMORY_PROMPT: ClassVar[str] = PromptTemplate.from_template(
|
||||
ROLE_PLAYING_SLICE + TOOLS_SLICE + MEMORY_SLICE + TASK_SLICE
|
||||
)
|
||||
|
||||
TASK_EXECUTION_PROMPT: ClassVar[str] = PromptTemplate.from_template(
|
||||
ROLE_PLAYING_SLICE + TOOLS_SLICE + TASK_SLICE
|
||||
)
|
||||
TASK_EXECUTION_PROMPT: ClassVar[str] = PromptTemplate.from_template(
|
||||
ROLE_PLAYING_SLICE + TOOLS_SLICE + TASK_SLICE
|
||||
)
|
||||
|
||||
CONSENSUNS_VOTING_PROMPT: ClassVar[str] = PromptTemplate.from_template(
|
||||
ROLE_PLAYING_SLICE + VOTING_SLICE + TASK_SLICE
|
||||
)
|
||||
CONSENSUNS_VOTING_PROMPT: ClassVar[str] = PromptTemplate.from_template(
|
||||
ROLE_PLAYING_SLICE + VOTING_SLICE + TASK_SLICE
|
||||
)
|
||||
|
||||
@@ -1,42 +1,41 @@
|
||||
from typing import List, Optional
|
||||
from pydantic.v1 import BaseModel, Field, root_validator
|
||||
|
||||
from langchain.tools import Tool
|
||||
from pydantic.v1 import BaseModel, Field, root_validator
|
||||
|
||||
from .agent import Agent
|
||||
|
||||
|
||||
class Task(BaseModel):
|
||||
"""
|
||||
Class that represent a task to be executed.
|
||||
"""
|
||||
|
||||
description: str = Field(description="Description of the actual task.")
|
||||
agent: Optional[Agent] = Field(
|
||||
description="Agent responsible for the task.",
|
||||
default=None
|
||||
)
|
||||
tools: Optional[List[Tool]] = Field(
|
||||
description="Tools the agent are limited to use for this task.",
|
||||
default=[]
|
||||
)
|
||||
"""
|
||||
Class that represent a task to be executed.
|
||||
"""
|
||||
|
||||
@root_validator(pre=False)
|
||||
def _set_tools(_cls, values):
|
||||
if (values.get('agent')) and not (values.get('tools')):
|
||||
values['tools'] = values.get('agent').tools
|
||||
return values
|
||||
description: str = Field(description="Description of the actual task.")
|
||||
agent: Optional[Agent] = Field(
|
||||
description="Agent responsible for the task.", default=None
|
||||
)
|
||||
tools: Optional[List[Tool]] = Field(
|
||||
description="Tools the agent are limited to use for this task.", default=[]
|
||||
)
|
||||
|
||||
def execute(self, context: str = None) -> str:
|
||||
"""
|
||||
Execute the task.
|
||||
Returns:
|
||||
output (str): Output of the task.
|
||||
"""
|
||||
if self.agent:
|
||||
return self.agent.execute_task(
|
||||
task = self.description,
|
||||
context = context,
|
||||
tools = self.tools
|
||||
)
|
||||
else:
|
||||
raise Exception(f"The task '{self.description}' has no agent assigned, therefore it can't be executed directly and should be executed in a Crew using a specific process that support that, either consensual or hierarchical.")
|
||||
@root_validator(pre=False)
|
||||
def _set_tools(_cls, values):
|
||||
if (values.get("agent")) and not (values.get("tools")):
|
||||
values["tools"] = values.get("agent").tools
|
||||
return values
|
||||
|
||||
def execute(self, context: str = None) -> str:
|
||||
"""
|
||||
Execute the task.
|
||||
Returns:
|
||||
output (str): Output of the task.
|
||||
"""
|
||||
if self.agent:
|
||||
return self.agent.execute_task(
|
||||
task=self.description, context=context, tools=self.tools
|
||||
)
|
||||
else:
|
||||
raise Exception(
|
||||
f"The task '{self.description}' has no agent assigned, therefore it can't be executed directly and should be executed in a Crew using a specific process that support that, either consensual or hierarchical."
|
||||
)
|
||||
|
||||
0
crewai/tools/__init__.py
Normal file
0
crewai/tools/__init__.py
Normal file
@@ -1,61 +1,74 @@
|
||||
from typing import List, Any
|
||||
from pydantic.v1 import BaseModel, Field
|
||||
from textwrap import dedent
|
||||
from typing import List
|
||||
|
||||
from langchain.tools import Tool
|
||||
from pydantic.v1 import BaseModel, Field
|
||||
|
||||
from ..agent import Agent
|
||||
|
||||
class AgentTools(BaseModel):
|
||||
"""Tools for generic agent."""
|
||||
agents: List[Agent] = Field(description="List of agents in this crew.")
|
||||
|
||||
def tools(self):
|
||||
return [
|
||||
Tool.from_function(
|
||||
func=self.delegate_work,
|
||||
name="Delegate Work to Co-Worker",
|
||||
description=dedent(f"""Useful to delegate a specific task to one of the
|
||||
class AgentTools(BaseModel):
|
||||
"""Tools for generic agent."""
|
||||
|
||||
agents: List[Agent] = Field(description="List of agents in this crew.")
|
||||
|
||||
def tools(self):
|
||||
return [
|
||||
Tool.from_function(
|
||||
func=self.delegate_work,
|
||||
name="Delegate Work to Co-Worker",
|
||||
description=dedent(
|
||||
f"""Useful to delegate a specific task to one of the
|
||||
following co-workers: [{', '.join([agent.role for agent in self.agents])}].
|
||||
The input to this tool should be a pipe (|) separated text of length
|
||||
three, representing the role you want to delegate it to, the task and
|
||||
information necessary. For example, `coworker|task|information`.
|
||||
""")
|
||||
),
|
||||
Tool.from_function(
|
||||
func=self.ask_question,
|
||||
name="Ask Question to Co-Worker",
|
||||
description=dedent(f"""Useful to ask a question, opinion or take from on
|
||||
"""
|
||||
),
|
||||
),
|
||||
Tool.from_function(
|
||||
func=self.ask_question,
|
||||
name="Ask Question to Co-Worker",
|
||||
description=dedent(
|
||||
f"""Useful to ask a question, opinion or take from on
|
||||
of the following co-workers: [{', '.join([agent.role for agent in self.agents])}].
|
||||
The input to this tool should be a pipe (|) separated text of length
|
||||
three, representing the role you want to ask it to, the question and
|
||||
information necessary. For example, `coworker|question|information`.
|
||||
""")
|
||||
),
|
||||
]
|
||||
"""
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
def delegate_work(self, command):
|
||||
"""Useful to delegate a specific task to a coworker."""
|
||||
return self.__execute(command)
|
||||
def delegate_work(self, command):
|
||||
"""Useful to delegate a specific task to a coworker."""
|
||||
return self.__execute(command)
|
||||
|
||||
def ask_question(self, command):
|
||||
"""Useful to ask a question, opinion or take from a coworker."""
|
||||
return self.__execute(command)
|
||||
def ask_question(self, command):
|
||||
"""Useful to ask a question, opinion or take from a coworker."""
|
||||
return self.__execute(command)
|
||||
|
||||
def __execute(self, command):
|
||||
"""Execute the command."""
|
||||
try:
|
||||
agent, task, information = command.split("|")
|
||||
except ValueError:
|
||||
return "Error executing tool. Missing exact 3 pipe (|) separated values. For example, `coworker|task|information`."
|
||||
def __execute(self, command):
|
||||
"""Execute the command."""
|
||||
try:
|
||||
agent, task, information = command.split("|")
|
||||
except ValueError:
|
||||
return "Error executing tool. Missing exact 3 pipe (|) separated values. For example, `coworker|task|information`."
|
||||
|
||||
if not agent or not task or not information:
|
||||
return "Error executing tool. Missing exact 3 pipe (|) separated values. For example, `coworker|question|information`."
|
||||
if not agent or not task or not information:
|
||||
return "Error executing tool. Missing exact 3 pipe (|) separated values. For example, `coworker|question|information`."
|
||||
|
||||
agent = [available_agent for available_agent in self.agents if available_agent.role == agent]
|
||||
agent = [
|
||||
available_agent
|
||||
for available_agent in self.agents
|
||||
if available_agent.role == agent
|
||||
]
|
||||
|
||||
if len(agent) == 0:
|
||||
return "Error executing tool. Co-worker not found, double check the co-worker."
|
||||
if len(agent) == 0:
|
||||
return (
|
||||
"Error executing tool. Co-worker not found, double check the co-worker."
|
||||
)
|
||||
|
||||
agent = agent[0]
|
||||
result = agent.execute_task(task, information)
|
||||
return result
|
||||
agent = agent[0]
|
||||
result = agent.execute_task(task, information)
|
||||
return result
|
||||
|
||||
321
poetry.lock
generated
321
poetry.lock
generated
@@ -121,9 +121,6 @@ files = [
|
||||
{file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""}
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.2.0"
|
||||
@@ -175,6 +172,67 @@ docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-
|
||||
tests = ["attrs[tests-no-zope]", "zope-interface"]
|
||||
tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
|
||||
|
||||
[[package]]
|
||||
name = "autoflake"
|
||||
version = "2.2.1"
|
||||
description = "Removes unused imports and unused variables"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "autoflake-2.2.1-py3-none-any.whl", hash = "sha256:265cde0a43c1f44ecfb4f30d95b0437796759d07be7706a2f70e4719234c0f79"},
|
||||
{file = "autoflake-2.2.1.tar.gz", hash = "sha256:62b7b6449a692c3c9b0c916919bbc21648da7281e8506bcf8d3f8280e431ebc1"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pyflakes = ">=3.0.0"
|
||||
tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""}
|
||||
|
||||
[[package]]
|
||||
name = "black"
|
||||
version = "23.12.1"
|
||||
description = "The uncompromising code formatter."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"},
|
||||
{file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"},
|
||||
{file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"},
|
||||
{file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"},
|
||||
{file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"},
|
||||
{file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"},
|
||||
{file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"},
|
||||
{file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"},
|
||||
{file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"},
|
||||
{file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"},
|
||||
{file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"},
|
||||
{file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"},
|
||||
{file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"},
|
||||
{file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"},
|
||||
{file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"},
|
||||
{file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"},
|
||||
{file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"},
|
||||
{file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"},
|
||||
{file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"},
|
||||
{file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"},
|
||||
{file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"},
|
||||
{file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
click = ">=8.0.0"
|
||||
mypy-extensions = ">=0.4.3"
|
||||
packaging = ">=22.0"
|
||||
pathspec = ">=0.9.0"
|
||||
platformdirs = ">=2"
|
||||
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
|
||||
typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""}
|
||||
|
||||
[package.extras]
|
||||
colorama = ["colorama (>=0.4.3)"]
|
||||
d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"]
|
||||
jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
|
||||
uvloop = ["uvloop (>=0.15.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2023.11.17"
|
||||
@@ -186,6 +244,17 @@ files = [
|
||||
{file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfgv"
|
||||
version = "3.4.0"
|
||||
description = "Validate configuration and produce human readable error messages."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
|
||||
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.3.2"
|
||||
@@ -285,6 +354,20 @@ files = [
|
||||
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.1.7"
|
||||
description = "Composable command line interface toolkit"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
|
||||
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
@@ -311,6 +394,17 @@ files = [
|
||||
marshmallow = ">=3.18.0,<4.0.0"
|
||||
typing-inspect = ">=0.4.0,<1"
|
||||
|
||||
[[package]]
|
||||
name = "distlib"
|
||||
version = "0.3.8"
|
||||
description = "Distribution utilities"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"},
|
||||
{file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "distro"
|
||||
version = "1.9.0"
|
||||
@@ -336,6 +430,22 @@ files = [
|
||||
[package.extras]
|
||||
test = ["pytest (>=6)"]
|
||||
|
||||
[[package]]
|
||||
name = "filelock"
|
||||
version = "3.13.1"
|
||||
description = "A platform independent file lock."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"},
|
||||
{file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"]
|
||||
testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"]
|
||||
typing = ["typing-extensions (>=4.8)"]
|
||||
|
||||
[[package]]
|
||||
name = "frozenlist"
|
||||
version = "1.4.1"
|
||||
@@ -549,6 +659,20 @@ cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
|
||||
http2 = ["h2 (>=3,<5)"]
|
||||
socks = ["socksio (==1.*)"]
|
||||
|
||||
[[package]]
|
||||
name = "identify"
|
||||
version = "2.5.33"
|
||||
description = "File identification library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"},
|
||||
{file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
license = ["ukkonen"]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.6"
|
||||
@@ -571,6 +695,20 @@ files = [
|
||||
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "isort"
|
||||
version = "5.13.2"
|
||||
description = "A Python utility / library to sort Python imports."
|
||||
optional = false
|
||||
python-versions = ">=3.8.0"
|
||||
files = [
|
||||
{file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"},
|
||||
{file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
colors = ["colorama (>=0.4.6)"]
|
||||
|
||||
[[package]]
|
||||
name = "jsonpatch"
|
||||
version = "1.33"
|
||||
@@ -815,41 +953,63 @@ files = [
|
||||
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nodeenv"
|
||||
version = "1.8.0"
|
||||
description = "Node.js virtual environment builder"
|
||||
optional = false
|
||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
|
||||
files = [
|
||||
{file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"},
|
||||
{file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
setuptools = "*"
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "1.24.4"
|
||||
version = "1.26.2"
|
||||
description = "Fundamental package for array computing in Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"},
|
||||
{file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"},
|
||||
{file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"},
|
||||
{file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"},
|
||||
{file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"},
|
||||
{file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"},
|
||||
{file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"},
|
||||
{file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"},
|
||||
{file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"},
|
||||
{file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"},
|
||||
{file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"},
|
||||
{file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"},
|
||||
{file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"},
|
||||
{file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"},
|
||||
{file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"},
|
||||
{file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"},
|
||||
{file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"},
|
||||
{file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"},
|
||||
{file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"},
|
||||
{file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"},
|
||||
{file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"},
|
||||
{file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"},
|
||||
{file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"},
|
||||
{file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"},
|
||||
{file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"},
|
||||
{file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"},
|
||||
{file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"},
|
||||
{file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"},
|
||||
{file = "numpy-1.26.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3703fc9258a4a122d17043e57b35e5ef1c5a5837c3db8be396c82e04c1cf9b0f"},
|
||||
{file = "numpy-1.26.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cc392fdcbd21d4be6ae1bb4475a03ce3b025cd49a9be5345d76d7585aea69440"},
|
||||
{file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36340109af8da8805d8851ef1d74761b3b88e81a9bd80b290bbfed61bd2b4f75"},
|
||||
{file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcc008217145b3d77abd3e4d5ef586e3bdfba8fe17940769f8aa09b99e856c00"},
|
||||
{file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3ced40d4e9e18242f70dd02d739e44698df3dcb010d31f495ff00a31ef6014fe"},
|
||||
{file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b272d4cecc32c9e19911891446b72e986157e6a1809b7b56518b4f3755267523"},
|
||||
{file = "numpy-1.26.2-cp310-cp310-win32.whl", hash = "sha256:22f8fc02fdbc829e7a8c578dd8d2e15a9074b630d4da29cda483337e300e3ee9"},
|
||||
{file = "numpy-1.26.2-cp310-cp310-win_amd64.whl", hash = "sha256:26c9d33f8e8b846d5a65dd068c14e04018d05533b348d9eaeef6c1bd787f9919"},
|
||||
{file = "numpy-1.26.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b96e7b9c624ef3ae2ae0e04fa9b460f6b9f17ad8b4bec6d7756510f1f6c0c841"},
|
||||
{file = "numpy-1.26.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aa18428111fb9a591d7a9cc1b48150097ba6a7e8299fb56bdf574df650e7d1f1"},
|
||||
{file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06fa1ed84aa60ea6ef9f91ba57b5ed963c3729534e6e54055fc151fad0423f0a"},
|
||||
{file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96ca5482c3dbdd051bcd1fce8034603d6ebfc125a7bd59f55b40d8f5d246832b"},
|
||||
{file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:854ab91a2906ef29dc3925a064fcd365c7b4da743f84b123002f6139bcb3f8a7"},
|
||||
{file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f43740ab089277d403aa07567be138fc2a89d4d9892d113b76153e0e412409f8"},
|
||||
{file = "numpy-1.26.2-cp311-cp311-win32.whl", hash = "sha256:a2bbc29fcb1771cd7b7425f98b05307776a6baf43035d3b80c4b0f29e9545186"},
|
||||
{file = "numpy-1.26.2-cp311-cp311-win_amd64.whl", hash = "sha256:2b3fca8a5b00184828d12b073af4d0fc5fdd94b1632c2477526f6bd7842d700d"},
|
||||
{file = "numpy-1.26.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a4cd6ed4a339c21f1d1b0fdf13426cb3b284555c27ac2f156dfdaaa7e16bfab0"},
|
||||
{file = "numpy-1.26.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5d5244aabd6ed7f312268b9247be47343a654ebea52a60f002dc70c769048e75"},
|
||||
{file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a3cdb4d9c70e6b8c0814239ead47da00934666f668426fc6e94cce869e13fd7"},
|
||||
{file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa317b2325f7aa0a9471663e6093c210cb2ae9c0ad824732b307d2c51983d5b6"},
|
||||
{file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:174a8880739c16c925799c018f3f55b8130c1f7c8e75ab0a6fa9d41cab092fd6"},
|
||||
{file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f79b231bf5c16b1f39c7f4875e1ded36abee1591e98742b05d8a0fb55d8a3eec"},
|
||||
{file = "numpy-1.26.2-cp312-cp312-win32.whl", hash = "sha256:4a06263321dfd3598cacb252f51e521a8cb4b6df471bb12a7ee5cbab20ea9167"},
|
||||
{file = "numpy-1.26.2-cp312-cp312-win_amd64.whl", hash = "sha256:b04f5dc6b3efdaab541f7857351aac359e6ae3c126e2edb376929bd3b7f92d7e"},
|
||||
{file = "numpy-1.26.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4eb8df4bf8d3d90d091e0146f6c28492b0be84da3e409ebef54349f71ed271ef"},
|
||||
{file = "numpy-1.26.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1a13860fdcd95de7cf58bd6f8bc5a5ef81c0b0625eb2c9a783948847abbef2c2"},
|
||||
{file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64308ebc366a8ed63fd0bf426b6a9468060962f1a4339ab1074c228fa6ade8e3"},
|
||||
{file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baf8aab04a2c0e859da118f0b38617e5ee65d75b83795055fb66c0d5e9e9b818"},
|
||||
{file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d73a3abcac238250091b11caef9ad12413dab01669511779bc9b29261dd50210"},
|
||||
{file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b361d369fc7e5e1714cf827b731ca32bff8d411212fccd29ad98ad622449cc36"},
|
||||
{file = "numpy-1.26.2-cp39-cp39-win32.whl", hash = "sha256:bd3f0091e845164a20bd5a326860c840fe2af79fa12e0469a12768a3ec578d80"},
|
||||
{file = "numpy-1.26.2-cp39-cp39-win_amd64.whl", hash = "sha256:2beef57fb031dcc0dc8fa4fe297a742027b954949cabb52a2a376c144e5e6060"},
|
||||
{file = "numpy-1.26.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1cc3d5029a30fb5f06704ad6b23b35e11309491c999838c31f124fee32107c79"},
|
||||
{file = "numpy-1.26.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94cc3c222bb9fb5a12e334d0479b97bb2df446fbe622b470928f5284ffca3f8d"},
|
||||
{file = "numpy-1.26.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe6b44fb8fcdf7eda4ef4461b97b3f63c466b27ab151bec2366db8b197387841"},
|
||||
{file = "numpy-1.26.2.tar.gz", hash = "sha256:f65738447676ab5777f11e6bbbdb8ce11b785e105f690bc45966574816b6d3ea"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -886,6 +1046,32 @@ files = [
|
||||
{file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "0.12.1"
|
||||
description = "Utility library for gitignore style pattern matching of file paths."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
|
||||
{file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "platformdirs"
|
||||
version = "4.1.0"
|
||||
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"},
|
||||
{file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
|
||||
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "1.3.0"
|
||||
@@ -901,6 +1087,24 @@ files = [
|
||||
dev = ["pre-commit", "tox"]
|
||||
testing = ["pytest", "pytest-benchmark"]
|
||||
|
||||
[[package]]
|
||||
name = "pre-commit"
|
||||
version = "3.6.0"
|
||||
description = "A framework for managing and maintaining multi-language pre-commit hooks."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "pre_commit-3.6.0-py2.py3-none-any.whl", hash = "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376"},
|
||||
{file = "pre_commit-3.6.0.tar.gz", hash = "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
cfgv = ">=2.0.0"
|
||||
identify = ">=1.0.0"
|
||||
nodeenv = ">=0.11.1"
|
||||
pyyaml = ">=5.1"
|
||||
virtualenv = ">=20.10.0"
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.5.3"
|
||||
@@ -1037,6 +1241,17 @@ files = [
|
||||
[package.dependencies]
|
||||
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
||||
|
||||
[[package]]
|
||||
name = "pyflakes"
|
||||
version = "3.1.0"
|
||||
description = "passive checker of Python programs"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"},
|
||||
{file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "7.4.3"
|
||||
@@ -1168,6 +1383,22 @@ urllib3 = ">=1.21.1,<3"
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "69.0.3"
|
||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"},
|
||||
{file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
||||
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
||||
testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
|
||||
|
||||
[[package]]
|
||||
name = "sniffio"
|
||||
version = "1.3.0"
|
||||
@@ -1370,6 +1601,26 @@ urllib3 = {version = "<2", markers = "python_version < \"3.10\""}
|
||||
wrapt = "*"
|
||||
yarl = "*"
|
||||
|
||||
[[package]]
|
||||
name = "virtualenv"
|
||||
version = "20.25.0"
|
||||
description = "Virtual Python Environment builder"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"},
|
||||
{file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
distlib = ">=0.3.7,<1"
|
||||
filelock = ">=3.12.2,<4"
|
||||
platformdirs = ">=3.9.1,<5"
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
|
||||
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
|
||||
|
||||
[[package]]
|
||||
name = "wrapt"
|
||||
version = "1.16.0"
|
||||
@@ -1554,5 +1805,5 @@ multidict = ">=4.0"
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
content-hash = "d4b313f67f1942e153e515c12288b3252f955e1ebf75b4b7b28aa0c0f9dd4bd7"
|
||||
python-versions = ">=3.9,<4.0"
|
||||
content-hash = "6518523eef59e35f89783fbdd92ff6f06a5a1b0d32c3d4241b5cce9713c84e47"
|
||||
|
||||
@@ -12,11 +12,20 @@ Documentation = "https://github.com/joaomdmoura/CrewAI/wiki/Index"
|
||||
Repository = "https://github.com/joaomdmoura/crewai"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.8.1,<4.0"
|
||||
python = ">=3.9,<4.0"
|
||||
pydantic = "^2.4.2"
|
||||
langchain = "^0.0.351"
|
||||
openai = "^1.5.0"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
isort = "^5.13.2"
|
||||
black = "^23.12.1"
|
||||
autoflake = "^2.2.1"
|
||||
pre-commit = "^3.6.0"
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
|
||||
[tool.poetry.group.test.dependencies]
|
||||
pytest = "^7.4"
|
||||
pytest-vcr = "^1.0.2"
|
||||
|
||||
@@ -1,139 +1,125 @@
|
||||
"""Test Agent creation and execution basic functionality."""
|
||||
|
||||
import pytest
|
||||
|
||||
from langchain.chat_models import ChatOpenAI as OpenAI
|
||||
|
||||
from ..crewai import Agent
|
||||
|
||||
def test_agent_creation():
|
||||
agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory"
|
||||
)
|
||||
|
||||
assert agent.role == "test role"
|
||||
assert agent.goal == "test goal"
|
||||
assert agent.backstory == "test backstory"
|
||||
assert agent.tools == []
|
||||
def test_agent_creation():
|
||||
agent = Agent(role="test role", goal="test goal", backstory="test backstory")
|
||||
|
||||
assert agent.role == "test role"
|
||||
assert agent.goal == "test goal"
|
||||
assert agent.backstory == "test backstory"
|
||||
assert agent.tools == []
|
||||
|
||||
|
||||
def test_agent_default_values():
|
||||
agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory"
|
||||
)
|
||||
agent = Agent(role="test role", goal="test goal", backstory="test backstory")
|
||||
|
||||
assert isinstance(agent.llm, OpenAI)
|
||||
assert agent.llm.model_name == "gpt-4"
|
||||
assert agent.llm.temperature == 0.7
|
||||
assert agent.llm.verbose == False
|
||||
assert agent.allow_delegation == True
|
||||
|
||||
assert isinstance(agent.llm, OpenAI)
|
||||
assert agent.llm.model_name == "gpt-4"
|
||||
assert agent.llm.temperature == 0.7
|
||||
assert agent.llm.verbose == False
|
||||
assert agent.allow_delegation == True
|
||||
|
||||
def test_custom_llm():
|
||||
agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory",
|
||||
llm=OpenAI(
|
||||
temperature=0,
|
||||
model="gpt-4"
|
||||
)
|
||||
)
|
||||
agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory",
|
||||
llm=OpenAI(temperature=0, model="gpt-4"),
|
||||
)
|
||||
|
||||
assert isinstance(agent.llm, OpenAI)
|
||||
assert agent.llm.model_name == "gpt-4"
|
||||
assert agent.llm.temperature == 0
|
||||
|
||||
assert isinstance(agent.llm, OpenAI)
|
||||
assert agent.llm.model_name == "gpt-4"
|
||||
assert agent.llm.temperature == 0
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_agent_without_memory():
|
||||
no_memory_agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory",
|
||||
memory=False,
|
||||
llm=OpenAI(
|
||||
temperature=0,
|
||||
model="gpt-4"
|
||||
)
|
||||
)
|
||||
no_memory_agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory",
|
||||
memory=False,
|
||||
llm=OpenAI(temperature=0, model="gpt-4"),
|
||||
)
|
||||
|
||||
memory_agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory",
|
||||
memory=True,
|
||||
llm=OpenAI(
|
||||
temperature=0,
|
||||
model="gpt-4"
|
||||
)
|
||||
)
|
||||
memory_agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory",
|
||||
memory=True,
|
||||
llm=OpenAI(temperature=0, model="gpt-4"),
|
||||
)
|
||||
|
||||
result = no_memory_agent.execute_task("How much is 1 + 1?")
|
||||
result = no_memory_agent.execute_task("How much is 1 + 1?")
|
||||
|
||||
assert result == "1 + 1 equals 2."
|
||||
assert no_memory_agent.agent_executor.memory is None
|
||||
assert memory_agent.agent_executor.memory is not None
|
||||
|
||||
assert result == "1 + 1 equals 2."
|
||||
assert no_memory_agent.agent_executor.memory is None
|
||||
assert memory_agent.agent_executor.memory is not None
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_agent_execution():
|
||||
agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory",
|
||||
allow_delegation=False
|
||||
)
|
||||
agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory",
|
||||
allow_delegation=False,
|
||||
)
|
||||
|
||||
output = agent.execute_task("How much is 1 + 1?")
|
||||
assert output == "2"
|
||||
|
||||
output = agent.execute_task("How much is 1 + 1?")
|
||||
assert output == "2"
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_agent_execution_with_tools():
|
||||
from langchain.tools import tool
|
||||
from langchain.tools import tool
|
||||
|
||||
@tool
|
||||
def multiplier(numbers) -> float:
|
||||
"""Useful for when you need to multiply two numbers together.
|
||||
The input to this tool should be a comma separated list of numbers of
|
||||
length two, representing the two numbers you want to multiply together.
|
||||
For example, `1,2` would be the input if you wanted to multiply 1 by 2."""
|
||||
a, b = numbers.split(',')
|
||||
return int(a) * int(b)
|
||||
@tool
|
||||
def multiplier(numbers) -> float:
|
||||
"""Useful for when you need to multiply two numbers together.
|
||||
The input to this tool should be a comma separated list of numbers of
|
||||
length two, representing the two numbers you want to multiply together.
|
||||
For example, `1,2` would be the input if you wanted to multiply 1 by 2."""
|
||||
a, b = numbers.split(",")
|
||||
return int(a) * int(b)
|
||||
|
||||
agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory",
|
||||
tools=[multiplier],
|
||||
allow_delegation=False
|
||||
)
|
||||
agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory",
|
||||
tools=[multiplier],
|
||||
allow_delegation=False,
|
||||
)
|
||||
|
||||
output = agent.execute_task("What is 3 times 4")
|
||||
assert output == "12"
|
||||
|
||||
output = agent.execute_task("What is 3 times 4")
|
||||
assert output == "12"
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_agent_execution_with_specific_tools():
|
||||
from langchain.tools import tool
|
||||
from langchain.tools import tool
|
||||
|
||||
@tool
|
||||
def multiplier(numbers) -> float:
|
||||
"""Useful for when you need to multiply two numbers together.
|
||||
The input to this tool should be a comma separated list of numbers of
|
||||
length two, representing the two numbers you want to multiply together.
|
||||
For example, `1,2` would be the input if you wanted to multiply 1 by 2."""
|
||||
a, b = numbers.split(',')
|
||||
return int(a) * int(b)
|
||||
@tool
|
||||
def multiplier(numbers) -> float:
|
||||
"""Useful for when you need to multiply two numbers together.
|
||||
The input to this tool should be a comma separated list of numbers of
|
||||
length two, representing the two numbers you want to multiply together.
|
||||
For example, `1,2` would be the input if you wanted to multiply 1 by 2."""
|
||||
a, b = numbers.split(",")
|
||||
return int(a) * int(b)
|
||||
|
||||
agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory",
|
||||
allow_delegation=False
|
||||
)
|
||||
agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory",
|
||||
allow_delegation=False,
|
||||
)
|
||||
|
||||
output = agent.execute_task(
|
||||
task="What is 3 times 4",
|
||||
tools=[multiplier]
|
||||
)
|
||||
assert output == "3 times 4 is 12."
|
||||
output = agent.execute_task(task="What is 3 times 4", tools=[multiplier])
|
||||
assert output == "3 times 4 is 12."
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# conftest.py
|
||||
from dotenv import load_dotenv
|
||||
load_result = load_dotenv(override=True)
|
||||
|
||||
load_result = load_dotenv(override=True)
|
||||
|
||||
@@ -1,114 +1,131 @@
|
||||
"""Test Agent creation and execution basic functionality."""
|
||||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from ..crewai import Agent, Crew, Task, Process
|
||||
|
||||
from ..crewai import Agent, Crew, Process, Task
|
||||
|
||||
ceo = Agent(
|
||||
role="CEO",
|
||||
goal="Make sure the writers in your company produce amazing content.",
|
||||
backstory="You're an long time CEO of a content creation agency with a Senior Writer on the team. You're now working on a new project and want to make sure the content produced is amazing.",
|
||||
allow_delegation=True
|
||||
role="CEO",
|
||||
goal="Make sure the writers in your company produce amazing content.",
|
||||
backstory="You're an long time CEO of a content creation agency with a Senior Writer on the team. You're now working on a new project and want to make sure the content produced is amazing.",
|
||||
allow_delegation=True,
|
||||
)
|
||||
|
||||
researcher = Agent(
|
||||
role="Researcher",
|
||||
goal="Make the best research and analysis on content about AI and AI agents",
|
||||
backstory="You're an expert researcher, specialized in technology, software engineering, AI and startups. You work as a freelancer and is now working on doing research and analysis for a new customer.",
|
||||
allow_delegation=False
|
||||
role="Researcher",
|
||||
goal="Make the best research and analysis on content about AI and AI agents",
|
||||
backstory="You're an expert researcher, specialized in technology, software engineering, AI and startups. You work as a freelancer and is now working on doing research and analysis for a new customer.",
|
||||
allow_delegation=False,
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
role="Senior Writer",
|
||||
goal="Write the best content about AI and AI agents.",
|
||||
backstory="You're a senior writer, specialized in technology, software engineering, AI and startups. You work as a freelancer and are now working on writing content for a new customer.",
|
||||
allow_delegation=False
|
||||
role="Senior Writer",
|
||||
goal="Write the best content about AI and AI agents.",
|
||||
backstory="You're a senior writer, specialized in technology, software engineering, AI and startups. You work as a freelancer and are now working on writing content for a new customer.",
|
||||
allow_delegation=False,
|
||||
)
|
||||
|
||||
|
||||
def test_crew_config_conditional_requirement():
|
||||
with pytest.raises(ValueError):
|
||||
Crew(process=Process.sequential)
|
||||
with pytest.raises(ValueError):
|
||||
Crew(process=Process.sequential)
|
||||
|
||||
config = json.dumps({
|
||||
"agents": [
|
||||
{
|
||||
"role": "Senior Researcher",
|
||||
"goal": "Make the best research and analysis on content about AI and AI agents",
|
||||
"backstory": "You're an expert researcher, specialized in technology, software engineering, AI and startups. You work as a freelancer and is now working on doing research and analysis for a new customer."
|
||||
},
|
||||
{
|
||||
"role": "Senior Writer",
|
||||
"goal": "Write the best content about AI and AI agents.",
|
||||
"backstory": "You're a senior writer, specialized in technology, software engineering, AI and startups. You work as a freelancer and are now working on writing content for a new customer."
|
||||
}
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"description": "Give me a list of 5 interesting ideas to explore for na article, what makes them unique and interesting.",
|
||||
"agent": "Senior Researcher"
|
||||
},
|
||||
{
|
||||
"description": "Write a 1 amazing paragraph highlight for each idead that showcases how good an article about this topic could be, check references if necessary or search for more content but make sure it's unique, interesting and well written. Return the list of ideas with their paragraph and your notes.",
|
||||
"agent": "Senior Writer"
|
||||
}
|
||||
]
|
||||
})
|
||||
parsed_config = json.loads(config)
|
||||
config = json.dumps(
|
||||
{
|
||||
"agents": [
|
||||
{
|
||||
"role": "Senior Researcher",
|
||||
"goal": "Make the best research and analysis on content about AI and AI agents",
|
||||
"backstory": "You're an expert researcher, specialized in technology, software engineering, AI and startups. You work as a freelancer and is now working on doing research and analysis for a new customer.",
|
||||
},
|
||||
{
|
||||
"role": "Senior Writer",
|
||||
"goal": "Write the best content about AI and AI agents.",
|
||||
"backstory": "You're a senior writer, specialized in technology, software engineering, AI and startups. You work as a freelancer and are now working on writing content for a new customer.",
|
||||
},
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"description": "Give me a list of 5 interesting ideas to explore for na article, what makes them unique and interesting.",
|
||||
"agent": "Senior Researcher",
|
||||
},
|
||||
{
|
||||
"description": "Write a 1 amazing paragraph highlight for each idead that showcases how good an article about this topic could be, check references if necessary or search for more content but make sure it's unique, interesting and well written. Return the list of ideas with their paragraph and your notes.",
|
||||
"agent": "Senior Writer",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
parsed_config = json.loads(config)
|
||||
|
||||
try:
|
||||
crew = Crew(process=Process.sequential, config=config)
|
||||
except ValueError:
|
||||
pytest.fail("Unexpected ValidationError raised")
|
||||
try:
|
||||
crew = Crew(process=Process.sequential, config=config)
|
||||
except ValueError:
|
||||
pytest.fail("Unexpected ValidationError raised")
|
||||
|
||||
assert [agent.role for agent in crew.agents] == [
|
||||
agent["role"] for agent in parsed_config["agents"]
|
||||
]
|
||||
assert [task.description for task in crew.tasks] == [
|
||||
task["description"] for task in parsed_config["tasks"]
|
||||
]
|
||||
|
||||
assert [agent.role for agent in crew.agents] == [agent['role'] for agent in parsed_config['agents']]
|
||||
assert [task.description for task in crew.tasks] == [task['description'] for task in parsed_config['tasks']]
|
||||
|
||||
def test_crew_config_with_wrong_keys():
|
||||
no_tasks_config = json.dumps({
|
||||
"agents": [
|
||||
{
|
||||
"role": "Senior Researcher",
|
||||
"goal": "Make the best research and analysis on content about AI and AI agents",
|
||||
"backstory": "You're an expert researcher, specialized in technology, software engineering, AI and startups. You work as a freelancer and is now working on doing research and analysis for a new customer."
|
||||
}
|
||||
]
|
||||
})
|
||||
no_tasks_config = json.dumps(
|
||||
{
|
||||
"agents": [
|
||||
{
|
||||
"role": "Senior Researcher",
|
||||
"goal": "Make the best research and analysis on content about AI and AI agents",
|
||||
"backstory": "You're an expert researcher, specialized in technology, software engineering, AI and startups. You work as a freelancer and is now working on doing research and analysis for a new customer.",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
no_agents_config = json.dumps(
|
||||
{
|
||||
"tasks": [
|
||||
{
|
||||
"description": "Give me a list of 5 interesting ideas to explore for na article, what makes them unique and interesting.",
|
||||
"agent": "Senior Researcher",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
with pytest.raises(ValueError):
|
||||
Crew(process=Process.sequential, config='{"wrong_key": "wrong_value"}')
|
||||
with pytest.raises(ValueError):
|
||||
Crew(process=Process.sequential, config=no_tasks_config)
|
||||
with pytest.raises(ValueError):
|
||||
Crew(process=Process.sequential, config=no_agents_config)
|
||||
|
||||
no_agents_config = json.dumps({
|
||||
"tasks": [
|
||||
{
|
||||
"description": "Give me a list of 5 interesting ideas to explore for na article, what makes them unique and interesting.",
|
||||
"agent": "Senior Researcher"
|
||||
}
|
||||
]
|
||||
})
|
||||
with pytest.raises(ValueError):
|
||||
Crew(process=Process.sequential, config='{"wrong_key": "wrong_value"}')
|
||||
with pytest.raises(ValueError):
|
||||
Crew(process=Process.sequential, config=no_tasks_config)
|
||||
with pytest.raises(ValueError):
|
||||
Crew(process=Process.sequential, config=no_agents_config)
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_crew_creation():
|
||||
tasks = [
|
||||
Task(
|
||||
description="Give me a list of 5 interesting ideas to explore for na article, what makes them unique and interesting.",
|
||||
agent=researcher
|
||||
),
|
||||
Task(
|
||||
description="Write a 1 amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
agent=writer
|
||||
)
|
||||
]
|
||||
tasks = [
|
||||
Task(
|
||||
description="Give me a list of 5 interesting ideas to explore for na article, what makes them unique and interesting.",
|
||||
agent=researcher,
|
||||
),
|
||||
Task(
|
||||
description="Write a 1 amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
agent=writer,
|
||||
),
|
||||
]
|
||||
|
||||
crew = Crew(
|
||||
agents=[researcher, writer],
|
||||
process=Process.sequential,
|
||||
tasks=tasks,
|
||||
)
|
||||
crew = Crew(
|
||||
agents=[researcher, writer],
|
||||
process=Process.sequential,
|
||||
tasks=tasks,
|
||||
)
|
||||
|
||||
assert crew.kickoff() == """1. **The Evolution of AI: From Old Concepts to New Frontiers** - Journey with us as we traverse the fascinating timeline of artificial intelligence - from its philosophical and mathematical infancy to the sophisticated, problem-solving tool it has become today. This riveting account will not only educate but also inspire, as we delve deep into the milestones that brought us here and shine a beacon on the potential that lies ahead.
|
||||
assert (
|
||||
crew.kickoff()
|
||||
== """1. **The Evolution of AI: From Old Concepts to New Frontiers** - Journey with us as we traverse the fascinating timeline of artificial intelligence - from its philosophical and mathematical infancy to the sophisticated, problem-solving tool it has become today. This riveting account will not only educate but also inspire, as we delve deep into the milestones that brought us here and shine a beacon on the potential that lies ahead.
|
||||
|
||||
2. **AI Agents in Healthcare: The Future of Medicine** - Imagine a world where illnesses are diagnosed before symptoms appear, where patient outcomes are not mere guesses but accurate predictions. This is the world AI is crafting in healthcare - a revolution that's saving lives and changing the face of medicine as we know it. This article will spotlight this transformative journey, underlining the profound impact AI is having on our health and well-being.
|
||||
|
||||
@@ -117,60 +134,60 @@ def test_crew_creation():
|
||||
4. **Demystifying AI Algorithms: A Deep Dive into Machine Learning** - Ever wondered what goes on behind the scenes of AI? This enlightening article will break down the complex world of machine learning algorithms into digestible insights, unraveling the mystery of AI's 'black box'. It's a rare opportunity for the non-technical audience to appreciate the inner workings of AI, fostering a deeper understanding of this revolutionary technology.
|
||||
|
||||
5. **AI Startups: The Game Changers of the Tech Industry** - In the world of tech, AI startups are the bold pioneers charting new territories. This article will spotlight these game changers, showcasing how their innovative products and services are driving the AI revolution. It's a unique opportunity to catch a glimpse of the entrepreneurial side of AI, offering inspiration for the tech enthusiasts and dreamers alike."""
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_crew_with_delegating_agents():
|
||||
tasks = [
|
||||
Task(
|
||||
description="Produce and amazing 1 paragraph draft of an article about AI Agents.",
|
||||
agent=ceo
|
||||
)
|
||||
]
|
||||
tasks = [
|
||||
Task(
|
||||
description="Produce and amazing 1 paragraph draft of an article about AI Agents.",
|
||||
agent=ceo,
|
||||
)
|
||||
]
|
||||
|
||||
crew = Crew(
|
||||
agents=[ceo, writer],
|
||||
process=Process.sequential,
|
||||
tasks=tasks,
|
||||
)
|
||||
crew = Crew(
|
||||
agents=[ceo, writer],
|
||||
process=Process.sequential,
|
||||
tasks=tasks,
|
||||
)
|
||||
|
||||
assert (
|
||||
crew.kickoff()
|
||||
== "The Senior Writer has created a compelling and engaging 1 paragraph draft about AI agents. The paragraph provides a brief yet comprehensive overview of AI agents, their uses, and implications in the current world. It emphasizes their potential and the role they can play in the future. The tone is informative but captivating, meeting the objectives of the task."
|
||||
)
|
||||
|
||||
assert crew.kickoff() == 'The Senior Writer has created a compelling and engaging 1 paragraph draft about AI agents. The paragraph provides a brief yet comprehensive overview of AI agents, their uses, and implications in the current world. It emphasizes their potential and the role they can play in the future. The tone is informative but captivating, meeting the objectives of the task.'
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_crew_verbose_output(capsys):
|
||||
tasks = [
|
||||
Task(
|
||||
description="Research AI advancements.",
|
||||
agent=researcher
|
||||
),
|
||||
Task(
|
||||
description="Write about AI in healthcare.",
|
||||
agent=writer
|
||||
)
|
||||
]
|
||||
tasks = [
|
||||
Task(description="Research AI advancements.", agent=researcher),
|
||||
Task(description="Write about AI in healthcare.", agent=writer),
|
||||
]
|
||||
|
||||
crew = Crew(
|
||||
agents=[researcher, writer],
|
||||
tasks=tasks,
|
||||
process=Process.sequential,
|
||||
verbose=True
|
||||
)
|
||||
crew = Crew(
|
||||
agents=[researcher, writer],
|
||||
tasks=tasks,
|
||||
process=Process.sequential,
|
||||
verbose=True,
|
||||
)
|
||||
|
||||
crew.kickoff()
|
||||
captured = capsys.readouterr()
|
||||
expected_strings = [
|
||||
"Working Agent: Researcher",
|
||||
"Starting Task: Research AI advancements. ...",
|
||||
"Task output:",
|
||||
"Working Agent: Senior Writer",
|
||||
"Starting Task: Write about AI in healthcare. ...",
|
||||
"Task output:"
|
||||
]
|
||||
crew.kickoff()
|
||||
captured = capsys.readouterr()
|
||||
expected_strings = [
|
||||
"Working Agent: Researcher",
|
||||
"Starting Task: Research AI advancements. ...",
|
||||
"Task output:",
|
||||
"Working Agent: Senior Writer",
|
||||
"Starting Task: Write about AI in healthcare. ...",
|
||||
"Task output:",
|
||||
]
|
||||
|
||||
for expected_string in expected_strings:
|
||||
assert expected_string in captured.out
|
||||
for expected_string in expected_strings:
|
||||
assert expected_string in captured.out
|
||||
|
||||
# Now test with verbose set to False
|
||||
crew.verbose = False
|
||||
crew.kickoff()
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == ""
|
||||
# Now test with verbose set to False
|
||||
crew.verbose = False
|
||||
crew.kickoff()
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == ""
|
||||
|
||||
@@ -1,57 +1,56 @@
|
||||
"""Test Agent creation and execution basic functionality."""
|
||||
|
||||
import pytest
|
||||
|
||||
from ..crewai import Agent, Task
|
||||
|
||||
|
||||
def test_task_tool_reflect_agent_tools():
|
||||
from langchain.tools import tool
|
||||
from langchain.tools import tool
|
||||
|
||||
@tool
|
||||
def fake_tool() -> None:
|
||||
"Fake tool"
|
||||
pass
|
||||
|
||||
researcher = Agent(
|
||||
role="Researcher",
|
||||
goal="Make the best research and analysis on content about AI and AI agents",
|
||||
backstory="You're an expert researcher, specialized in technology, software engineering, AI and startups. You work as a freelancer and is now working on doing research and analysis for a new customer.",
|
||||
tools=[fake_tool],
|
||||
allow_delegation=False
|
||||
)
|
||||
@tool
|
||||
def fake_tool() -> None:
|
||||
"Fake tool"
|
||||
|
||||
researcher = Agent(
|
||||
role="Researcher",
|
||||
goal="Make the best research and analysis on content about AI and AI agents",
|
||||
backstory="You're an expert researcher, specialized in technology, software engineering, AI and startups. You work as a freelancer and is now working on doing research and analysis for a new customer.",
|
||||
tools=[fake_tool],
|
||||
allow_delegation=False,
|
||||
)
|
||||
|
||||
task = Task(
|
||||
description="Give me a list of 5 interesting ideas to explore for na article, what makes them unique and interesting.",
|
||||
agent=researcher,
|
||||
)
|
||||
|
||||
assert task.tools == [fake_tool]
|
||||
|
||||
task = Task(
|
||||
description="Give me a list of 5 interesting ideas to explore for na article, what makes them unique and interesting.",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
assert task.tools == [fake_tool]
|
||||
|
||||
def test_task_tool_takes_precedence_ove_agent_tools():
|
||||
from langchain.tools import tool
|
||||
from langchain.tools import tool
|
||||
|
||||
@tool
|
||||
def fake_tool() -> None:
|
||||
"Fake tool"
|
||||
pass
|
||||
@tool
|
||||
def fake_tool() -> None:
|
||||
"Fake tool"
|
||||
|
||||
@tool
|
||||
def fake_task_tool() -> None:
|
||||
"Fake tool"
|
||||
pass
|
||||
|
||||
researcher = Agent(
|
||||
role="Researcher",
|
||||
goal="Make the best research and analysis on content about AI and AI agents",
|
||||
backstory="You're an expert researcher, specialized in technology, software engineering, AI and startups. You work as a freelancer and is now working on doing research and analysis for a new customer.",
|
||||
tools=[fake_tool],
|
||||
allow_delegation=False
|
||||
)
|
||||
@tool
|
||||
def fake_task_tool() -> None:
|
||||
"Fake tool"
|
||||
|
||||
task = Task(
|
||||
description="Give me a list of 5 interesting ideas to explore for na article, what makes them unique and interesting.",
|
||||
agent=researcher,
|
||||
tools=[fake_task_tool],
|
||||
allow_delegation=False
|
||||
)
|
||||
|
||||
assert task.tools == [fake_task_tool]
|
||||
researcher = Agent(
|
||||
role="Researcher",
|
||||
goal="Make the best research and analysis on content about AI and AI agents",
|
||||
backstory="You're an expert researcher, specialized in technology, software engineering, AI and startups. You work as a freelancer and is now working on doing research and analysis for a new customer.",
|
||||
tools=[fake_tool],
|
||||
allow_delegation=False,
|
||||
)
|
||||
|
||||
task = Task(
|
||||
description="Give me a list of 5 interesting ideas to explore for na article, what makes them unique and interesting.",
|
||||
agent=researcher,
|
||||
tools=[fake_task_tool],
|
||||
allow_delegation=False,
|
||||
)
|
||||
|
||||
assert task.tools == [fake_task_tool]
|
||||
|
||||
Reference in New Issue
Block a user