Skip to content

Commit

Permalink
merge with main
Browse files Browse the repository at this point in the history
  • Loading branch information
davorrunje committed Dec 19, 2024
2 parents 1342f75 + 5ec0198 commit d3fa24d
Show file tree
Hide file tree
Showing 37 changed files with 2,265 additions and 10 deletions.
7 changes: 3 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@ jobs:
- name: Install packages and dependencies
run: |
python -m pip install --upgrade pip wheel
pip install -e .[cosmosdb]
pip install -e .[test,cosmosdb,interop]
python -c "import autogen"
pip install pytest-cov>=5 mock
- name: Install optional dependencies for code executors
# code executors and udfs auto skip without deps, so only run for python 3.11
if: matrix.python-version == '3.11'
run: |
pip install -e ".[jupyter-executor,test]"
pip install -e ".[jupyter-executor]"
python -m ipykernel install --user --name python3
- name: Set AUTOGEN_USE_DOCKER based on OS
shell: bash
Expand All @@ -97,11 +97,10 @@ jobs:
- name: Coverage with Redis
if: matrix.python-version == '3.10'
run: |
pip install -e .[test,redis,websockets]
pip install -e .[redis,websockets]
pytest test --ignore=test/agentchat/contrib --skip-openai --durations=10 --durations-min=1.0
- name: Test with Cosmos DB
run: |
pip install -e .[test,cosmosdb]
pytest test/cache/test_cosmos_db_cache.py --skip-openai --durations=10 --durations-min=1.0
- name: Upload coverage to Codecov
if: matrix.python-version == '3.10'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/openai.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
if: matrix.python-version == '3.9'
run: |
pip install docker
pip install -e .[redis]
pip install -e .[redis,interop]
- name: Coverage
if: matrix.python-version == '3.9'
env:
Expand Down
6 changes: 6 additions & 0 deletions =8
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Requirement already satisfied: pytest in ./.venv-3.9/lib/python3.9/site-packages (7.4.4)
Requirement already satisfied: iniconfig in ./.venv-3.9/lib/python3.9/site-packages (from pytest) (2.0.0)
Requirement already satisfied: packaging in ./.venv-3.9/lib/python3.9/site-packages (from pytest) (24.2)
Requirement already satisfied: pluggy<2.0,>=0.12 in ./.venv-3.9/lib/python3.9/site-packages (from pytest) (1.5.0)
Requirement already satisfied: exceptiongroup>=1.0.0rc8 in ./.venv-3.9/lib/python3.9/site-packages (from pytest) (1.2.2)
Requirement already satisfied: tomli>=1.0.0 in ./.venv-3.9/lib/python3.9/site-packages (from pytest) (2.2.1)
2 changes: 1 addition & 1 deletion autogen/agentchat/conversable_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -2600,7 +2600,7 @@ def update_function_signature(self, func_sig: Union[str, Dict], is_remove: None)

self.client = OpenAIWrapper(**self.llm_config)

def update_tool_signature(self, tool_sig: Union[str, Dict], is_remove: None):
def update_tool_signature(self, tool_sig: Union[str, Dict], is_remove: bool):
"""update a tool_signature in the LLM configuration for tool_call.
Args:
Expand Down
4 changes: 3 additions & 1 deletion autogen/coding/jupyter/embedded_ipython_code_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
import uuid
from pathlib import Path
from queue import Empty
from typing import Any, ClassVar, List
from typing import Any, List

# this is needed for CI to work. The import of this file should fail if jupyter-kernel-gateway is not installed
import jupyter_kernel_gateway
from jupyter_client import KernelManager # type: ignore[attr-defined]
from jupyter_client.kernelspec import KernelSpecManager
from pydantic import BaseModel, Field, field_validator
Expand Down
12 changes: 12 additions & 0 deletions autogen/interop/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
#
# SPDX-License-Identifier: Apache-2.0

from .crewai import CrewAIInteroperability
from .interoperability import Interoperability
from .interoperable import Interoperable
from .langchain import LangChainInteroperability
from .pydantic_ai import PydanticAIInteroperability
from .registry import register_interoperable_class

__all__ = ["Interoperability", "Interoperable", "register_interoperable_class"]
7 changes: 7 additions & 0 deletions autogen/interop/crewai/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
#
# SPDX-License-Identifier: Apache-2.0

from .crewai import CrewAIInteroperability

__all__ = ["CrewAIInteroperability"]
83 changes: 83 additions & 0 deletions autogen/interop/crewai/crewai.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
#
# SPDX-License-Identifier: Apache-2.0

import re
import sys
from typing import Any, Optional

from ...tools import Tool
from ..registry import register_interoperable_class

__all__ = ["CrewAIInteroperability"]


def _sanitize_name(s: str) -> str:
return re.sub(r"\W|^(?=\d)", "_", s)


@register_interoperable_class("crewai")
class CrewAIInteroperability:
"""
A class implementing the `Interoperable` protocol for converting CrewAI tools
to a general `Tool` format.
This class takes a `CrewAITool` and converts it into a standard `Tool` object.
"""

@classmethod
def convert_tool(cls, tool: Any, **kwargs: Any) -> Tool:
"""
Converts a given CrewAI tool into a general `Tool` format.
This method ensures that the provided tool is a valid `CrewAITool`, sanitizes
the tool's name, processes its description, and prepares a function to interact
with the tool's arguments. It then returns a standardized `Tool` object.
Args:
tool (Any): The tool to convert, expected to be an instance of `CrewAITool`.
**kwargs (Any): Additional arguments, which are not supported by this method.
Returns:
Tool: A standardized `Tool` object converted from the CrewAI tool.
Raises:
ValueError: If the provided tool is not an instance of `CrewAITool`, or if
any additional arguments are passed.
"""
from crewai.tools import BaseTool as CrewAITool

if not isinstance(tool, CrewAITool):
raise ValueError(f"Expected an instance of `crewai.tools.BaseTool`, got {type(tool)}")
if kwargs:
raise ValueError(f"The CrewAIInteroperability does not support any additional arguments, got {kwargs}")

# needed for type checking
crewai_tool: CrewAITool = tool # type: ignore[no-any-unimported]

name = _sanitize_name(crewai_tool.name)
description = (
crewai_tool.description.split("Tool Description: ")[-1]
+ " (IMPORTANT: When using arguments, put them all in an `args` dictionary)"
)

def func(args: crewai_tool.args_schema) -> Any: # type: ignore[no-any-unimported]
return crewai_tool.run(**args.model_dump())

return Tool(
name=name,
description=description,
func=func,
)

@classmethod
def get_unsupported_reason(cls) -> Optional[str]:
if sys.version_info < (3, 10) or sys.version_info >= (3, 13):
return "This submodule is only supported for Python versions 3.10, 3.11, and 3.12"

try:
import crewai.tools
except ImportError:
return "Please install `interop-crewai` extra to use this module:\n\n\tpip install ag2[interop-crewai]"

return None
73 changes: 73 additions & 0 deletions autogen/interop/interoperability.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
#
# SPDX-License-Identifier: Apache-2.0
from typing import Any, Dict, List, Type

from ..tools import Tool
from .interoperable import Interoperable
from .registry import InteroperableRegistry

__all__ = ["Interoperable"]


class Interoperability:
"""
A class to handle interoperability between different tool types.
This class allows the conversion of tools to various interoperability classes and provides functionality
for retrieving and registering interoperability classes.
"""

registry = InteroperableRegistry.get_instance()

@classmethod
def convert_tool(cls, *, tool: Any, type: str, **kwargs: Any) -> Tool:
"""
Converts a given tool to an instance of a specified interoperability type.
Args:
tool (Any): The tool object to be converted.
type (str): The type of interoperability to convert the tool to.
**kwargs (Any): Additional arguments to be passed during conversion.
Returns:
Tool: The converted tool.
Raises:
ValueError: If the interoperability class for the provided type is not found.
"""
interop = cls.get_interoperability_class(type)
return interop.convert_tool(tool, **kwargs)

@classmethod
def get_interoperability_class(cls, type: str) -> Type[Interoperable]:
"""
Retrieves the interoperability class corresponding to the specified type.
Args:
type (str): The type of the interoperability class to retrieve.
Returns:
Type[Interoperable]: The interoperability class type.
Raises:
ValueError: If no interoperability class is found for the provided type.
"""
supported_types = cls.registry.get_supported_types()
if type not in supported_types:
supported_types_formated = ", ".join(["'t'" for t in supported_types])
raise ValueError(
f"Interoperability class {type} is not supported, supported types: {supported_types_formated}"
)

return cls.registry.get_class(type)

@classmethod
def get_supported_types(cls) -> List[str]:
"""
Returns a sorted list of all supported interoperability types.
Returns:
List[str]: A sorted list of strings representing the supported interoperability types.
"""
return sorted(cls.registry.get_supported_types())
46 changes: 46 additions & 0 deletions autogen/interop/interoperable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
#
# SPDX-License-Identifier: Apache-2.0

from typing import Any, Optional, Protocol, runtime_checkable

from ..tools import Tool

__all__ = ["Interoperable"]


@runtime_checkable
class Interoperable(Protocol):
"""
A Protocol defining the interoperability interface for tool conversion.
This protocol ensures that any class implementing it provides the method
`convert_tool` to convert a given tool into a desired format or type.
"""

@classmethod
def convert_tool(cls, tool: Any, **kwargs: Any) -> Tool:
"""
Converts a given tool to a desired format or type.
This method should be implemented by any class adhering to the `Interoperable` protocol.
Args:
tool (Any): The tool object to be converted.
**kwargs (Any): Additional parameters to pass during the conversion process.
Returns:
Tool: The converted tool in the desired format or type.
"""
...

@classmethod
def get_unsupported_reason(cls) -> Optional[str]:
"""Returns the reason for the tool being unsupported.
This method should be implemented by any class adhering to the `Interoperable` protocol.
Returns:
str: The reason for the interoperability class being unsupported.
"""
...
7 changes: 7 additions & 0 deletions autogen/interop/langchain/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
#
# SPDX-License-Identifier: Apache-2.0

from .langchain import LangChainInteroperability

__all__ = ["LangChainInteroperability"]
76 changes: 76 additions & 0 deletions autogen/interop/langchain/langchain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
#
# SPDX-License-Identifier: Apache-2.0

import sys
from typing import Any, Optional

from ...tools import Tool
from ..registry import register_interoperable_class

__all__ = ["LangChainInteroperability"]


@register_interoperable_class("langchain")
class LangChainInteroperability:
"""
A class implementing the `Interoperable` protocol for converting Langchain tools
into a general `Tool` format.
This class takes a `LangchainTool` and converts it into a standard `Tool` object,
ensuring compatibility between Langchain tools and other systems that expect
the `Tool` format.
"""

@classmethod
def convert_tool(cls, tool: Any, **kwargs: Any) -> Tool:
"""
Converts a given Langchain tool into a general `Tool` format.
This method verifies that the provided tool is a valid `LangchainTool`,
processes the tool's input and description, and returns a standardized
`Tool` object.
Args:
tool (Any): The tool to convert, expected to be an instance of `LangchainTool`.
**kwargs (Any): Additional arguments, which are not supported by this method.
Returns:
Tool: A standardized `Tool` object converted from the Langchain tool.
Raises:
ValueError: If the provided tool is not an instance of `LangchainTool`, or if
any additional arguments are passed.
"""
from langchain_core.tools import BaseTool as LangchainTool

if not isinstance(tool, LangchainTool):
raise ValueError(f"Expected an instance of `langchain_core.tools.BaseTool`, got {type(tool)}")
if kwargs:
raise ValueError(f"The LangchainInteroperability does not support any additional arguments, got {kwargs}")

# needed for type checking
langchain_tool: LangchainTool = tool # type: ignore

def func(tool_input: langchain_tool.args_schema) -> Any: # type: ignore
return langchain_tool.run(tool_input.model_dump())

return Tool(
name=langchain_tool.name,
description=langchain_tool.description,
func=func,
)

@classmethod
def get_unsupported_reason(cls) -> Optional[str]:
if sys.version_info < (3, 9):
return "This submodule is only supported for Python versions 3.9 and above"

try:
import langchain_core.tools
except ImportError:
return (
"Please install `interop-langchain` extra to use this module:\n\n\tpip install ag2[interop-langchain]"
)

return None
7 changes: 7 additions & 0 deletions autogen/interop/pydantic_ai/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
#
# SPDX-License-Identifier: Apache-2.0

from .pydantic_ai import PydanticAIInteroperability

__all__ = ["PydanticAIInteroperability"]
Loading

0 comments on commit d3fa24d

Please sign in to comment.