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

Added documentation, comments, translation to IT language #293

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
1579156
Refactor Converter class to improve readability and add descriptive c…
capimichi Feb 29, 2024
11daba8
Refactor code to improve performance and readability
capimichi Feb 29, 2024
95b3d68
Refactor CrewAgentParser class to improve readability and add documen…
capimichi Feb 29, 2024
fa0655e
Refactor ToolsHandler class and add docstrings
capimichi Feb 29, 2024
d2842fa
Update TaskOutput class with additional fields and methods
capimichi Feb 29, 2024
fc651cc
Refactor AgentTools class and add method descriptions
capimichi Feb 29, 2024
a2af0a5
Refactor CacheTools class to improve readability and add method docum…
capimichi Feb 29, 2024
6b51c28
Refactor ToolCalling and InstructorToolCalling classes
capimichi Feb 29, 2024
e676ef2
Refactor ToolOutputParser to parse tool usage result as valid JSON
capimichi Feb 29, 2024
2408b08
Update user authentication logic
capimichi Feb 29, 2024
4ea1aaf
Add Italian translation for crew AI
capimichi Feb 29, 2024
0941f1c
Refactor CrewPydanticOutputParser class to improve JSON parsing and e…
capimichi Feb 29, 2024
a8aff86
Refactor i18n class to improve translation loading and retrieval
capimichi Feb 29, 2024
74875ca
Refactor Instructor class to improve code structure and documentation
capimichi Feb 29, 2024
c554983
Refactor logger to support verbose level
capimichi Feb 29, 2024
9368bb5
Add color printing functionality to Printer class
capimichi Feb 29, 2024
6eb4ee2
Refactor Prompts class to improve readability and documentation
capimichi Feb 29, 2024
d0ba47e
Refactor PydanticSchemaParser to improve readability and maintainability
capimichi Feb 29, 2024
f50bd9b
Refactor RPMController class for better readability and maintainability
capimichi Feb 29, 2024
61887e9
Refactor token counting and tracking***
capimichi Feb 29, 2024
49627ea
Fix GPT model check in Converter class
capimichi Feb 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
287 changes: 163 additions & 124 deletions src/crewai/agents/executor.py

Large diffs are not rendered by default.

37 changes: 24 additions & 13 deletions src/crewai/agents/parser.py
Expand Up @@ -12,46 +12,57 @@


class CrewAgentParser(ReActSingleInputOutputParser):
"""Parses Crew-style LLM calls that have a single tool input.

Expects output to be in one of two formats.

If the output signals that an action should be taken,
should be in the below format. This will result in an AgentAction
being returned.
"""
This class is responsible for parsing the output of the Crew-style Language Learning Model (LLM) calls that have a single tool input.
The output is expected to be in one of two formats.

If the output signals that an action should be taken, it should be in the below format.
This will result in an AgentAction being returned.
```
Use Tool: All context for using the tool here
```

If the output signals that a final answer should be given,
should be in the below format. This will result in an AgentFinish
being returned.

If the output signals that a final answer should be given, it should be in the below format.
This will result in an AgentFinish being returned.
```
Final Answer: The temperature is 100 degrees
```
"""

_i18n: I18N = I18N()
agent: Any = None
_i18n: I18N = I18N() # Internationalization object for multilingual support
agent: Any = None # The agent that will use this parser

def parse(self, text: str) -> Union[AgentAction, AgentFinish]:
"""
This method parses the given text and returns an AgentAction or AgentFinish object based on the content of the text.

Parameters:
text: The text to be parsed.

Returns:
An AgentAction object if the text includes a tool usage section, or an AgentFinish object if the text includes a final answer action.
"""

# Check if the text includes a final answer action or a tool usage section
includes_answer = FINAL_ANSWER_ACTION in text
includes_tool = TOOL_USAGE_SECTION in text

# If the text includes a tool usage section, return an AgentAction object
if includes_tool:
# If the text also includes a final answer action, increment the number of formatting errors and raise an OutputParserException
if includes_answer:
self.agent.increment_formatting_errors()
raise OutputParserException(f"{FINAL_ANSWER_AND_TOOL_ERROR_MESSAGE}")

return AgentAction("", "", text)

# If the text includes a final answer action, return an AgentFinish object
elif includes_answer:
return AgentFinish(
{"output": text.split(FINAL_ANSWER_ACTION)[-1].strip()}, text
)

# If the text does not include a tool usage section or a final answer action, increment the number of formatting errors and raise an OutputParserException
format = self._i18n.slice("format_without_tools")
error = f"{format}"
self.agent.increment_formatting_errors()
Expand Down
28 changes: 23 additions & 5 deletions src/crewai/agents/tools_handler.py
Expand Up @@ -6,18 +6,36 @@


class ToolsHandler:
"""Callback handler for tool usage."""
"""
This class serves as a callback handler for tool usage. It keeps track of the last used tool and
manages the caching of tool usage results.
"""

last_used_tool: ToolCalling = {}
cache: CacheHandler
last_used_tool: ToolCalling = {} # Stores the last tool that was used along with its arguments
cache: CacheHandler # CacheHandler object for caching tool usage results

def __init__(self, cache: CacheHandler):
"""Initialize the callback handler."""
"""
Initialize the callback handler with a CacheHandler object.

Parameters:
cache: A CacheHandler object for caching tool usage results.
"""
self.cache = cache
self.last_used_tool = {}

def on_tool_use(self, calling: ToolCalling, output: str) -> Any:
"""Run when tool ends running."""
"""
This method is called when a tool finishes running. It updates the last used tool and
adds the tool usage result to the cache (unless the tool is the CacheTools tool).

Parameters:
calling: A ToolCalling object representing the tool usage.
output: The output of the tool usage.

Returns:
None
"""
self.last_used_tool = calling
if calling.tool_name != CacheTools().name:
self.cache.add(
Expand Down
20 changes: 15 additions & 5 deletions src/crewai/tasks/task_output.py
Expand Up @@ -4,20 +4,30 @@


class TaskOutput(BaseModel):
"""Class that represents the result of a task."""
"""
Class that represents the result of a task.
It contains four fields: description, summary, exported_output, and raw_output.
"""

description: str = Field(description="Description of the task")
summary: Optional[str] = Field(description="Summary of the task", default=None)
description: str = Field(description="Description of the task. This is a detailed explanation of what the task is about.")
summary: Optional[str] = Field(description="Summary of the task. This is a brief overview of the task.", default=None)
exported_output: Union[str, BaseModel] = Field(
description="Output of the task", default=None
description="Output of the task. This is the result produced by the task.", default=None
)
raw_output: str = Field(description="Result of the task")
raw_output: str = Field(description="Result of the task. This is the raw, unprocessed result of the task.")

@model_validator(mode="after")
def set_summary(self):
"""
This method generates a summary of the task by taking the first 10 words from the description.
It then sets the 'summary' field to this excerpt.
"""
excerpt = " ".join(self.description.split(" ")[:10])
self.summary = f"{excerpt}..."
return self

def result(self):
"""
This method returns the exported output of the task.
"""
return self.exported_output
24 changes: 20 additions & 4 deletions src/crewai/tools/agent_tools.py
Expand Up @@ -9,12 +9,19 @@


class AgentTools(BaseModel):
"""Default tools around agent delegation"""
"""
This class represents the default tools for agent delegation. It contains a list of agents and internationalization settings.
It also provides methods to delegate work to a coworker and ask a question to a coworker.
"""

agents: List[Agent] = Field(description="List of agents in this crew.")
i18n: I18N = Field(default=I18N(), description="Internationalization settings.")

def tools(self):
"""
This method returns a list of StructuredTool objects. Each tool is created from a function (delegate_work or ask_question)
and has a name and a description.
"""
return [
StructuredTool.from_function(
func=self.delegate_work,
Expand All @@ -33,15 +40,24 @@ def tools(self):
]

def delegate_work(self, coworker: str, task: str, context: str):
"""Useful to delegate a specific task to a coworker."""
"""
This method is used to delegate a specific task to a coworker. It takes the coworker's name, the task, and the context as input.
It then calls the _execute method to perform the delegation.
"""
return self._execute(coworker, task, context)

def ask_question(self, coworker: str, question: str, context: str):
"""Useful to ask a question, opinion or take from a coworker."""
"""
This method is used to ask a question, opinion or take from a coworker. It takes the coworker's name, the question, and the context as input.
It then calls the _execute method to perform the action.
"""
return self._execute(coworker, question, context)

def _execute(self, agent, task, context):
"""Execute the command."""
"""
This method is used to execute the command. It first checks if the agent exists in the list of agents.
If the agent does not exist, it returns an error message. If the agent exists, it creates a new Task object and calls the execute_task method on the agent.
"""
try:
agent = [
available_agent
Expand Down
25 changes: 18 additions & 7 deletions src/crewai/tools/cache_tools.py
Expand Up @@ -5,24 +5,35 @@


class CacheTools(BaseModel):
"""Default tools to hit the cache."""
"""
This class represents the default tools for interacting with the cache. It contains a cache handler and a name.
It also provides a method to hit the cache.
"""

model_config = ConfigDict(arbitrary_types_allowed=True)
name: str = "Hit Cache"
name: str = "Hit Cache" # The name of this tool
cache_handler: CacheHandler = Field(
description="Cache Handler for the crew",
description="Cache Handler for the crew", # The cache handler used by this tool
default=CacheHandler(),
)

def tool(self):
"""
This method returns a StructuredTool object. The tool is created from the hit_cache function
and has a name and a description.
"""
return StructuredTool.from_function(
func=self.hit_cache,
name=self.name,
description="Reads directly from the cache",
)

def hit_cache(self, key):
split = key.split("tool:")
tool = split[1].split("|input:")[0].strip()
tool_input = split[1].split("|input:")[1].strip()
return self.cache_handler.read(tool, tool_input)
"""
This method is used to read data from the cache. It takes a key as input, which is split to extract the tool name and input.
It then calls the read method on the cache handler with the tool name and input.
"""
split = key.split("tool:") # Split the key on "tool:"
tool = split[1].split("|input:")[0].strip() # Extract the tool name
tool_input = split[1].split("|input:")[1].strip() # Extract the tool input
return self.cache_handler.read(tool, tool_input) # Read from the cache using the tool name and input
20 changes: 16 additions & 4 deletions src/crewai/tools/tool_calling.py
Expand Up @@ -6,16 +6,28 @@


class ToolCalling(BaseModel):
tool_name: str = Field(..., description="The name of the tool to be called.")
"""
This class represents a tool call. It contains the name of the tool to be called and a dictionary of arguments to be passed to the tool.
"""
tool_name: str = Field(
...,
description="The name of the tool that is intended to be called. This should be a string representing the unique identifier of the tool."
)
arguments: Optional[Dict[str, Any]] = Field(
..., description="A dictinary of arguments to be passed to the tool."
...,
description="A dictionary of arguments that are to be passed to the tool. Each key-value pair represents an argument name and its corresponding value."
)


class InstructorToolCalling(PydanticBaseModel):
"""
This class represents a tool call made by an instructor. It contains the name of the tool to be called and a dictionary of arguments to be passed to the tool.
"""
tool_name: str = PydanticField(
..., description="The name of the tool to be called."
...,
description="The name of the tool that the instructor intends to call. This should be a string representing the unique identifier of the tool."
)
arguments: Optional[Dict[str, Any]] = PydanticField(
..., description="A dictinary of arguments to be passed to the tool."
...,
description="A dictionary of arguments that the instructor wants to pass to the tool. Each key-value pair represents an argument name and its corresponding value."
)
17 changes: 16 additions & 1 deletion src/crewai/tools/tool_output_parser.py
Expand Up @@ -9,9 +9,17 @@


class ToolOutputParser(PydanticOutputParser):
"""Parses the function calling of a tool usage and it's arguments."""
"""
This class extends the PydanticOutputParser and is used to parse the output of a tool usage.
It provides methods to parse the result and transform the output into valid JSON.
"""

def parse_result(self, result: List[Generation], *, partial: bool = False) -> Any:
"""
This method is used to parse the result of a tool usage. It first transforms the result into valid JSON.
It then calls the parse_result method of the superclass to parse the JSON object.
If parsing fails, it raises an OutputParserException.
"""
result[0].text = self._transform_in_valid_json(result[0].text)
json_object = super().parse_result(result)
try:
Expand All @@ -22,6 +30,13 @@ def parse_result(self, result: List[Generation], *, partial: bool = False) -> An
raise OutputParserException(msg, llm_output=json_object)

def _transform_in_valid_json(self, text) -> str:
"""
This method is used to transform the output of a tool usage into valid JSON.
It first removes any backticks and the word 'json' from the text.
It then uses a regular expression to find all JSON objects in the text.
It attempts to parse each match as JSON and returns the first successfully parsed JSON object.
If no match can be parsed as JSON, it returns the original text.
"""
text = text.replace("```", "").replace("json", "")
json_pattern = r"\{(?:[^{}]|(?R))*\}"
matches = regex.finditer(json_pattern, text)
Expand Down