mirror of
https://github.com/crewAIInc/crewAI.git
synced 2025-12-18 13:28:31 +00:00
Compare commits
12 Commits
bugfix/upd
...
feat/remov
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e748615c9c | ||
|
|
94176552f3 | ||
|
|
a737d4f27b | ||
|
|
4d67b2db8e | ||
|
|
44b9fc5058 | ||
|
|
65f0730d5a | ||
|
|
5195d9edce | ||
|
|
3b8ab25714 | ||
|
|
9c3843f925 | ||
|
|
6e492e90e4 | ||
|
|
aaec3e1713 | ||
|
|
1edff675eb |
@@ -19,6 +19,7 @@ from crewai.agents.agent_builder.utilities.base_token_process import TokenProces
|
|||||||
from crewai.agents.cache.cache_handler import CacheHandler
|
from crewai.agents.cache.cache_handler import CacheHandler
|
||||||
from crewai.agents.tools_handler import ToolsHandler
|
from crewai.agents.tools_handler import ToolsHandler
|
||||||
from crewai.tools import BaseTool
|
from crewai.tools import BaseTool
|
||||||
|
from crewai.tools.base_tool import Tool
|
||||||
from crewai.utilities import I18N, Logger, RPMController
|
from crewai.utilities import I18N, Logger, RPMController
|
||||||
from crewai.utilities.config import process_config
|
from crewai.utilities.config import process_config
|
||||||
|
|
||||||
@@ -106,7 +107,7 @@ class BaseAgent(ABC, BaseModel):
|
|||||||
default=False,
|
default=False,
|
||||||
description="Enable agent to delegate and ask questions among each other.",
|
description="Enable agent to delegate and ask questions among each other.",
|
||||||
)
|
)
|
||||||
tools: Optional[List[BaseTool]] = Field(
|
tools: Optional[List[Any]] = Field(
|
||||||
default_factory=list, description="Tools at agents' disposal"
|
default_factory=list, description="Tools at agents' disposal"
|
||||||
)
|
)
|
||||||
max_iter: Optional[int] = Field(
|
max_iter: Optional[int] = Field(
|
||||||
@@ -135,6 +136,35 @@ class BaseAgent(ABC, BaseModel):
|
|||||||
def process_model_config(cls, values):
|
def process_model_config(cls, values):
|
||||||
return process_config(values, cls)
|
return process_config(values, cls)
|
||||||
|
|
||||||
|
@field_validator("tools")
|
||||||
|
@classmethod
|
||||||
|
def validate_tools(cls, tools: List[Any]) -> List[BaseTool]:
|
||||||
|
"""Validate and process the tools provided to the agent.
|
||||||
|
|
||||||
|
This method ensures that each tool is either an instance of BaseTool
|
||||||
|
or an object with 'name', 'func', and 'description' attributes. If the
|
||||||
|
tool meets these criteria, it is processed and added to the list of
|
||||||
|
tools. Otherwise, a ValueError is raised.
|
||||||
|
"""
|
||||||
|
processed_tools = []
|
||||||
|
for tool in tools:
|
||||||
|
if isinstance(tool, BaseTool):
|
||||||
|
processed_tools.append(tool)
|
||||||
|
elif (
|
||||||
|
hasattr(tool, "name")
|
||||||
|
and hasattr(tool, "func")
|
||||||
|
and hasattr(tool, "description")
|
||||||
|
):
|
||||||
|
# Tool has the required attributes, create a Tool instance
|
||||||
|
processed_tools.append(Tool.from_langchain(tool))
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f"Invalid tool type: {type(tool)}. "
|
||||||
|
"Tool must be an instance of BaseTool or "
|
||||||
|
"an object with 'name', 'func', and 'description' attributes."
|
||||||
|
)
|
||||||
|
return processed_tools
|
||||||
|
|
||||||
@model_validator(mode="after")
|
@model_validator(mode="after")
|
||||||
def validate_and_set_attributes(self):
|
def validate_and_set_attributes(self):
|
||||||
# Validate required fields
|
# Validate required fields
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
from inspect import signature
|
||||||
from typing import Any, Callable, Type, get_args, get_origin
|
from typing import Any, Callable, Type, get_args, get_origin
|
||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field, validator
|
from pydantic import BaseModel, ConfigDict, Field, create_model, validator
|
||||||
from pydantic import BaseModel as PydanticBaseModel
|
from pydantic import BaseModel as PydanticBaseModel
|
||||||
|
|
||||||
from crewai.tools.structured_tool import CrewStructuredTool
|
from crewai.tools.structured_tool import CrewStructuredTool
|
||||||
@@ -75,17 +76,47 @@ class BaseTool(BaseModel, ABC):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_langchain(cls, tool: CrewStructuredTool) -> "BaseTool":
|
def from_langchain(cls, tool: Any) -> "BaseTool":
|
||||||
if cls == Tool:
|
"""Create a Tool instance from a CrewStructuredTool.
|
||||||
if tool.func is None:
|
|
||||||
raise ValueError("CrewStructuredTool must have a callable 'func'")
|
This method takes a CrewStructuredTool object and converts it into a
|
||||||
return Tool(
|
Tool instance. It ensures that the provided tool has a callable 'func'
|
||||||
name=tool.name,
|
attribute and infers the argument schema if not explicitly provided.
|
||||||
description=tool.description,
|
"""
|
||||||
args_schema=tool.args_schema,
|
if not hasattr(tool, "func") or not callable(tool.func):
|
||||||
func=tool.func,
|
raise ValueError("The provided tool must have a callable 'func' attribute.")
|
||||||
)
|
|
||||||
raise NotImplementedError(f"from_langchain not implemented for {cls.__name__}")
|
args_schema = getattr(tool, "args_schema", None)
|
||||||
|
|
||||||
|
if args_schema is None:
|
||||||
|
# Infer args_schema from the function signature if not provided
|
||||||
|
func_signature = signature(tool.func)
|
||||||
|
annotations = func_signature.parameters
|
||||||
|
args_fields = {}
|
||||||
|
for name, param in annotations.items():
|
||||||
|
if name != "self":
|
||||||
|
param_annotation = (
|
||||||
|
param.annotation if param.annotation != param.empty else Any
|
||||||
|
)
|
||||||
|
field_info = Field(
|
||||||
|
default=...,
|
||||||
|
description="",
|
||||||
|
)
|
||||||
|
args_fields[name] = (param_annotation, field_info)
|
||||||
|
if args_fields:
|
||||||
|
args_schema = create_model(f"{tool.name}Input", **args_fields)
|
||||||
|
else:
|
||||||
|
# Create a default schema with no fields if no parameters are found
|
||||||
|
args_schema = create_model(
|
||||||
|
f"{tool.name}Input", __base__=PydanticBaseModel
|
||||||
|
)
|
||||||
|
|
||||||
|
return cls(
|
||||||
|
name=getattr(tool, "name", "Unnamed Tool"),
|
||||||
|
description=getattr(tool, "description", ""),
|
||||||
|
func=tool.func,
|
||||||
|
args_schema=args_schema,
|
||||||
|
)
|
||||||
|
|
||||||
def _set_args_schema(self):
|
def _set_args_schema(self):
|
||||||
if self.args_schema is None:
|
if self.args_schema is None:
|
||||||
@@ -136,12 +167,65 @@ class BaseTool(BaseModel, ABC):
|
|||||||
|
|
||||||
|
|
||||||
class Tool(BaseTool):
|
class Tool(BaseTool):
|
||||||
func: Callable
|
|
||||||
"""The function that will be executed when the tool is called."""
|
"""The function that will be executed when the tool is called."""
|
||||||
|
|
||||||
|
func: Callable
|
||||||
|
|
||||||
def _run(self, *args: Any, **kwargs: Any) -> Any:
|
def _run(self, *args: Any, **kwargs: Any) -> Any:
|
||||||
return self.func(*args, **kwargs)
|
return self.func(*args, **kwargs)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_langchain(cls, tool: Any) -> "Tool":
|
||||||
|
"""Create a Tool instance from a CrewStructuredTool.
|
||||||
|
|
||||||
|
This method takes a CrewStructuredTool object and converts it into a
|
||||||
|
Tool instance. It ensures that the provided tool has a callable 'func'
|
||||||
|
attribute and infers the argument schema if not explicitly provided.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tool (Any): The CrewStructuredTool object to be converted.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Tool: A new Tool instance created from the provided CrewStructuredTool.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the provided tool does not have a callable 'func' attribute.
|
||||||
|
"""
|
||||||
|
if not hasattr(tool, "func") or not callable(tool.func):
|
||||||
|
raise ValueError("The provided tool must have a callable 'func' attribute.")
|
||||||
|
|
||||||
|
args_schema = getattr(tool, "args_schema", None)
|
||||||
|
|
||||||
|
if args_schema is None:
|
||||||
|
# Infer args_schema from the function signature if not provided
|
||||||
|
func_signature = signature(tool.func)
|
||||||
|
annotations = func_signature.parameters
|
||||||
|
args_fields = {}
|
||||||
|
for name, param in annotations.items():
|
||||||
|
if name != "self":
|
||||||
|
param_annotation = (
|
||||||
|
param.annotation if param.annotation != param.empty else Any
|
||||||
|
)
|
||||||
|
field_info = Field(
|
||||||
|
default=...,
|
||||||
|
description="",
|
||||||
|
)
|
||||||
|
args_fields[name] = (param_annotation, field_info)
|
||||||
|
if args_fields:
|
||||||
|
args_schema = create_model(f"{tool.name}Input", **args_fields)
|
||||||
|
else:
|
||||||
|
# Create a default schema with no fields if no parameters are found
|
||||||
|
args_schema = create_model(
|
||||||
|
f"{tool.name}Input", __base__=PydanticBaseModel
|
||||||
|
)
|
||||||
|
|
||||||
|
return cls(
|
||||||
|
name=getattr(tool, "name", "Unnamed Tool"),
|
||||||
|
description=getattr(tool, "description", ""),
|
||||||
|
func=tool.func,
|
||||||
|
args_schema=args_schema,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def to_langchain(
|
def to_langchain(
|
||||||
tools: list[BaseTool | CrewStructuredTool],
|
tools: list[BaseTool | CrewStructuredTool],
|
||||||
|
|||||||
Reference in New Issue
Block a user