Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated documentation #1

Merged
merged 1 commit into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 51 additions & 11 deletions src/crewai/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,35 @@ class Agent(BaseModel):
@field_validator("id", mode="before")
@classmethod
def _deny_user_set_id(cls, v: Optional[UUID4]) -> None:
""" Deny the user from setting the ID.

Args:
cls: The class instance.
v: The value to be checked.

Returns:
None

Raises:
PydanticCustomError: If the user tries to set the ID, a PydanticCustomError is raised with the message
"may_not_set_field" and details "{}".
"""

if v:
raise PydanticCustomError(
"may_not_set_field", "This field is not to be set by the user.", {}
)

@model_validator(mode="after")
def set_private_attrs(self):
"""Set private attributes."""
""" Set private attributes.

Returns:
None

Raises:
SomeException: An explanation of when this exception is raised.
"""
self._logger = Logger(self.verbose)
if self.max_rpm and not self._rpm_controller:
self._rpm_controller = RPMController(
Expand All @@ -118,7 +139,14 @@ def set_private_attrs(self):

@model_validator(mode="after")
def check_agent_executor(self) -> "Agent":
"""Check if the agent executor is set."""
""" Check if the agent executor is set.

Returns:
The current instance of the class.

Raises:
None
"""
if not self.agent_executor:
self.set_cache_handler(self.cache_handler)
return self
Expand All @@ -129,15 +157,15 @@ def execute_task(
context: Optional[str] = None,
tools: Optional[List[Any]] = None,
) -> str:
"""Execute a task with the agent.
""" Execute a task with the agent.

Args:
task: Task to execute.
context: Context to execute the task in.
tools: Tools to use for the task.
task (str): Task to execute.
context (Optional[str]?): Context to execute the task in. Defaults to None.
tools (Optional[List[Any]]?): Tools to use for the task. Defaults to None.

Returns:
Output of the agent
str: Output of the agent
"""

if context:
Expand All @@ -163,7 +191,7 @@ def execute_task(
return result

def set_cache_handler(self, cache_handler: CacheHandler) -> None:
"""Set the cache handler for the agent.
""" Set the cache handler for the agent.

Args:
cache_handler: An instance of the CacheHandler class.
Expand All @@ -173,17 +201,20 @@ def set_cache_handler(self, cache_handler: CacheHandler) -> None:
self._create_agent_executor()

def set_rpm_controller(self, rpm_controller: RPMController) -> None:
"""Set the rpm controller for the agent.
""" Set the RPM controller for the agent.

Args:
rpm_controller: An instance of the RPMController class.
rpm_controller (RPMController): An instance of the RPMController class.

Returns:
None
"""
if not self._rpm_controller:
self._rpm_controller = rpm_controller
self._create_agent_executor()

def _create_agent_executor(self) -> None:
"""Create an agent executor for the agent.
""" Create an agent executor for the agent.

Returns:
An instance of the CrewAgentExecutor class.
Expand Down Expand Up @@ -240,4 +271,13 @@ def _create_agent_executor(self) -> None:

@staticmethod
def __tools_names(tools) -> str:
""" Return a comma-separated string of tool names.

Args:
tools (list): A list of tool objects.

Returns:
str: A comma-separated string of tool names.
"""

return ", ".join([t.name for t in tools])
24 changes: 24 additions & 0 deletions src/crewai/agents/cache/cache_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,36 @@ class CacheHandler:
_cache: dict = {}

def __init__(self):
""" Initialize the object.

Returns:
None
"""

self._cache = {}

def add(self, tool, input, output):
""" Add the output of a tool with the given input to the cache.

Args:
tool (str): The name of the tool.
input (str): The input for the tool.
output: The output generated by the tool.
"""

input = input.strip()
self._cache[f"{tool}-{input}"] = output

def read(self, tool, input) -> Optional[str]:
""" Read the cached data for the given tool and input.

Args:
tool: The tool for which the data is being read.
input: The input for which the data is being read.

Returns:
Optional[str]: The cached data for the given tool and input, or None if not found.
"""

input = input.strip()
return self._cache.get(f"{tool}-{input}")
18 changes: 18 additions & 0 deletions src/crewai/agents/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ class TaskRepeatedUsageException(OutputParserException):
message: str

def __init__(self, i18n: I18N, tool: str, tool_input: str, text: str):
""" Initialize the class with the provided parameters.

Args:
i18n (I18N): An instance of the I18N class.
tool (str): The tool being used.
tool_input (str): The input for the tool.
text (str): The text associated with the task.

Returns:
None
"""

self.i18n = i18n
self.text = text
self.tool = tool
Expand All @@ -27,4 +39,10 @@ def __init__(self, i18n: I18N, tool: str, tool_input: str, text: str):
)

def __str__(self):
""" Return the string representation of the object.

Returns:
str: The string representation of the object.
"""

return self.message
59 changes: 57 additions & 2 deletions src/crewai/agents/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,42 @@ class CrewAgentExecutor(AgentExecutor):

@root_validator()
def set_force_answer_max_iterations(cls, values: Dict) -> Dict:
""" Set the 'force_answer_max_iterations' value in the input dictionary.

Args:
cls: The class instance (not used in the function)
values: A dictionary containing the input values with the key 'max_iterations'

Returns:
A dictionary with the updated 'force_answer_max_iterations' value

Raises:
KeyError: If 'max_iterations' key is not present in the input dictionary
TypeError: If the input 'values' is not a dictionary
"""

values["force_answer_max_iterations"] = values["max_iterations"] - 2
return values

def _should_force_answer(self) -> bool:
""" Check if the answer should be forced based on the number of iterations.

Returns:
bool: True if the number of iterations is equal to force_answer_max_iterations, False otherwise.
"""

return True if self.iterations == self.force_answer_max_iterations else False

def _force_answer(self, output: AgentAction):
""" Force an answer with the given output.

Args:
output (AgentAction): The action to be forced as the answer.

Returns:
AgentStep: An AgentStep object with the forced action and an observation message.
"""

return AgentStep(
action=output, observation=self.i18n.errors("force_final_answer")
)
Expand All @@ -41,7 +70,15 @@ def _call(
inputs: Dict[str, str],
run_manager: Optional[CallbackManagerForChainRun] = None,
) -> Dict[str, Any]:
"""Run text through and get agent response."""
""" Run text through and get agent response.

Args:
inputs (Dict[str, str]): The input data for the agent.
run_manager (Optional[CallbackManagerForChainRun]?): The callback manager for chain run. Defaults to None.

Returns:
Dict[str, Any]: The agent response.
"""
# Construct a mapping of tool name to tool for easy lookup
name_to_tool_map = {tool.name: tool for tool in self.tools}
# We construct a mapping from each tool to a color, used for logging.
Expand Down Expand Up @@ -92,9 +129,27 @@ def _iter_next_step(
intermediate_steps: List[Tuple[AgentAction, str]],
run_manager: Optional[CallbackManagerForChainRun] = None,
) -> Iterator[Union[AgentFinish, AgentAction, AgentStep]]:
"""Take a single step in the thought-action-observation loop.
""" Take a single step in the thought-action-observation loop.

Override this to take control of how the agent makes and acts on choices.

Args:
name_to_tool_map (Dict[str, BaseTool]): Mapping of tool names to BaseTool instances.
color_mapping (Dict[str, str]): Mapping of tool names to color codes.
inputs (Dict[str, str]): Input data for the agent.
intermediate_steps (List[Tuple[AgentAction, str]]): List of intermediate steps.
run_manager (Optional[CallbackManagerForChainRun]?): Callback manager for chain run. Defaults to None.

Returns:
Iterator[Union[AgentFinish, AgentAction, AgentStep]]: Yields the next step in the agent's action loop.

Yields:
Iterator[Union[AgentFinish, AgentAction, AgentStep]]: Yields the next step in the agent's action loop.

Raises:
ValueError: If an unexpected output type is received from the agent.
ValueError: If an output parsing error occurs and `handle_parsing_errors` is not set to True.
ValueError: If an unexpected type of `handle_parsing_errors` is encountered.
"""
try:
intermediate_steps = self._prepare_intermediate_steps(intermediate_steps)
Expand Down
12 changes: 12 additions & 0 deletions src/crewai/agents/output_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ class Config:
i18n: I18N

def parse(self, text: str) -> Union[AgentAction, AgentFinish, CacheHit]:
""" Parse the given text to extract action and input information.

Args:
text (str): The input text to be parsed.

Returns:
Union[AgentAction, AgentFinish, CacheHit]: An instance of AgentAction, AgentFinish, or CacheHit based on the parsed information.

Raises:
TaskRepeatedUsageException: If the parsed action and input are the same as the last used tool.
"""

regex = (
r"Action\s*\d*\s*:[\s]*(.*?)[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)"
)
Expand Down
31 changes: 28 additions & 3 deletions src/crewai/agents/tools_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,31 @@ class ToolsHandler(BaseCallbackHandler):
cache: CacheHandler

def __init__(self, cache: CacheHandler, **kwargs: Any):
"""Initialize the callback handler."""
""" Initialize the callback handler.

Args:
cache (CacheHandler): The cache object to be used.
**kwargs (Any): Additional keyword arguments.

Returns:
None
"""
self.cache = cache
super().__init__(**kwargs)

def on_tool_start(
self, serialized: Dict[str, Any], input_str: str, **kwargs: Any
) -> Any:
"""Run when tool starts running."""
""" Run when tool starts running.

Args:
serialized (Dict[str, Any]): Serialized data.
input_str (str): Input string.
**kwargs (Any): Additional keyword arguments.

Returns:
Any: The return value is not specified.
"""
name = serialized.get("name")
if name not in ["invalid_tool", "_Exception"]:
tools_usage = {
Expand All @@ -30,7 +47,15 @@ def on_tool_start(
self.last_used_tool = tools_usage

def on_tool_end(self, output: str, **kwargs: Any) -> Any:
"""Run when tool ends running."""
""" Run when tool ends running.

Args:
output (str): The output of the tool.
**kwargs (Any): Additional keyword arguments.

Returns:
Any: The return value of the function.
"""
if (
"is not a valid tool" not in output
and "Invalid or incomplete response" not in output
Expand Down
Loading