diff --git a/python/packages/autogen-ext/pyproject.toml b/python/packages/autogen-ext/pyproject.toml index 2b753daf0..6390ee2e0 100644 --- a/python/packages/autogen-ext/pyproject.toml +++ b/python/packages/autogen-ext/pyproject.toml @@ -175,7 +175,7 @@ exclude = ["src/autogen_ext/agents/web_surfer/*.js", "src/autogen_ext/runtimes/g [tool.pyright] extends = "../../pyproject.toml" include = ["src", "tests"] -exclude = ["src/autogen_ext/runtimes/grpc/protos", "tests/protos"] +exclude = ["src/autogen_ext/runtimes/grpc/protos", "tests/protos", "src/autogen_ext/agents/openai/_openai_assistant_agent.py", "tests/test_openai_assistant_agent.py"] [tool.pytest.ini_options] minversion = "6.0" @@ -195,7 +195,7 @@ test.sequence = [ test.default_item_type = "cmd" test-grpc = "pytest -n 1 --cov=src --cov-report=term-missing --cov-report=xml --grpc" test-windows = "pytest -n 1 --cov=src --cov-report=term-missing --cov-report=xml -m 'windows'" -mypy = "mypy --config-file ../../pyproject.toml --exclude src/autogen_ext/runtimes/grpc/protos --exclude tests/protos src tests" +mypy = "mypy --config-file ../../pyproject.toml --exclude src/autogen_ext/runtimes/grpc/protos --exclude tests/protos --exclude src/autogen_ext/agents/openai/_openai_assistant_agent.py --exclude tests/test_openai_assistant_agent.py --ignore-missing-imports src tests" [tool.mypy] [[tool.mypy.overrides]] diff --git a/python/packages/autogen-ext/src/autogen_ext/agents/openai/__init__.py b/python/packages/autogen-ext/src/autogen_ext/agents/openai/__init__.py index 76c14b2a5..d44fec7d8 100644 --- a/python/packages/autogen-ext/src/autogen_ext/agents/openai/__init__.py +++ b/python/packages/autogen-ext/src/autogen_ext/agents/openai/__init__.py @@ -1,11 +1,39 @@ try: from ._openai_agent import OpenAIAgent - from ._openai_assistant_agent import OpenAIAssistantAgent + + # Check OpenAI version to conditionally import OpenAIAssistantAgent + try: + from openai import __version__ as openai_version + + def _parse_openai_version(version_str: str) -> tuple[int, int, int]: + """Parse a semantic version string into a tuple of integers.""" + try: + parts = version_str.split(".") + major = int(parts[0]) + minor = int(parts[1]) if len(parts) > 1 else 0 + patch = int(parts[2].split("-")[0]) if len(parts) > 2 else 0 # Handle pre-release versions + return (major, minor, patch) + except (ValueError, IndexError): + # If version parsing fails, assume it's a newer version + return (999, 999, 999) + + _current_version = _parse_openai_version(openai_version) + _target_version = (1, 83, 0) + + # Only import OpenAIAssistantAgent if OpenAI version is less than 1.83 + if _current_version < _target_version: + from ._openai_assistant_agent import OpenAIAssistantAgent # type: ignore[import] + + __all__ = ["OpenAIAssistantAgent", "OpenAIAgent"] + else: + __all__ = ["OpenAIAgent"] + except ImportError: + # If OpenAI is not available, skip OpenAIAssistantAgent import + __all__ = ["OpenAIAgent"] + except ImportError as e: raise ImportError( "Dependencies for OpenAI agents not found. " 'Please install autogen-ext with the "openai" extra: ' 'pip install "autogen-ext[openai]"' ) from e - -__all__ = ["OpenAIAssistantAgent", "OpenAIAgent"] diff --git a/python/packages/autogen-ext/src/autogen_ext/agents/openai/_openai_assistant_agent.py b/python/packages/autogen-ext/src/autogen_ext/agents/openai/_openai_assistant_agent.py index 327b88b04..d62bb9c58 100644 --- a/python/packages/autogen-ext/src/autogen_ext/agents/openai/_openai_assistant_agent.py +++ b/python/packages/autogen-ext/src/autogen_ext/agents/openai/_openai_assistant_agent.py @@ -1,7 +1,17 @@ +""" +OpenAI Assistant Agent implementation. + +This module is deprecated starting v0.7.0 and will be removed in a future version. +""" +# pyright: ignore +# mypy: ignore-errors + import asyncio import json import logging import os +import warnings +from functools import wraps from typing import ( Any, AsyncGenerator, @@ -57,9 +67,33 @@ from openai.types.beta.threads.text_content_block_param import TextContentBlockP from openai.types.shared_params.function_definition import FunctionDefinition from openai.types.vector_store import VectorStore +# Deprecation warning +warnings.warn( + "The OpenAIAssistantAgent module is deprecated and will be removed in a future version, use OpenAIAgent instead.", + DeprecationWarning, + stacklevel=2, +) + event_logger = logging.getLogger(EVENT_LOGGER_NAME) +def deprecated_class(reason: str) -> Callable[[type], type]: + """Decorator to mark a class as deprecated.""" + + def decorator(cls: type) -> type: + original_init = cls.__init__ + + @wraps(original_init) + def new_init(self, *args, **kwargs) -> None: + warnings.warn(f"{cls.__name__} is deprecated: {reason}", DeprecationWarning, stacklevel=2) + original_init(self, *args, **kwargs) + + cls.__init__ = new_init + return cls + + return decorator + + def _convert_tool_to_function_param(tool: Tool) -> "FunctionToolParam": """Convert an autogen Tool to an OpenAI Assistant function tool parameter.""" @@ -90,14 +124,22 @@ class OpenAIAssistantAgentState(BaseModel): uploaded_file_ids: List[str] = Field(default_factory=list) +@deprecated_class( + "This class is deprecated starting v0.7.0 and will be removed in a future version. Use OpenAIAgent instead." +) class OpenAIAssistantAgent(BaseChatAgent): """An agent implementation that uses the Assistant API to generate responses. + .. warning:: + + This module is deprecated starting v0.7.0 and will be removed in a future version. + Please use :class:`~autogen_ext.agents.openai.OpenAIAgent` instead. + Installation: .. code-block:: bash - pip install "autogen-ext[openai]" + pip install "autogen-ext[openai]" # For OpenAI Assistant # pip install "autogen-ext[openai,azure]" # For Azure OpenAI Assistant @@ -146,7 +188,7 @@ class OpenAIAssistantAgent(BaseChatAgent): # Create an assistant with code interpreter assistant = OpenAIAssistantAgent( - name="Python Helper", + name="PythonHelper", description="Helps with Python programming", client=client, model="gpt-4", @@ -197,7 +239,7 @@ class OpenAIAssistantAgent(BaseChatAgent): # Create an assistant with code interpreter assistant = OpenAIAssistantAgent( - name="Python Helper", + name="PythonHelper", description="Helps with Python programming", client=client, model="gpt-4o", diff --git a/python/packages/autogen-ext/tests/test_openai_assistant_agent.py b/python/packages/autogen-ext/tests/test_openai_assistant_agent.py index b76279c92..71975b4bf 100644 --- a/python/packages/autogen-ext/tests/test_openai_assistant_agent.py +++ b/python/packages/autogen-ext/tests/test_openai_assistant_agent.py @@ -14,9 +14,33 @@ from autogen_core.tools._base import BaseTool, Tool from autogen_ext.agents.openai import OpenAIAssistantAgent from azure.identity import DefaultAzureCredential, get_bearer_token_provider from openai import AsyncAzureOpenAI, AsyncOpenAI +from openai import __version__ as openai_version from pydantic import BaseModel +def _parse_openai_version(version_str: str) -> tuple[int, int, int]: + """Parse a semantic version string into a tuple of integers.""" + try: + parts = version_str.split(".") + major = int(parts[0]) + minor = int(parts[1]) if len(parts) > 1 else 0 + patch = int(parts[2].split("-")[0]) if len(parts) > 2 else 0 # Handle pre-release versions + return (major, minor, patch) + except (ValueError, IndexError): + # If version parsing fails, assume it's a newer version + return (999, 999, 999) + + +# Skip all tests if OpenAI version is less than 1.83 +_current_version = _parse_openai_version(openai_version) +_target_version = (1, 83, 0) +if _current_version < _target_version: + pytest.skip( + f"OpenAI version {openai_version} is less than 1.83. OpenAIAssistantAgent tests are skipped for older versions.", + allow_module_level=True, + ) + + class QuestionType(str, Enum): MULTIPLE_CHOICE = "MULTIPLE_CHOICE" FREE_RESPONSE = "FREE_RESPONSE"