From 4c8837565b5ab8d71b6b9ca55b97c8116828bbaf Mon Sep 17 00:00:00 2001 From: olgavrou Date: Thu, 4 Jan 2024 16:22:39 -0500 Subject: [PATCH 01/18] set use_docker to default to true --- autogen/agentchat/conversable_agent.py | 15 +++++- autogen/code_utils.py | 65 +++++++++++++++++--------- setup.py | 1 + website/docs/FAQ.md | 2 +- 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/autogen/agentchat/conversable_agent.py b/autogen/agentchat/conversable_agent.py index 08f71160057..f672a51894b 100644 --- a/autogen/agentchat/conversable_agent.py +++ b/autogen/agentchat/conversable_agent.py @@ -8,7 +8,7 @@ from typing import Any, Awaitable, Callable, Dict, List, Literal, Optional, Tuple, Type, TypeVar, Union from .. import OpenAIWrapper -from ..code_utils import DEFAULT_MODEL, UNKNOWN, content_str, execute_code, extract_code, infer_lang +from ..code_utils import DEFAULT_MODEL, UNKNOWN, content_str, execute_code, extract_code, infer_lang, is_docker_running, in_docker_container from ..function_utils import get_function_schema, load_basemodels_if_needed, serialize_to_str from .agent import Agent from .._pydantic import model_dump @@ -129,6 +129,19 @@ def __init__( self._code_execution_config: Union[Dict, Literal[False]] = ( {} if code_execution_config is None else code_execution_config ) + + if isinstance(self._code_execution_config, Dict): + if "use_docker" in self._code_execution_config: + use_docker = self._code_execution_config["use_docker"] + else: + use_docker = True + if use_docker is not None: + inside_docker = in_docker_container() + docker_installed_and_running = is_docker_running() + if use_docker and not inside_docker and not docker_installed_and_running: + raise RuntimeError("Docker is not running, please make sure docker is running (advised approach for code execution) or set \"use_docker\":False.") + if not use_docker: + logger.warning("use_docker was set to False. Any code execution will be run natively but we strongly advise to set \"use_docker\":True. Set \"use_docker\":None to silence this message.") self.human_input_mode = human_input_mode self._max_consecutive_auto_reply = ( max_consecutive_auto_reply if max_consecutive_auto_reply is not None else self.MAX_CONSECUTIVE_AUTO_REPLY diff --git a/autogen/code_utils.py b/autogen/code_utils.py index dbb8637162d..4feb337ab0e 100644 --- a/autogen/code_utils.py +++ b/autogen/code_utils.py @@ -223,13 +223,35 @@ def _cmd(lang): return "powershell" raise NotImplementedError(f"{lang} not recognized in code execution") +def is_docker_running(): + """Check if docker is running. + + Returns: + bool: True if docker is running; False otherwise. + """ + if docker is None: + return False + try: + client = docker.from_env() + client.ping() + return True + except docker.errors.DockerException: + return False + +def in_docker_container(): + """Check if the code is running in a docker container. + + Returns: + bool: True if the code is running in a docker container; False otherwise. + """ + return os.path.exists("/.dockerenv") def execute_code( code: Optional[str] = None, timeout: Optional[int] = None, filename: Optional[str] = None, work_dir: Optional[str] = None, - use_docker: Optional[Union[List[str], str, bool]] = None, + use_docker: Union[List[str], str, bool] = True, lang: Optional[str] = "python", ) -> Tuple[int, str, str]: """Execute code in a docker container. @@ -249,15 +271,15 @@ def execute_code( If None, a default working directory will be used. The default working directory is the "extensions" directory under "path_to_autogen". - use_docker (Optional, list, str or bool): The docker image to use for code execution. + use_docker (list, str or bool): The docker image to use for code execution. If a list or a str of image name(s) is provided, the code will be executed in a docker container with the first image successfully pulled. If None, False or empty, the code will be executed in the current environment. - Default is None, which will be converted into an empty list when docker package is available. + Default is True. Expected behaviour: - - If `use_docker` is explicitly set to True and the docker package is available, the code will run in a Docker container. - - If `use_docker` is explicitly set to True but the Docker package is missing, an error will be raised. - - If `use_docker` is not set (i.e., left default to None) and the Docker package is not available, a warning will be displayed, but the code will run natively. + - If `use_docker` is not set (i.e. left default to True) or is explicitly set to True and the docker package is available, the code will run in a Docker container. + - If `use_docker` is not set (i.e. left default to True) or is explicitly set to True but the Docker package is missing, an error will be raised. + - If `use_docker` is explicitly set to False, a warning will be displayed, but the code will run natively. If the code is executed in the current environment, the code must be trusted. lang (Optional, str): The language of the code. Default is "python". @@ -272,18 +294,16 @@ def execute_code( logger.error(error_msg) raise AssertionError(error_msg) - # Warn if use_docker was unspecified (or None), and cannot be provided (the default). - # In this case the current behavior is to fall back to run natively, but this behavior - # is subject to change. - if use_docker is None: - if docker is None: - use_docker = False - logger.warning( - "execute_code was called without specifying a value for use_docker. Since the python docker package is not available, code will be run natively. Note: this fallback behavior is subject to change" - ) - else: - # Default to true - use_docker = True + # # Warn if use_docker was set to False + # # In this case the current behavior is to fall back to run natively, but this behavior + # # is subject to change. + running_inside_docker = in_docker_container() + docker_running = is_docker_running() + + if use_docker is not None and not use_docker and not running_inside_docker: + logger.warning( + "execute_code was called with use_docker set to False. Code will be run natively but we strongly advise to set use_docker=True. Set use_docker=None to silence this message." + ) timeout = timeout or DEFAULT_TIMEOUT original_filename = filename @@ -301,9 +321,8 @@ def execute_code( if code is not None: with open(filepath, "w", encoding="utf-8") as fout: fout.write(code) - # check if already running in a docker container - in_docker_container = os.path.exists("/.dockerenv") - if not use_docker or in_docker_container: + + if not use_docker or running_inside_docker: # already running in a docker container cmd = [ sys.executable if lang.startswith("python") else _cmd(lang), @@ -347,7 +366,11 @@ def execute_code( return result.returncode, logs, None # create a docker client + if use_docker and not docker_running: + raise RuntimeError("Docker package is missing or docker is not running. Please make sure docker is running or set use_docker=False.") + client = docker.from_env() + image_list = ( ["python:3-alpine", "python:3", "python:3-windowsservercore"] if use_docker is True diff --git a/setup.py b/setup.py index ea8f83be279..1789fdb4fef 100644 --- a/setup.py +++ b/setup.py @@ -21,6 +21,7 @@ "python-dotenv", "tiktoken", "pydantic>=1.10,<3", # could be both V1 and V2 + "docker", ] setuptools.setup( diff --git a/website/docs/FAQ.md b/website/docs/FAQ.md index dcd4dab6f54..37b699027a5 100644 --- a/website/docs/FAQ.md +++ b/website/docs/FAQ.md @@ -72,7 +72,7 @@ The `AssistantAgent` doesn't save all the code by default, because there are cas We strongly recommend using docker to execute code. There are two ways to use docker: 1. Run autogen in a docker container. For example, when developing in GitHub codespace, the autogen runs in a docker container. -2. Run autogen outside of a docker, while perform code execution with a docker container. For this option, make sure the python package `docker` is installed. When it is not installed and `use_docker` is omitted in `code_execution_config`, the code will be executed locally (this behavior is subject to change in future). +2. Run autogen outside of a docker container, while performing code execution with a docker container. For this option, make sure the python package `docker` is installed. When it is not installed and `use_docker` is explicitly set to False in `code_execution_config`, the code will be executed locally (this behavior is subject to change in future). ### Enable Python 3 docker image From a21e800efc6d8a4a9483555bcaab3c1a5f04caaa Mon Sep 17 00:00:00 2001 From: olgavrou Date: Thu, 4 Jan 2024 16:31:33 -0500 Subject: [PATCH 02/18] black formatting --- autogen/agentchat/conversable_agent.py | 19 ++++++++++++++++--- autogen/code_utils.py | 7 ++++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/autogen/agentchat/conversable_agent.py b/autogen/agentchat/conversable_agent.py index f672a51894b..012215b5a01 100644 --- a/autogen/agentchat/conversable_agent.py +++ b/autogen/agentchat/conversable_agent.py @@ -8,7 +8,16 @@ from typing import Any, Awaitable, Callable, Dict, List, Literal, Optional, Tuple, Type, TypeVar, Union from .. import OpenAIWrapper -from ..code_utils import DEFAULT_MODEL, UNKNOWN, content_str, execute_code, extract_code, infer_lang, is_docker_running, in_docker_container +from ..code_utils import ( + DEFAULT_MODEL, + UNKNOWN, + content_str, + execute_code, + extract_code, + infer_lang, + is_docker_running, + in_docker_container, +) from ..function_utils import get_function_schema, load_basemodels_if_needed, serialize_to_str from .agent import Agent from .._pydantic import model_dump @@ -139,9 +148,13 @@ def __init__( inside_docker = in_docker_container() docker_installed_and_running = is_docker_running() if use_docker and not inside_docker and not docker_installed_and_running: - raise RuntimeError("Docker is not running, please make sure docker is running (advised approach for code execution) or set \"use_docker\":False.") + raise RuntimeError( + 'Docker is not running, please make sure docker is running (advised approach for code execution) or set "use_docker":False.' + ) if not use_docker: - logger.warning("use_docker was set to False. Any code execution will be run natively but we strongly advise to set \"use_docker\":True. Set \"use_docker\":None to silence this message.") + logger.warning( + 'use_docker was set to False. Any code execution will be run natively but we strongly advise to set "use_docker":True. Set "use_docker":None to silence this message.' + ) self.human_input_mode = human_input_mode self._max_consecutive_auto_reply = ( max_consecutive_auto_reply if max_consecutive_auto_reply is not None else self.MAX_CONSECUTIVE_AUTO_REPLY diff --git a/autogen/code_utils.py b/autogen/code_utils.py index 4feb337ab0e..5ef1adf03ad 100644 --- a/autogen/code_utils.py +++ b/autogen/code_utils.py @@ -223,6 +223,7 @@ def _cmd(lang): return "powershell" raise NotImplementedError(f"{lang} not recognized in code execution") + def is_docker_running(): """Check if docker is running. @@ -238,6 +239,7 @@ def is_docker_running(): except docker.errors.DockerException: return False + def in_docker_container(): """Check if the code is running in a docker container. @@ -246,6 +248,7 @@ def in_docker_container(): """ return os.path.exists("/.dockerenv") + def execute_code( code: Optional[str] = None, timeout: Optional[int] = None, @@ -367,7 +370,9 @@ def execute_code( # create a docker client if use_docker and not docker_running: - raise RuntimeError("Docker package is missing or docker is not running. Please make sure docker is running or set use_docker=False.") + raise RuntimeError( + "Docker package is missing or docker is not running. Please make sure docker is running or set use_docker=False." + ) client = docker.from_env() From 28cbd5aa145525c903d28b43a361c23a4a6e0e2c Mon Sep 17 00:00:00 2001 From: olgavrou Date: Fri, 5 Jan 2024 04:04:29 -0500 Subject: [PATCH 03/18] centralize checking and add env variable option --- .github/workflows/build.yml | 8 ++++ autogen/agentchat/conversable_agent.py | 25 ++++-------- autogen/code_utils.py | 54 ++++++++++++++++++++++---- test/test_code.py | 4 +- 4 files changed, 64 insertions(+), 27 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2f1af9ab744..f296a797160 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,6 +41,14 @@ jobs: pip install -e . python -c "import autogen" pip install -e. pytest mock + - name: Set AUTOGEN_USE_DOCKER based on OS + shell: bash + run: | + if [[ ${{ matrix.os }} == windows-2019 ]]; then + echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV + elif [[ ${{ matrix.os }} == macos-latest ]]; then + echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV + fi - name: Test with pytest if: matrix.python-version != '3.10' run: | diff --git a/autogen/agentchat/conversable_agent.py b/autogen/agentchat/conversable_agent.py index 012215b5a01..6f5a47c417a 100644 --- a/autogen/agentchat/conversable_agent.py +++ b/autogen/agentchat/conversable_agent.py @@ -12,12 +12,13 @@ DEFAULT_MODEL, UNKNOWN, content_str, + check_use_docker, + decide_use_docker, execute_code, extract_code, infer_lang, - is_docker_running, - in_docker_container, ) + from ..function_utils import get_function_schema, load_basemodels_if_needed, serialize_to_str from .agent import Agent from .._pydantic import model_dump @@ -140,21 +141,11 @@ def __init__( ) if isinstance(self._code_execution_config, Dict): - if "use_docker" in self._code_execution_config: - use_docker = self._code_execution_config["use_docker"] - else: - use_docker = True - if use_docker is not None: - inside_docker = in_docker_container() - docker_installed_and_running = is_docker_running() - if use_docker and not inside_docker and not docker_installed_and_running: - raise RuntimeError( - 'Docker is not running, please make sure docker is running (advised approach for code execution) or set "use_docker":False.' - ) - if not use_docker: - logger.warning( - 'use_docker was set to False. Any code execution will be run natively but we strongly advise to set "use_docker":True. Set "use_docker":None to silence this message.' - ) + use_docker = self._code_execution_config.get("use_docker", None) + use_docker = decide_use_docker(use_docker) + check_use_docker(use_docker) + self._code_execution_config["use_docker"] = use_docker + self.human_input_mode = human_input_mode self._max_consecutive_auto_reply = ( max_consecutive_auto_reply if max_consecutive_auto_reply is not None else self.MAX_CONSECUTIVE_AUTO_REPLY diff --git a/autogen/code_utils.py b/autogen/code_utils.py index 5ef1adf03ad..746237d9a85 100644 --- a/autogen/code_utils.py +++ b/autogen/code_utils.py @@ -16,6 +16,7 @@ except ImportError: docker = None +SENTINEL = object() DEFAULT_MODEL = "gpt-4" FAST_MODEL = "gpt-3.5-turbo" # Regular expression for finding a code block @@ -249,12 +250,51 @@ def in_docker_container(): return os.path.exists("/.dockerenv") +def decide_use_docker(use_docker) -> bool: + if use_docker is None: + env_var_use_docker = os.environ.get("AUTOGEN_USE_DOCKER", "True") + + truthy_values = {"1", "true", "yes", "t"} + falsy_values = {"0", "false", "no", "f"} + + # Convert the value to lowercase for case-insensitive comparison + env_var_use_docker_lower = env_var_use_docker.lower() + + # Determine the boolean value based on the environment variable + if env_var_use_docker_lower in truthy_values: + use_docker = True + elif env_var_use_docker_lower in falsy_values: + use_docker = False + elif env_var_use_docker_lower == "none": # Special case for 'None' as a string + use_docker = None + else: + # Raise an error for any unrecognized value + raise ValueError( + f'Invalid value for AUTOGEN_USE_DOCKER: {env_var_use_docker}. Please set AUTOGEN_USE_DOCKER to "1/True/yes", "0/False/no", or "None".' + ) + return use_docker + + +def check_use_docker(use_docker) -> None: + if use_docker is not None: + inside_docker = in_docker_container() + docker_installed_and_running = is_docker_running() + if use_docker and not inside_docker and not docker_installed_and_running: + raise RuntimeError( + 'Docker is not running, please make sure docker is running (advised approach for code execution) or set "use_docker":False.' + ) + if not use_docker: + logger.warning( + 'use_docker was set to False. Any code execution will be run natively but we strongly advise to set "use_docker":True. Set "use_docker":None to silence this message.' + ) + + def execute_code( code: Optional[str] = None, timeout: Optional[int] = None, filename: Optional[str] = None, work_dir: Optional[str] = None, - use_docker: Union[List[str], str, bool] = True, + use_docker: Union[List[str], str, bool] = SENTINEL, lang: Optional[str] = "python", ) -> Tuple[int, str, str]: """Execute code in a docker container. @@ -297,16 +337,12 @@ def execute_code( logger.error(error_msg) raise AssertionError(error_msg) - # # Warn if use_docker was set to False - # # In this case the current behavior is to fall back to run natively, but this behavior - # # is subject to change. running_inside_docker = in_docker_container() docker_running = is_docker_running() - if use_docker is not None and not use_docker and not running_inside_docker: - logger.warning( - "execute_code was called with use_docker set to False. Code will be run natively but we strongly advise to set use_docker=True. Set use_docker=None to silence this message." - ) + if use_docker is SENTINEL: + use_docker = decide_use_docker(use_docker=None) + check_use_docker(use_docker) timeout = timeout or DEFAULT_TIMEOUT original_filename = filename @@ -318,9 +354,11 @@ def execute_code( filename = f"tmp_code_{code_hash}.{'py' if lang.startswith('python') else lang}" if work_dir is None: work_dir = WORKING_DIR + filepath = os.path.join(work_dir, filename) file_dir = os.path.dirname(filepath) os.makedirs(file_dir, exist_ok=True) + if code is not None: with open(filepath, "w", encoding="utf-8") as fout: fout.write(code) diff --git a/test/test_code.py b/test/test_code.py index ec8ada2c906..801f6cddf42 100644 --- a/test/test_code.py +++ b/test/test_code.py @@ -294,8 +294,8 @@ def scrape(url): @pytest.mark.skipif( - sys.platform in ["darwin"], - reason="do not run on MacOS", + sys.platform in ["darwin", "win32"], + reason="do not run on MacOS or Windows", ) def test_execute_code(use_docker=None): try: From 8bc1257a2278d9eb4adf9b354e9699bb376afb93 Mon Sep 17 00:00:00 2001 From: olgavrou Date: Thu, 11 Jan 2024 16:39:22 -0500 Subject: [PATCH 04/18] set docker env flag for contrib tests --- .github/workflows/contrib-tests.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/contrib-tests.yml b/.github/workflows/contrib-tests.yml index 27a616b7719..aa9656ff3d9 100644 --- a/.github/workflows/contrib-tests.yml +++ b/.github/workflows/contrib-tests.yml @@ -45,6 +45,14 @@ jobs: - name: Install packages and dependencies for RetrieveChat run: | pip install -e .[retrievechat] + - name: Set AUTOGEN_USE_DOCKER based on OS + shell: bash + run: | + if [[ ${{ matrix.os }} == windows-2019 ]]; then + echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV + elif [[ ${{ matrix.os }} == macos-latest ]]; then + echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV + fi - name: Test RetrieveChat run: | pytest test/test_retrieve_utils.py test/agentchat/contrib/test_retrievechat.py test/agentchat/contrib/test_qdrant_retrievechat.py --skip-openai From 1216e9d924cfb2b21cceb6c29975d87671c55fcd Mon Sep 17 00:00:00 2001 From: olgavrou Date: Thu, 11 Jan 2024 16:43:40 -0500 Subject: [PATCH 05/18] set docker env flag for contrib tests --- .github/workflows/contrib-tests.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/contrib-tests.yml b/.github/workflows/contrib-tests.yml index aa9656ff3d9..d28b4dbb040 100644 --- a/.github/workflows/contrib-tests.yml +++ b/.github/workflows/contrib-tests.yml @@ -45,14 +45,6 @@ jobs: - name: Install packages and dependencies for RetrieveChat run: | pip install -e .[retrievechat] - - name: Set AUTOGEN_USE_DOCKER based on OS - shell: bash - run: | - if [[ ${{ matrix.os }} == windows-2019 ]]; then - echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV - elif [[ ${{ matrix.os }} == macos-latest ]]; then - echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV - fi - name: Test RetrieveChat run: | pytest test/test_retrieve_utils.py test/agentchat/contrib/test_retrievechat.py test/agentchat/contrib/test_qdrant_retrievechat.py --skip-openai @@ -200,6 +192,14 @@ jobs: - name: Install packages and dependencies for LMM run: | pip install -e .[lmm] + - name: Set AUTOGEN_USE_DOCKER based on OS + shell: bash + run: | + if [[ ${{ matrix.os }} == windows-2019 ]]; then + echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV + elif [[ ${{ matrix.os }} == macos-latest ]]; then + echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV + fi - name: Test LMM and LLaVA run: | pytest test/agentchat/contrib/test_img_utils.py test/agentchat/contrib/test_lmm.py test/agentchat/contrib/test_llava.py --skip-openai From 5dedb51b0496daf01c5c1d52c4c0f93c410998eb Mon Sep 17 00:00:00 2001 From: olgavrou Date: Tue, 16 Jan 2024 15:55:44 -0500 Subject: [PATCH 06/18] better error message and cleanup --- autogen/agentchat/conversable_agent.py | 3 ++- autogen/code_utils.py | 10 +++++----- setup.py | 4 ---- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/autogen/agentchat/conversable_agent.py b/autogen/agentchat/conversable_agent.py index 92577d55f60..857e516b344 100644 --- a/autogen/agentchat/conversable_agent.py +++ b/autogen/agentchat/conversable_agent.py @@ -20,6 +20,7 @@ infer_lang, ) + from ..function_utils import get_function_schema, load_basemodels_if_needed, serialize_to_str from .agent import Agent from .._pydantic import model_dump @@ -139,7 +140,7 @@ def __init__( {} if code_execution_config is None else code_execution_config ) - if isinstance(self._code_execution_config, Dict): + if isinstance(self._code_execution_config, dict): use_docker = self._code_execution_config.get("use_docker", None) use_docker = decide_use_docker(use_docker) check_use_docker(use_docker) diff --git a/autogen/code_utils.py b/autogen/code_utils.py index 746237d9a85..db46fb86657 100644 --- a/autogen/code_utils.py +++ b/autogen/code_utils.py @@ -281,11 +281,11 @@ def check_use_docker(use_docker) -> None: docker_installed_and_running = is_docker_running() if use_docker and not inside_docker and not docker_installed_and_running: raise RuntimeError( - 'Docker is not running, please make sure docker is running (advised approach for code execution) or set "use_docker":False.' - ) - if not use_docker: - logger.warning( - 'use_docker was set to False. Any code execution will be run natively but we strongly advise to set "use_docker":True. Set "use_docker":None to silence this message.' + "Code execution is set to be run in docker (default behaviour) but docker is not running.\n" + "The options available are:\n" + "- Make sure docker is running (advised approach for code execution)\n" + '- Set "use_docker": False in code_execution_config\n' + '- Set AUTOGEN_USE_DOCKER to "0/False/no" in your environment variables' ) diff --git a/setup.py b/setup.py index c2435c15a41..718cd90ab3d 100644 --- a/setup.py +++ b/setup.py @@ -34,10 +34,6 @@ long_description_content_type="text/markdown", url="https://github.com/microsoft/autogen", packages=setuptools.find_packages(include=["autogen*"], exclude=["test"]), - # package_data={ - # "autogen.default": ["*/*.json"], - # }, - # include_package_data=True, install_requires=install_requires, extras_require={ "test": [ From 86ca7b3f9d486dd21b6f3f8c4465ec571f2dc58f Mon Sep 17 00:00:00 2001 From: olgavrou Date: Tue, 16 Jan 2024 16:14:24 -0500 Subject: [PATCH 07/18] disable explicit docker tests --- test/test_code.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/test_code.py b/test/test_code.py index e7306125de2..27d21702756 100644 --- a/test/test_code.py +++ b/test/test_code.py @@ -309,6 +309,10 @@ def scrape(url): assert len(codeblocks) == 1 and codeblocks[0] == ("", "source setup.sh") +@pytest.mark.skipif( + sys.platform in ["darwin", "win32"], + reason="do not run on MacOS or Windows", +) def test_execute_code(use_docker=None): try: import docker From ebaff8f16cf7b6c985d98b55f48af99cd3218ffc Mon Sep 17 00:00:00 2001 From: olgavrou Date: Tue, 16 Jan 2024 16:20:19 -0500 Subject: [PATCH 08/18] docker is installed so can't check for that in test --- test/test_code.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/test/test_code.py b/test/test_code.py index 27d21702756..80e8cac9dc6 100644 --- a/test/test_code.py +++ b/test/test_code.py @@ -309,10 +309,6 @@ def scrape(url): assert len(codeblocks) == 1 and codeblocks[0] == ("", "source setup.sh") -@pytest.mark.skipif( - sys.platform in ["darwin", "win32"], - reason="do not run on MacOS or Windows", -) def test_execute_code(use_docker=None): try: import docker @@ -354,14 +350,20 @@ def test_execute_code(use_docker=None): assert isinstance(image, str) or docker is None or os.path.exists("/.dockerenv") or use_docker is False -@pytest.mark.skipif(docker_package_installed is False, reason="docker package not installed") +@pytest.mark.skipif( + sys.platform in ["darwin", "win32"], + reason="do not run on MacOS or Windows", +) def test_execute_code_with_custom_filename_on_docker(): exit_code, msg, image = execute_code("print('hello world')", filename="tmp/codetest.py", use_docker=True) assert exit_code == 0 and msg == "hello world\n", msg assert image == "python:tmp_codetest.py" -@pytest.mark.skipif(docker_package_installed is False, reason="docker package not installed") +@pytest.mark.skipif( + sys.platform in ["darwin", "win32"], + reason="do not run on MacOS or Windows", +) def test_execute_code_with_misformed_filename_on_docker(): exit_code, msg, image = execute_code( "print('hello world')", filename="tmp/codetest.py (some extra information)", use_docker=True From ba982accec61e230f443d3aa909b5ffb3c342e84 Mon Sep 17 00:00:00 2001 From: olgavrou Date: Wed, 17 Jan 2024 09:38:33 -0500 Subject: [PATCH 09/18] pr comments and fix test --- .github/workflows/build.yml | 4 +--- .github/workflows/contrib-tests.yml | 4 +--- test/test_code.py | 4 ++++ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f296a797160..397c6f1cc48 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,9 +44,7 @@ jobs: - name: Set AUTOGEN_USE_DOCKER based on OS shell: bash run: | - if [[ ${{ matrix.os }} == windows-2019 ]]; then - echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV - elif [[ ${{ matrix.os }} == macos-latest ]]; then + if [[ ${{ matrix.os }} != ubuntu-latest ]]; then echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV fi - name: Test with pytest diff --git a/.github/workflows/contrib-tests.yml b/.github/workflows/contrib-tests.yml index d28b4dbb040..ffce67df900 100644 --- a/.github/workflows/contrib-tests.yml +++ b/.github/workflows/contrib-tests.yml @@ -195,9 +195,7 @@ jobs: - name: Set AUTOGEN_USE_DOCKER based on OS shell: bash run: | - if [[ ${{ matrix.os }} == windows-2019 ]]; then - echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV - elif [[ ${{ matrix.os }} == macos-latest ]]; then + if [[ ${{ matrix.os }} != ubuntu-latest ]]; then echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV fi - name: Test LMM and LLaVA diff --git a/test/test_code.py b/test/test_code.py index 80e8cac9dc6..36e0e17e38d 100644 --- a/test/test_code.py +++ b/test/test_code.py @@ -309,6 +309,10 @@ def scrape(url): assert len(codeblocks) == 1 and codeblocks[0] == ("", "source setup.sh") +@pytest.mark.skipif( + sys.platform in ["darwin", "win32"], + reason="do not run on MacOS or Windows", +) def test_execute_code(use_docker=None): try: import docker From 00ec55f31367962a66b75def63c96dcc07d1d154 Mon Sep 17 00:00:00 2001 From: olgavrou Date: Wed, 17 Jan 2024 10:49:53 -0500 Subject: [PATCH 10/18] rename and fix function descriptions --- autogen/agentchat/conversable_agent.py | 9 ++++----- autogen/code_utils.py | 13 +++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/autogen/agentchat/conversable_agent.py b/autogen/agentchat/conversable_agent.py index 8741f28e67c..a8016fb398f 100644 --- a/autogen/agentchat/conversable_agent.py +++ b/autogen/agentchat/conversable_agent.py @@ -13,7 +13,7 @@ DEFAULT_MODEL, UNKNOWN, content_str, - check_use_docker, + check_can_use_docker_or_throw, decide_use_docker, execute_code, extract_code, @@ -100,11 +100,10 @@ def __init__( The default working directory is the "extensions" directory under "path_to_autogen". - use_docker (Optional, list, str or bool): The docker image to use for code execution. + Default is True, which means the code will be executed in a docker container. A default list of images will be used. If a list or a str of image name(s) is provided, the code will be executed in a docker container with the first image successfully pulled. - If None, False or empty, the code will be executed in the current environment. - Default is True when the docker python package is installed. - When set to True, a default list will be used. + If False, the code will be executed in the current environment. We strongly recommend using docker for code execution. - timeout (Optional, int): The maximum execution time in seconds. - last_n_messages (Experimental, Optional, int or str): The number of messages to look back for code execution. Default to 1. If set to 'auto', it will scan backwards through all messages arriving since the agent last spoke (typically this is the last time execution was attempted). @@ -143,7 +142,7 @@ def __init__( if isinstance(self._code_execution_config, dict): use_docker = self._code_execution_config.get("use_docker", None) use_docker = decide_use_docker(use_docker) - check_use_docker(use_docker) + check_can_use_docker_or_throw(use_docker) self._code_execution_config["use_docker"] = use_docker self.human_input_mode = human_input_mode diff --git a/autogen/code_utils.py b/autogen/code_utils.py index ab580f8096a..00fe01589d8 100644 --- a/autogen/code_utils.py +++ b/autogen/code_utils.py @@ -276,7 +276,7 @@ def decide_use_docker(use_docker) -> bool: return use_docker -def check_use_docker(use_docker) -> None: +def check_can_use_docker_or_throw(use_docker) -> None: if use_docker is not None: inside_docker = in_docker_container() docker_installed_and_running = is_docker_running() @@ -339,14 +339,14 @@ def execute_code( The default working directory is the "extensions" directory under "path_to_autogen". use_docker (list, str or bool): The docker image to use for code execution. + Default is True, which means the code will be executed in a docker container. A default list of images will be used. If a list or a str of image name(s) is provided, the code will be executed in a docker container with the first image successfully pulled. - If None, False or empty, the code will be executed in the current environment. - Default is True. + If False, the code will be executed in the current environment. Expected behaviour: - If `use_docker` is not set (i.e. left default to True) or is explicitly set to True and the docker package is available, the code will run in a Docker container. - - If `use_docker` is not set (i.e. left default to True) or is explicitly set to True but the Docker package is missing, an error will be raised. - - If `use_docker` is explicitly set to False, a warning will be displayed, but the code will run natively. + - If `use_docker` is not set (i.e. left default to True) or is explicitly set to True but the Docker package is missing or docker isn't running, an error will be raised. + - If `use_docker` is explicitly set to False, the code will run natively. If the code is executed in the current environment, the code must be trusted. lang (Optional, str): The language of the code. Default is "python". @@ -364,9 +364,10 @@ def execute_code( running_inside_docker = in_docker_container() docker_running = is_docker_running() + # SENTINEL is used to indicate that the user did not explicitly set the argument if use_docker is SENTINEL: use_docker = decide_use_docker(use_docker=None) - check_use_docker(use_docker) + check_can_use_docker_or_throw(use_docker) timeout = timeout or DEFAULT_TIMEOUT original_filename = filename From 636e9289a1af102a2bbd3e6734dad3ed5bc5c7dc Mon Sep 17 00:00:00 2001 From: olgavrou Date: Wed, 17 Jan 2024 11:36:59 -0500 Subject: [PATCH 11/18] documentation --- autogen/agentchat/user_proxy_agent.py | 7 ++-- website/docs/FAQ.md | 28 ++++++++++++- website/docs/Installation.md | 58 ++++++++++++--------------- 3 files changed, 56 insertions(+), 37 deletions(-) diff --git a/autogen/agentchat/user_proxy_agent.py b/autogen/agentchat/user_proxy_agent.py index 97af776aa7a..86b7e1e7b1c 100644 --- a/autogen/agentchat/user_proxy_agent.py +++ b/autogen/agentchat/user_proxy_agent.py @@ -62,12 +62,11 @@ def __init__( The default working directory is the "extensions" directory under "path_to_autogen". - use_docker (Optional, list, str or bool): The docker image to use for code execution. + Default is True, which means the code will be executed in a docker container. A default list of images will be used. If a list or a str of image name(s) is provided, the code will be executed in a docker container with the first image successfully pulled. - If None, False or empty, the code will be executed in the current environment. - Default is True, which will be converted into a list. - If the code is executed in the current environment, - the code must be trusted. + If False, the code will be executed in the current environment. + We strongly recommend using docker for code execution. - timeout (Optional, int): The maximum execution time in seconds. - last_n_messages (Experimental, Optional, int): The number of messages to look back for code execution. Default to 1. default_auto_reply (str or dict or None): the default auto reply message when no code execution or llm based reply is generated. diff --git a/website/docs/FAQ.md b/website/docs/FAQ.md index a54d0ab24a9..f6df3c236c3 100644 --- a/website/docs/FAQ.md +++ b/website/docs/FAQ.md @@ -1,5 +1,23 @@ # Frequently Asked Questions +- [Set your API endpoints](#set-your-api-endpoints) + - [Use the constructed configuration list in agents](#use-the-constructed-configuration-list-in-agents) + - [Unexpected keyword argument 'base_url'](#unexpected-keyword-argument-base_url) + - [Can I use non-OpenAI models?](#can-i-use-non-openai-models) +- [Handle Rate Limit Error and Timeout Error](#handle-rate-limit-error-and-timeout-error) +- [How to continue a finished conversation](#how-to-continue-a-finished-conversation) +- [How do we decide what LLM is used for each agent? How many agents can be used? How do we decide how many agents in the group?](#how-do-we-decide-what-llm-is-used-for-each-agent-how-many-agents-can-be-used-how-do-we-decide-how-many-agents-in-the-group) +- [Why is code not saved as file?](#why-is-code-not-saved-as-file) +- [Code execution](#code-execution) + - [Enable Python 3 docker image](#enable-python-3-docker-image) + - [Agents keep thanking each other when using `gpt-3.5-turbo`](#agents-keep-thanking-each-other-when-using-gpt-35-turbo) +- [ChromaDB fails in codespaces because of old version of sqlite3](#chromadb-fails-in-codespaces-because-of-old-version-of-sqlite3) +- [How to register a reply function](#how-to-register-a-reply-function) +- [How to get last message?](#how-to-get-last-message) +- [How to get each agent message?](#how-to-get-each-agent-message) +- [When using autogen docker, is it always necessary to reinstall modules?](#when-using-autogen-docker-is-it-always-necessary-to-reinstall-modules) +- [Agents are throwing due to docker not running, how can I resolve this?](#agents-are-throwing-due-to-docker-not-running-how-can-i-resolve-this) + ## Set your API endpoints There are multiple ways to construct configurations for LLM inference in the `oai` utilities: @@ -72,7 +90,7 @@ The `AssistantAgent` doesn't save all the code by default, because there are cas We strongly recommend using docker to execute code. There are two ways to use docker: 1. Run AutoGen in a docker container. For example, when developing in [GitHub codespace](https://codespaces.new/microsoft/autogen?quickstart=1), AutoGen runs in a docker container. If you are not developing in Github codespace, follow instructions [here](Installation.md#option-1-install-and-run-autogen-in-docker) to install and run AutoGen in docker. -2. Run AutoGen outside of a docker, while performing code execution with a docker container. For this option, set up docker and make sure the python package `docker` is installed. When not installed and `use_docker` is omitted in `code_execution_config`, the code will be executed locally (this behavior is subject to change in future). +2. Run AutoGen outside of a docker, while performing code execution with a docker container. For this option, make sure docker is up and running. If you want to run the code locally (not recommended) then `use_docker` can be set to `False` in `code_execution_config` for each code-execution agent, or set `AUTOGEN_USE_DOCKER` to `False` as an environment variable. ### Enable Python 3 docker image @@ -173,3 +191,11 @@ Please refer to https://microsoft.github.io/autogen/docs/reference/agentchat/con The "use_docker" arg in an agent's code_execution_config will be set to the name of the image containing the change after execution, when the conversation finishes. You can save that image name. For a new conversation, you can set "use_docker" to the saved name of the image to start execution there. + +## Agents are throwing due to docker not running, how can I resolve this? + +If running AutoGen locally the default for agents who execute code is for them to try and perform code execution within a docker container. If docker is not running, this will cause the agent to throw an error. To resolve this you have the below options: + +- **Recommended**: Make sure docker is up and running. +- If you want to run the code locally then `use_docker` can be set to `False` in `code_execution_config` for each code-execution agent. +- If you want to run the code locally for all code-execution agents: set `AUTOGEN_USE_DOCKER` to `False` as an environment variable. diff --git a/website/docs/Installation.md b/website/docs/Installation.md index 7360204692d..49537c6f79f 100644 --- a/website/docs/Installation.md +++ b/website/docs/Installation.md @@ -94,7 +94,9 @@ docker run -it -p {WorkstationPortNum}:{DockerPortNum} -v {WorkStation_Dir}:{Doc When installing AutoGen locally, we recommend using a virtual environment for the installation. This will ensure that the dependencies for AutoGen are isolated from the rest of your system. -### Option a: venv +### Setup a virtual environment + +#### Option a: venv You can create a virtual environment with `venv` as below: @@ -109,7 +111,7 @@ The following command will deactivate the current `venv` environment: deactivate ``` -### Option b: conda +#### Option b: conda Another option is with `Conda`. You can install it by following [this doc](https://docs.conda.io/projects/conda/en/stable/user-guide/install/index.html), and then create a virtual environment as below: @@ -125,7 +127,7 @@ The following command will deactivate the current `conda` environment: conda deactivate ``` -### Option c: poetry +#### Option c: poetry Another option is with `poetry`, which is a dependency manager for Python. @@ -149,7 +151,7 @@ exit Now, you're ready to install AutoGen in the virtual environment you've just created. -## Python +### Python requirements AutoGen requires **Python version >= 3.8, < 3.12**. It can be installed from pip: @@ -159,11 +161,27 @@ pip install pyautogen `pyautogen<0.2` requires `openai<1`. Starting from pyautogen v0.2, `openai>=1` is required. - + +## Other Installation Options ### Migration guide to v0.2 @@ -189,30 +207,6 @@ Inference parameter tuning can be done via [`flaml.tune`](https://microsoft.gith ### Optional Dependencies -- #### Docker - -Even if you install AutoGen locally, we highly recommend using Docker for [code execution](FAQ.md#enable-python-3-docker-image). - -To use docker for code execution, you also need to install the python package `docker`: - -```bash -pip install docker -``` - -You might want to override the default docker image used for code execution. To do that set `use_docker` key of `code_execution_config` property to the name of the image. E.g.: - -```python -user_proxy = autogen.UserProxyAgent( - name="agent", - human_input_mode="TERMINATE", - max_consecutive_auto_reply=10, - code_execution_config={"work_dir":"_output", "use_docker":"python:3"}, - llm_config=llm_config, - system_message=""""Reply TERMINATE if the task has been solved at full satisfaction. -Otherwise, reply CONTINUE, or the reason why the task is not solved yet.""" -) -``` - - #### blendsearch `pyautogen<0.2` offers a cost-effective hyperparameter optimization technique [EcoOptiGen](https://arxiv.org/abs/2303.04673) for tuning Large Language Models. Please install with the [blendsearch] option to use it. From 39c18d3ec5f59290a3721499756fcfb1786f0cb3 Mon Sep 17 00:00:00 2001 From: olgavrou Date: Wed, 17 Jan 2024 13:22:33 -0500 Subject: [PATCH 12/18] update notebooks so that they can be run with change in default --- ...tchat_auto_feedback_from_code_execution.ipynb | 2 +- notebook/agentchat_compression.ipynb | 14 +++++++++++--- notebook/agentchat_function_call.ipynb | 5 ++++- notebook/agentchat_groupchat.ipynb | 6 +++++- notebook/agentchat_groupchat_research.ipynb | 6 +++++- notebook/agentchat_groupchat_vis.ipynb | 6 +++++- notebook/agentchat_guidance.ipynb | 5 ++++- notebook/agentchat_human_feedback.ipynb | 3 +++ notebook/agentchat_langchain.ipynb | 10 ++++++++-- notebook/agentchat_lmm_gpt-4v.ipynb | 10 +++++++++- notebook/agentchat_lmm_llava.ipynb | 16 +++++++++++++--- notebook/agentchat_microsoft_fabric.ipynb | 4 ++-- .../agentchat_oai_assistant_function_call.ipynb | 5 ++++- notebook/agentchat_oai_assistant_groupchat.ipynb | 6 +++++- ...agentchat_oai_assistant_twoagents_basic.ipynb | 5 ++++- notebook/agentchat_oai_code_interpreter.ipynb | 2 +- notebook/agentchat_planning.ipynb | 8 +++++++- notebook/agentchat_teachability.ipynb | 3 +++ .../agentchat_teachable_oai_assistants.ipynb | 7 +++++-- notebook/agentchat_two_users.ipynb | 10 ++++++++-- ...video_transcript_translate_with_whisper.ipynb | 5 ++++- notebook/agentchat_web_info.ipynb | 5 ++++- notebook/agenteval_cq_math.ipynb | 6 ++++++ 23 files changed, 121 insertions(+), 28 deletions(-) diff --git a/notebook/agentchat_auto_feedback_from_code_execution.ipynb b/notebook/agentchat_auto_feedback_from_code_execution.ipynb index 9c85fad5767..061078afda2 100644 --- a/notebook/agentchat_auto_feedback_from_code_execution.ipynb +++ b/notebook/agentchat_auto_feedback_from_code_execution.ipynb @@ -348,7 +348,7 @@ " is_termination_msg=lambda x: x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", " code_execution_config={\n", " \"work_dir\": \"coding\",\n", - " \"use_docker\": False, # set to True or image name like \"python:3\" to use docker\n", + " \"use_docker\": False, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " },\n", ")\n", "# the assistant receives a message from the user_proxy, which contains the task description\n", diff --git a/notebook/agentchat_compression.ipynb b/notebook/agentchat_compression.ipynb index f11417ba5cf..688c2d0e99e 100644 --- a/notebook/agentchat_compression.ipynb +++ b/notebook/agentchat_compression.ipynb @@ -561,7 +561,9 @@ "mathproxyagent = MathUserProxyAgent(\n", " name=\"mathproxyagent\",\n", " human_input_mode=\"NEVER\",\n", - " code_execution_config={\"use_docker\": False},\n", + " code_execution_config={\n", + " \"use_docker\": False\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " max_consecutive_auto_reply=5,\n", ")\n", "math_problem = (\n", @@ -835,7 +837,10 @@ " is_termination_msg=lambda x: x.get(\"content\", \"\") and x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", " human_input_mode=\"NEVER\",\n", " max_consecutive_auto_reply=10,\n", - " code_execution_config={\"work_dir\": \"coding\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"coding\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", ")\n", "\n", "\n", @@ -1259,7 +1264,10 @@ " max_consecutive_auto_reply=10,\n", " is_termination_msg=lambda x: x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\")\n", " or x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE.\"),\n", - " code_execution_config={\"work_dir\": \"web\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"web\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " system_message=\"\"\"Reply TERMINATE if the task has been solved at full satisfaction.\n", "Otherwise, reply CONTINUE, or the reason why the task is not solved yet.\"\"\",\n", ")\n", diff --git a/notebook/agentchat_function_call.ipynb b/notebook/agentchat_function_call.ipynb index b6e077cba50..8716ed32ee8 100644 --- a/notebook/agentchat_function_call.ipynb +++ b/notebook/agentchat_function_call.ipynb @@ -211,7 +211,10 @@ " is_termination_msg=lambda x: x.get(\"content\", \"\") and x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", " human_input_mode=\"NEVER\",\n", " max_consecutive_auto_reply=10,\n", - " code_execution_config={\"work_dir\": \"coding\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"coding\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", ")\n", "\n", "\n", diff --git a/notebook/agentchat_groupchat.ipynb b/notebook/agentchat_groupchat.ipynb index 5a928cc06d7..28b0edd26c8 100644 --- a/notebook/agentchat_groupchat.ipynb +++ b/notebook/agentchat_groupchat.ipynb @@ -128,7 +128,11 @@ "user_proxy = autogen.UserProxyAgent(\n", " name=\"User_proxy\",\n", " system_message=\"A human admin.\",\n", - " code_execution_config={\"last_n_messages\": 2, \"work_dir\": \"groupchat\"},\n", + " code_execution_config={\n", + " \"last_n_messages\": 2,\n", + " \"work_dir\": \"groupchat\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " human_input_mode=\"TERMINATE\",\n", ")\n", "coder = autogen.AssistantAgent(\n", diff --git a/notebook/agentchat_groupchat_research.ipynb b/notebook/agentchat_groupchat_research.ipynb index 23056703c6f..360ed11f4e4 100644 --- a/notebook/agentchat_groupchat_research.ipynb +++ b/notebook/agentchat_groupchat_research.ipynb @@ -146,7 +146,11 @@ " name=\"Executor\",\n", " system_message=\"Executor. Execute the code written by the engineer and report the result.\",\n", " human_input_mode=\"NEVER\",\n", - " code_execution_config={\"last_n_messages\": 3, \"work_dir\": \"paper\"},\n", + " code_execution_config={\n", + " \"last_n_messages\": 3,\n", + " \"work_dir\": \"paper\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", ")\n", "critic = autogen.AssistantAgent(\n", " name=\"Critic\",\n", diff --git a/notebook/agentchat_groupchat_vis.ipynb b/notebook/agentchat_groupchat_vis.ipynb index 5d0549bd7dd..c935984955c 100644 --- a/notebook/agentchat_groupchat_vis.ipynb +++ b/notebook/agentchat_groupchat_vis.ipynb @@ -141,7 +141,11 @@ "user_proxy = autogen.UserProxyAgent(\n", " name=\"User_proxy\",\n", " system_message=\"A human admin.\",\n", - " code_execution_config={\"last_n_messages\": 3, \"work_dir\": \"groupchat\"},\n", + " code_execution_config={\n", + " \"last_n_messages\": 3,\n", + " \"work_dir\": \"groupchat\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " human_input_mode=\"NEVER\",\n", ")\n", "coder = autogen.AssistantAgent(\n", diff --git a/notebook/agentchat_guidance.ipynb b/notebook/agentchat_guidance.ipynb index efd8aa5de35..2412c3a228d 100644 --- a/notebook/agentchat_guidance.ipynb +++ b/notebook/agentchat_guidance.ipynb @@ -178,7 +178,10 @@ "user_proxy = UserProxyAgent(\n", " \"user\",\n", " human_input_mode=\"TERMINATE\",\n", - " code_execution_config={\"work_dir\": \"coding\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"coding\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " is_termination_msg=lambda msg: \"TERMINATE\" in msg.get(\"content\"),\n", ")\n", "user_proxy.initiate_chat(guidance_agent, message=\"Plot and save a chart of nvidia and tsla stock price change YTD.\")" diff --git a/notebook/agentchat_human_feedback.ipynb b/notebook/agentchat_human_feedback.ipynb index 4bf073deae2..d78b8a3f1d3 100644 --- a/notebook/agentchat_human_feedback.ipynb +++ b/notebook/agentchat_human_feedback.ipynb @@ -134,6 +134,9 @@ " name=\"user_proxy\",\n", " human_input_mode=\"ALWAYS\",\n", " is_termination_msg=lambda x: x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", + " code_execution_config={\n", + " \"use_docker\": False\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", ")" ] }, diff --git a/notebook/agentchat_langchain.ipynb b/notebook/agentchat_langchain.ipynb index 14d749c0ed3..38623031bfb 100644 --- a/notebook/agentchat_langchain.ipynb +++ b/notebook/agentchat_langchain.ipynb @@ -312,7 +312,10 @@ " is_termination_msg=lambda x: x.get(\"content\", \"\") and x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", " human_input_mode=\"NEVER\",\n", " max_consecutive_auto_reply=10,\n", - " code_execution_config={\"work_dir\": \"coding\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"coding\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", ")\n", "\n", "# Register the tool and start the conversation\n", @@ -659,7 +662,10 @@ " is_termination_msg=lambda x: x.get(\"content\", \"\") and x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", " human_input_mode=\"NEVER\",\n", " max_consecutive_auto_reply=10,\n", - " code_execution_config={\"work_dir\": \"coding\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"coding\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", ")\n", "\n", "print(function_map)\n", diff --git a/notebook/agentchat_lmm_gpt-4v.ipynb b/notebook/agentchat_lmm_gpt-4v.ipynb index 5e074e494b2..cc176b44935 100644 --- a/notebook/agentchat_lmm_gpt-4v.ipynb +++ b/notebook/agentchat_lmm_gpt-4v.ipynb @@ -130,6 +130,9 @@ " system_message=\"A human admin.\",\n", " human_input_mode=\"NEVER\", # Try between ALWAYS or NEVER\n", " max_consecutive_auto_reply=0,\n", + " code_execution_config={\n", + " \"use_docker\": False\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", ")\n", "\n", "# Ask the question with an image\n", @@ -662,7 +665,9 @@ "\n", "creator = FigureCreator(name=\"Figure Creator~\", llm_config=gpt4_llm_config)\n", "\n", - "user_proxy = autogen.UserProxyAgent(name=\"User\", human_input_mode=\"NEVER\", max_consecutive_auto_reply=0)\n", + "user_proxy = autogen.UserProxyAgent(\n", + " name=\"User\", human_input_mode=\"NEVER\", max_consecutive_auto_reply=0, code_execution_config={\"use_docker\": False}\n", + ")\n", "\n", "user_proxy.initiate_chat(\n", " creator,\n", @@ -770,6 +775,9 @@ " system_message=\"Ask both image explainer 1 and 2 for their description.\",\n", " human_input_mode=\"TERMINATE\", # Try between ALWAYS, NEVER, and TERMINATE\n", " max_consecutive_auto_reply=10,\n", + " code_execution_config={\n", + " \"use_docker\": False\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", ")\n", "\n", "# We set max_round to 5\n", diff --git a/notebook/agentchat_lmm_llava.ipynb b/notebook/agentchat_lmm_llava.ipynb index 061d84e2445..61efc74e00e 100644 --- a/notebook/agentchat_lmm_llava.ipynb +++ b/notebook/agentchat_lmm_llava.ipynb @@ -283,7 +283,11 @@ "user_proxy = autogen.UserProxyAgent(\n", " name=\"User_proxy\",\n", " system_message=\"A human admin.\",\n", - " code_execution_config={\"last_n_messages\": 3, \"work_dir\": \"groupchat\"},\n", + " code_execution_config={\n", + " \"last_n_messages\": 3,\n", + " \"work_dir\": \"groupchat\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " human_input_mode=\"NEVER\", # Try between ALWAYS or NEVER\n", " max_consecutive_auto_reply=0,\n", ")\n", @@ -412,7 +416,11 @@ " max_consecutive_auto_reply=10,\n", " system_message=\"Help me run the code, and tell other agents it is in the file location.\",\n", " is_termination_msg=lambda x: x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", - " code_execution_config={\"last_n_messages\": 3, \"work_dir\": \".\", \"use_docker\": False},\n", + " code_execution_config={\n", + " \"last_n_messages\": 3,\n", + " \"work_dir\": \".\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " llm_config=self.llm_config,\n", " )\n", "\n", @@ -823,7 +831,9 @@ "\n", "creator = FigureCreator(name=\"Figure Creator~\", llm_config=gpt4_llm_config)\n", "\n", - "user_proxy = autogen.UserProxyAgent(name=\"User\", human_input_mode=\"NEVER\", max_consecutive_auto_reply=0)\n", + "user_proxy = autogen.UserProxyAgent(\n", + " name=\"User\", human_input_mode=\"NEVER\", max_consecutive_auto_reply=0, code_execution_config={\"use_docker\": False}\n", + ") # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", "\n", "user_proxy.initiate_chat(\n", " creator,\n", diff --git a/notebook/agentchat_microsoft_fabric.ipynb b/notebook/agentchat_microsoft_fabric.ipynb index 84e43dbb820..f4de95f69cf 100644 --- a/notebook/agentchat_microsoft_fabric.ipynb +++ b/notebook/agentchat_microsoft_fabric.ipynb @@ -327,7 +327,7 @@ " is_termination_msg=lambda x: x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", " code_execution_config={\n", " \"work_dir\": \"coding\",\n", - " \"use_docker\": False, # set to True or image name like \"python:3\" to use docker\n", + " \"use_docker\": False, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " },\n", " llm_config=llm_config,\n", " system_message=\"\"\"Reply TERMINATE if the task has been solved at full satisfaction.\n", @@ -768,7 +768,7 @@ " is_termination_msg=lambda x: x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", " code_execution_config={\n", " \"work_dir\": \"coding\",\n", - " \"use_docker\": False, # set to True or image name like \"python:3\" to use docker\n", + " \"use_docker\": False, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " },\n", ")\n", "# the assistant receives a message from the user_proxy, which contains the task description\n", diff --git a/notebook/agentchat_oai_assistant_function_call.ipynb b/notebook/agentchat_oai_assistant_function_call.ipynb index 64393be1562..804a413966e 100644 --- a/notebook/agentchat_oai_assistant_function_call.ipynb +++ b/notebook/agentchat_oai_assistant_function_call.ipynb @@ -233,7 +233,10 @@ "source": [ "user_proxy = UserProxyAgent(\n", " name=\"user_proxy\",\n", - " code_execution_config={\"work_dir\": \"coding\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"coding\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " is_termination_msg=lambda msg: \"TERMINATE\" in msg[\"content\"],\n", " human_input_mode=\"NEVER\",\n", " max_consecutive_auto_reply=1,\n", diff --git a/notebook/agentchat_oai_assistant_groupchat.ipynb b/notebook/agentchat_oai_assistant_groupchat.ipynb index 9a0bf89f909..d30ef0bab02 100644 --- a/notebook/agentchat_oai_assistant_groupchat.ipynb +++ b/notebook/agentchat_oai_assistant_groupchat.ipynb @@ -92,7 +92,11 @@ "user_proxy = autogen.UserProxyAgent(\n", " name=\"User_proxy\",\n", " system_message=\"A human admin.\",\n", - " code_execution_config={\"last_n_messages\": 2, \"work_dir\": \"groupchat\"},\n", + " code_execution_config={\n", + " \"last_n_messages\": 2,\n", + " \"work_dir\": \"groupchat\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " human_input_mode=\"TERMINATE\",\n", ")\n", "\n", diff --git a/notebook/agentchat_oai_assistant_twoagents_basic.ipynb b/notebook/agentchat_oai_assistant_twoagents_basic.ipynb index 3db0e937ad7..a4343e46e03 100644 --- a/notebook/agentchat_oai_assistant_twoagents_basic.ipynb +++ b/notebook/agentchat_oai_assistant_twoagents_basic.ipynb @@ -96,7 +96,10 @@ "\n", "user_proxy = UserProxyAgent(\n", " name=\"user_proxy\",\n", - " code_execution_config={\"work_dir\": \"coding\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"coding\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " is_termination_msg=lambda msg: \"TERMINATE\" in msg[\"content\"],\n", " human_input_mode=\"NEVER\",\n", " max_consecutive_auto_reply=1,\n", diff --git a/notebook/agentchat_oai_code_interpreter.ipynb b/notebook/agentchat_oai_code_interpreter.ipynb index c8c97fe47fe..c31c2f03881 100644 --- a/notebook/agentchat_oai_code_interpreter.ipynb +++ b/notebook/agentchat_oai_code_interpreter.ipynb @@ -127,7 +127,7 @@ " is_termination_msg=lambda msg: \"TERMINATE\" in msg[\"content\"],\n", " code_execution_config={\n", " \"work_dir\": \"coding\",\n", - " \"use_docker\": False, # set to True or image name like \"python:3\" to use docker\n", + " \"use_docker\": False, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " },\n", " human_input_mode=\"NEVER\",\n", ")\n", diff --git a/notebook/agentchat_planning.ipynb b/notebook/agentchat_planning.ipynb index 84b8c05b2cc..6a43cc249cd 100644 --- a/notebook/agentchat_planning.ipynb +++ b/notebook/agentchat_planning.ipynb @@ -128,6 +128,9 @@ " name=\"planner_user\",\n", " max_consecutive_auto_reply=0, # terminate without auto-reply\n", " human_input_mode=\"NEVER\",\n", + " code_execution_config={\n", + " \"use_docker\": False\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", ")\n", "\n", "\n", @@ -184,7 +187,10 @@ " human_input_mode=\"TERMINATE\",\n", " max_consecutive_auto_reply=10,\n", " # is_termination_msg=lambda x: \"content\" in x and x[\"content\"] is not None and x[\"content\"].rstrip().endswith(\"TERMINATE\"),\n", - " code_execution_config={\"work_dir\": \"planning\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"planning\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " function_map={\"ask_planner\": ask_planner},\n", ")" ] diff --git a/notebook/agentchat_teachability.ipynb b/notebook/agentchat_teachability.ipynb index 7b2f6c63f75..564fd9e781a 100644 --- a/notebook/agentchat_teachability.ipynb +++ b/notebook/agentchat_teachability.ipynb @@ -175,6 +175,9 @@ " human_input_mode=\"NEVER\",\n", " is_termination_msg=lambda x: True if \"TERMINATE\" in x.get(\"content\") else False,\n", " max_consecutive_auto_reply=0,\n", + " code_execution_config={\n", + " \"use_docker\": False\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", ")" ] }, diff --git a/notebook/agentchat_teachable_oai_assistants.ipynb b/notebook/agentchat_teachable_oai_assistants.ipynb index 931ac10fded..8647b4a4171 100644 --- a/notebook/agentchat_teachable_oai_assistants.ipynb +++ b/notebook/agentchat_teachable_oai_assistants.ipynb @@ -330,7 +330,10 @@ "source": [ "user_proxy = UserProxyAgent(\n", " name=\"user_proxy\",\n", - " code_execution_config={\"work_dir\": \"coding\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"coding\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " is_termination_msg=lambda msg: \"TERMINATE\" in msg[\"content\"],\n", " human_input_mode=\"NEVER\",\n", " max_consecutive_auto_reply=0,\n", @@ -587,7 +590,7 @@ " is_termination_msg=lambda msg: \"TERMINATE\" in msg[\"content\"],\n", " code_execution_config={\n", " \"work_dir\": \"coding\",\n", - " \"use_docker\": False, # set to True or image name like \"python:3\" to use docker\n", + " \"use_docker\": False, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " },\n", " human_input_mode=\"NEVER\",\n", " max_consecutive_auto_reply=0,\n", diff --git a/notebook/agentchat_two_users.ipynb b/notebook/agentchat_two_users.ipynb index 54fe9f4d05e..4da4d90b2a2 100644 --- a/notebook/agentchat_two_users.ipynb +++ b/notebook/agentchat_two_users.ipynb @@ -128,7 +128,10 @@ " expert = autogen.UserProxyAgent(\n", " name=\"expert\",\n", " human_input_mode=\"ALWAYS\",\n", - " code_execution_config={\"work_dir\": \"expert\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"expert\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " )\n", "\n", " expert.initiate_chat(assistant_for_expert, message=message)\n", @@ -187,7 +190,10 @@ " name=\"student\",\n", " human_input_mode=\"TERMINATE\",\n", " max_consecutive_auto_reply=10,\n", - " code_execution_config={\"work_dir\": \"student\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"student\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " function_map={\"ask_expert\": ask_expert},\n", ")" ] diff --git a/notebook/agentchat_video_transcript_translate_with_whisper.ipynb b/notebook/agentchat_video_transcript_translate_with_whisper.ipynb index 62d30b7f7af..f100933ff32 100644 --- a/notebook/agentchat_video_transcript_translate_with_whisper.ipynb +++ b/notebook/agentchat_video_transcript_translate_with_whisper.ipynb @@ -359,7 +359,10 @@ " is_termination_msg=lambda x: x.get(\"content\", \"\") and x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", " human_input_mode=\"NEVER\",\n", " max_consecutive_auto_reply=10,\n", - " code_execution_config={\"work_dir\": \"coding_2\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"coding_2\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", ")\n", "\n", "user_proxy.register_function(\n", diff --git a/notebook/agentchat_web_info.ipynb b/notebook/agentchat_web_info.ipynb index abf527c3e29..d10fa1ab825 100644 --- a/notebook/agentchat_web_info.ipynb +++ b/notebook/agentchat_web_info.ipynb @@ -146,7 +146,10 @@ " human_input_mode=\"TERMINATE\",\n", " max_consecutive_auto_reply=10,\n", " is_termination_msg=lambda x: x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", - " code_execution_config={\"work_dir\": \"web\"},\n", + " code_execution_config={\n", + " \"work_dir\": \"web\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", " llm_config=llm_config,\n", " system_message=\"\"\"Reply TERMINATE if the task has been solved at full satisfaction.\n", "Otherwise, reply CONTINUE, or the reason why the task is not solved yet.\"\"\",\n", diff --git a/notebook/agenteval_cq_math.ipynb b/notebook/agenteval_cq_math.ipynb index 613d2b753c9..b1b893975d3 100644 --- a/notebook/agenteval_cq_math.ipynb +++ b/notebook/agenteval_cq_math.ipynb @@ -134,6 +134,9 @@ " name=\"critic_user\",\n", " max_consecutive_auto_reply=0, # terminate without auto-reply\n", " human_input_mode=\"NEVER\",\n", + " code_execution_config={\n", + " \"use_docker\": False\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", ")\n", "\n", "\n", @@ -414,6 +417,9 @@ " name=\"quantifier_user\",\n", " max_consecutive_auto_reply=0, # terminate without auto-reply\n", " human_input_mode=\"NEVER\",\n", + " code_execution_config={\n", + " \"use_docker\": False\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", ")\n", "\n", "dictionary_for_eval = open(criteria_file, \"r\").read()" From fb424c975a3f747947b27a146fef8e6bb5c0b688 Mon Sep 17 00:00:00 2001 From: olgavrou Date: Wed, 17 Jan 2024 15:24:04 -0500 Subject: [PATCH 13/18] add unit tests for new code --- ...st_agent_setup_with_use_docker_settings.py | 116 ++++++++++++++++++ test/test_code.py | 99 +++++++++++++-- 2 files changed, 203 insertions(+), 12 deletions(-) create mode 100644 test/agentchat/test_agent_setup_with_use_docker_settings.py diff --git a/test/agentchat/test_agent_setup_with_use_docker_settings.py b/test/agentchat/test_agent_setup_with_use_docker_settings.py new file mode 100644 index 00000000000..f4b5325ee44 --- /dev/null +++ b/test/agentchat/test_agent_setup_with_use_docker_settings.py @@ -0,0 +1,116 @@ +from autogen import UserProxyAgent +import pytest +from conftest import skip_openai + +from autogen.code_utils import ( + is_docker_running, + in_docker_container, +) + +try: + import openai +except ImportError: + skip = True +else: + skip = False or skip_openai + + +def clear_autogen_use_docker_env_var(): + import os + + # Ensure the environment variable is cleared + if "AUTOGEN_USE_DOCKER" in os.environ: + del os.environ["AUTOGEN_USE_DOCKER"] + + +def docker_running(): + return is_docker_running() or in_docker_container() + + +@pytest.mark.skipif(skip, reason="openai not installed") +def test_agent_setup_with_code_execution_off(): + user_proxy = UserProxyAgent( + name="test_agent", + human_input_mode="NEVER", + code_execution_config=False, + ) + + assert user_proxy._code_execution_config is False + + +@pytest.mark.skipif(skip, reason="openai not installed") +def test_agent_setup_with_use_docker_false(): + user_proxy = UserProxyAgent( + name="test_agent", + human_input_mode="NEVER", + code_execution_config={"use_docker": False}, + ) + + assert user_proxy._code_execution_config["use_docker"] is False + + +@pytest.mark.skipif(skip, reason="openai not installed") +def test_agent_setup_with_env_variable_false_and_docker_running(): + clear_autogen_use_docker_env_var() + import os + + os.environ["AUTOGEN_USE_DOCKER"] = "False" + user_proxy = UserProxyAgent( + name="test_agent", + human_input_mode="NEVER", + ) + + assert user_proxy._code_execution_config["use_docker"] is False + clear_autogen_use_docker_env_var() + + +@pytest.mark.skipif(skip or (not docker_running()), reason="openai not installed OR docker not running") +def test_agent_setup_with_default_and_docker_running(): + user_proxy = UserProxyAgent( + name="test_agent", + human_input_mode="NEVER", + ) + + assert user_proxy._code_execution_config["use_docker"] is True + + +@pytest.mark.skipif(skip or (docker_running()), reason="openai not installed OR docker running") +def test_raises_error_agent_setup_with_default_and_docker_not_running(): + with pytest.raises(RuntimeError): + UserProxyAgent( + name="test_agent", + human_input_mode="NEVER", + ) + + +@pytest.mark.skipif(skip or (docker_running()), reason="openai not installed OR docker running") +def test_raises_error_agent_setup_with_env_variable_true_and_docker_not_running(): + clear_autogen_use_docker_env_var() + import os + + os.environ["AUTOGEN_USE_DOCKER"] = "True" + + with pytest.raises(RuntimeError): + UserProxyAgent( + name="test_agent", + human_input_mode="NEVER", + ) + + clear_autogen_use_docker_env_var() + + +@pytest.mark.skipif(skip or (not docker_running()), reason="openai not installed OR docker not running") +def test_agent_setup_with_env_variable_true_and_docker_running(): + clear_autogen_use_docker_env_var() + import os + + os.environ["AUTOGEN_USE_DOCKER"] = "True" + + user_proxy = UserProxyAgent( + name="test_agent", + human_input_mode="NEVER", + ) + + assert user_proxy._code_execution_config["use_docker"] is True + + clear_autogen_use_docker_env_var() diff --git a/test/test_code.py b/test/test_code.py index 36e0e17e38d..3cb8d09190d 100644 --- a/test/test_code.py +++ b/test/test_code.py @@ -16,6 +16,10 @@ improve_code, improve_function, infer_lang, + is_docker_running, + in_docker_container, + decide_use_docker, + check_can_use_docker_or_throw, ) KEY_LOC = "notebook" @@ -309,10 +313,7 @@ def scrape(url): assert len(codeblocks) == 1 and codeblocks[0] == ("", "source setup.sh") -@pytest.mark.skipif( - sys.platform in ["darwin", "win32"], - reason="do not run on MacOS or Windows", -) +@pytest.mark.skipif(not is_docker_running() and not in_docker_container(), reason="docker is not running") def test_execute_code(use_docker=None): try: import docker @@ -354,20 +355,14 @@ def test_execute_code(use_docker=None): assert isinstance(image, str) or docker is None or os.path.exists("/.dockerenv") or use_docker is False -@pytest.mark.skipif( - sys.platform in ["darwin", "win32"], - reason="do not run on MacOS or Windows", -) +@pytest.mark.skipif(not is_docker_running() and not in_docker_container(), reason="docker is not running") def test_execute_code_with_custom_filename_on_docker(): exit_code, msg, image = execute_code("print('hello world')", filename="tmp/codetest.py", use_docker=True) assert exit_code == 0 and msg == "hello world\n", msg assert image == "python:tmp_codetest.py" -@pytest.mark.skipif( - sys.platform in ["darwin", "win32"], - reason="do not run on MacOS or Windows", -) +@pytest.mark.skipif(not is_docker_running() and not in_docker_container(), reason="docker is not running") def test_execute_code_with_misformed_filename_on_docker(): exit_code, msg, image = execute_code( "print('hello world')", filename="tmp/codetest.py (some extra information)", use_docker=True @@ -392,6 +387,86 @@ def test_execute_code_no_docker(): assert image is None +def clear_autogen_use_docker_env_var(): + # Ensure the environment variable is cleared + if "AUTOGEN_USE_DOCKER" in os.environ: + del os.environ["AUTOGEN_USE_DOCKER"] + + +def test_decide_use_docker_truthy_values(): + clear_autogen_use_docker_env_var() + for truthy_value in ["1", "true", "yes", "t"]: + os.environ["AUTOGEN_USE_DOCKER"] = truthy_value + assert decide_use_docker(None) is True + clear_autogen_use_docker_env_var() + + +def test_decide_use_docker_falsy_values(): + clear_autogen_use_docker_env_var() + for falsy_value in ["0", "false", "no", "f"]: + os.environ["AUTOGEN_USE_DOCKER"] = falsy_value + assert decide_use_docker(None) is False + clear_autogen_use_docker_env_var() + + +def test_decide_use_docker_none_value(): + clear_autogen_use_docker_env_var() + os.environ["AUTOGEN_USE_DOCKER"] = "none" + assert decide_use_docker(None) is None + clear_autogen_use_docker_env_var() + + +def test_decide_use_docker_invalid_value(): + clear_autogen_use_docker_env_var() + os.environ["AUTOGEN_USE_DOCKER"] = "invalid" + with pytest.raises(ValueError): + decide_use_docker(None) + clear_autogen_use_docker_env_var() + + +# test that input overrides environment variable +def test_decide_use_docker_with_env_var(): + clear_autogen_use_docker_env_var() + os.environ["AUTOGEN_USE_DOCKER"] = "false" + assert decide_use_docker(None) is False + clear_autogen_use_docker_env_var() + os.environ["AUTOGEN_USE_DOCKER"] = "true" + assert decide_use_docker(None) is True + clear_autogen_use_docker_env_var() + os.environ["AUTOGEN_USE_DOCKER"] = "none" + assert decide_use_docker(None) is None + clear_autogen_use_docker_env_var() + os.environ["AUTOGEN_USE_DOCKER"] = "invalid" + with pytest.raises(ValueError): + decide_use_docker(None) + clear_autogen_use_docker_env_var() + + +def test_decide_use_docker_with_env_var_and_argument(): + clear_autogen_use_docker_env_var() + os.environ["AUTOGEN_USE_DOCKER"] = "false" + assert decide_use_docker(True) is True + clear_autogen_use_docker_env_var() + os.environ["AUTOGEN_USE_DOCKER"] = "true" + assert decide_use_docker(False) is False + clear_autogen_use_docker_env_var() + os.environ["AUTOGEN_USE_DOCKER"] = "none" + assert decide_use_docker(True) is True + clear_autogen_use_docker_env_var() + os.environ["AUTOGEN_USE_DOCKER"] = "invalid" + assert decide_use_docker(True) is True + clear_autogen_use_docker_env_var() + + +def test_can_use_docker_or_throw(): + check_can_use_docker_or_throw(None) + if not is_docker_running() and not in_docker_container(): + check_can_use_docker_or_throw(False) + if not is_docker_running() and not in_docker_container(): + with pytest.raises(RuntimeError): + check_can_use_docker_or_throw(True) + + def _test_improve(): try: import openai From eff47ea5a4df15bb4db25ac190946b76daa8c755 Mon Sep 17 00:00:00 2001 From: olgavrou Date: Wed, 17 Jan 2024 15:50:27 -0500 Subject: [PATCH 14/18] cache and restore env var --- ...st_agent_setup_with_use_docker_settings.py | 28 +++++----- test/test_code.py | 55 ++++++++++--------- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/test/agentchat/test_agent_setup_with_use_docker_settings.py b/test/agentchat/test_agent_setup_with_use_docker_settings.py index f4b5325ee44..8cda4466e16 100644 --- a/test/agentchat/test_agent_setup_with_use_docker_settings.py +++ b/test/agentchat/test_agent_setup_with_use_docker_settings.py @@ -1,6 +1,7 @@ from autogen import UserProxyAgent import pytest from conftest import skip_openai +import os from autogen.code_utils import ( is_docker_running, @@ -15,12 +16,15 @@ skip = False or skip_openai -def clear_autogen_use_docker_env_var(): - import os +def get_current_autogen_env_var(): + return os.environ.get("AUTOGEN_USE_DOCKER", None) - # Ensure the environment variable is cleared - if "AUTOGEN_USE_DOCKER" in os.environ: + +def restore_autogen_env_var(current_env_value): + if current_env_value is None: del os.environ["AUTOGEN_USE_DOCKER"] + else: + os.environ["AUTOGEN_USE_DOCKER"] = current_env_value def docker_running(): @@ -51,8 +55,7 @@ def test_agent_setup_with_use_docker_false(): @pytest.mark.skipif(skip, reason="openai not installed") def test_agent_setup_with_env_variable_false_and_docker_running(): - clear_autogen_use_docker_env_var() - import os + current_env_value = get_current_autogen_env_var() os.environ["AUTOGEN_USE_DOCKER"] = "False" user_proxy = UserProxyAgent( @@ -61,7 +64,8 @@ def test_agent_setup_with_env_variable_false_and_docker_running(): ) assert user_proxy._code_execution_config["use_docker"] is False - clear_autogen_use_docker_env_var() + + restore_autogen_env_var(current_env_value) @pytest.mark.skipif(skip or (not docker_running()), reason="openai not installed OR docker not running") @@ -85,8 +89,7 @@ def test_raises_error_agent_setup_with_default_and_docker_not_running(): @pytest.mark.skipif(skip or (docker_running()), reason="openai not installed OR docker running") def test_raises_error_agent_setup_with_env_variable_true_and_docker_not_running(): - clear_autogen_use_docker_env_var() - import os + current_env_value = get_current_autogen_env_var() os.environ["AUTOGEN_USE_DOCKER"] = "True" @@ -96,13 +99,12 @@ def test_raises_error_agent_setup_with_env_variable_true_and_docker_not_running( human_input_mode="NEVER", ) - clear_autogen_use_docker_env_var() + restore_autogen_env_var(current_env_value) @pytest.mark.skipif(skip or (not docker_running()), reason="openai not installed OR docker not running") def test_agent_setup_with_env_variable_true_and_docker_running(): - clear_autogen_use_docker_env_var() - import os + current_env_value = get_current_autogen_env_var() os.environ["AUTOGEN_USE_DOCKER"] = "True" @@ -113,4 +115,4 @@ def test_agent_setup_with_env_variable_true_and_docker_running(): assert user_proxy._code_execution_config["use_docker"] is True - clear_autogen_use_docker_env_var() + restore_autogen_env_var(current_env_value) diff --git a/test/test_code.py b/test/test_code.py index 3cb8d09190d..5729c711fef 100644 --- a/test/test_code.py +++ b/test/test_code.py @@ -387,75 +387,78 @@ def test_execute_code_no_docker(): assert image is None -def clear_autogen_use_docker_env_var(): - # Ensure the environment variable is cleared - if "AUTOGEN_USE_DOCKER" in os.environ: +def get_current_autogen_env_var(): + return os.environ.get("AUTOGEN_USE_DOCKER", None) + + +def restore_autogen_env_var(current_env_value): + if current_env_value is None: del os.environ["AUTOGEN_USE_DOCKER"] + else: + os.environ["AUTOGEN_USE_DOCKER"] = current_env_value def test_decide_use_docker_truthy_values(): - clear_autogen_use_docker_env_var() + current_env_value = get_current_autogen_env_var() + for truthy_value in ["1", "true", "yes", "t"]: os.environ["AUTOGEN_USE_DOCKER"] = truthy_value assert decide_use_docker(None) is True - clear_autogen_use_docker_env_var() + + restore_autogen_env_var(current_env_value) def test_decide_use_docker_falsy_values(): - clear_autogen_use_docker_env_var() + current_env_value = get_current_autogen_env_var() + for falsy_value in ["0", "false", "no", "f"]: os.environ["AUTOGEN_USE_DOCKER"] = falsy_value assert decide_use_docker(None) is False - clear_autogen_use_docker_env_var() + restore_autogen_env_var(current_env_value) -def test_decide_use_docker_none_value(): - clear_autogen_use_docker_env_var() - os.environ["AUTOGEN_USE_DOCKER"] = "none" - assert decide_use_docker(None) is None - clear_autogen_use_docker_env_var() +def test_decide_use_docker(): + current_env_value = get_current_autogen_env_var() -def test_decide_use_docker_invalid_value(): - clear_autogen_use_docker_env_var() + os.environ["AUTOGEN_USE_DOCKER"] = "none" + assert decide_use_docker(None) is None os.environ["AUTOGEN_USE_DOCKER"] = "invalid" with pytest.raises(ValueError): decide_use_docker(None) - clear_autogen_use_docker_env_var() + + restore_autogen_env_var(current_env_value) -# test that input overrides environment variable def test_decide_use_docker_with_env_var(): - clear_autogen_use_docker_env_var() + current_env_value = get_current_autogen_env_var() + os.environ["AUTOGEN_USE_DOCKER"] = "false" assert decide_use_docker(None) is False - clear_autogen_use_docker_env_var() os.environ["AUTOGEN_USE_DOCKER"] = "true" assert decide_use_docker(None) is True - clear_autogen_use_docker_env_var() os.environ["AUTOGEN_USE_DOCKER"] = "none" assert decide_use_docker(None) is None - clear_autogen_use_docker_env_var() os.environ["AUTOGEN_USE_DOCKER"] = "invalid" with pytest.raises(ValueError): decide_use_docker(None) - clear_autogen_use_docker_env_var() + + restore_autogen_env_var(current_env_value) def test_decide_use_docker_with_env_var_and_argument(): - clear_autogen_use_docker_env_var() + current_env_value = get_current_autogen_env_var() + os.environ["AUTOGEN_USE_DOCKER"] = "false" assert decide_use_docker(True) is True - clear_autogen_use_docker_env_var() os.environ["AUTOGEN_USE_DOCKER"] = "true" assert decide_use_docker(False) is False - clear_autogen_use_docker_env_var() os.environ["AUTOGEN_USE_DOCKER"] = "none" assert decide_use_docker(True) is True - clear_autogen_use_docker_env_var() os.environ["AUTOGEN_USE_DOCKER"] = "invalid" assert decide_use_docker(True) is True - clear_autogen_use_docker_env_var() + + restore_autogen_env_var(current_env_value) def test_can_use_docker_or_throw(): From 185840b8adb631f7cc72b6bf6f1583063e156f48 Mon Sep 17 00:00:00 2001 From: olgavrou Date: Wed, 17 Jan 2024 16:18:19 -0500 Subject: [PATCH 15/18] skip on windows because docker is running in the CI but there are problems connecting the volume --- test/test_code.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/test/test_code.py b/test/test_code.py index 5729c711fef..cf3d7f27a9c 100644 --- a/test/test_code.py +++ b/test/test_code.py @@ -313,7 +313,10 @@ def scrape(url): assert len(codeblocks) == 1 and codeblocks[0] == ("", "source setup.sh") -@pytest.mark.skipif(not is_docker_running() and not in_docker_container(), reason="docker is not running") +# skip if os is windows +@pytest.mark.skipif( + sys.platform in ["win32"] or (not is_docker_running() and not in_docker_container()), reason="docker is not running" +) def test_execute_code(use_docker=None): try: import docker @@ -355,14 +358,18 @@ def test_execute_code(use_docker=None): assert isinstance(image, str) or docker is None or os.path.exists("/.dockerenv") or use_docker is False -@pytest.mark.skipif(not is_docker_running() and not in_docker_container(), reason="docker is not running") +@pytest.mark.skipif( + sys.platform in ["win32"] or (not is_docker_running() and not in_docker_container()), reason="docker is not running" +) def test_execute_code_with_custom_filename_on_docker(): exit_code, msg, image = execute_code("print('hello world')", filename="tmp/codetest.py", use_docker=True) assert exit_code == 0 and msg == "hello world\n", msg assert image == "python:tmp_codetest.py" -@pytest.mark.skipif(not is_docker_running() and not in_docker_container(), reason="docker is not running") +@pytest.mark.skipif( + sys.platform in ["win32"] or (not is_docker_running() and not in_docker_container()), reason="docker is not running" +) def test_execute_code_with_misformed_filename_on_docker(): exit_code, msg, image = execute_code( "print('hello world')", filename="tmp/codetest.py (some extra information)", use_docker=True From 9bb31876b79294ff8adabd50830707ab811125af Mon Sep 17 00:00:00 2001 From: olgavrou Date: Wed, 17 Jan 2024 18:27:14 -0500 Subject: [PATCH 16/18] update documentation --- README.md | 6 +++--- test/twoagent.py | 4 +++- website/docs/Getting-Started.md | 2 +- website/docs/Installation.md | 4 +++- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 99131cb461f..bcb6b413919 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ The easiest way to start playing is ## [Installation](https://microsoft.github.io/autogen/docs/Installation) ### Option 1. Install and Run AutoGen in Docker -Find detailed instructions for users [here](https://microsoft.github.io/autogen/docs/Installation#option-1-install-and-run-autogen-in-docker), and for developers [here](https://microsoft.github.io/autogen/docs/Contribute#docker). +Find detailed instructions for users [here](https://microsoft.github.io/autogen/docs/Installation#option-1-install-and-run-autogen-in-docker), and for developers [here](https://microsoft.github.io/autogen/docs/Contribute#docker-for-development). ### Option 2. Install AutoGen Locally @@ -86,7 +86,7 @@ Find more options in [Installation](https://microsoft.github.io/autogen/docs/Ins -Even if you are installing AutoGen locally out of docker, we recommend performing [code execution](https://microsoft.github.io/autogen/docs/FAQ/#code-execution) in docker. Find more instructions [here](https://microsoft.github.io/autogen/docs/Installation#docker). +Even if you are installing and running AutoGen locally outside of docker, the recommendation and default behavior of agents is to perform [code execution](https://microsoft.github.io/autogen/docs/FAQ/#code-execution) in docker. Find more instructions and how to change the default behaviour [here](https://microsoft.github.io/autogen/docs/Installation#code-execution-with-docker-(default)). For LLM inference configurations, check the [FAQs](https://microsoft.github.io/autogen/docs/FAQ#set-your-api-endpoints). @@ -111,7 +111,7 @@ from autogen import AssistantAgent, UserProxyAgent, config_list_from_json config_list = config_list_from_json(env_or_file="OAI_CONFIG_LIST") # You can also set config_list directly as a list, for example, config_list = [{'model': 'gpt-4', 'api_key': ''},] assistant = AssistantAgent("assistant", llm_config={"config_list": config_list}) -user_proxy = UserProxyAgent("user_proxy", code_execution_config={"work_dir": "coding"}) +user_proxy = UserProxyAgent("user_proxy", code_execution_config={"work_dir": "coding", "use_docker": False}) # IMPORTANT: set to True to run code in docker, recommended user_proxy.initiate_chat(assistant, message="Plot a chart of NVDA and TESLA stock price change YTD.") # This initiates an automated chat between the two agents to solve the task ``` diff --git a/test/twoagent.py b/test/twoagent.py index e2e1818e8ad..15a0f701bbd 100644 --- a/test/twoagent.py +++ b/test/twoagent.py @@ -5,5 +5,7 @@ # and OAI_CONFIG_LIST_sample config_list = config_list_from_json(env_or_file="OAI_CONFIG_LIST") assistant = AssistantAgent("assistant", llm_config={"config_list": config_list}) -user_proxy = UserProxyAgent("user_proxy", code_execution_config={"work_dir": "coding"}) +user_proxy = UserProxyAgent( + "user_proxy", code_execution_config={"work_dir": "coding", "use_docker": False} +) # IMPORTANT: set to True to run code in docker, recommended user_proxy.initiate_chat(assistant, message="Plot a chart of NVDA and TESLA stock price change YTD.") diff --git a/website/docs/Getting-Started.md b/website/docs/Getting-Started.md index 374396b9edf..fa3ec3ac01c 100644 --- a/website/docs/Getting-Started.md +++ b/website/docs/Getting-Started.md @@ -32,7 +32,7 @@ from autogen import AssistantAgent, UserProxyAgent, config_list_from_json # and OAI_CONFIG_LIST_sample.json config_list = config_list_from_json(env_or_file="OAI_CONFIG_LIST") assistant = AssistantAgent("assistant", llm_config={"config_list": config_list}) -user_proxy = UserProxyAgent("user_proxy", code_execution_config={"work_dir": "coding"}) +user_proxy = UserProxyAgent("user_proxy", code_execution_config={"work_dir": "coding", "use_docker": False}) # IMPORTANT: set to True to run code in docker, recommended user_proxy.initiate_chat(assistant, message="Plot a chart of NVDA and TESLA stock price change YTD.") # This initiates an automated chat between the two agents to solve the task ``` diff --git a/website/docs/Installation.md b/website/docs/Installation.md index 49537c6f79f..56d5f12c7e6 100644 --- a/website/docs/Installation.md +++ b/website/docs/Installation.md @@ -165,7 +165,9 @@ pip install pyautogen Even if you install AutoGen locally, we highly recommend using Docker for [code execution](FAQ.md#code-execution). -The default behaviour for code-execution agents is for code execution to be performed in a docker container. If you want to run the code locally (not recommended) then `use_docker` can be set to `False` in `code_execution_config` for each code-execution agent, or set `AUTOGEN_USE_DOCKER` to `False` as an environment variable. +The default behaviour for code-execution agents is for code execution to be performed in a docker container. + +**To turn this off**: if you want to run the code locally (not recommended) then `use_docker` can be set to `False` in `code_execution_config` for each code-execution agent, or set `AUTOGEN_USE_DOCKER` to `False` as an environment variable. You might want to override the default docker image used for code execution. To do that set `use_docker` key of `code_execution_config` property to the name of the image. E.g.: From f9025775408ed90817027061ffcea4d56a432705 Mon Sep 17 00:00:00 2001 From: olgavrou Date: Wed, 17 Jan 2024 18:28:41 -0500 Subject: [PATCH 17/18] move header --- website/docs/Installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/Installation.md b/website/docs/Installation.md index 56d5f12c7e6..61d3aab11d8 100644 --- a/website/docs/Installation.md +++ b/website/docs/Installation.md @@ -183,8 +183,6 @@ Otherwise, reply CONTINUE, or the reason why the task is not solved yet.""" ) ``` -## Other Installation Options - ### Migration guide to v0.2 openai v1 is a total rewrite of the library with many breaking changes. For example, the inference requires instantiating a client, instead of using a global class method. @@ -207,6 +205,8 @@ Inference parameter tuning can be done via [`flaml.tune`](https://microsoft.gith - autogen uses local disk cache to guarantee the exactly same output is produced for the same input and when cache is hit, no openai api call will be made. - openai's `seed` is a best-effort deterministic sampling with no guarantee of determinism. When using openai's `seed` with `cache_seed` set to None, even for the same input, an openai api call will be made and there is no guarantee for getting exactly the same output. +## Other Installation Options + ### Optional Dependencies - #### blendsearch From d69464e2d3480f0ee9cba4abf3cf572fc25f1237 Mon Sep 17 00:00:00 2001 From: olgavrou Date: Wed, 17 Jan 2024 18:54:29 -0500 Subject: [PATCH 18/18] update contrib tests --- .github/workflows/contrib-tests.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/contrib-tests.yml b/.github/workflows/contrib-tests.yml index ffce67df900..670fed262f0 100644 --- a/.github/workflows/contrib-tests.yml +++ b/.github/workflows/contrib-tests.yml @@ -45,6 +45,12 @@ jobs: - name: Install packages and dependencies for RetrieveChat run: | pip install -e .[retrievechat] + - name: Set AUTOGEN_USE_DOCKER based on OS + shell: bash + run: | + if [[ ${{ matrix.os }} != ubuntu-latest ]]; then + echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV + fi - name: Test RetrieveChat run: | pytest test/test_retrieve_utils.py test/agentchat/contrib/test_retrievechat.py test/agentchat/contrib/test_qdrant_retrievechat.py --skip-openai @@ -81,6 +87,12 @@ jobs: - name: Install packages and dependencies for Compression run: | pip install -e . + - name: Set AUTOGEN_USE_DOCKER based on OS + shell: bash + run: | + if [[ ${{ matrix.os }} != ubuntu-latest ]]; then + echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV + fi - name: Test Compression if: matrix.python-version != '3.10' # diversify the python versions run: | @@ -118,6 +130,12 @@ jobs: - name: Install packages and dependencies for GPTAssistantAgent run: | pip install -e . + - name: Set AUTOGEN_USE_DOCKER based on OS + shell: bash + run: | + if [[ ${{ matrix.os }} != ubuntu-latest ]]; then + echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV + fi - name: Test GPTAssistantAgent if: matrix.python-version != '3.11' # diversify the python versions run: | @@ -155,6 +173,12 @@ jobs: - name: Install packages and dependencies for Teachability run: | pip install -e .[teachable] + - name: Set AUTOGEN_USE_DOCKER based on OS + shell: bash + run: | + if [[ ${{ matrix.os }} != ubuntu-latest ]]; then + echo "AUTOGEN_USE_DOCKER=False" >> $GITHUB_ENV + fi - name: Test TeachableAgent if: matrix.python-version != '3.9' # diversify the python versions run: |