mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-05-12 20:48:15 +00:00
feat: implement BaseAgentAdapter for agent integration
- Introduced BaseAgentAdapter as an abstract base class for agent adapters in CrewAI. - Defined common interface and methods for configuring tools and structured output. - Updated OpenAIAgentAdapter to inherit from BaseAgentAdapter, enhancing its structure and functionality.
This commit is contained in:
40
src/crewai/agents/agent_adapters/base_agent_adapter.py
Normal file
40
src/crewai/agents/agent_adapters/base_agent_adapter.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import Any, List, Optional
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from crewai.agent import BaseAgent
|
||||||
|
from crewai.tools import BaseTool
|
||||||
|
|
||||||
|
|
||||||
|
class BaseAgentAdapter(BaseAgent, ABC):
|
||||||
|
"""Base class for all agent adapters in CrewAI.
|
||||||
|
|
||||||
|
This abstract class defines the common interface and functionality that all
|
||||||
|
agent adapters must implement. It extends BaseAgent to maintain compatibility
|
||||||
|
with the CrewAI framework while adding adapter-specific requirements.
|
||||||
|
"""
|
||||||
|
|
||||||
|
adapted_structured_output: bool = False
|
||||||
|
|
||||||
|
model_config = {"arbitrary_types_allowed": True}
|
||||||
|
|
||||||
|
def __init__(self, **kwargs: Any):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def configure_tools(self, tools: Optional[List[BaseTool]] = None) -> None:
|
||||||
|
"""Configure and adapt tools for the specific agent implementation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tools: Optional list of BaseTool instances to be configured
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def configure_structured_output(self, structured_output: Any) -> None:
|
||||||
|
"""Configure the structured output for the specific agent implementation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
structured_output: The structured output to be configured
|
||||||
|
"""
|
||||||
|
pass
|
||||||
@@ -2,11 +2,11 @@ from typing import Any, List, Optional
|
|||||||
|
|
||||||
from agents import Agent as OpenAIAgent
|
from agents import Agent as OpenAIAgent
|
||||||
from agents import Runner, Tool, enable_verbose_stdout_logging
|
from agents import Runner, Tool, enable_verbose_stdout_logging
|
||||||
from pydantic import BaseModel, Field, PrivateAttr
|
from pydantic import Field, PrivateAttr
|
||||||
|
|
||||||
from crewai.agent import BaseAgent
|
from crewai.agents.agent_adapters.base_agent_adapter import BaseAgentAdapter
|
||||||
|
from crewai.agents.agent_builder.base_agent import BaseAgent
|
||||||
from crewai.tools import BaseTool
|
from crewai.tools import BaseTool
|
||||||
|
|
||||||
from crewai.tools.agent_tools.agent_tools import AgentTools
|
from crewai.tools.agent_tools.agent_tools import AgentTools
|
||||||
from crewai.utilities import Logger
|
from crewai.utilities import Logger
|
||||||
from crewai.utilities.events import crewai_event_bus
|
from crewai.utilities.events import crewai_event_bus
|
||||||
@@ -14,10 +14,11 @@ from crewai.utilities.events.agent_events import (
|
|||||||
AgentExecutionErrorEvent,
|
AgentExecutionErrorEvent,
|
||||||
AgentExecutionStartedEvent,
|
AgentExecutionStartedEvent,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .openai_agent_tool_adapter import OpenAIAgentToolAdapter
|
from .openai_agent_tool_adapter import OpenAIAgentToolAdapter
|
||||||
|
|
||||||
|
|
||||||
class OpenAIAgentAdapter(BaseAgent, BaseModel):
|
class OpenAIAgentAdapter(BaseAgentAdapter):
|
||||||
"""Adapter for OpenAI Assistants"""
|
"""Adapter for OpenAI Assistants"""
|
||||||
|
|
||||||
model_config = {"arbitrary_types_allowed": True}
|
model_config = {"arbitrary_types_allowed": True}
|
||||||
@@ -47,6 +48,7 @@ class OpenAIAgentAdapter(BaseAgent, BaseModel):
|
|||||||
self._openai_agent.model = model
|
self._openai_agent.model = model
|
||||||
self.tools = tools
|
self.tools = tools
|
||||||
self._tool_adapter = OpenAIAgentToolAdapter(tools=tools)
|
self._tool_adapter = OpenAIAgentToolAdapter(tools=tools)
|
||||||
|
self.llm = model
|
||||||
|
|
||||||
def execute_task(
|
def execute_task(
|
||||||
self,
|
self,
|
||||||
@@ -77,7 +79,7 @@ class OpenAIAgentAdapter(BaseAgent, BaseModel):
|
|||||||
)
|
)
|
||||||
# This is pretty much the agent_executor logic:
|
# This is pretty much the agent_executor logic:
|
||||||
result = self.agent_executor.run_sync(self._openai_agent, task_prompt)
|
result = self.agent_executor.run_sync(self._openai_agent, task_prompt)
|
||||||
return result.final_output
|
return self.handle_execution_result(result)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._logger.log("error", f"Error executing OpenAI task: {str(e)}")
|
self._logger.log("error", f"Error executing OpenAI task: {str(e)}")
|
||||||
@@ -100,18 +102,20 @@ class OpenAIAgentAdapter(BaseAgent, BaseModel):
|
|||||||
all_tools = list(self.tools or []) + list(tools or [])
|
all_tools = list(self.tools or []) + list(tools or [])
|
||||||
|
|
||||||
if all_tools:
|
if all_tools:
|
||||||
self._tool_adapter.configure_tools(all_tools)
|
self.configure_tools(all_tools)
|
||||||
if self._tool_adapter.converted_tools:
|
|
||||||
self._openai_agent.tools = self._tool_adapter.converted_tools
|
|
||||||
|
|
||||||
self.agent_executor = Runner
|
self.agent_executor = Runner
|
||||||
|
|
||||||
def _prepare_task_input(self, task: Any, context: Optional[str]) -> str:
|
def configure_tools(self, tools: Optional[List[BaseTool]] = None) -> None:
|
||||||
"""Prepare the task input with context if available"""
|
"""Configure tools for the OpenAI Assistant"""
|
||||||
task_input = task.description if hasattr(task, "description") else str(task)
|
if tools:
|
||||||
if context:
|
self._tool_adapter.configure_tools(tools)
|
||||||
task_input = f"Context:\n{context}\n\nTask:\n{task_input}"
|
if self._tool_adapter.converted_tools:
|
||||||
return task_input
|
self._openai_agent.tools = self._tool_adapter.converted_tools
|
||||||
|
|
||||||
|
def handle_execution_result(self, result: Any) -> str:
|
||||||
|
"""Process OpenAI Assistant execution result"""
|
||||||
|
return result.final_output
|
||||||
|
|
||||||
def get_delegation_tools(self, agents: List[BaseAgent]) -> List[BaseTool]:
|
def get_delegation_tools(self, agents: List[BaseAgent]) -> List[BaseTool]:
|
||||||
"""Implement delegation tools support"""
|
"""Implement delegation tools support"""
|
||||||
@@ -129,4 +133,34 @@ class OpenAIAgentAdapter(BaseAgent, BaseModel):
|
|||||||
|
|
||||||
def _parse_tools(self, tools: List[BaseTool]) -> List[BaseTool]:
|
def _parse_tools(self, tools: List[BaseTool]) -> List[BaseTool]:
|
||||||
"""Parse and validate tools"""
|
"""Parse and validate tools"""
|
||||||
return tools
|
tools_list = []
|
||||||
|
try:
|
||||||
|
# tentatively try to import from crewai_tools import BaseTool as CrewAITool
|
||||||
|
from crewai.tools import BaseTool as CrewAITool
|
||||||
|
|
||||||
|
for tool in tools:
|
||||||
|
if isinstance(tool, CrewAITool):
|
||||||
|
tools_list.append(tool.to_structured_tool())
|
||||||
|
else:
|
||||||
|
tools_list.append(tool)
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
tools_list = []
|
||||||
|
for tool in tools:
|
||||||
|
tools_list.append(tool)
|
||||||
|
|
||||||
|
return tools_list
|
||||||
|
|
||||||
|
def configure_structured_output(self, task) -> None:
|
||||||
|
"""Configure the structured output for the specific agent implementation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
structured_output: The structured output to be configured
|
||||||
|
"""
|
||||||
|
if task.output_json or task.output_pydantic:
|
||||||
|
# Generate the schema based on the output format
|
||||||
|
if task.output_json:
|
||||||
|
# schema = json.dumps(task.output_json, indent=2)
|
||||||
|
self._openai_agent.output_type = task.output_json
|
||||||
|
|
||||||
|
elif task.output_pydantic:
|
||||||
|
self._openai_agent.output_type = task.output_pydantic
|
||||||
|
|||||||
Reference in New Issue
Block a user