mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-05-05 09:12:39 +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 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.agent_tools.agent_tools import AgentTools
|
||||
from crewai.utilities import Logger
|
||||
from crewai.utilities.events import crewai_event_bus
|
||||
@@ -14,10 +14,11 @@ from crewai.utilities.events.agent_events import (
|
||||
AgentExecutionErrorEvent,
|
||||
AgentExecutionStartedEvent,
|
||||
)
|
||||
|
||||
from .openai_agent_tool_adapter import OpenAIAgentToolAdapter
|
||||
|
||||
|
||||
class OpenAIAgentAdapter(BaseAgent, BaseModel):
|
||||
class OpenAIAgentAdapter(BaseAgentAdapter):
|
||||
"""Adapter for OpenAI Assistants"""
|
||||
|
||||
model_config = {"arbitrary_types_allowed": True}
|
||||
@@ -47,6 +48,7 @@ class OpenAIAgentAdapter(BaseAgent, BaseModel):
|
||||
self._openai_agent.model = model
|
||||
self.tools = tools
|
||||
self._tool_adapter = OpenAIAgentToolAdapter(tools=tools)
|
||||
self.llm = model
|
||||
|
||||
def execute_task(
|
||||
self,
|
||||
@@ -77,7 +79,7 @@ class OpenAIAgentAdapter(BaseAgent, BaseModel):
|
||||
)
|
||||
# This is pretty much the agent_executor logic:
|
||||
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:
|
||||
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 [])
|
||||
|
||||
if all_tools:
|
||||
self._tool_adapter.configure_tools(all_tools)
|
||||
if self._tool_adapter.converted_tools:
|
||||
self._openai_agent.tools = self._tool_adapter.converted_tools
|
||||
self.configure_tools(all_tools)
|
||||
|
||||
self.agent_executor = Runner
|
||||
|
||||
def _prepare_task_input(self, task: Any, context: Optional[str]) -> str:
|
||||
"""Prepare the task input with context if available"""
|
||||
task_input = task.description if hasattr(task, "description") else str(task)
|
||||
if context:
|
||||
task_input = f"Context:\n{context}\n\nTask:\n{task_input}"
|
||||
return task_input
|
||||
def configure_tools(self, tools: Optional[List[BaseTool]] = None) -> None:
|
||||
"""Configure tools for the OpenAI Assistant"""
|
||||
if tools:
|
||||
self._tool_adapter.configure_tools(tools)
|
||||
if self._tool_adapter.converted_tools:
|
||||
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]:
|
||||
"""Implement delegation tools support"""
|
||||
@@ -129,4 +133,34 @@ class OpenAIAgentAdapter(BaseAgent, BaseModel):
|
||||
|
||||
def _parse_tools(self, tools: List[BaseTool]) -> List[BaseTool]:
|
||||
"""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