you are an excellent expert in crewai framework , your goal is to answer any question that the user asks you about the crewai framework , here is the detailed crewai framework :
"""{
    "agent.py": "import os\nimport uuid\nfrom typing import Any, Dict, List, Optional, Tuple\n\nfrom langchain.agents.agent import RunnableAgent\nfrom langchain.agents.tools import tool as LangChainTool\nfrom langchain.memory import ConversationSummaryMemory\nfrom langchain.tools.render import render_text_description\nfrom langchain_core.agents import AgentAction\nfrom langchain_core.callbacks import BaseCallbackHandler\nfrom langchain_openai import ChatOpenAI\nfrom pydantic import (\n    UUID4,\n    BaseModel,\n    ConfigDict,\n    Field,\n    InstanceOf,\n    PrivateAttr,\n    field_validator,\n    model_validator,\n)\nfrom pydantic_core import PydanticCustomError\n\nfrom crewai.agents import CacheHandler, CrewAgentExecutor, CrewAgentParser, ToolsHandler\nfrom crewai.utilities import I18N, Logger, Prompts, RPMController\nfrom crewai.utilities.token_counter_callback import TokenCalcHandler, TokenProcess\n\n\nclass Agent(BaseModel):\n    \"\"\"Represents an agent in a system.\n\n    Each agent has a role, a goal, a backstory, and an optional language model (llm).\n    The agent can also have memory, can operate in verbose mode, and can delegate tasks to other agents.\n\n    Attributes:\n            agent_executor: An instance of the CrewAgentExecutor class.\n            role: The role of the agent.\n            goal: The objective of the agent.\n            backstory: The backstory of the agent.\n            config: Dict representation of agent configuration.\n            llm: The language model that will run the agent.\n            function_calling_llm: The language model that will the tool calling for this agent, it overrides the crew function_calling_llm.\n            max_iter: Maximum number of iterations for an agent to execute a task.\n            memory: Whether the agent should have memory or not.\n            max_rpm: Maximum number of requests per minute for the agent execution to be respected.\n            verbose: Whether the agent execution should be in verbose mode.\n            allow_delegation: Whether the agent is allowed to delegate tasks to other agents.\n            tools: Tools at agents disposal\n            step_callback: Callback to be executed after each step of the agent execution.\n            callbacks: A list of callback functions from the langchain library that are triggered during the agent's execution process\n    \"\"\"\n\n    __hash__ = object.__hash__  # type: ignore\n    _logger: Logger = PrivateAttr()\n    _rpm_controller: RPMController = PrivateAttr(default=None)\n    _request_within_rpm_limit: Any = PrivateAttr(default=None)\n    _token_process: TokenProcess = TokenProcess()\n\n    formatting_errors: int = 0\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    id: UUID4 = Field(\n        default_factory=uuid.uuid4,\n        frozen=True,\n        description=\"Unique identifier for the object, not set by user.\",\n    )\n    role: str = Field(description=\"Role of the agent\")\n    goal: str = Field(description=\"Objective of the agent\")\n    backstory: str = Field(description=\"Backstory of the agent\")\n    config: Optional[Dict[str, Any]] = Field(\n        description=\"Configuration for the agent\",\n        default=None,\n    )\n    max_rpm: Optional[int] = Field(\n        default=None,\n        description=\"Maximum number of requests per minute for the agent execution to be respected.\",\n    )\n    memory: bool = Field(\n        default=False, description=\"Whether the agent should have memory or not\"\n    )\n    verbose: bool = Field(\n        default=False, description=\"Verbose mode for the Agent Execution\"\n    )\n    allow_delegation: bool = Field(\n        default=True, description=\"Allow delegation of tasks to agents\"\n    )\n    tools: Optional[List[Any]] = Field(\n        default_factory=list, description=\"Tools at agents disposal\"\n    )\n    max_iter: Optional[int] = Field(\n        default=15, description=\"Maximum iterations for an agent to execute a task\"\n    )\n    agent_executor: InstanceOf[CrewAgentExecutor] = Field(\n        default=None, description=\"An instance of the CrewAgentExecutor class.\"\n    )\n    tools_handler: InstanceOf[ToolsHandler] = Field(\n        default=None, description=\"An instance of the ToolsHandler class.\"\n    )\n    cache_handler: InstanceOf[CacheHandler] = Field(\n        default=CacheHandler(), description=\"An instance of the CacheHandler class.\"\n    )\n    step_callback: Optional[Any] = Field(\n        default=None,\n        description=\"Callback to be executed after each step of the agent execution.\",\n    )\n    i18n: I18N = Field(default=I18N(), description=\"Internationalization settings.\")\n    llm: Any = Field(\n        default_factory=lambda: ChatOpenAI(\n            model=os.environ.get(\"OPENAI_MODEL_NAME\", \"gpt-4\")\n        ),\n        description=\"Language model that will run the agent.\",\n    )\n    function_calling_llm: Optional[Any] = Field(\n        description=\"Language model that will run the agent.\", default=None\n    )\n    callbacks: Optional[List[InstanceOf[BaseCallbackHandler]]] = Field(\n        default=None, description=\"Callback to be executed\"\n    )\n\n    def __init__(__pydantic_self__, **data):\n        config = data.pop(\"config\", {})\n        super().__init__(**config, **data)\n\n    @field_validator(\"id\", mode=\"before\")\n    @classmethod\n    def _deny_user_set_id(cls, v: Optional[UUID4]) -> None:\n        if v:\n            raise PydanticCustomError(\n                \"may_not_set_field\", \"This field is not to be set by the user.\", {}\n            )\n\n    @model_validator(mode=\"after\")\n    def set_attributes_based_on_config(self) -> \"Agent\":\n        \"\"\"Set attributes based on the agent configuration.\"\"\"\n        if self.config:\n            for key, value in self.config.items():\n                setattr(self, key, value)\n        return self\n\n    @model_validator(mode=\"after\")\n    def set_private_attrs(self):\n        \"\"\"Set private attributes.\"\"\"\n        self._logger = Logger(self.verbose)\n        if self.max_rpm and not self._rpm_controller:\n            self._rpm_controller = RPMController(\n                max_rpm=self.max_rpm, logger=self._logger\n            )\n        return self\n\n    @model_validator(mode=\"after\")\n    def set_agent_executor(self) -> \"Agent\":\n        \"\"\"set agent executor is set.\"\"\"\n        if hasattr(self.llm, \"model_name\"):\n            self.llm.callbacks = [\n                TokenCalcHandler(self.llm.model_name, self._token_process)\n            ]\n        if not self.agent_executor:\n            self.set_cache_handler(self.cache_handler)\n        return self\n\n    def execute_task(\n        self,\n        task: Any,\n        context: Optional[str] = None,\n        tools: Optional[List[Any]] = None,\n    ) -> str:\n        \"\"\"Execute a task with the agent.\n\n        Args:\n            task: Task to execute.\n            context: Context to execute the task in.\n            tools: Tools to use for the task.\n\n        Returns:\n            Output of the agent\n        \"\"\"\n        self.tools_handler.last_used_tool = {}\n\n        task_prompt = task.prompt()\n\n        if context:\n            task_prompt = self.i18n.slice(\"task_with_context\").format(\n                task=task_prompt, context=context\n            )\n\n        tools = self._parse_tools(tools or self.tools)\n        self.create_agent_executor(tools=tools)\n        self.agent_executor.tools = tools\n        self.agent_executor.task = task\n\n        self.agent_executor.tools_description = render_text_description(tools)\n        self.agent_executor.tools_names = self.__tools_names(tools)\n\n        result = self.agent_executor.invoke(\n            {\n                \"input\": task_prompt,\n                \"tool_names\": self.agent_executor.tools_names,\n                \"tools\": self.agent_executor.tools_description,\n            }\n        )[\"output\"]\n\n        if self.max_rpm:\n            self._rpm_controller.stop_rpm_counter()\n\n        return result\n\n    def set_cache_handler(self, cache_handler: CacheHandler) -> None:\n        \"\"\"Set the cache handler for the agent.\n\n        Args:\n            cache_handler: An instance of the CacheHandler class.\n        \"\"\"\n        self.cache_handler = cache_handler\n        self.tools_handler = ToolsHandler(cache=self.cache_handler)\n        self.create_agent_executor()\n\n    def set_rpm_controller(self, rpm_controller: RPMController) -> None:\n        \"\"\"Set the rpm controller for the agent.\n\n        Args:\n            rpm_controller: An instance of the RPMController class.\n        \"\"\"\n        if not self._rpm_controller:\n            self._rpm_controller = rpm_controller\n            self.create_agent_executor()\n\n    def create_agent_executor(self, tools=None) -> None:\n        \"\"\"Create an agent executor for the agent.\n\n        Returns:\n            An instance of the CrewAgentExecutor class.\n        \"\"\"\n        tools = tools or self.tools\n\n        agent_args = {\n            \"input\": lambda x: x[\"input\"],\n            \"tools\": lambda x: x[\"tools\"],\n            \"tool_names\": lambda x: x[\"tool_names\"],\n            \"agent_scratchpad\": lambda x: self.format_log_to_str(\n                x[\"intermediate_steps\"]\n            ),\n        }\n\n        executor_args = {\n            \"llm\": self.llm,\n            \"i18n\": self.i18n,\n            \"tools\": self._parse_tools(tools),\n            \"verbose\": self.verbose,\n            \"handle_parsing_errors\": True,\n            \"max_iterations\": self.max_iter,\n            \"step_callback\": self.step_callback,\n            \"tools_handler\": self.tools_handler,\n            \"function_calling_llm\": self.function_calling_llm,\n            \"callbacks\": self.callbacks,\n        }\n\n        if self._rpm_controller:\n            executor_args[\n                \"request_within_rpm_limit\"\n            ] = self._rpm_controller.check_or_wait\n\n        if self.memory:\n            summary_memory = ConversationSummaryMemory(\n                llm=self.llm, input_key=\"input\", memory_key=\"chat_history\"\n            )\n            executor_args[\"memory\"] = summary_memory\n            agent_args[\"chat_history\"] = lambda x: x[\"chat_history\"]\n            prompt = Prompts(i18n=self.i18n, tools=tools).task_execution_with_memory()\n        else:\n            prompt = Prompts(i18n=self.i18n, tools=tools).task_execution()\n\n        execution_prompt = prompt.partial(\n            goal=self.goal,\n            role=self.role,\n            backstory=self.backstory,\n        )\n\n        bind = self.llm.bind(stop=[self.i18n.slice(\"observation\")])\n        inner_agent = agent_args | execution_prompt | bind | CrewAgentParser(agent=self)\n        self.agent_executor = CrewAgentExecutor(\n            agent=RunnableAgent(runnable=inner_agent), **executor_args\n        )\n\n    def interpolate_inputs(self, inputs: Dict[str, Any]) -> None:\n        \"\"\"Interpolate inputs into the agent description and backstory.\"\"\"\n        if inputs:\n            self.role = self.role.format(**inputs)\n            self.goal = self.goal.format(**inputs)\n            self.backstory = self.backstory.format(**inputs)\n\n    def increment_formatting_errors(self) -> None:\n        \"\"\"Count the formatting errors of the agent.\"\"\"\n        self.formatting_errors += 1\n\n    def format_log_to_str(\n        self,\n        intermediate_steps: List[Tuple[AgentAction, str]],\n        observation_prefix: str = \"Observation: \",\n        llm_prefix: str = \"\",\n    ) -> str:\n        \"\"\"Construct the scratchpad that lets the agent continue its thought process.\"\"\"\n        thoughts = \"\"\n        for action, observation in intermediate_steps:\n            thoughts += action.log\n            thoughts += f\"\\n{observation_prefix}{observation}\\n{llm_prefix}\"\n        return thoughts\n\n    def _parse_tools(self, tools: List[Any]) -> List[LangChainTool]:\n        \"\"\"Parse tools to be used for the task.\"\"\"\n        # tentatively try to import from crewai_tools import BaseTool as CrewAITool\n        tools_list = []\n        try:\n            from crewai_tools import BaseTool as CrewAITool\n\n            for tool in tools:\n                if isinstance(tool, CrewAITool):\n                    tools_list.append(tool.to_langchain())\n                else:\n                    tools_list.append(tool)\n        except ModuleNotFoundError:\n            for tool in tools:\n                tools_list.append(tool)\n        return tools_list\n\n    @staticmethod\n    def __tools_names(tools) -> str:\n        return \", \".join([t.name for t in tools])\n\n    def __repr__(self):\n        return f\"Agent(role={self.role}, goal={self.goal}, backstory={self.backstory})\"\n",
    "agents": {
        "cache": {
            "cache_handler.py": "from typing import Optional\n\n\nclass CacheHandler:\n    \"\"\"Callback handler for tool usage.\"\"\"\n\n    _cache: dict = {}\n\n    def __init__(self):\n        self._cache = {}\n\n    def add(self, tool, input, output):\n        self._cache[f\"{tool}-{input}\"] = output\n\n    def read(self, tool, input) -> Optional[str]:\n        return self._cache.get(f\"{tool}-{input}\")\n",
            "__init__.py": "from .cache_handler import CacheHandler\n",
            "__pycache__": {}
        },
        "executor.py": "import time\nfrom typing import Any, Dict, Iterator, List, Optional, Tuple, Union\n\nfrom langchain.agents import AgentExecutor\nfrom langchain.agents.agent import ExceptionTool\nfrom langchain.callbacks.manager import CallbackManagerForChainRun\nfrom langchain_core.agents import AgentAction, AgentFinish, AgentStep\nfrom langchain_core.exceptions import OutputParserException\nfrom langchain_core.pydantic_v1 import root_validator\nfrom langchain_core.tools import BaseTool\nfrom langchain_core.utils.input import get_color_mapping\nfrom pydantic import InstanceOf\n\nfrom crewai.agents.tools_handler import ToolsHandler\nfrom crewai.tools.tool_usage import ToolUsage, ToolUsageErrorException\nfrom crewai.utilities import I18N\n\n\nclass CrewAgentExecutor(AgentExecutor):\n    _i18n: I18N = I18N()\n    llm: Any = None\n    iterations: int = 0\n    task: Any = None\n    tools_description: str = \"\"\n    tools_names: str = \"\"\n    function_calling_llm: Any = None\n    request_within_rpm_limit: Any = None\n    tools_handler: InstanceOf[ToolsHandler] = None\n    max_iterations: Optional[int] = 15\n    have_forced_answer: bool = False\n    force_answer_max_iterations: Optional[int] = None\n    step_callback: Optional[Any] = None\n\n    @root_validator()\n    def set_force_answer_max_iterations(cls, values: Dict) -> Dict:\n        values[\"force_answer_max_iterations\"] = values[\"max_iterations\"] - 2\n        return values\n\n    def _should_force_answer(self) -> bool:\n        return (\n            self.iterations == self.force_answer_max_iterations\n        ) and not self.have_forced_answer\n\n    def _call(\n        self,\n        inputs: Dict[str, str],\n        run_manager: Optional[CallbackManagerForChainRun] = None,\n    ) -> Dict[str, Any]:\n        \"\"\"Run text through and get agent response.\"\"\"\n        # Construct a mapping of tool name to tool for easy lookup\n        name_to_tool_map = {tool.name: tool for tool in self.tools}\n        # We construct a mapping from each tool to a color, used for logging.\n        color_mapping = get_color_mapping(\n            [tool.name for tool in self.tools], excluded_colors=[\"green\", \"red\"]\n        )\n        intermediate_steps: List[Tuple[AgentAction, str]] = []\n        # Let's start tracking the number of iterations and time elapsed\n        self.iterations = 0\n        time_elapsed = 0.0\n        start_time = time.time()\n        # We now enter the agent loop (until it returns something).\n        while self._should_continue(self.iterations, time_elapsed):\n            if not self.request_within_rpm_limit or self.request_within_rpm_limit():\n                next_step_output = self._take_next_step(\n                    name_to_tool_map,\n                    color_mapping,\n                    inputs,\n                    intermediate_steps,\n                    run_manager=run_manager,\n                )\n\n                if self.step_callback:\n                    self.step_callback(next_step_output)\n\n                if isinstance(next_step_output, AgentFinish):\n                    return self._return(\n                        next_step_output, intermediate_steps, run_manager=run_manager\n                    )\n\n                intermediate_steps.extend(next_step_output)\n                if len(next_step_output) == 1:\n                    next_step_action = next_step_output[0]\n                    # See if tool should return directly\n                    tool_return = self._get_tool_return(next_step_action)\n                    if tool_return is not None:\n                        return self._return(\n                            tool_return, intermediate_steps, run_manager=run_manager\n                        )\n                self.iterations += 1\n                time_elapsed = time.time() - start_time\n        output = self.agent.return_stopped_response(\n            self.early_stopping_method, intermediate_steps, **inputs\n        )\n        return self._return(output, intermediate_steps, run_manager=run_manager)\n\n    def _iter_next_step(\n        self,\n        name_to_tool_map: Dict[str, BaseTool],\n        color_mapping: Dict[str, str],\n        inputs: Dict[str, str],\n        intermediate_steps: List[Tuple[AgentAction, str]],\n        run_manager: Optional[CallbackManagerForChainRun] = None,\n    ) -> Iterator[Union[AgentFinish, AgentAction, AgentStep]]:\n        \"\"\"Take a single step in the thought-action-observation loop.\n\n        Override this to take control of how the agent makes and acts on choices.\n        \"\"\"\n        try:\n            if self._should_force_answer():\n                error = self._i18n.errors(\"force_final_answer\")\n                output = AgentAction(\"_Exception\", error, error)\n                self.have_forced_answer = True\n                yield AgentStep(action=output, observation=error)\n                return\n\n            intermediate_steps = self._prepare_intermediate_steps(intermediate_steps)\n            # Call the LLM to see what to do.\n            output = self.agent.plan(\n                intermediate_steps,\n                callbacks=run_manager.get_child() if run_manager else None,\n                **inputs,\n            )\n\n        except OutputParserException as e:\n            if isinstance(self.handle_parsing_errors, bool):\n                raise_error = not self.handle_parsing_errors\n            else:\n                raise_error = False\n            if raise_error:\n                raise ValueError(\n                    \"An output parsing error occurred. \"\n                    \"In order to pass this error back to the agent and have it try \"\n                    \"again, pass `handle_parsing_errors=True` to the AgentExecutor. \"\n                    f\"This is the error: {str(e)}\"\n                )\n            str(e)\n            if isinstance(self.handle_parsing_errors, bool):\n                if e.send_to_llm:\n                    observation = f\"\\n{str(e.observation)}\"\n                    str(e.llm_output)\n                else:\n                    observation = \"\"\n            elif isinstance(self.handle_parsing_errors, str):\n                observation = f\"\\n{self.handle_parsing_errors}\"\n            elif callable(self.handle_parsing_errors):\n                observation = f\"\\n{self.handle_parsing_errors(e)}\"\n            else:\n                raise ValueError(\"Got unexpected type of `handle_parsing_errors`\")\n            output = AgentAction(\"_Exception\", observation, \"\")\n            if run_manager:\n                run_manager.on_agent_action(output, color=\"green\")\n            tool_run_kwargs = self.agent.tool_run_logging_kwargs()\n            observation = ExceptionTool().run(\n                output.tool_input,\n                verbose=False,\n                color=None,\n                callbacks=run_manager.get_child() if run_manager else None,\n                **tool_run_kwargs,\n            )\n\n            if self._should_force_answer():\n                error = self._i18n.errors(\"force_final_answer\")\n                output = AgentAction(\"_Exception\", error, error)\n                yield AgentStep(action=output, observation=error)\n                return\n\n            yield AgentStep(action=output, observation=observation)\n            return\n\n        # If the tool chosen is the finishing tool, then we end and return.\n        if isinstance(output, AgentFinish):\n            yield output\n            return\n\n        actions: List[AgentAction]\n        actions = [output] if isinstance(output, AgentAction) else output\n        yield from actions\n        for agent_action in actions:\n            if run_manager:\n                run_manager.on_agent_action(agent_action, color=\"green\")\n            # Otherwise we lookup the tool\n            tool_usage = ToolUsage(\n                tools_handler=self.tools_handler,\n                tools=self.tools,\n                tools_description=self.tools_description,\n                tools_names=self.tools_names,\n                function_calling_llm=self.function_calling_llm,\n                task=self.task,\n                action=agent_action,\n            )\n            tool_calling = tool_usage.parse(agent_action.log)\n\n            if isinstance(tool_calling, ToolUsageErrorException):\n                observation = tool_calling.message\n            else:\n                if tool_calling.tool_name.lower().strip() in [\n                    name.lower().strip() for name in name_to_tool_map\n                ]:\n                    observation = tool_usage.use(tool_calling, agent_action.log)\n                else:\n                    observation = self._i18n.errors(\"wrong_tool_name\").format(\n                        tool=tool_calling.tool_name,\n                        tools=\", \".join([tool.name for tool in self.tools]),\n                    )\n            yield AgentStep(action=agent_action, observation=observation)\n",
        "parser.py": "import re\nfrom typing import Any, Union\n\nfrom langchain.agents.output_parsers import ReActSingleInputOutputParser\nfrom langchain_core.agents import AgentAction, AgentFinish\nfrom langchain_core.exceptions import OutputParserException\n\nfrom crewai.utilities import I18N\n\nFINAL_ANSWER_ACTION = \"Final Answer:\"\nMISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE = \"I did it wrong. Invalid Format: I missed the 'Action:' after 'Thought:'. I will do right next, and don't use a tool I have already used.\\n\"\nMISSING_ACTION_INPUT_AFTER_ACTION_ERROR_MESSAGE = \"I did it wrong. Invalid Format: I missed the 'Action Input:' after 'Action:'. I will do right next, and don't use a tool I have already used.\\n\"\nFINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE = \"I did it wrong. Tried to both perform Action and give a Final Answer at the same time, I must do one or the other\"\n\n\nclass CrewAgentParser(ReActSingleInputOutputParser):\n    \"\"\"Parses ReAct-style LLM calls that have a single tool input.\n\n    Expects output to be in one of two formats.\n\n    If the output signals that an action should be taken,\n    should be in the below format. This will result in an AgentAction\n    being returned.\n\n    Thought: agent thought here\n    Action: search\n    Action Input: what is the temperature in SF?\n\n    If the output signals that a final answer should be given,\n    should be in the below format. This will result in an AgentFinish\n    being returned.\n\n    Thought: agent thought here\n    Final Answer: The temperature is 100 degrees\n    \"\"\"\n\n    _i18n: I18N = I18N()\n    agent: Any = None\n\n    def parse(self, text: str) -> Union[AgentAction, AgentFinish]:\n        includes_answer = FINAL_ANSWER_ACTION in text\n        regex = (\n            r\"Action\\s*\\d*\\s*:[\\s]*(.*?)[\\s]*Action\\s*\\d*\\s*Input\\s*\\d*\\s*:[\\s]*(.*)\"\n        )\n        action_match = re.search(regex, text, re.DOTALL)\n        if action_match:\n            if includes_answer:\n                raise OutputParserException(\n                    f\"{FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE}: {text}\"\n                )\n            action = action_match.group(1).strip()\n            action_input = action_match.group(2)\n            tool_input = action_input.strip(\" \")\n            tool_input = tool_input.strip('\"')\n\n            return AgentAction(action, tool_input, text)\n\n        elif includes_answer:\n            return AgentFinish(\n                {\"output\": text.split(FINAL_ANSWER_ACTION)[-1].strip()}, text\n            )\n\n        if not re.search(r\"Action\\s*\\d*\\s*:[\\s]*(.*?)\", text, re.DOTALL):\n            self.agent.increment_formatting_errors()\n            raise OutputParserException(\n                f\"Could not parse LLM output: `{text}`\",\n                observation=f\"{MISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE}\\n{self._i18n.slice('final_answer_format')}\",\n                llm_output=text,\n                send_to_llm=True,\n            )\n        elif not re.search(\n            r\"[\\s]*Action\\s*\\d*\\s*Input\\s*\\d*\\s*:[\\s]*(.*)\", text, re.DOTALL\n        ):\n            self.agent.increment_formatting_errors()\n            raise OutputParserException(\n                f\"Could not parse LLM output: `{text}`\",\n                observation=MISSING_ACTION_INPUT_AFTER_ACTION_ERROR_MESSAGE,\n                llm_output=text,\n                send_to_llm=True,\n            )\n        else:\n            format = self._i18n.slice(\"format_without_tools\")\n            error = f\"{format}\"\n            self.agent.increment_formatting_errors()\n            raise OutputParserException(\n                error,\n                observation=error,\n                llm_output=text,\n                send_to_llm=True,\n            )\n",
        "tools_handler.py": "from typing import Any\n\nfrom ..tools.cache_tools import CacheTools\nfrom ..tools.tool_calling import ToolCalling\nfrom .cache.cache_handler import CacheHandler\n\n\nclass ToolsHandler:\n    \"\"\"Callback handler for tool usage.\"\"\"\n\n    last_used_tool: ToolCalling = {}\n    cache: CacheHandler\n\n    def __init__(self, cache: CacheHandler):\n        \"\"\"Initialize the callback handler.\"\"\"\n        self.cache = cache\n        self.last_used_tool = {}\n\n    def on_tool_use(self, calling: ToolCalling, output: str) -> Any:\n        \"\"\"Run when tool ends running.\"\"\"\n        self.last_used_tool = calling\n        if calling.tool_name != CacheTools().name:\n            self.cache.add(\n                tool=calling.tool_name,\n                input=calling.arguments,\n                output=output,\n            )\n",
        "__init__.py": "from .cache.cache_handler import CacheHandler\nfrom .executor import CrewAgentExecutor\nfrom .parser import CrewAgentParser\nfrom .tools_handler import ToolsHandler\n",
        "__pycache__": {}
    },
    "cli": {
        "cli.py": "import click\n\nfrom .create_crew import create_crew\n\n\<PRESIDIO_ANONYMIZED_EMAIL_ADDRESS>()\ndef crewai():\n    \"\"\"Top-level command group for crewai.\"\"\"\n\n\n@crewai.command()\n@click.argument(\"project_name\")\ndef create(project_name):\n    \"\"\"Create a new crew.\"\"\"\n    create_crew(project_name)\n\n\nif __name__ == \"__main__\":\n    crewai()\n",
        "create_crew.py": "import os\nfrom pathlib import Path\n\nimport click\n\n\ndef create_crew(name):\n    \"\"\"Create a new crew.\"\"\"\n    folder_name = name.replace(\" \", \"_\").replace(\"-\", \"_\").lower()\n    class_name = name.replace(\"_\", \" \").replace(\"-\", \" \").title().replace(\" \", \"\")\n\n    click.secho(f\"Creating folder {folder_name}...\", fg=\"green\", bold=True)\n\n    if not os.path.exists(folder_name):\n        os.mkdir(folder_name)\n        os.mkdir(folder_name + \"/tests\")\n        os.mkdir(folder_name + \"/src\")\n        os.mkdir(folder_name + f\"/src/{folder_name}\")\n        os.mkdir(folder_name + f\"/src/{folder_name}/tools\")\n        os.mkdir(folder_name + f\"/src/{folder_name}/config\")\n        with open(folder_name + \"/.env\", \"w\") as file:\n            file.write(\"OPENAI_API_KEY=YOUR_API_KEY\")\n    else:\n        click.secho(\n            f\"\\tFolder {folder_name} already exists. Please choose a different name.\",\n            fg=\"red\",\n        )\n        return\n\n    package_dir = Path(__file__).parent\n    templates_dir = package_dir / \"templates\"\n\n    # List of template files to copy\n    root_template_files = [\n        \".gitignore\",\n        \"pyproject.toml\",\n        \"README.md\",\n    ]\n    tools_template_files = [\"tools/custom_tool.py\", \"tools/__init__.py\"]\n    config_template_files = [\"config/agents.yaml\", \"config/tasks.yaml\"]\n    src_template_files = [\"__init__.py\", \"main.py\", \"crew.py\"]\n\n    for file_name in root_template_files:\n        src_file = templates_dir / file_name\n        dst_file = Path(folder_name) / file_name\n        copy_template(src_file, dst_file, name, class_name, folder_name)\n\n    for file_name in src_template_files:\n        src_file = templates_dir / file_name\n        dst_file = Path(folder_name) / \"src\" / folder_name / file_name\n        copy_template(src_file, dst_file, name, class_name, folder_name)\n\n    for file_name in tools_template_files:\n        src_file = templates_dir / file_name\n        dst_file = Path(folder_name) / \"src\" / folder_name / file_name\n        copy_template(src_file, dst_file, name, class_name, folder_name)\n\n    for file_name in config_template_files:\n        src_file = templates_dir / file_name\n        dst_file = Path(folder_name) / \"src\" / folder_name / file_name\n        copy_template(src_file, dst_file, name, class_name, folder_name)\n\n    click.secho(f\"Crew {name} created successfully!\", fg=\"green\", bold=True)\n\n\ndef copy_template(src, dst, name, class_name, folder_name):\n    \"\"\"Copy a file from src to dst.\"\"\"\n    with open(src, \"r\") as file:\n        content = file.read()\n\n    # Interpolate the content\n    content = content.replace(\"{{name}}\", name)\n    content = content.replace(\"{{crew_name}}\", class_name)\n    content = content.replace(\"{{folder_name}}\", folder_name)\n\n    # Write the interpolated content to the new file\n    with open(dst, \"w\") as file:\n        file.write(content)\n\n    click.secho(f\"  - Created {dst}\", fg=\"green\")\n",
        "templates": {
            "config": {
                "agents.yaml": "researcher:\n  role: >\n    {topic} Senior Data Researcher\n  goal: >\n    Uncover cutting-edge developments in {topic}\n  backstory: >\n    You're a seasoned researcher with a knack for uncovering the latest\n    developments in {topic}. Known for your ability to find the most relevant\n    information and present it in a clear and concise manner.\n\nreporting_analyst:\n  role: >\n    {topic} Reporting Analyst\n  goal: >\n    Create detailed reports based on {topic} data analysis and research findings\n  backstory: >\n    You're a meticulous analyst with a keen eye for detail. You're known for\n    your ability to turn complex data into clear and concise reports, making\n    it easy for others to understand and act on the information you provide.",
                "tasks.yaml": "research_task:\n  description: >\n    Conduct a thorough research about {topic}\n    Make sure you find any interesting and relevant information given\n    the current year is 2024.\n  expected_output: >\n    A list with 10 bullet points of the most relevant information about {topic}\n\nreporting_task:\n  description: >\n    Review the context you got and expand each topic into a full section for a report.\n    Make sure the report is detailed and contains any and all relevant information.\n  expected_output: >\n    A fully fledge reports with the mains topics, each with a full section of information.\n    Formated as markdown with out '```'\n"
            },
            "crew.py": "from crewai import Agent, Crew, Process, Task\nfrom crewai.project import CrewBase, agent, crew, task\n\n# Uncomment the following line to use an example of a custom tool\n# from {{folder_name}}.tools.custom_tool import MyCustomTool\n\n# Check our tools documentations for more information on how to use them\n# from crewai_tools import SerperDevTool\n\n@CrewBase\nclass {{crew_name}}Crew():\n\t\"\"\"{{crew_name}} crew\"\"\"\n\tagents_config = 'config/agents.yaml'\n\ttasks_config = 'config/tasks.yaml'\n\n\t@agent\n\tdef researcher(self) -> Agent:\n\t\treturn Agent(\n\t\t\tconfig=self.agents_config['researcher'],\n\t\t\t# tools=[MyCustomTool()], # Example of custom tool, loaded on the beginning of file\n\t\t\tverbose=True\n\t\t)\n\n\t@agent\n\tdef reporting_analyst(self) -> Agent:\n\t\treturn Agent(\n\t\t\tconfig=self.agents_config['reporting_analyst'],\n\t\t\tverbose=True\n\t\t)\n\n\t@task\n\tdef research_task(self) -> Task:\n\t\treturn Task(\n\t\t\tconfig=self.tasks_config['research_task'],\n\t\t\tagent=self.researcher()\n\t\t)\n\n\t@task\n\tdef reporting_task(self) -> Task:\n\t\treturn Task(\n\t\t\tconfig=self.tasks_config['reporting_task'],\n\t\t\tagent=self.reporting_analyst(),\n\t\t\toutput_file='report.md'\n\t\t)\n\n\t@crew\n\tdef crew(self) -> Crew:\n\t\t\"\"\"Creates the {{crew_name}} crew\"\"\"\n\t\treturn Crew(\n\t\t\tagents=self.agents, # Automatically created by the @agent decorator\n\t\t\ttasks=self.tasks, # Automatically created by the @task decorator\n\t\t\tprocess=Process.sequential,\n\t\t\tverbose=2,\n\t\t\t# process=Process.hierarchical, # In case you wanna use that instead https://docs.crewai.com/how-to/Hierarchical/\n\t\t)",
            "main.py": "#!/usr/bin/env python\nfrom {{folder_name}}.crew import {{crew_name}}Crew\n\n\ndef run():\n    # Replace with your inputs, it will automatically interpolate any tasks and agents information\n    inputs = {\n        'topic': 'AI LLMs'\n    }\n    {{crew_name}}Crew().crew().kickoff(inputs=inputs)",
            "README.md": "# {{crew_name}} Crew\n\nWelcome to the {{crew_name}} Crew project, powered by [crewAI](https://crewai.com). This template is designed to help you set up a multi-agent AI system with ease, leveraging the powerful and flexible framework provided by crewAI. Our goal is to enable your agents to collaborate effectively on complex tasks, maximizing their collective intelligence and capabilities.\n\n## Installation\n\nEnsure you have Python >=3.10 <=3.13 installed on your system. This project uses [Poetry](https://python-poetry.org/) for dependency management and package handling, offering a seamless setup and execution experience.\n\nFirst, if you haven't already, install Poetry:\n\n```bash\npip install poetry\n```\n\nNext, navigate to your project directory and install the dependencies:\n\n1. First lock the dependencies and then install them:\n```bash\npoetry lock\n```\n```bash\npoetry install\n```\n### Customizing\n\n**Add you `OPENAI_API_KEY` on the `.env` file**\n\n- Modify `src/{{folder_name}}/config/agents.yaml` to define your agents\n- Modify `src/{{folder_name}}/config/tasks.yaml` to define your tasks\n- Modify `src/{{folder_name}}/crew.py` to add your own logic, tools and specific args\n- Modify `src/{{folder_name}}/main.py` to add custom inputs for your agents and tasks\n\n## Running the Project\n\nTo kickstart your crew of AI agents and begin task execution, run this from the root folder of your project:\n\n```bash\npoetry run {{folder_name}}\n```\n\nThis command initializes the {{name}} Crew, assembling the agents and assigning them tasks as defined in your configuration.\n\nThis example, unmodified, will run the create a `report.md` file with the output of a research on LLMs in the root folser\n\n## Understanding Your Crew\n\nThe {{name}} Crew is composed of multiple AI agents, each with unique roles, goals, and tools. These agents collaborate on a series of tasks, defined in `config/tasks.yaml`, leveraging their collective skills to achieve complex objectives. The `config/agents.yaml` file outlines the capabilities and configurations of each agent in your crew.\n\n## Support\n\nFor support, questions, or feedback regarding the {{crew_name}} Crew or crewAI.\n- Visit our [documentation](https://docs.crewai.com)\n- Reach out to us through our [GitHub repository](https://github.com/joaomdmoura/crewai)\n- [Joing our Discord](https://discord.com/invite/X4JWnZnxPb)\n- [Chat wtih our docs](https://chatg.pt/DWjSBZn)\n\nLet's create wonders together with the power and simplicity of crewAI.",
            "tools": {
                "custom_tool.py": "from crewai_tools import BaseTool\n\n\nclass MyCustomTool(BaseTool):\n    name: str = \"Name of my tool\"\n    description: str = \"Clear description for what this tool is useful for, you agent will need this information to use it.\"\n\n    def _run(self, argument: str) -> str:\n        # Implementation goes here\n        return \"this is an example of a tool output, ignore it and move along.\"\n",
                "__init__.py": "",
                "__pycache__": {}
            },
            "__init__.py": "",
            "__pycache__": {}
        },
        "__init__.py": "",
        "__pycache__": {}
    },
    "crew.py": "import json\nimport uuid\nfrom typing import Any, Dict, List, Optional, Union\n\nfrom langchain_core.callbacks import BaseCallbackHandler\nfrom pydantic import (\n    UUID4,\n    BaseModel,\n    ConfigDict,\n    Field,\n    InstanceOf,\n    Json,\n    PrivateAttr,\n    field_validator,\n    model_validator,\n)\nfrom pydantic_core import PydanticCustomError\n\nfrom crewai.agent import Agent\nfrom crewai.agents.cache import CacheHandler\nfrom crewai.process import Process\nfrom crewai.task import Task\nfrom crewai.telemetry import Telemetry\nfrom crewai.tools.agent_tools import AgentTools\nfrom crewai.utilities import I18N, Logger, RPMController\n\n\nclass Crew(BaseModel):\n    \"\"\"\n    Represents a group of agents, defining how they should collaborate and the tasks they should perform.\n\n    Attributes:\n        tasks: List of tasks assigned to the crew.\n        agents: List of agents part of this crew.\n        manager_llm: The language model that will run manager agent.\n        manager_callbacks: The callback handlers to be executed by the manager agent when hierarchical process is used\n        function_calling_llm: The language model that will run the tool calling for all the agents.\n        process: The process flow that the crew will follow (e.g., sequential).\n        verbose: Indicates the verbosity level for logging during execution.\n        config: Configuration settings for the crew.\n        max_rpm: Maximum number of requests per minute for the crew execution to be respected.\n        id: A unique identifier for the crew instance.\n        full_output: Whether the crew should return the full output with all tasks outputs or just the final output.\n        step_callback: Callback to be executed after each step for every agents execution.\n        share_crew: Whether you want to share the complete crew infromation and execution with crewAI to make the library better, and allow us to train models.\n    \"\"\"\n\n    __hash__ = object.__hash__  # type: ignore\n    _execution_span: Any = PrivateAttr()\n    _rpm_controller: RPMController = PrivateAttr()\n    _logger: Logger = PrivateAttr()\n    _cache_handler: InstanceOf[CacheHandler] = PrivateAttr(default=CacheHandler())\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    tasks: List[Task] = Field(default_factory=list)\n    agents: List[Agent] = Field(default_factory=list)\n    process: Process = Field(default=Process.sequential)\n    verbose: Union[int, bool] = Field(default=0)\n    usage_metrics: Optional[dict] = Field(\n        default=None,\n        description=\"Metrics for the LLM usage during all tasks execution.\",\n    )\n    full_output: Optional[bool] = Field(\n        default=False,\n        description=\"Whether the crew should return the full output with all tasks outputs or just the final output.\",\n    )\n    manager_llm: Optional[Any] = Field(\n        description=\"Language model that will run the agent.\", default=None\n    )\n    manager_callbacks: Optional[List[InstanceOf[BaseCallbackHandler]]] = Field(\n        default=None,\n        description=\"A list of callback handlers to be executed by the manager agent when hierarchical process is used\",\n    )\n    function_calling_llm: Optional[Any] = Field(\n        description=\"Language model that will run the agent.\", default=None\n    )\n    config: Optional[Union[Json, Dict[str, Any]]] = Field(default=None)\n    id: UUID4 = Field(default_factory=uuid.uuid4, frozen=True)\n    share_crew: Optional[bool] = Field(default=False)\n    step_callback: Optional[Any] = Field(\n        default=None,\n        description=\"Callback to be executed after each step for all agents execution.\",\n    )\n    max_rpm: Optional[int] = Field(\n        default=None,\n        description=\"Maximum number of requests per minute for the crew execution to be respected.\",\n    )\n    language: str = Field(\n        default=\"en\",\n        description=\"Language used for the crew, defaults to English.\",\n    )\n\n    @field_validator(\"id\", mode=\"before\")\n    @classmethod\n    def _deny_user_set_id(cls, v: Optional[UUID4]) -> None:\n        \"\"\"Prevent manual setting of the 'id' field by users.\"\"\"\n        if v:\n            raise PydanticCustomError(\n                \"may_not_set_field\", \"The 'id' field cannot be set by the user.\", {}\n            )\n\n    @field_validator(\"config\", mode=\"before\")\n    @classmethod\n    def check_config_type(\n        cls, v: Union[Json, Dict[str, Any]]\n    ) -> Union[Json, Dict[str, Any]]:\n        \"\"\"Validates that the config is a valid type.\n        Args:\n            v: The config to be validated.\n        Returns:\n            The config if it is valid.\n        \"\"\"\n\n        # TODO: Improve typing\n        return json.loads(v) if isinstance(v, Json) else v  # type: ignore\n\n    @model_validator(mode=\"after\")\n    def set_private_attrs(self) -> \"Crew\":\n        \"\"\"Set private attributes.\"\"\"\n        self._cache_handler = CacheHandler()\n        self._logger = Logger(self.verbose)\n        self._rpm_controller = RPMController(max_rpm=self.max_rpm, logger=self._logger)\n        self._telemetry = Telemetry()\n        self._telemetry.set_tracer()\n        self._telemetry.crew_creation(self)\n        return self\n\n    @model_validator(mode=\"after\")\n    def check_manager_llm(self):\n        \"\"\"Validates that the language model is set when using hierarchical process.\"\"\"\n        if self.process == Process.hierarchical and not self.manager_llm:\n            raise PydanticCustomError(\n                \"missing_manager_llm\",\n                \"Attribute `manager_llm` is required when using hierarchical process.\",\n                {},\n            )\n        return self\n\n    @model_validator(mode=\"after\")\n    def check_config(self):\n        \"\"\"Validates that the crew is properly configured with agents and tasks.\"\"\"\n        if not self.config and not self.tasks and not self.agents:\n            raise PydanticCustomError(\n                \"missing_keys\",\n                \"Either 'agents' and 'tasks' need to be set or 'config'.\",\n                {},\n            )\n\n        if self.config:\n            self._setup_from_config()\n\n        if self.agents:\n            for agent in self.agents:\n                agent.set_cache_handler(self._cache_handler)\n                if self.max_rpm:\n                    agent.set_rpm_controller(self._rpm_controller)\n        return self\n\n    def _setup_from_config(self):\n        assert self.config is not None, \"Config should not be None.\"\n\n        \"\"\"Initializes agents and tasks from the provided config.\"\"\"\n        if not self.config.get(\"agents\") or not self.config.get(\"tasks\"):\n            raise PydanticCustomError(\n                \"missing_keys_in_config\", \"Config should have 'agents' and 'tasks'.\", {}\n            )\n\n        self.process = self.config.get(\"process\", self.process)\n        self.agents = [Agent(**agent) for agent in self.config[\"agents\"]]\n        self.tasks = [self._create_task(task) for task in self.config[\"tasks\"]]\n\n    def _create_task(self, task_config: Dict[str, Any]) -> Task:\n        \"\"\"Creates a task instance from its configuration.\n\n        Args:\n            task_config: The configuration of the task.\n\n        Returns:\n            A task instance.\n        \"\"\"\n        task_agent = next(\n            agt for agt in self.agents if agt.role == task_config[\"agent\"]\n        )\n        del task_config[\"agent\"]\n        return Task(**task_config, agent=task_agent)\n\n    def kickoff(self, inputs: Optional[Dict[str, Any]] = {}) -> str:\n        \"\"\"Starts the crew to work on its assigned tasks.\"\"\"\n        self._execution_span = self._telemetry.crew_execution_span(self)\n        self._interpolate_inputs(inputs)\n\n        for agent in self.agents:\n            agent.i18n = I18N(language=self.language)\n\n            if not agent.function_calling_llm:\n                agent.function_calling_llm = self.function_calling_llm\n                agent.create_agent_executor()\n            if not agent.step_callback:\n                agent.step_callback = self.step_callback\n                agent.create_agent_executor()\n\n        metrics = []\n\n        if self.process == Process.sequential:\n            result = self._run_sequential_process()\n        elif self.process == Process.hierarchical:\n            result, manager_metrics = self._run_hierarchical_process()\n            metrics.append(manager_metrics)\n\n        else:\n            raise NotImplementedError(\n                f\"The process '{self.process}' is not implemented yet.\"\n            )\n\n        metrics = metrics + [\n            agent._token_process.get_summary() for agent in self.agents\n        ]\n        self.usage_metrics = {\n            key: sum([m[key] for m in metrics if m is not None]) for key in metrics[0]\n        }\n\n        return result\n\n    def _run_sequential_process(self) -> str:\n        \"\"\"Executes tasks sequentially and returns the final output.\"\"\"\n        task_output = \"\"\n        for task in self.tasks:\n            if task.agent.allow_delegation:\n                agents_for_delegation = [\n                    agent for agent in self.agents if agent != task.agent\n                ]\n                if len(self.agents) > 1 and len(agents_for_delegation) > 0:\n                    task.tools += AgentTools(agents=agents_for_delegation).tools()\n\n            role = task.agent.role if task.agent is not None else \"None\"\n            self._logger.log(\"debug\", f\"== Working Agent: {role}\", color=\"bold_yellow\")\n            self._logger.log(\n                \"info\", f\"== Starting Task: {task.description}\", color=\"bold_yellow\"\n            )\n\n            output = task.execute(context=task_output)\n            if not task.async_execution:\n                task_output = output\n\n            role = task.agent.role if task.agent is not None else \"None\"\n            self._logger.log(\"debug\", f\"== [{role}] Task output: {task_output}\\n\\n\")\n\n        self._finish_execution(task_output)\n        return self._format_output(task_output)\n\n    def _run_hierarchical_process(self) -> str:\n        \"\"\"Creates and assigns a manager agent to make sure the crew completes the tasks.\"\"\"\n\n        i18n = I18N(language=self.language)\n        manager = Agent(\n            role=i18n.retrieve(\"hierarchical_manager_agent\", \"role\"),\n            goal=i18n.retrieve(\"hierarchical_manager_agent\", \"goal\"),\n            backstory=i18n.retrieve(\"hierarchical_manager_agent\", \"backstory\"),\n            tools=AgentTools(agents=self.agents).tools(),\n            llm=self.manager_llm,\n            verbose=True,\n        )\n\n        task_output = \"\"\n        for task in self.tasks:\n            self._logger.log(\"debug\", f\"Working Agent: {manager.role}\")\n            self._logger.log(\"info\", f\"Starting Task: {task.description}\")\n\n            task_output = task.execute(\n                agent=manager, context=task_output, tools=manager.tools\n            )\n\n            self._logger.log(\"debug\", f\"[{manager.role}] Task output: {task_output}\")\n\n        self._finish_execution(task_output)\n        return self._format_output(task_output), manager._token_process.get_summary()\n\n    def _interpolate_inputs(self, inputs: Dict[str, Any]) -> str:\n        \"\"\"Interpolates the inputs in the tasks and agents.\"\"\"\n        [task.interpolate_inputs(inputs) for task in self.tasks]\n        [agent.interpolate_inputs(inputs) for agent in self.agents]\n\n    def _format_output(self, output: str) -> str:\n        \"\"\"Formats the output of the crew execution.\"\"\"\n        if self.full_output:\n            return {\n                \"final_output\": output,\n                \"tasks_outputs\": [task.output for task in self.tasks if task],\n            }\n        else:\n            return output\n\n    def _finish_execution(self, output) -> None:\n        if self.max_rpm:\n            self._rpm_controller.stop_rpm_counter()\n        self._telemetry.end_crew(self, output)\n\n    def __repr__(self):\n        return f\"Crew(id={self.id}, process={self.process}, number_of_agents={len(self.agents)}, number_of_tasks={len(self.tasks)})\"\n",
    "process.py": "from enum import Enum\n\n\nclass Process(str, Enum):\n    \"\"\"\n    Class representing the different processes that can be used to tackle tasks\n    \"\"\"\n\n    sequential = \"sequential\"\n    hierarchical = \"hierarchical\"\n    # TODO: consensual = 'consensual'\n",
    "project": {
        "annotations.py": "tasks_order = []\n\n\ndef task(func):\n    func.is_task = True\n    tasks_order.append(func.__name__)\n    return func\n\n\ndef agent(func):\n    func.is_agent = True\n    return func\n\n\ndef crew(func):\n    def wrapper(self, *args, **kwargs):\n        instantiated_tasks = []\n        instantiated_agents = []\n\n        agent_roles = set()\n        # Iterate over tasks_order to maintain the defined order\n        for task_name in tasks_order:\n            possible_task = getattr(self, task_name)\n            if callable(possible_task):\n                task_instance = possible_task()\n                instantiated_tasks.append(task_instance)\n                if hasattr(task_instance, \"agent\"):\n                    agent_instance = task_instance.agent\n                    if agent_instance.role not in agent_roles:\n                        instantiated_agents.append(agent_instance)\n                        agent_roles.add(agent_instance.role)\n\n        # Instantiate any additional agents not already included by tasks\n        for attr_name in dir(self):\n            possible_agent = getattr(self, attr_name)\n            if callable(possible_agent) and hasattr(possible_agent, \"is_agent\"):\n                temp_agent_instance = possible_agent()\n                if temp_agent_instance.role not in agent_roles:\n                    instantiated_agents.append(temp_agent_instance)\n                    agent_roles.add(temp_agent_instance.role)\n\n        self.agents = instantiated_agents\n        self.tasks = instantiated_tasks\n\n        return func(self, *args, **kwargs)\n\n    return wrapper\n",
        "crew_base.py": "import inspect\nimport os\nfrom pathlib import Path\n\nimport yaml\nfrom dotenv import load_dotenv\n\nload_dotenv()\n\n\ndef CrewBase(cls):\n    class WrappedClass(cls):\n        is_crew_class = True\n\n        base_directory = None\n        for frame_info in inspect.stack():\n            if \"site-packages\" not in frame_info.filename:\n                base_directory = Path(frame_info.filename).parent.resolve()\n                break\n\n        if base_directory is None:\n            raise Exception(\n                \"Unable to dynamically determine the project's base directory, you must run it from the project's root directory.\"\n            )\n\n        original_agents_config_path = getattr(\n            cls, \"agents_config\", \"config/agents.yaml\"\n        )\n        original_tasks_config_path = getattr(cls, \"tasks_config\", \"config/tasks.yaml\")\n\n        def __init__(self, *args, **kwargs):\n            super().__init__(*args, **kwargs)\n            self.agents_config = self.load_yaml(\n                os.path.join(self.base_directory, self.original_agents_config_path)\n            )\n            self.tasks_config = self.load_yaml(\n                os.path.join(self.base_directory, self.original_tasks_config_path)\n            )\n\n        @staticmethod\n        def load_yaml(config_path: str):\n            with open(config_path, \"r\") as file:\n                return yaml.safe_load(file)\n\n    return WrappedClass\n",
        "__init__.py": "from .annotations import agent, crew, task\nfrom .crew_base import CrewBase\n",
        "__pycache__": {}
    },
    "task.py": "import threading\nimport uuid\nfrom typing import Any, Dict, List, Optional, Type\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic import UUID4, BaseModel, Field, field_validator, model_validator\nfrom pydantic_core import PydanticCustomError\n\nfrom crewai.agent import Agent\nfrom crewai.tasks.task_output import TaskOutput\nfrom crewai.utilities import I18N, Converter, ConverterError, Printer\nfrom crewai.utilities.pydantic_schema_parser import PydanticSchemaParser\n\n\nclass Task(BaseModel):\n    \"\"\"Class that represent a task to be executed.\"\"\"\n\n    class Config:\n        arbitrary_types_allowed = True\n\n    __hash__ = object.__hash__  # type: ignore\n    used_tools: int = 0\n    tools_errors: int = 0\n    delegations: int = 0\n    i18n: I18N = I18N()\n    thread: threading.Thread = None\n    description: str = Field(description=\"Description of the actual task.\")\n    expected_output: str = Field(\n        description=\"Clear definition of expected output for the task.\"\n    )\n    config: Optional[Dict[str, Any]] = Field(\n        description=\"Configuration for the agent\",\n        default=None,\n    )\n    callback: Optional[Any] = Field(\n        description=\"Callback to be executed after the task is completed.\", default=None\n    )\n    agent: Optional[Agent] = Field(\n        description=\"Agent responsible for execution the task.\", default=None\n    )\n    context: Optional[List[\"Task\"]] = Field(\n        description=\"Other tasks that will have their output used as context for this task.\",\n        default=None,\n    )\n    async_execution: Optional[bool] = Field(\n        description=\"Whether the task should be executed asynchronously or not.\",\n        default=False,\n    )\n    output_json: Optional[Type[BaseModel]] = Field(\n        description=\"A Pydantic model to be used to create a JSON output.\",\n        default=None,\n    )\n    output_pydantic: Optional[Type[BaseModel]] = Field(\n        description=\"A Pydantic model to be used to create a Pydantic output.\",\n        default=None,\n    )\n    output_file: Optional[str] = Field(\n        description=\"A file path to be used to create a file output.\",\n        default=None,\n    )\n    output: Optional[TaskOutput] = Field(\n        description=\"Task output, it's final result after being executed\", default=None\n    )\n    tools: Optional[List[Any]] = Field(\n        default_factory=list,\n        description=\"Tools the agent is limited to use for this task.\",\n    )\n    id: UUID4 = Field(\n        default_factory=uuid.uuid4,\n        frozen=True,\n        description=\"Unique identifier for the object, not set by user.\",\n    )\n\n    def __init__(__pydantic_self__, **data):\n        config = data.pop(\"config\", {})\n        super().__init__(**config, **data)\n\n    @field_validator(\"id\", mode=\"before\")\n    @classmethod\n    def _deny_user_set_id(cls, v: Optional[UUID4]) -> None:\n        if v:\n            raise PydanticCustomError(\n                \"may_not_set_field\", \"This field is not to be set by the user.\", {}\n            )\n\n    @model_validator(mode=\"after\")\n    def set_attributes_based_on_config(self) -> \"Task\":\n        \"\"\"Set attributes based on the agent configuration.\"\"\"\n        if self.config:\n            for key, value in self.config.items():\n                setattr(self, key, value)\n        return self\n\n    @model_validator(mode=\"after\")\n    def check_tools(self):\n        \"\"\"Check if the tools are set.\"\"\"\n        if not self.tools and self.agent and self.agent.tools:\n            self.tools.extend(self.agent.tools)\n        return self\n\n    @model_validator(mode=\"after\")\n    def check_output(self):\n        \"\"\"Check if an output type is set.\"\"\"\n        output_types = [self.output_json, self.output_pydantic]\n        if len([type for type in output_types if type]) > 1:\n            raise PydanticCustomError(\n                \"output_type\",\n                \"Only one output type can be set, either output_pydantic or output_json.\",\n                {},\n            )\n        return self\n\n    def execute(\n        self,\n        agent: Agent | None = None,\n        context: Optional[str] = None,\n        tools: Optional[List[Any]] = None,\n    ) -> str:\n        \"\"\"Execute the task.\n\n        Returns:\n            Output of the task.\n        \"\"\"\n\n        agent = agent or self.agent\n        if not agent:\n            raise Exception(\n                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, like hierarchical.\"\n            )\n\n        if self.context:\n            context = []\n            for task in self.context:\n                if task.async_execution:\n                    task.thread.join()\n                if task and task.output:\n                    context.append(task.output.raw_output)\n            context = \"\\n\".join(context)\n\n        tools = tools or self.tools\n\n        if self.async_execution:\n            self.thread = threading.Thread(\n                target=self._execute, args=(agent, self, context, tools)\n            )\n            self.thread.start()\n        else:\n            result = self._execute(\n                task=self,\n                agent=agent,\n                context=context,\n                tools=tools,\n            )\n            return result\n\n    def _execute(self, agent, task, context, tools):\n        result = agent.execute_task(\n            task=task,\n            context=context,\n            tools=tools,\n        )\n\n        exported_output = self._export_output(result)\n\n        self.output = TaskOutput(\n            description=self.description,\n            exported_output=exported_output,\n            raw_output=result,\n        )\n\n        if self.callback:\n            self.callback(self.output)\n\n        return exported_output\n\n    def prompt(self) -> str:\n        \"\"\"Prompt the task.\n\n        Returns:\n            Prompt of the task.\n        \"\"\"\n        tasks_slices = [self.description]\n\n        output = self.i18n.slice(\"expected_output\").format(\n            expected_output=self.expected_output\n        )\n        tasks_slices = [self.description, output]\n        return \"\\n\".join(tasks_slices)\n\n    def interpolate_inputs(self, inputs: Dict[str, Any]) -> None:\n        \"\"\"Interpolate inputs into the task description and expected output.\"\"\"\n        if inputs:\n            self.description = self.description.format(**inputs)\n            self.expected_output = self.expected_output.format(**inputs)\n\n    def increment_tools_errors(self) -> None:\n        \"\"\"Increment the tools errors counter.\"\"\"\n        self.tools_errors += 1\n\n    def increment_delegations(self) -> None:\n        \"\"\"Increment the delegations counter.\"\"\"\n        self.delegations += 1\n\n    def _export_output(self, result: str) -> Any:\n        exported_result = result\n        instructions = \"I'm gonna convert this raw text into valid JSON.\"\n\n        if self.output_pydantic or self.output_json:\n            model = self.output_pydantic or self.output_json\n            llm = self.agent.function_calling_llm or self.agent.llm\n\n            if not self._is_gpt(llm):\n                model_schema = PydanticSchemaParser(model=model).get_schema()\n                instructions = f\"{instructions}\\n\\nThe json should have the following structure, with the following keys:\\n{model_schema}\"\n\n            converter = Converter(\n                llm=llm, text=result, model=model, instructions=instructions\n            )\n\n            if self.output_pydantic:\n                exported_result = converter.to_pydantic()\n            elif self.output_json:\n                exported_result = converter.to_json()\n\n            if isinstance(exported_result, ConverterError):\n                Printer().print(\n                    content=f\"{exported_result.message} Using raw output instead.\",\n                    color=\"red\",\n                )\n                exported_result = result\n\n        if self.output_file:\n            content = (\n                exported_result if not self.output_pydantic else exported_result.json()\n            )\n            self._save_file(content)\n\n        return exported_result\n\n    def _is_gpt(self, llm) -> bool:\n        return isinstance(llm, ChatOpenAI) and llm.openai_api_base == None\n\n    def _save_file(self, result: Any) -> None:\n        with open(self.output_file, \"w\") as file:\n            file.write(result)\n        return None\n\n    def __repr__(self):\n        return f\"Task(description={self.description}, expected_output={self.expected_output})\"\n",
    "tasks": {
        "task_output.py": "from typing import Optional, Union\n\nfrom pydantic import BaseModel, Field, model_validator\n\n\nclass TaskOutput(BaseModel):\n    \"\"\"Class that represents the result of a task.\"\"\"\n\n    description: str = Field(description=\"Description of the task\")\n    summary: Optional[str] = Field(description=\"Summary of the task\", default=None)\n    exported_output: Union[str, BaseModel] = Field(\n        description=\"Output of the task\", default=None\n    )\n    raw_output: str = Field(description=\"Result of the task\")\n\n    @model_validator(mode=\"after\")\n    def set_summary(self):\n        excerpt = \" \".join(self.description.split(\" \")[:10])\n        self.summary = f\"{excerpt}...\"\n        return self\n\n    def result(self):\n        return self.exported_output\n",
        "__init__.py": "",
        "__pycache__": {}
    },
    "telemetry": {
        "telemetry.py": "import json\nimport os\nimport platform\nfrom typing import Any\n\nimport pkg_resources\nfrom opentelemetry import trace\nfrom opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter\nfrom opentelemetry.sdk.resources import SERVICE_NAME, Resource\nfrom opentelemetry.sdk.trace import TracerProvider\nfrom opentelemetry.sdk.trace.export import BatchSpanProcessor\nfrom opentelemetry.trace import Status, StatusCode\n\n\nclass Telemetry:\n    \"\"\"A class to handle anonymous telemetry for the crewai package.\n\n    The data being collected is for development purpose, all data is anonymous.\n\n    There is NO data being collected on the prompts, tasks descriptions\n    agents backstories or goals nor responses or any data that is being\n    processed by the agents, nor any secrets and env vars.\n\n    Data collected includes:\n    - Version of crewAI\n    - Version of Python\n    - General OS (e.g. number of CPUs, macOS/Windows/Linux)\n    - Number of agents and tasks in a crew\n    - Crew Process being used\n    - If Agents are using memory or allowing delegation\n    - If Tasks are being executed in parallel or sequentially\n    - Language model being used\n    - Roles of agents in a crew\n    - Tools names available\n\n    Users can opt-in to sharing more complete data suing the `share_crew`\n    attribute in the Crew class.\n    \"\"\"\n\n    def __init__(self):\n        self.ready = False\n        try:\n            telemetry_endpoint = \"http://telemetry.crewai.com:4318\"\n            self.resource = Resource(\n                attributes={SERVICE_NAME: \"crewAI-telemetry\"},\n            )\n            self.provider = TracerProvider(resource=self.resource)\n            processor = BatchSpanProcessor(\n                OTLPSpanExporter(endpoint=f\"{telemetry_endpoint}/v1/traces\", timeout=15)\n            )\n            self.provider.add_span_processor(processor)\n            self.ready = True\n        except Exception:\n            pass\n\n    def set_tracer(self):\n        if self.ready:\n            try:\n                trace.set_tracer_provider(self.provider)\n            except Exception:\n                pass\n\n    def crew_creation(self, crew):\n        \"\"\"Records the creation of a crew.\"\"\"\n        if self.ready:\n            try:\n                tracer = trace.get_tracer(\"crewai.telemetry\")\n                span = tracer.start_span(\"Crew Created\")\n                self._add_attribute(\n                    span,\n                    \"crewai_version\",\n                    pkg_resources.get_distribution(\"crewai\").version,\n                )\n                self._add_attribute(span, \"python_version\", platform.python_version())\n                self._add_attribute(span, \"crew_id\", str(crew.id))\n                self._add_attribute(span, \"crew_process\", crew.process)\n                self._add_attribute(span, \"crew_language\", crew.language)\n                self._add_attribute(span, \"crew_number_of_tasks\", len(crew.tasks))\n                self._add_attribute(span, \"crew_number_of_agents\", len(crew.agents))\n                self._add_attribute(\n                    span,\n                    \"crew_agents\",\n                    json.dumps(\n                        [\n                            {\n                                \"id\": str(agent.id),\n                                \"role\": agent.role,\n                                \"memory_enabled?\": agent.memory,\n                                \"verbose?\": agent.verbose,\n                                \"max_iter\": agent.max_iter,\n                                \"max_rpm\": agent.max_rpm,\n                                \"i18n\": agent.i18n.language,\n                                \"llm\": json.dumps(self._safe_llm_attributes(agent.llm)),\n                                \"delegation_enabled?\": agent.allow_delegation,\n                                \"tools_names\": [tool.name for tool in agent.tools],\n                            }\n                            for agent in crew.agents\n                        ]\n                    ),\n                )\n                self._add_attribute(\n                    span,\n                    \"crew_tasks\",\n                    json.dumps(\n                        [\n                            {\n                                \"id\": str(task.id),\n                                \"async_execution?\": task.async_execution,\n                                \"agent_role\": task.agent.role if task.agent else \"None\",\n                                \"tools_names\": [tool.name for tool in task.tools],\n                            }\n                            for task in crew.tasks\n                        ]\n                    ),\n                )\n                self._add_attribute(span, \"platform\", platform.platform())\n                self._add_attribute(span, \"platform_release\", platform.release())\n                self._add_attribute(span, \"platform_system\", platform.system())\n                self._add_attribute(span, \"platform_version\", platform.version())\n                self._add_attribute(span, \"cpus\", os.cpu_count())\n                span.set_status(Status(StatusCode.OK))\n                span.end()\n            except Exception:\n                pass\n\n    def tool_repeated_usage(self, llm: Any, tool_name: str, attempts: int):\n        \"\"\"Records the repeated usage 'error' of a tool by an agent.\"\"\"\n        if self.ready:\n            try:\n                tracer = trace.get_tracer(\"crewai.telemetry\")\n                span = tracer.start_span(\"Tool Repeated Usage\")\n                self._add_attribute(span, \"tool_name\", tool_name)\n                self._add_attribute(span, \"attempts\", attempts)\n                self._add_attribute(\n                    span, \"llm\", json.dumps(self._safe_llm_attributes(llm))\n                )\n                span.set_status(Status(StatusCode.OK))\n                span.end()\n            except Exception:\n                pass\n\n    def tool_usage(self, llm: Any, tool_name: str, attempts: int):\n        \"\"\"Records the usage of a tool by an agent.\"\"\"\n        if self.ready:\n            try:\n                tracer = trace.get_tracer(\"crewai.telemetry\")\n                span = tracer.start_span(\"Tool Usage\")\n                self._add_attribute(span, \"tool_name\", tool_name)\n                self._add_attribute(span, \"attempts\", attempts)\n                self._add_attribute(\n                    span, \"llm\", json.dumps(self._safe_llm_attributes(llm))\n                )\n                span.set_status(Status(StatusCode.OK))\n                span.end()\n            except Exception:\n                pass\n\n    def tool_usage_error(self, llm: Any):\n        \"\"\"Records the usage of a tool by an agent.\"\"\"\n        if self.ready:\n            try:\n                tracer = trace.get_tracer(\"crewai.telemetry\")\n                span = tracer.start_span(\"Tool Usage Error\")\n                self._add_attribute(\n                    span, \"llm\", json.dumps(self._safe_llm_attributes(llm))\n                )\n                span.set_status(Status(StatusCode.OK))\n                span.end()\n            except Exception:\n                pass\n\n    def crew_execution_span(self, crew):\n        \"\"\"Records the complete execution of a crew.\n        This is only collected if the user has opted-in to share the crew.\n        \"\"\"\n        if (self.ready) and (crew.share_crew):\n            try:\n                tracer = trace.get_tracer(\"crewai.telemetry\")\n                span = tracer.start_span(\"Crew Execution\")\n                self._add_attribute(span, \"crew_id\", str(crew.id))\n                self._add_attribute(\n                    span,\n                    \"crew_agents\",\n                    json.dumps(\n                        [\n                            {\n                                \"id\": str(agent.id),\n                                \"role\": agent.role,\n                                \"goal\": agent.goal,\n                                \"backstory\": agent.backstory,\n                                \"memory_enabled?\": agent.memory,\n                                \"verbose?\": agent.verbose,\n                                \"max_iter\": agent.max_iter,\n                                \"max_rpm\": agent.max_rpm,\n                                \"i18n\": agent.i18n.language,\n                                \"llm\": json.dumps(self._safe_llm_attributes(agent.llm)),\n                                \"delegation_enabled?\": agent.allow_delegation,\n                                \"tools_names\": [tool.name for tool in agent.tools],\n                            }\n                            for agent in crew.agents\n                        ]\n                    ),\n                )\n                self._add_attribute(\n                    span,\n                    \"crew_tasks\",\n                    json.dumps(\n                        [\n                            {\n                                \"id\": str(task.id),\n                                \"description\": task.description,\n                                \"async_execution?\": task.async_execution,\n                                \"output\": task.expected_output,\n                                \"agent_role\": task.agent.role if task.agent else \"None\",\n                                \"context\": [task.description for task in task.context]\n                                if task.context\n                                else \"None\",\n                                \"tools_names\": [tool.name for tool in task.tools],\n                            }\n                            for task in crew.tasks\n                        ]\n                    ),\n                )\n                return span\n            except Exception:\n                pass\n\n    def end_crew(self, crew, output):\n        if (self.ready) and (crew.share_crew):\n            try:\n                self._add_attribute(crew._execution_span, \"crew_output\", output)\n                self._add_attribute(\n                    crew._execution_span,\n                    \"crew_tasks_output\",\n                    json.dumps(\n                        [\n                            {\n                                \"id\": str(task.id),\n                                \"description\": task.description,\n                                \"output\": task.output.raw_output,\n                            }\n                            for task in crew.tasks\n                        ]\n                    ),\n                )\n                crew._execution_span.set_status(Status(StatusCode.OK))\n                crew._execution_span.end()\n            except Exception:\n                pass\n\n    def _add_attribute(self, span, key, value):\n        \"\"\"Add an attribute to a span.\"\"\"\n        try:\n            return span.set_attribute(key, value)\n        except Exception:\n            pass\n\n    def _safe_llm_attributes(self, llm):\n        attributes = [\"name\", \"model_name\", \"base_url\", \"model\", \"top_k\", \"temperature\"]\n        safe_attributes = {k: v for k, v in vars(llm).items() if k in attributes}\n        safe_attributes[\"class\"] = llm.__class__.__name__\n        return safe_attributes\n",
        "__init__.py": "from .telemetry import Telemetry\n",
        "__pycache__": {}
    },
    "tools": {
        "agent_tools.py": "from typing import List\n\nfrom langchain.tools import StructuredTool\nfrom pydantic import BaseModel, Field\n\nfrom crewai.agent import Agent\nfrom crewai.task import Task\nfrom crewai.utilities import I18N\n\n\nclass AgentTools(BaseModel):\n    \"\"\"Default tools around agent delegation\"\"\"\n\n    agents: List[Agent] = Field(description=\"List of agents in this crew.\")\n    i18n: I18N = Field(default=I18N(), description=\"Internationalization settings.\")\n\n    def tools(self):\n        return [\n            StructuredTool.from_function(\n                func=self.delegate_work,\n                name=\"Delegate work to co-worker\",\n                description=self.i18n.tools(\"delegate_work\").format(\n                    coworkers=[f\"{agent.role}\" for agent in self.agents]\n                ),\n            ),\n            StructuredTool.from_function(\n                func=self.ask_question,\n                name=\"Ask question to co-worker\",\n                description=self.i18n.tools(\"ask_question\").format(\n                    coworkers=[f\"{agent.role}\" for agent in self.agents]\n                ),\n            ),\n        ]\n\n    def delegate_work(self, coworker: str, task: str, context: str):\n        \"\"\"Useful to delegate a specific task to a coworker passing all necessary context and names.\"\"\"\n        return self._execute(coworker, task, context)\n\n    def ask_question(self, coworker: str, question: str, context: str):\n        \"\"\"Useful to ask a question, opinion or take from a coworker passing all necessary context and names.\"\"\"\n        return self._execute(coworker, question, context)\n\n    def _execute(self, agent, task, context):\n        \"\"\"Execute the command.\"\"\"\n        try:\n            agent = [\n                available_agent\n                for available_agent in self.agents\n                if available_agent.role.strip().lower() == agent.strip().lower()\n            ]\n        except:\n            return self.i18n.errors(\"agent_tool_unexsiting_coworker\").format(\n                coworkers=\"\\n\".join([f\"- {agent.role}\" for agent in self.agents])\n            )\n\n        if not agent:\n            return self.i18n.errors(\"agent_tool_unexsiting_coworker\").format(\n                coworkers=\"\\n\".join([f\"- {agent.role}\" for agent in self.agents])\n            )\n\n        agent = agent[0]\n        task = Task(\n            description=task,\n            agent=agent,\n            expected_output=\"Your best answer to your coworker asking you this, accounting for the context shared.\",\n        )\n        return agent.execute_task(task, context)\n",
        "cache_tools.py": "from langchain.tools import StructuredTool\nfrom pydantic import BaseModel, ConfigDict, Field\n\nfrom crewai.agents.cache import CacheHandler\n\n\nclass CacheTools(BaseModel):\n    \"\"\"Default tools to hit the cache.\"\"\"\n\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    name: str = \"Hit Cache\"\n    cache_handler: CacheHandler = Field(\n        description=\"Cache Handler for the crew\",\n        default=CacheHandler(),\n    )\n\n    def tool(self):\n        return StructuredTool.from_function(\n            func=self.hit_cache,\n            name=self.name,\n            description=\"Reads directly from the cache\",\n        )\n\n    def hit_cache(self, key):\n        split = key.split(\"tool:\")\n        tool = split[1].split(\"|input:\")[0].strip()\n        tool_input = split[1].split(\"|input:\")[1].strip()\n        return self.cache_handler.read(tool, tool_input)\n",
        "tool_calling.py": "from typing import Any, Dict, Optional\n\nfrom pydantic import BaseModel as PydanticBaseModel\nfrom pydantic import Field as PydanticField\nfrom pydantic.v1 import BaseModel, Field\n\n\nclass ToolCalling(BaseModel):\n    tool_name: str = Field(..., description=\"The name of the tool to be called.\")\n    arguments: Optional[Dict[str, Any]] = Field(\n        ..., description=\"A dictinary of arguments to be passed to the tool.\"\n    )\n\n\nclass InstructorToolCalling(PydanticBaseModel):\n    tool_name: str = PydanticField(\n        ..., description=\"The name of the tool to be called.\"\n    )\n    arguments: Optional[Dict[str, Any]] = PydanticField(\n        ..., description=\"A dictinary of arguments to be passed to the tool.\"\n    )\n",
        "tool_output_parser.py": "import json\nfrom typing import Any, List\n\nimport regex\nfrom langchain.output_parsers import PydanticOutputParser\nfrom langchain_core.exceptions import OutputParserException\nfrom langchain_core.outputs import Generation\nfrom langchain_core.pydantic_v1 import ValidationError\n\n\nclass ToolOutputParser(PydanticOutputParser):\n    \"\"\"Parses the function calling of a tool usage and it's arguments.\"\"\"\n\n    def parse_result(self, result: List[Generation], *, partial: bool = False) -> Any:\n        result[0].text = self._transform_in_valid_json(result[0].text)\n        json_object = super().parse_result(result)\n        try:\n            return self.pydantic_object.parse_obj(json_object)\n        except ValidationError as e:\n            name = self.pydantic_object.__name__\n            msg = f\"Failed to parse {name} from completion {json_object}. Got: {e}\"\n            raise OutputParserException(msg, llm_output=json_object)\n\n    def _transform_in_valid_json(self, text) -> str:\n        text = text.replace(\"```\", \"\").replace(\"json\", \"\")\n        json_pattern = r\"\\{(?:[^{}]|(?R))*\\}\"\n        matches = regex.finditer(json_pattern, text)\n\n        for match in matches:\n            try:\n                # Attempt to parse the matched string as JSON\n                json_obj = json.loads(match.group())\n                # Return the first successfully parsed JSON object\n                json_obj = json.dumps(json_obj)\n                return str(json_obj)\n            except json.JSONDecodeError:\n                # If parsing fails, skip to the next match\n                continue\n        return text\n",
        "tool_usage.py": "import ast\nfrom textwrap import dedent\nfrom typing import Any, List, Union\n\nfrom langchain_core.tools import BaseTool\nfrom langchain_openai import ChatOpenAI\n\nfrom crewai.agents.tools_handler import ToolsHandler\nfrom crewai.telemetry import Telemetry\nfrom crewai.tools.tool_calling import InstructorToolCalling, ToolCalling\nfrom crewai.utilities import I18N, Converter, ConverterError, Printer\n\nOPENAI_BIGGER_MODELS = [\"gpt-4\"]\n\n\nclass ToolUsageErrorException(Exception):\n    \"\"\"Exception raised for errors in the tool usage.\"\"\"\n\n    def __init__(self, message: str) -> None:\n        self.message = message\n        super().__init__(self.message)\n\n\nclass ToolUsage:\n    \"\"\"\n    Class that represents the usage of a tool by an agent.\n\n    Attributes:\n        task: Task being executed.\n        tools_handler: Tools handler that will manage the tool usage.\n        tools: List of tools available for the agent.\n        tools_description: Description of the tools available for the agent.\n        tools_names: Names of the tools available for the agent.\n        function_calling_llm: Language model to be used for the tool usage.\n    \"\"\"\n\n    def __init__(\n        self,\n        tools_handler: ToolsHandler,\n        tools: List[BaseTool],\n        tools_description: str,\n        tools_names: str,\n        task: Any,\n        function_calling_llm: Any,\n        action: Any,\n    ) -> None:\n        self._i18n: I18N = I18N()\n        self._printer: Printer = Printer()\n        self._telemetry: Telemetry = Telemetry()\n        self._run_attempts: int = 1\n        self._max_parsing_attempts: int = 3\n        self._remember_format_after_usages: int = 3\n        self.tools_description = tools_description\n        self.tools_names = tools_names\n        self.tools_handler = tools_handler\n        self.tools = tools\n        self.task = task\n        self.action = action\n        self.function_calling_llm = function_calling_llm\n\n        # Set the maximum parsing attempts for bigger models\n        if (isinstance(self.function_calling_llm, ChatOpenAI)) and (\n            self.function_calling_llm.openai_api_base == None\n        ):\n            if self.function_calling_llm.model_name in OPENAI_BIGGER_MODELS:\n                self._max_parsing_attempts = 2\n                self._remember_format_after_usages = 4\n\n    def parse(self, tool_string: str):\n        \"\"\"Parse the tool string and return the tool calling.\"\"\"\n        return self._tool_calling(tool_string)\n\n    def use(\n        self, calling: Union[ToolCalling, InstructorToolCalling], tool_string: str\n    ) -> str:\n        if isinstance(calling, ToolUsageErrorException):\n            error = calling.message\n            self._printer.print(content=f\"\\n\\n{error}\\n\", color=\"red\")\n            self.task.increment_tools_errors()\n            return error\n        try:\n            tool = self._select_tool(calling.tool_name)\n        except Exception as e:\n            error = getattr(e, \"message\", str(e))\n            self.task.increment_tools_errors()\n            self._printer.print(content=f\"\\n\\n{error}\\n\", color=\"red\")\n            return error\n        return f\"{self._use(tool_string=tool_string, tool=tool, calling=calling)}\"\n\n    def _use(\n        self,\n        tool_string: str,\n        tool: BaseTool,\n        calling: Union[ToolCalling, InstructorToolCalling],\n    ) -> None:\n        if self._check_tool_repeated_usage(calling=calling):\n            try:\n                result = self._i18n.errors(\"task_repeated_usage\").format(\n                    tool_names=self.tools_names\n                )\n                self._printer.print(content=f\"\\n\\n{result}\\n\", color=\"yellow\")\n                self._telemetry.tool_repeated_usage(\n                    llm=self.function_calling_llm,\n                    tool_name=tool.name,\n                    attempts=self._run_attempts,\n                )\n                result = self._format_result(result=result)\n                return result\n            except Exception:\n                self.task.increment_tools_errors()\n\n        result = self.tools_handler.cache.read(\n            tool=calling.tool_name, input=calling.arguments\n        )\n\n        if not result:\n            try:\n                if calling.tool_name in [\n                    \"Delegate work to co-worker\",\n                    \"Ask question to co-worker\",\n                ]:\n                    self.task.increment_delegations()\n\n                if calling.arguments:\n                    try:\n                        acceptable_args = tool.args_schema.schema()[\"properties\"].keys()\n                        arguments = {\n                            k: v\n                            for k, v in calling.arguments.items()\n                            if k in acceptable_args\n                        }\n                        result = tool._run(**arguments)\n                    except Exception:\n                        if tool.args_schema:\n                            arguments = calling.arguments\n                            result = tool._run(**arguments)\n                        else:\n                            arguments = calling.arguments.values()\n                            result = tool._run(*arguments)\n                else:\n                    result = tool._run()\n            except Exception as e:\n                self._run_attempts += 1\n                if self._run_attempts > self._max_parsing_attempts:\n                    self._telemetry.tool_usage_error(llm=self.function_calling_llm)\n                    error_message = self._i18n.errors(\"tool_usage_exception\").format(\n                        error=e, tool=tool.name, tool_inputs=tool.description\n                    )\n                    error = ToolUsageErrorException(\n                        f'\\n{error_message}.\\nMoving on then. {self._i18n.slice(\"format\").format(tool_names=self.tools_names)}'\n                    ).message\n                    self.task.increment_tools_errors()\n                    self._printer.print(content=f\"\\n\\n{error_message}\\n\", color=\"red\")\n                    return error\n                self.task.increment_tools_errors()\n                return self.use(calling=calling, tool_string=tool_string)\n\n            self.tools_handler.on_tool_use(calling=calling, output=result)\n\n        self._printer.print(content=f\"\\n\\n{result}\\n\", color=\"yellow\")\n        self._telemetry.tool_usage(\n            llm=self.function_calling_llm,\n            tool_name=tool.name,\n            attempts=self._run_attempts,\n        )\n        result = self._format_result(result=result)\n        return result\n\n    def _format_result(self, result: Any) -> None:\n        self.task.used_tools += 1\n        if self._should_remember_format():\n            result = self._remember_format(result=result)\n        return result\n\n    def _should_remember_format(self) -> None:\n        return self.task.used_tools % self._remember_format_after_usages == 0\n\n    def _remember_format(self, result: str) -> None:\n        result = str(result)\n        result += \"\\n\\n\" + self._i18n.slice(\"tools\").format(\n            tools=self.tools_description, tool_names=self.tools_names\n        )\n        return result\n\n    def _check_tool_repeated_usage(\n        self, calling: Union[ToolCalling, InstructorToolCalling]\n    ) -> None:\n        if last_tool_usage := self.tools_handler.last_used_tool:\n            return (calling.tool_name == last_tool_usage.tool_name) and (\n                calling.arguments == last_tool_usage.arguments\n            )\n\n    def _select_tool(self, tool_name: str) -> BaseTool:\n        for tool in self.tools:\n            if tool.name.lower().strip() == tool_name.lower().strip():\n                return tool\n        self.task.increment_tools_errors()\n        if tool_name and tool_name != \"\":\n            raise Exception(\n                f\"Action '{tool_name}' don't exist, these are the only available Actions: {self.tools_description}\"\n            )\n        else:\n            raise Exception(\n                f\"I forgot the Action name, these are the only available Actions: {self.tools_description}\"\n            )\n\n    def _render(self) -> str:\n        \"\"\"Render the tool name and description in plain text.\"\"\"\n        descriptions = []\n        for tool in self.tools:\n            args = {\n                k: {k2: v2 for k2, v2 in v.items() if k2 in [\"description\", \"type\"]}\n                for k, v in tool.args.items()\n            }\n            descriptions.append(\n                \"\\n\".join(\n                    [\n                        f\"Tool Name: {tool.name.lower()}\",\n                        f\"Tool Description: {tool.description}\",\n                        f\"Tool Arguments: {args}\",\n                    ]\n                )\n            )\n        return \"\\n--\\n\".join(descriptions)\n\n    def _is_gpt(self, llm) -> bool:\n        return isinstance(llm, ChatOpenAI) and llm.openai_api_base == None\n\n    def _tool_calling(\n        self, tool_string: str\n    ) -> Union[ToolCalling, InstructorToolCalling]:\n        try:\n            if self.function_calling_llm:\n                model = (\n                    InstructorToolCalling\n                    if self._is_gpt(self.function_calling_llm)\n                    else ToolCalling\n                )\n                converter = Converter(\n                    text=f\"Only tools available:\\n###\\n{self._render()}\\n\\nReturn a valid schema for the tool, the tool name must be exactly equal one of the options, use this text to inform the valid ouput schema:\\n\\n{tool_string}```\",\n                    llm=self.function_calling_llm,\n                    model=model,\n                    instructions=dedent(\n                        \"\"\"\\\n                                            The schema should have the following structure, only two keys:\n                                            - tool_name: str\n                                            - arguments: dict (with all arguments being passed)\n\n                                            Example:\n                                            {\"tool_name\": \"tool name\", \"arguments\": {\"arg_name1\": \"value\", \"arg_name2\": 2}}\"\"\",\n                    ),\n                    max_attemps=1,\n                )\n                calling = converter.to_pydantic()\n\n                if isinstance(calling, ConverterError):\n                    raise calling\n            else:\n                tool_name = self.action.tool\n                tool = self._select_tool(tool_name)\n                try:\n                    arguments = ast.literal_eval(self.action.tool_input)\n                except Exception:\n                    return ToolUsageErrorException(\n                        f'{self._i18n.errors(\"tool_arguments_error\")}'\n                    )\n                if not isinstance(arguments, dict):\n                    return ToolUsageErrorException(\n                        f'{self._i18n.errors(\"tool_arguments_error\")}'\n                    )\n                calling = ToolCalling(\n                    tool_name=tool.name,\n                    arguments=arguments,\n                    log=tool_string,\n                )\n        except Exception as e:\n            self._run_attempts += 1\n            if self._run_attempts > self._max_parsing_attempts:\n                self._telemetry.tool_usage_error(llm=self.function_calling_llm)\n                self.task.increment_tools_errors()\n                self._printer.print(content=f\"\\n\\n{e}\\n\", color=\"red\")\n                return ToolUsageErrorException(\n                    f'{self._i18n.errors(\"tool_usage_error\").format(error=e)}\\nMoving on then. {self._i18n.slice(\"format\").format(tool_names=self.tools_names)}'\n                )\n            return self._tool_calling(tool_string)\n\n        return calling\n",
        "__init__.py": "",
        "__pycache__": {}
    },
    "translations": {
        "el.json": "{\n  \"hierarchical_manager_agent\": {\n    \"role\": \"\u0394\u03b9\u03b5\u03c5\u03b8\u03c5\u03bd\u03c4\u03ae\u03c2 \u039f\u03bc\u03ac\u03b4\u03b1\u03c2\",\n    \"goal\": \"\u0394\u03b9\u03b1\u03c7\u03b5\u03b9\u03c1\u03af\u03c3\u03bf\u03c5 \u03c4\u03b7\u03bd \u03bf\u03bc\u03ac\u03b4\u03b1 \u03c3\u03bf\u03c5 \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03c3\u03b5\u03b9 \u03c4\u03b7\u03bd \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1 \u03bc\u03b5 \u03c4\u03bf\u03bd \u03ba\u03b1\u03bb\u03cd\u03c4\u03b5\u03c1\u03bf \u03b4\u03c5\u03bd\u03b1\u03c4\u03cc \u03c4\u03c1\u03cc\u03c0\u03bf.\",\n    \"backstory\": \"\u0395\u03af\u03c3\u03b1\u03b9 \u03ad\u03bd\u03b1\u03c2 \u03ad\u03bc\u03c0\u03b5\u03b9\u03c1\u03bf\u03c2 \u03b4\u03b9\u03b5\u03c5\u03b8\u03c5\u03bd\u03c4\u03ae\u03c2 \u03bc\u03b5 \u03c4\u03b7\u03bd \u03b9\u03ba\u03b1\u03bd\u03cc\u03c4\u03b7\u03c4\u03b1 \u03bd\u03b1 \u03b2\u03b3\u03ac\u03b6\u03b5\u03b9\u03c2 \u03c4\u03bf \u03ba\u03b1\u03bb\u03cd\u03c4\u03b5\u03c1\u03bf \u03b1\u03c0\u03cc \u03c4\u03b7\u03bd \u03bf\u03bc\u03ac\u03b4\u03b1 \u03c3\u03bf\u03c5.\\n\u0395\u03af\u03c3\u03b1\u03b9 \u03b5\u03c0\u03af\u03c3\u03b7\u03c2 \u03b3\u03bd\u03c9\u03c3\u03c4\u03cc\u03c2 \u03b3\u03b9\u03b1 \u03c4\u03b7\u03bd \u03b9\u03ba\u03b1\u03bd\u03cc\u03c4\u03b7\u03c4\u03ac \u03c3\u03bf\u03c5 \u03bd\u03b1 \u03b1\u03bd\u03b1\u03b8\u03ad\u03c4\u03b5\u03b9\u03c2 \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b5\u03c2 \u03c3\u03c4\u03bf\u03c5\u03c2 \u03c3\u03c9\u03c3\u03c4\u03bf\u03cd\u03c2 \u03b1\u03bd\u03b8\u03c1\u03ce\u03c0\u03bf\u03c5\u03c2 \u03ba\u03b1\u03b9 \u03bd\u03b1 \u03ba\u03ac\u03bd\u03b5\u03b9\u03c2 \u03c4\u03b9\u03c2 \u03c3\u03c9\u03c3\u03c4\u03ad\u03c2 \u03b5\u03c1\u03c9\u03c4\u03ae\u03c3\u03b5\u03b9\u03c2 \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03c0\u03ac\u03c1\u03b5\u03b9\u03c2 \u03c4\u03bf \u03ba\u03b1\u03bb\u03cd\u03c4\u03b5\u03c1\u03bf \u03b1\u03c0\u03cc \u03c4\u03b7\u03bd \u03bf\u03bc\u03ac\u03b4\u03b1 \u03c3\u03bf\u03c5.\\n\u0391\u03ba\u03cc\u03bc\u03b1 \u03ba\u03b9 \u03b1\u03bd \u03b4\u03b5\u03bd \u03b5\u03ba\u03c4\u03b5\u03bb\u03b5\u03af\u03c2 \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b5\u03c2 \u03bc\u03cc\u03bd\u03bf\u03c2 \u03c3\u03bf\u03c5, \u03ad\u03c7\u03b5\u03b9\u03c2 \u03c0\u03bf\u03bb\u03bb\u03ae \u03b5\u03bc\u03c0\u03b5\u03b9\u03c1\u03af\u03b1 \u03c3\u03c4\u03bf\u03bd \u03c4\u03bf\u03bc\u03ad\u03b1, \u03c0\u03bf\u03c5 \u03c3\u03bf\u03c5 \u03b5\u03c0\u03b9\u03c4\u03c1\u03ad\u03c0\u03b5\u03b9 \u03bd\u03b1 \u03b1\u03be\u03b9\u03bf\u03bb\u03bf\u03b3\u03b5\u03af\u03c2 \u03c3\u03c9\u03c3\u03c4\u03ac \u03c4\u03b7 \u03b4\u03bf\u03c5\u03bb\u03b5\u03b9\u03ac \u03c4\u03c9\u03bd \u03bc\u03b5\u03bb\u03ce\u03bd \u03c4\u03b7\u03c2 \u03bf\u03bc\u03ac\u03b4\u03b1\u03c2 \u03c3\u03bf\u03c5.\"\n  },\n  \"slices\": {\n    \"observation\": \"\\n\u03a0\u03b1\u03c1\u03b1\u03c4\u03ae\u03c1\u03b7\u03c3\u03b7\",\n    \"task\": \"\u0391\u03c1\u03c7\u03ae! \u0391\u03c5\u03c4\u03cc \u03b5\u03af\u03bd\u03b1\u03b9 \u03a0\u039f\u039b\u03a5 \u03c3\u03b7\u03bc\u03b1\u03bd\u03c4\u03b9\u03ba\u03cc \u03b3\u03b9\u03b1 \u03b5\u03c3\u03ac\u03c2, \u03b7 \u03b4\u03bf\u03c5\u03bb\u03b5\u03b9\u03ac \u03c3\u03b1\u03c2 \u03b5\u03be\u03b1\u03c1\u03c4\u03ac\u03c4\u03b1\u03b9 \u03b1\u03c0\u03cc \u03b1\u03c5\u03c4\u03cc!\\n\\n\u03a4\u03c1\u03ad\u03c7\u03bf\u03c5\u03c3\u03b1 \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1: {input}\",\n    \"memory\": \"\u0391\u03c5\u03c4\u03ae \u03b5\u03af\u03bd\u03b1\u03b9 \u03b7 \u03c0\u03b5\u03c1\u03af\u03bb\u03b7\u03c8\u03b7 \u03c4\u03b7\u03c2 \u03bc\u03ad\u03c7\u03c1\u03b9 \u03c4\u03ce\u03c1\u03b1 \u03b4\u03bf\u03c5\u03bb\u03b5\u03b9\u03ac\u03c2 \u03c3\u03b1\u03c2:\\n{chat_history}\",\n    \"role_playing\": \"\u0395\u03af\u03c3\u03b1\u03b9 {role}.\\n{backstory}\\n\\n\u039f \u03c0\u03c1\u03bf\u03c3\u03c9\u03c0\u03b9\u03ba\u03cc\u03c2 \u03c3\u03b1\u03c2 \u03c3\u03c4\u03cc\u03c7\u03bf\u03c2 \u03b5\u03af\u03bd\u03b1\u03b9: {goal}\",\n    \"tools\": \"\u0395\u03a1\u0393\u0391\u039b\u0395\u0399\u0391:\\n------\\n\u0388\u03c7\u03b5\u03c4\u03b5 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03bc\u03cc\u03bd\u03bf \u03c3\u03c4\u03b1 \u03b1\u03ba\u03cc\u03bb\u03bf\u03c5\u03b8\u03b1 \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03b1:\\n\\n{tools}\\n\\n\u0393\u03b9\u03b1 \u03bd\u03b1 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 \u03ad\u03bd\u03b1 \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf, \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03c4\u03b5 \u03c4\u03b7\u03bd \u03b1\u03ba\u03cc\u03bb\u03bf\u03c5\u03b8\u03b7 \u03b1\u03ba\u03c1\u03b9\u03b2\u03ce\u03c2 \u03bc\u03bf\u03c1\u03c6\u03ae:\\n\\n```\\nThought: \u03a7\u03c1\u03b5\u03b9\u03ac\u03b6\u03b5\u03c4\u03b1\u03b9 \u03bd\u03b1 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03c9 \u03ba\u03ac\u03c0\u03bf\u03b9\u03bf \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf; \u039d\u03b1\u03b9\\n\u0395\u03bd\u03ad\u03c1\u03b3\u03b5\u03b9\u03b1: \u03c4\u03bf \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf \u03c0\u03bf\u03c5 \u03b8\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5, \u03b8\u03b1 \u03c0\u03c1\u03ad\u03c0\u03b5\u03b9 \u03bd\u03b1 \u03b5\u03af\u03bd\u03b1\u03b9 \u03ad\u03bd\u03b1 \u03b1\u03c0\u03cc \u03c4\u03b1 [{tool_names}], \u03bc\u03cc\u03bd\u03bf \u03c4\u03bf \u03cc\u03bd\u03bf\u03bc\u03b1.\\n\u0395\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae \u03b5\u03bd\u03ad\u03c1\u03b3\u03b5\u03b9\u03b1\u03c2: \u039f\u03c0\u03bf\u03b9\u03b1\u03b4\u03ae\u03c0\u03bf\u03c4\u03b5 \u03ba\u03b1\u03b9 \u03cc\u03bb\u03b5\u03c2 \u03bf\u03b9 \u03c3\u03c7\u03b5\u03c4\u03b9\u03ba\u03ad\u03c2 \u03c0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 \u03ba\u03b1\u03b9 \u03c4\u03bf \u03c0\u03bb\u03b1\u03af\u03c3\u03b9\u03bf \u03c7\u03c1\u03ae\u03c3\u03b7\u03c2 \u03c4\u03bf\u03c5 \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf\u03c5\\n\u03a0\u03b1\u03c1\u03b1\u03c4\u03ae\u03c1\u03b7\u03c3\u03b7: \u03c4\u03bf \u03b1\u03c0\u03bf\u03c4\u03ad\u03bb\u03b5\u03c3\u03bc\u03b1 \u03c4\u03b7\u03c2 \u03c7\u03c1\u03ae\u03c3\u03b7\u03c2 \u03c4\u03bf\u03c5 \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf\u03c5\\n```\\n\\n\u038c\u03c4\u03b1\u03bd \u03ad\u03c7\u03b5\u03c4\u03b5 \u03bc\u03b9\u03b1 \u03b1\u03c0\u03ac\u03bd\u03c4\u03b7\u03c3\u03b7 \u03b3\u03b9\u03b1 \u03c4\u03b7\u03bd \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1 \u03c3\u03b1\u03c2 \u03ae \u03b5\u03ac\u03bd \u03b4\u03b5\u03bd \u03c7\u03c1\u03b5\u03b9\u03ac\u03b6\u03b5\u03c4\u03b1\u03b9 \u03bd\u03b1 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 \u03ad\u03bd\u03b1 \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf, \u03a0\u03a1\u0395\u03a0\u0395\u0399 \u03bd\u03b1 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 \u03c4\u03b7 \u03bc\u03bf\u03c1\u03c6\u03ae:\\n\\n```\\n\u03a3\u03ba\u03ad\u03c8\u03b7: \u03a0\u03c1\u03ad\u03c0\u03b5\u03b9 \u03bd\u03b1 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03c9 \u03ad\u03bd\u03b1 \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf ? \u038c\u03c7\u03b9\\n\u03a4\u03b5\u03bb\u03b9\u03ba\u03ae \u03b1\u03c0\u03ac\u03bd\u03c4\u03b7\u03c3\u03b7: [\u03b7 \u03b1\u03c0\u03ac\u03bd\u03c4\u03b7\u03c3\u03ae \u03c3\u03b1\u03c2 \u03b5\u03b4\u03ce]```\",\n    \"task_with_context\": \"{task}\\n\u0391\u03c5\u03c4\u03cc \u03b5\u03af\u03bd\u03b1\u03b9 \u03c4\u03bf \u03c0\u03bb\u03b1\u03af\u03c3\u03b9\u03bf \u03bc\u03b5 \u03c4\u03bf \u03bf\u03c0\u03bf\u03af\u03bf \u03b5\u03c1\u03b3\u03ac\u03b6\u03b5\u03c3\u03c4\u03b5:\\n{context}\",\n    \"expected_output\": \"\u0397 \u03c4\u03b5\u03bb\u03b9\u03ba\u03ae \u03c3\u03b1\u03c2 \u03b1\u03c0\u03ac\u03bd\u03c4\u03b7\u03c3\u03b7 \u03c0\u03c1\u03ad\u03c0\u03b5\u03b9 \u03bd\u03b1 \u03b5\u03af\u03bd\u03b1\u03b9: {expected_output}\"\n  },\n  \"errors\": {\n    \"force_final_answer\": \"\u03a3\u03c4\u03b7\u03bd \u03c0\u03c1\u03b1\u03b3\u03bc\u03b1\u03c4\u03b9\u03ba\u03cc\u03c4\u03b7\u03c4\u03b1, \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b1 \u03c0\u03ac\u03c1\u03b1 \u03c0\u03bf\u03bb\u03bb\u03ac \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03b1, \u03bf\u03c0\u03cc\u03c4\u03b5 \u03b8\u03b1 \u03c3\u03c4\u03b1\u03bc\u03b1\u03c4\u03ae\u03c3\u03c9 \u03c4\u03ce\u03c1\u03b1 \u03ba\u03b1\u03b9 \u03b8\u03b1 \u03c3\u03b1\u03c2 \u03b4\u03ce\u03c3\u03c9 \u03c4\u03b7\u03bd \u03b1\u03c0\u03cc\u03bb\u03c5\u03c4\u03b7 \u039a\u0391\u039b\u03a5\u03a4\u0395\u03a1\u0397 \u03c4\u03b5\u03bb\u03b9\u03ba\u03ae \u03bc\u03bf\u03c5 \u03b1\u03c0\u03ac\u03bd\u03c4\u03b7\u03c3\u03b7 \u03a4\u03a9\u03a1\u0391, \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ce\u03bd\u03c4\u03b1\u03c2 \u03c4\u03b7\u03bd \u03b1\u03bd\u03b1\u03bc\u03b5\u03bd\u03cc\u03bc\u03b5\u03bd\u03b7 \u03bc\u03bf\u03c1\u03c6\u03ae: ```\\n\u03a3\u03ba\u03ad\u03c6\u03c4\u03b7\u03ba\u03b1: \u03a7\u03c1\u03b5\u03b9\u03ac\u03b6\u03b5\u03c4\u03b1\u03b9 \u03bd\u03b1 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03c9 \u03ad\u03bd\u03b1 \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf; \u038c\u03c7\u03b9\\n\u03a4\u03b5\u03bb\u03b9\u03ba\u03ae \u03b1\u03c0\u03ac\u03bd\u03c4\u03b7\u03c3\u03b7: [\u03b7 \u03b1\u03c0\u03ac\u03bd\u03c4\u03b7\u03c3\u03ae \u03c3\u03b1\u03c2 \u03b5\u03b4\u03ce]```\",\n    \"agent_tool_unexsiting_coworker\": \"\\n\u03a3\u03c6\u03ac\u03bb\u03bc\u03b1 \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7\u03bd \u03b5\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b7 \u03c4\u03bf\u03c5 \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf\u03c5. \u039f \u03c3\u03c5\u03bd\u03ac\u03b4\u03b5\u03bb\u03c6\u03bf\u03c2 \u03c0\u03bf\u03c5 \u03b1\u03bd\u03b1\u03c6\u03ad\u03c1\u03b5\u03c4\u03b1\u03b9 \u03c3\u03c4\u03bf Action Input \u03b4\u03b5\u03bd \u03b2\u03c1\u03ad\u03b8\u03b7\u03ba\u03b5, \u03c0\u03c1\u03ad\u03c0\u03b5\u03b9 \u03bd\u03b1 \u03b5\u03af\u03bd\u03b1\u03b9 \u03bc\u03af\u03b1 \u03b1\u03c0\u03cc \u03c4\u03b9\u03c2 \u03b1\u03ba\u03cc\u03bb\u03bf\u03c5\u03b8\u03b5\u03c2 \u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ad\u03c2:\\n{coworkers}..\\n\",\n    \"task_repeated_usage\": \"\u039c\u03cc\u03bb\u03b9\u03c2 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b1 \u03c4\u03bf \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf {tool} \u03bc\u03b5 \u03b5\u03af\u03c3\u03bf\u03b4\u03bf {tool_input}. \u0386\u03c1\u03b1 \u03c4\u03bf \u03be\u03ad\u03c1\u03c9 \u03ae\u03b4\u03b7 \u03ba\u03b1\u03b9 \u03c0\u03c1\u03ad\u03c0\u03b5\u03b9 \u03bd\u03b1 \u03c3\u03c4\u03b1\u03bc\u03b1\u03c4\u03ae\u03c3\u03c9 \u03bd\u03b1 \u03c4\u03bf \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ce \u03c3\u03c4\u03b7 \u03c3\u03b5\u03b9\u03c1\u03ac \u03bc\u03b5 \u03c4\u03b7\u03bd \u03af\u03b4\u03b9\u03b1 \u03b5\u03af\u03c3\u03bf\u03b4\u03bf. \\n\u0398\u03b1 \u03bc\u03c0\u03bf\u03c1\u03bf\u03cd\u03c3\u03b1 \u03bd\u03b1 \u03b4\u03ce\u03c3\u03c9 \u03c4\u03b7\u03bd \u03c4\u03b5\u03bb\u03b9\u03ba\u03ae \u03bc\u03bf\u03c5 \u03b1\u03c0\u03ac\u03bd\u03c4\u03b7\u03c3\u03b7 \u03b5\u03ac\u03bd \u03b5\u03af\u03bc\u03b1\u03b9 \u03ad\u03c4\u03bf\u03b9\u03bc\u03bf\u03c2, \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ce\u03bd\u03c4\u03b1\u03c2 \u03b1\u03ba\u03c1\u03b9\u03b2\u03ce\u03c2 \u03c4\u03b7\u03bd \u03b1\u03bd\u03b1\u03bc\u03b5\u03bd\u03cc\u03bc\u03b5\u03bd\u03b7 \u03bc\u03bf\u03c1\u03c6\u03ae \u03c0\u03b1\u03c1\u03b1\u03ba\u03ac\u03c4\u03c9: \\n\\n\u03a3\u03ba\u03ad\u03c6\u03c4\u03b7\u03ba\u03b1: \u03a7\u03c1\u03b5\u03b9\u03ac\u03b6\u03b5\u03c4\u03b1\u03b9 \u03bd\u03b1 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03c9 \u03ba\u03ac\u03c0\u03bf\u03b9\u03bf \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf; \u038c\u03c7\u03b9\\n\u03a4\u03b5\u03bb\u03b9\u03ba\u03ae \u03b1\u03c0\u03ac\u03bd\u03c4\u03b7\u03c3\u03b7: [\u03b7 \u03b1\u03c0\u03ac\u03bd\u03c4\u03b7\u03c3\u03ae \u03c3\u03b1\u03c2 \u03b5\u03b4\u03ce]\\n\",\n    \"tool_usage_error\": \"\u03a6\u03b1\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03cc\u03c4\u03b9 \u03b1\u03bd\u03c4\u03b9\u03bc\u03b5\u03c4\u03c9\u03c0\u03af\u03c3\u03b1\u03bc\u03b5 \u03ad\u03bd\u03b1 \u03b1\u03c0\u03c1\u03bf\u03c3\u03b4\u03cc\u03ba\u03b7\u03c4\u03bf \u03c3\u03c6\u03ac\u03bb\u03bc\u03b1 \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7\u03bd \u03c0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b5\u03b9\u03b1 \u03c7\u03c1\u03ae\u03c3\u03b7\u03c2 \u03c4\u03bf\u03c5 \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf\u03c5.\",\n    \"tool_usage_exception\": \"\u03a6\u03b1\u03af\u03bd\u03b5\u03c4\u03b1\u03b9 \u03cc\u03c4\u03b9 \u03b1\u03bd\u03c4\u03b9\u03bc\u03b5\u03c4\u03c9\u03c0\u03af\u03c3\u03b1\u03bc\u03b5 \u03ad\u03bd\u03b1 \u03b1\u03c0\u03c1\u03bf\u03c3\u03b4\u03cc\u03ba\u03b7\u03c4\u03bf \u03c3\u03c6\u03ac\u03bb\u03bc\u03b1 \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7\u03bd \u03c0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b5\u03b9\u03b1 \u03c7\u03c1\u03ae\u03c3\u03b7\u03c2 \u03c4\u03bf\u03c5 \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf\u03c5. \u0391\u03c5\u03c4\u03cc \u03ae\u03c4\u03b1\u03bd \u03c4\u03bf \u03c3\u03c6\u03ac\u03bb\u03bc\u03b1: {error}\"\n  },\n  \"tools\": {\n    \"delegate_work\": \"\u0391\u03bd\u03b1\u03b8\u03ad\u03c3\u03c4\u03b5 \u03bc\u03b9\u03b1 \u03c3\u03c5\u03b3\u03ba\u03b5\u03ba\u03c1\u03b9\u03bc\u03ad\u03bd\u03b7 \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1 \u03c3\u03b5 \u03ad\u03bd\u03b1\u03bd \u03b1\u03c0\u03cc \u03c4\u03bf\u03c5\u03c2 \u03c0\u03b1\u03c1\u03b1\u03ba\u03ac\u03c4\u03c9 \u03c3\u03c5\u03bd\u03b1\u03b4\u03ad\u03bb\u03c6\u03bf\u03c5\u03c2:\\n{coworkers}.\\n\u0397 \u03b5\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae \u03c3\u03b5 \u03b1\u03c5\u03c4\u03cc \u03c4\u03bf \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf \u03b8\u03b1 \u03c0\u03c1\u03ad\u03c0\u03b5\u03b9 \u03bd\u03b1 \u03b5\u03af\u03bd\u03b1\u03b9 \u03bf \u03c1\u03cc\u03bb\u03bf\u03c2 \u03c4\u03bf\u03c5 \u03c3\u03c5\u03bd\u03b1\u03b4\u03ad\u03bb\u03c6\u03bf\u03c5, \u03b7 \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1 \u03c0\u03bf\u03c5 \u03b8\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03ba\u03ac\u03bd\u03b5\u03b9 \u03ba\u03b1\u03b9 \u039f\u039b\u039f \u03c4\u03bf \u03b1\u03c0\u03b1\u03c1\u03b1\u03af\u03c4\u03b7\u03c4\u03bf \u03c0\u03bb\u03b1\u03af\u03c3\u03b9\u03bf \u03b3\u03b9\u03b1 \u03c4\u03b7\u03bd \u03b5\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b7 \u03c4\u03b7\u03c2 \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1\u03c2, \u03b4\u03b5\u03bd \u03b3\u03bd\u03c9\u03c1\u03af\u03b6\u03bf\u03c5\u03bd \u03c4\u03af\u03c0\u03bf\u03c4\u03b1 \u03b3\u03b9\u03b1 \u03c4\u03b7\u03bd \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1, \u03b3\u03b9' \u03b1\u03c5\u03c4\u03cc \u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03c4\u03b5\u03af\u03c4\u03b5 \u03b1\u03c0\u03bf\u03bb\u03cd\u03c4\u03c9\u03c2 \u03cc\u03bb\u03b1 \u03cc\u03c3\u03b1 \u03b3\u03bd\u03c9\u03c1\u03af\u03b6\u03b5\u03c4\u03b5, \u03bc\u03b7\u03bd \u03b1\u03bd\u03b1\u03c6\u03ad\u03c1\u03b5\u03c4\u03b5 \u03c0\u03c1\u03ac\u03b3\u03bc\u03b1\u03c4\u03b1, \u03b1\u03bb\u03bb\u03ac \u03b5\u03be\u03b7\u03b3\u03ae\u03c3\u03c4\u03b5 \u03c4\u03b1.\",\n    \"ask_question\": \"\u039a\u03ac\u03bd\u03c4\u03b5 \u03bc\u03b9\u03b1 \u03c3\u03c5\u03b3\u03ba\u03b5\u03ba\u03c1\u03b9\u03bc\u03ad\u03bd\u03b7 \u03b5\u03c1\u03ce\u03c4\u03b7\u03c3\u03b7 \u03c3\u03b5 \u03ad\u03bd\u03b1\u03bd \u03b1\u03c0\u03cc \u03c4\u03bf\u03c5\u03c2 \u03c0\u03b1\u03c1\u03b1\u03ba\u03ac\u03c4\u03c9 \u03c3\u03c5\u03bd\u03b1\u03b4\u03ad\u03bb\u03c6\u03bf\u03c5\u03c2:\\n{coworkers}.\\n\u0397 \u03b5\u03af\u03c3\u03bf\u03b4\u03bf\u03c2 \u03c3\u03b5 \u03b1\u03c5\u03c4\u03cc \u03c4\u03bf \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf \u03b8\u03b1 \u03c0\u03c1\u03ad\u03c0\u03b5\u03b9 \u03bd\u03b1 \u03b5\u03af\u03bd\u03b1\u03b9 \u03bf \u03c1\u03cc\u03bb\u03bf\u03c2 \u03c4\u03bf\u03c5 \u03c3\u03c5\u03bd\u03b1\u03b4\u03ad\u03bb\u03c6\u03bf\u03c5, \u03b7 \u03b5\u03c1\u03ce\u03c4\u03b7\u03c3\u03b7 \u03c0\u03bf\u03c5 \u03ad\u03c7\u03b5\u03c4\u03b5 \u03b3\u03b9\u03b1 \u03b1\u03c5\u03c4\u03cc\u03bd \u03ba\u03b1\u03b9 \u039f\u039b\u039f \u03c4\u03bf \u03b1\u03c0\u03b1\u03c1\u03b1\u03af\u03c4\u03b7\u03c4\u03bf \u03c0\u03bb\u03b1\u03af\u03c3\u03b9\u03bf \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03ba\u03ac\u03bd\u03b5\u03c4\u03b5 \u03c3\u03c9\u03c3\u03c4\u03ac \u03c4\u03b7\u03bd \u03b5\u03c1\u03ce\u03c4\u03b7\u03c3\u03b7, \u03b4\u03b5\u03bd \u03b3\u03bd\u03c9\u03c1\u03af\u03b6\u03bf\u03c5\u03bd \u03c4\u03af\u03c0\u03bf\u03c4\u03b1 \u03b3\u03b9\u03b1 \u03c4\u03b7\u03bd \u03b5\u03c1\u03ce\u03c4\u03b7\u03c3\u03b7, \u03b3\u03b9' \u03b1\u03c5\u03c4\u03cc \u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03c4\u03b5\u03af\u03c4\u03b5 \u03b1\u03c0\u03bf\u03bb\u03cd\u03c4\u03c9\u03c2 \u03cc\u03bb\u03b1 \u03cc\u03c3\u03b1 \u03b3\u03bd\u03c9\u03c1\u03af\u03b6\u03b5\u03c4\u03b5, \u03bc\u03b7\u03bd \u03b1\u03bd\u03b1\u03c6\u03ad\u03c1\u03b5\u03c4\u03b5 \u03c0\u03c1\u03ac\u03b3\u03bc\u03b1\u03c4\u03b1, \u03b1\u03bb\u03bb\u03ac \u03b5\u03be\u03b7\u03b3\u03ae\u03c3\u03c4\u03b5 \u03c4\u03b1.\"\n  }\n}\n",
        "en.json": "{\n  \"hierarchical_manager_agent\": {\n    \"role\": \"Crew Manager\",\n    \"goal\": \"Manage the team to complete the task in the best way possible.\",\n    \"backstory\": \"You are a seasoned manager with a knack for getting the best out of your team.\\nYou are also known for your ability to delegate work to the right people, and to ask the right questions to get the best out of your team.\\nEven though you don't perform tasks by yourself, you have a lot of experience in the field, which allows you to properly evaluate the work of your team members.\"\n  },\n  \"slices\": {\n    \"observation\": \"\\nObservation\",\n    \"task\": \"\\n\\nCurrent Task: {input}\\n\\nBegin! This is VERY important to you, use the tools available and give your best Final Answer, your job depends on it!\\n\\nThought: \",\n    \"memory\": \"This is the summary of your work so far:\\n{chat_history}\",\n    \"role_playing\": \"You are {role}. {backstory}\\nYour personal goal is: {goal}\",\n    \"tools\": \"\\n\\nYou ONLY have access to the following tools, and should NEVER make up tools that are not listed here:\\n\\n{tools}\\n\\nUse the following format:\\n\\nThought: you should always think about what to do\\nAction: the action to take, only one name of [{tool_names}], just the name, exactly as it's written.\\nAction Input: the input to the action, just a simple a python dictionary using \\\" to wrap keys and values.\\nObservation: the result of the action\\n\\nOnce all necessary information is gathered:\\n\\nThought: I now know the final answer\\nFinal Answer: the final answer to the original input question\\n\",\n    \"no_tools\": \"To give my best complete final answer to the task use the exact following format:\\n\\nThought: I now can give a great answer\\nFinal Answer: my best complete final answer to the task.\\nYour final answer must be the great and the most complete as possible, it must be outcome described.\\n\\nI MUST use these formats, my job depends on it!\\n\\nThought: \",\n    \"format\": \"I MUST either use a tool (use one at time) OR give my best final answer. To Use the following format:\\n\\nThought: you should always think about what to do\\nAction: the action to take, should be one of [{tool_names}]\\nAction Input: the input to the action, dictionary\\nObservation: the result of the action\\n... (this Thought/Action/Action Input/Observation can repeat N times)\\nThought: I now can give a great answer\\nFinal Answer: my best complete final answer to the task.\\nYour final answer must be the great and the most complete as possible, it must be outcome described\\n\\n \",\n    \"final_answer_format\": \"If you don't need to use any more tools, you must give your best complete final answer, make sure it satisfy the expect criteria, use the EXACT format below:\\n\\nThought: I now can give a great answer\\nFinal Answer: my best complete final answer to the task.\\n\\n\",\n    \"format_without_tools\": \"\\nSorry, I didn't use the right format. I MUST either use a tool (among the available ones), OR give my best final answer.\\nI just remembered the expected format I must follow:\\n\\nQuestion: the input question you must answer\\nThought: you should always think about what to do\\nAction: the action to take, should be one of [{tool_names}]\\nAction Input: the input to the action\\nObservation: the result of the action\\n... (this Thought/Action/Action Input/Observation can repeat N times)\\nThought: I now can give a great answer\\nFinal Answer: my best complete final answer to the task\\nYour final answer must be the great and the most complete as possible, it must be outcome described\\n\\n\",\n    \"task_with_context\": \"{task}\\n\\nThis is the context you're working with:\\n{context}\",\n    \"expected_output\": \"\\nThis is the expect criteria for your final answer: {expected_output} \\n you MUST return the actual complete content as the final answer, not a summary.\"\n  },\n  \"errors\": {\n    \"unexpected_format\": \"\\nSorry, I didn't use the expected format, I MUST either use a tool (use one at time) OR give my best final answer.\\n\",\n    \"force_final_answer\": \"Tool won't be use because it's time to give your final answer. Don't use tools and just your absolute BEST Final answer.\",\n    \"agent_tool_unexsiting_coworker\": \"\\nError executing tool. Co-worker mentioned not found, it must to be one of the following options:\\n{coworkers}\\n\",\n    \"task_repeated_usage\": \"I tried reusing the same input, I must stop using this action input. I'll try something else instead.\\n\\n\",\n    \"tool_usage_error\": \"I encountered an error: {error}\",\n    \"tool_arguments_error\": \"Error: the Action Input is not a valid key, value dictionary.\",\n    \"wrong_tool_name\": \"You tried to use the tool {tool}, but it doesn't exist. You must use one of the following tools, use one at time: {tools}.\",\n    \"tool_usage_exception\": \"I encountered an error while trying to use the tool. This was the error: {error}.\\n Tool {tool} accepts these inputs: {tool_inputs}\"\n  },\n  \"tools\": {\n    \"delegate_work\": \"Delegate a specific task to one of the following co-workers: {coworkers}\\nThe input to this tool should be the coworker, the task you want them to do, and ALL necessary context to exectue the task, they know nothing about the task, so share absolute everything you know, don't reference things but instead explain them.\",\n    \"ask_question\": \"Ask a specific question to one of the following co-workers: {coworkers}\\nThe input to this tool should be the coworker, the question you have for them, and ALL necessary context to ask the question properly, they know nothing about the question, so share absolute everything you know, don't reference things but instead explain them.\"\n  }\n}\n"
    },
    "utilities": {
        "converter.py": "import json\nfrom typing import Any, Optional\n\nfrom langchain.schema import HumanMessage, SystemMessage\nfrom langchain_openai import ChatOpenAI\nfrom pydantic import BaseModel, Field, PrivateAttr, model_validator\n\n\nclass ConverterError(Exception):\n    \"\"\"Error raised when Converter fails to parse the input.\"\"\"\n\n    def __init__(self, message: str, *args: object) -> None:\n        super().__init__(message, *args)\n        self.message = message\n\n\nclass Converter(BaseModel):\n    \"\"\"Class that converts text into either pydantic or json.\"\"\"\n\n    _is_gpt: bool = PrivateAttr(default=True)\n    text: str = Field(description=\"Text to be converted.\")\n    llm: Any = Field(description=\"The language model to be used to convert the text.\")\n    model: Any = Field(description=\"The model to be used to convert the text.\")\n    instructions: str = Field(description=\"Conversion instructions to the LLM.\")\n    max_attemps: Optional[int] = Field(\n        description=\"Max number of attemps to try to get the output formated.\",\n        default=3,\n    )\n\n    @model_validator(mode=\"after\")\n    def check_llm_provider(self):\n        if not self._is_gpt(self.llm):\n            self._is_gpt = False\n\n    def to_pydantic(self, current_attempt=1):\n        \"\"\"Convert text to pydantic.\"\"\"\n        try:\n            if self._is_gpt:\n                return self._create_instructor().to_pydantic()\n            else:\n                return self._create_chain().invoke({})\n        except Exception as e:\n            if current_attempt < self.max_attemps:\n                return self.to_pydantic(current_attempt + 1)\n            return ConverterError(\n                f\"Failed to convert text into a pydantic model due to the following error: {e}\"\n            )\n\n    def to_json(self, current_attempt=1):\n        \"\"\"Convert text to json.\"\"\"\n        try:\n            if self._is_gpt:\n                return self._create_instructor().to_json()\n            else:\n                return json.dumps(self._create_chain().invoke({}).model_dump())\n        except Exception:\n            if current_attempt < self.max_attemps:\n                return self.to_json(current_attempt + 1)\n            return ConverterError(\"Failed to convert text into JSON.\")\n\n    def _create_instructor(self):\n        \"\"\"Create an instructor.\"\"\"\n        from crewai.utilities import Instructor\n\n        inst = Instructor(\n            llm=self.llm,\n            max_attemps=self.max_attemps,\n            model=self.model,\n            content=self.text,\n            instructions=self.instructions,\n        )\n        return inst\n\n    def _create_chain(self):\n        \"\"\"Create a chain.\"\"\"\n        from crewai.utilities.crew_pydantic_output_parser import (\n            CrewPydanticOutputParser,\n        )\n\n        parser = CrewPydanticOutputParser(pydantic_object=self.model)\n        new_prompt = SystemMessage(content=self.instructions) + HumanMessage(\n            content=self.text\n        )\n        return new_prompt | self.llm | parser\n\n    def _is_gpt(self, llm) -> bool:\n        return isinstance(llm, ChatOpenAI) and llm.openai_api_base == None\n",
        "crew_pydantic_output_parser.py": "import json\nfrom typing import Any, List, Type, Union\n\nimport regex\nfrom langchain.output_parsers import PydanticOutputParser\nfrom langchain_core.exceptions import OutputParserException\nfrom langchain_core.outputs import Generation\nfrom langchain_core.pydantic_v1 import ValidationError\nfrom pydantic import BaseModel\nfrom pydantic.v1 import BaseModel as V1BaseModel\n\n\nclass CrewPydanticOutputParser(PydanticOutputParser):\n    \"\"\"Parses the text into pydantic models\"\"\"\n\n    pydantic_object: Union[Type[BaseModel], Type[V1BaseModel]]\n\n    def parse_result(self, result: List[Generation], *, partial: bool = False) -> Any:\n        result[0].text = self._transform_in_valid_json(result[0].text)\n        json_object = super().parse_result(result)\n        try:\n            return self.pydantic_object.parse_obj(json_object)\n        except ValidationError as e:\n            name = self.pydantic_object.__name__\n            msg = f\"Failed to parse {name} from completion {json_object}. Got: {e}\"\n            raise OutputParserException(msg, llm_output=json_object)\n\n    def _transform_in_valid_json(self, text) -> str:\n        text = text.replace(\"```\", \"\").replace(\"json\", \"\")\n        json_pattern = r\"\\{(?:[^{}]|(?R))*\\}\"\n        matches = regex.finditer(json_pattern, text)\n\n        for match in matches:\n            try:\n                # Attempt to parse the matched string as JSON\n                json_obj = json.loads(match.group())\n                # Return the first successfully parsed JSON object\n                json_obj = json.dumps(json_obj)\n                return str(json_obj)\n            except json.JSONDecodeError:\n                # If parsing fails, skip to the next match\n                continue\n        return text\n",
        "i18n.py": "import json\nimport os\nfrom typing import Dict, Optional\n\nfrom pydantic import BaseModel, Field, PrivateAttr, ValidationError, model_validator\n\n\nclass I18N(BaseModel):\n    _translations: Dict[str, Dict[str, str]] = PrivateAttr()\n    language: Optional[str] = Field(\n        default=\"en\",\n        description=\"Language used to load translations\",\n    )\n\n    @model_validator(mode=\"after\")\n    def load_translation(self) -> \"I18N\":\n        \"\"\"Load translations from a JSON file based on the specified language.\"\"\"\n        try:\n            dir_path = os.path.dirname(os.path.realpath(__file__))\n            prompts_path = os.path.join(\n                dir_path, f\"../translations/{self.language}.json\"\n            )\n\n            with open(prompts_path, \"r\") as f:\n                self._translations = json.load(f)\n        except FileNotFoundError:\n            raise ValidationError(\n                f\"Translation file for language '{self.language}' not found.\"\n            )\n        except json.JSONDecodeError:\n            raise ValidationError(f\"Error decoding JSON from the prompts file.\")\n\n        if not self._translations:\n            self._translations = {}\n\n        return self\n\n    def slice(self, slice: str) -> str:\n        return self.retrieve(\"slices\", slice)\n\n    def errors(self, error: str) -> str:\n        return self.retrieve(\"errors\", error)\n\n    def tools(self, error: str) -> str:\n        return self.retrieve(\"tools\", error)\n\n    def retrieve(self, kind, key) -> str:\n        try:\n            return self._translations[kind][key]\n        except:\n            raise ValidationError(f\"Translation for '{kind}':'{key}'  not found.\")\n",
        "instructor.py": "from typing import Any, Optional, Type\n\nimport instructor\nfrom pydantic import BaseModel, Field, PrivateAttr, model_validator\n\n\nclass Instructor(BaseModel):\n    \"\"\"Class that wraps an agent llm with instructor.\"\"\"\n\n    _client: Any = PrivateAttr()\n    content: str = Field(description=\"Content to be sent to the instructor.\")\n    agent: Optional[Any] = Field(\n        description=\"The agent that needs to use instructor.\", default=None\n    )\n    llm: Optional[Any] = Field(\n        description=\"The agent that needs to use instructor.\", default=None\n    )\n    instructions: Optional[str] = Field(\n        description=\"Instructions to be sent to the instructor.\",\n        default=None,\n    )\n    model: Type[BaseModel] = Field(\n        description=\"Pydantic model to be used to create an output.\"\n    )\n\n    @model_validator(mode=\"after\")\n    def set_instructor(self):\n        \"\"\"Set instructor.\"\"\"\n        if self.agent and not self.llm:\n            self.llm = self.agent.function_calling_llm or self.agent.llm\n\n        self._client = instructor.patch(\n            self.llm.client._client,\n            mode=instructor.Mode.TOOLS,\n        )\n        return self\n\n    def to_json(self):\n        model = self.to_pydantic()\n        return model.model_dump_json(indent=2)\n\n    def to_pydantic(self):\n        messages = [{\"role\": \"user\", \"content\": self.content}]\n        if self.instructions:\n            messages.append({\"role\": \"system\", \"content\": self.instructions})\n\n        model = self._client.chat.completions.create(\n            model=self.llm.model_name, response_model=self.model, messages=messages\n        )\n        return model\n",
        "logger.py": "from crewai.utilities.printer import Printer\n\n\nclass Logger:\n    _printer = Printer()\n\n    def __init__(self, verbose_level=0):\n        verbose_level = (\n            2 if isinstance(verbose_level, bool) and verbose_level else verbose_level\n        )\n        self.verbose_level = verbose_level\n\n    def log(self, level, message, color=\"bold_green\"):\n        level_map = {\"debug\": 1, \"info\": 2}\n        if self.verbose_level and level_map.get(level, 0) <= self.verbose_level:\n            self._printer.print(f\"[{level.upper()}]: {message}\", color=color)\n",
        "printer.py": "class Printer:\n    def print(self, content: str, color: str):\n        if color == \"yellow\":\n            self._print_yellow(content)\n        elif color == \"red\":\n            self._print_red(content)\n        elif color == \"bold_green\":\n            self._print_bold_green(content)\n        elif color == \"bold_yellow\":\n            self._print_bold_yellow(content)\n        else:\n            print(content)\n\n    def _print_bold_yellow(self, content):\n        print(\"\\033[1m\\033[93m {}\\033[00m\".format(content))\n\n    def _print_bold_green(self, content):\n        print(\"\\033[1m\\033[92m {}\\033[00m\".format(content))\n\n    def _print_yellow(self, content):\n        print(\"\\033[93m {}\\033[00m\".format(content))\n\n    def _print_red(self, content):\n        print(\"\\033[91m {}\\033[00m\".format(content))\n",
        "prompts.py": "from typing import Any, ClassVar\n\nfrom langchain.prompts import BasePromptTemplate, PromptTemplate\nfrom pydantic import BaseModel, Field\n\nfrom crewai.utilities import I18N\n\n\nclass Prompts(BaseModel):\n    \"\"\"Manages and generates prompts for a generic agent with support for different languages.\"\"\"\n\n    i18n: I18N = Field(default=I18N())\n    tools: list[Any] = Field(default=[])\n    SCRATCHPAD_SLICE: ClassVar[str] = \"\\n{agent_scratchpad}\"\n\n    def task_execution_with_memory(self) -> BasePromptTemplate:\n        \"\"\"Generate a prompt for task execution with memory components.\"\"\"\n        slices = [\"role_playing\"]\n        if len(self.tools) > 0:\n            slices.append(\"tools\")\n        else:\n            slices.append(\"no_tools\")\n        slices.extend([\"memory\", \"task\"])\n        return self._build_prompt(slices)\n\n    def task_execution_without_tools(self) -> BasePromptTemplate:\n        \"\"\"Generate a prompt for task execution without tools components.\"\"\"\n        return self._build_prompt([\"role_playing\", \"task\"])\n\n    def task_execution(self) -> BasePromptTemplate:\n        \"\"\"Generate a standard prompt for task execution.\"\"\"\n        slices = [\"role_playing\"]\n        if len(self.tools) > 0:\n            slices.append(\"tools\")\n        else:\n            slices.append(\"no_tools\")\n        slices.append(\"task\")\n        return self._build_prompt(slices)\n\n    def _build_prompt(self, components: list[str]) -> BasePromptTemplate:\n        \"\"\"Constructs a prompt string from specified components.\"\"\"\n        prompt_parts = [self.i18n.slice(component) for component in components]\n        prompt_parts.append(self.SCRATCHPAD_SLICE)\n        prompt = PromptTemplate.from_template(\"\".join(prompt_parts))\n        return prompt\n",
        "pydantic_schema_parser.py": "from typing import Type, get_args, get_origin\n\nfrom pydantic import BaseModel\n\n\nclass PydanticSchemaParser(BaseModel):\n    model: Type[BaseModel]\n\n    def get_schema(self) -> str:\n        \"\"\"\n        Public method to get the schema of a Pydantic model.\n\n        :param model: The Pydantic model class to generate schema for.\n        :return: String representation of the model schema.\n        \"\"\"\n        return self._get_model_schema(self.model)\n\n    def _get_model_schema(self, model, depth=0) -> str:\n        lines = []\n        for field_name, field in model.model_fields.items():\n            field_type_str = self._get_field_type(field, depth + 1)\n            lines.append(f\"{' ' * 4 * depth}- {field_name}: {field_type_str}\")\n\n        return \"\\n\".join(lines)\n\n    def _get_field_type(self, field, depth) -> str:\n        field_type = field.annotation\n        if get_origin(field_type) is list:\n            list_item_type = get_args(field_type)[0]\n            if isinstance(list_item_type, type) and issubclass(\n                list_item_type, BaseModel\n            ):\n                nested_schema = self._get_model_schema(list_item_type, depth + 1)\n                return f\"List[\\n{nested_schema}\\n{' ' * 4 * depth}]\"\n            else:\n                return f\"List[{list_item_type.__name__}]\"\n        elif issubclass(field_type, BaseModel):\n            return f\"\\n{self._get_model_schema(field_type, depth)}\"\n        else:\n            return field_type.__name__\n",
        "rpm_controller.py": "import threading\nimport time\nfrom typing import Union\n\nfrom pydantic import BaseModel, ConfigDict, Field, PrivateAttr, model_validator\n\nfrom crewai.utilities.logger import Logger\n\n\nclass RPMController(BaseModel):\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    max_rpm: Union[int, None] = Field(default=None)\n    logger: Logger = Field(default=None)\n    _current_rpm: int = PrivateAttr(default=0)\n    _timer: threading.Timer | None = PrivateAttr(default=None)\n    _lock: threading.Lock = PrivateAttr(default=None)\n    _shutdown_flag = False\n\n    @model_validator(mode=\"after\")\n    def reset_counter(self):\n        if self.max_rpm:\n            if not self._shutdown_flag:\n                self._lock = threading.Lock()\n                self._reset_request_count()\n        return self\n\n    def check_or_wait(self):\n        if not self.max_rpm:\n            return True\n\n        with self._lock:\n            if self._current_rpm < self.max_rpm:\n                self._current_rpm += 1\n                return True\n            else:\n                self.logger.log(\n                    \"info\", \"Max RPM reached, waiting for next minute to start.\"\n                )\n                self._wait_for_next_minute()\n                self._current_rpm = 1\n                return True\n\n    def stop_rpm_counter(self):\n        if self._timer:\n            self._timer.cancel()\n            self._timer = None\n\n    def _wait_for_next_minute(self):\n        time.sleep(60)\n        self._current_rpm = 0\n\n    def _reset_request_count(self):\n        with self._lock:\n            self._current_rpm = 0\n        if self._timer:\n            self._shutdown_flag = True\n            self._timer.cancel()\n        self._timer = threading.Timer(60.0, self._reset_request_count)\n        self._timer.start()\n",
        "token_counter_callback.py": "from typing import Any, Dict, List\n\nimport tiktoken\nfrom langchain.callbacks.base import BaseCallbackHandler\nfrom langchain.schema import LLMResult\n\n\nclass TokenProcess:\n    total_tokens: int = 0\n    prompt_tokens: int = 0\n    completion_tokens: int = 0\n    successful_requests: int = 0\n\n    def sum_prompt_tokens(self, tokens: int):\n        self.prompt_tokens = self.prompt_tokens + tokens\n        self.total_tokens = self.total_tokens + tokens\n\n    def sum_completion_tokens(self, tokens: int):\n        self.completion_tokens = self.completion_tokens + tokens\n        self.total_tokens = self.total_tokens + tokens\n\n    def sum_successful_requests(self, requests: int):\n        self.successful_requests = self.successful_requests + requests\n\n    def get_summary(self) -> str:\n        return {\n            \"total_tokens\": self.total_tokens,\n            \"prompt_tokens\": self.prompt_tokens,\n            \"completion_tokens\": self.completion_tokens,\n            \"successful_requests\": self.successful_requests,\n        }\n\n\nclass TokenCalcHandler(BaseCallbackHandler):\n    model: str = \"\"\n    token_cost_process: TokenProcess\n\n    def __init__(self, model, token_cost_process):\n        self.model = model\n        self.token_cost_process = token_cost_process\n\n    def on_llm_start(\n        self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any\n    ) -> None:\n        if \"gpt\" in self.model:\n            encoding = tiktoken.encoding_for_model(self.model)\n        else:\n            encoding = tiktoken.get_encoding(\"cl100k_base\")\n\n        if self.token_cost_process == None:\n            return\n\n        for prompt in prompts:\n            self.token_cost_process.sum_prompt_tokens(len(encoding.encode(prompt)))\n\n    async def on_llm_new_token(self, token: str, **kwargs) -> None:\n        self.token_cost_process.sum_completion_tokens(1)\n\n    def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:\n        self.token_cost_process.sum_successful_requests(1)\n",
        "__init__.py": "from .converter import Converter, ConverterError\nfrom .i18n import I18N\nfrom .instructor import Instructor\nfrom .logger import Logger\nfrom .printer import Printer\nfrom .prompts import Prompts\nfrom .rpm_controller import RPMController\n",
        "__pycache__": {}
    },
    "__init__.py": "from crewai.agent import Agent\nfrom crewai.crew import Crew\nfrom crewai.process import Process\nfrom crewai.task import Task\n",
    "__pycache__": {}
}"""