From 54681b2aec005b3a2174e6e5f7eda3c756898dab Mon Sep 17 00:00:00 2001 From: Eric Zhu Date: Fri, 14 Feb 2025 18:59:52 -0800 Subject: [PATCH] fix: Add warning and doc for Windows event loop policy to avoid subprocess issues in web surfer and local executor (#5557) --- .../web_surfer/_multimodal_web_surfer.py | 31 +++++++++++++++++++ .../code_executors/local/__init__.py | 27 ++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/python/packages/autogen-ext/src/autogen_ext/agents/web_surfer/_multimodal_web_surfer.py b/python/packages/autogen-ext/src/autogen_ext/agents/web_surfer/_multimodal_web_surfer.py index 2c62caf2cad0..f4fb3abd10ea 100644 --- a/python/packages/autogen-ext/src/autogen_ext/agents/web_surfer/_multimodal_web_surfer.py +++ b/python/packages/autogen-ext/src/autogen_ext/agents/web_surfer/_multimodal_web_surfer.py @@ -1,3 +1,4 @@ +import asyncio import base64 import hashlib import io @@ -5,8 +6,10 @@ import logging import os import re +import sys import time import traceback +import warnings from typing import ( Any, AsyncGenerator, @@ -113,6 +116,18 @@ class MultimodalWebSurfer(BaseChatAgent, Component[MultimodalWebSurferConfig]): Be aware that agents may occasionally attempt risky actions, such as recruiting humans for help or accepting cookie agreements without human involvement. Always ensure agents are monitored and operate within a controlled environment to prevent unintended consequences. Moreover, be cautious that MultimodalWebSurfer may be susceptible to prompt injection attacks from webpages. + .. note:: + + On Windows, the event loop policy must be set to `WindowsProactorEventLoopPolicy` to avoid issues with subprocesses. + + .. code-block:: python + + import sys + import asyncio + + if sys.platform == "win32": + asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) + Args: name (str): The name of the agent. model_client (ChatCompletionClient): The model client used by the agent. Must be multimodal and support function calling. @@ -277,6 +292,22 @@ async def _lazy_init( """ On the first call, we initialize the browser and the page. """ + + # Check the current event loop policy if on windows. + if sys.platform == "win32": + current_policy = asyncio.get_event_loop_policy() + if hasattr(asyncio, "WindowsProactorEventLoopPolicy") and not isinstance( + current_policy, asyncio.WindowsProactorEventLoopPolicy + ): + warnings.warn( + "The current event loop policy is not WindowsProactorEventLoopPolicy. " + "This may cause issues with subprocesses. " + "Try setting the event loop policy to WindowsProactorEventLoopPolicy. " + "For example: `asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())`. " + "See https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.ProactorEventLoop.", + stacklevel=2, + ) + self._last_download = None self._prior_metadata_hash = None diff --git a/python/packages/autogen-ext/src/autogen_ext/code_executors/local/__init__.py b/python/packages/autogen-ext/src/autogen_ext/code_executors/local/__init__.py index 1513f723e9c2..aefd366c3bad 100644 --- a/python/packages/autogen-ext/src/autogen_ext/code_executors/local/__init__.py +++ b/python/packages/autogen-ext/src/autogen_ext/code_executors/local/__init__.py @@ -59,6 +59,18 @@ class LocalCommandLineCodeExecutor(CodeExecutor, Component[LocalCommandLineCodeE For shell scripts, use the language "bash", "shell", or "sh" for the code block. + .. note:: + + On Windows, the event loop policy must be set to `WindowsProactorEventLoopPolicy` to avoid issues with subprocesses. + + .. code-block:: python + + import sys + import asyncio + + if sys.platform == "win32": + asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) + Args: timeout (int): The timeout for the execution of any single code block. Default is 60. work_dir (str): The working directory for the code execution. If None, @@ -165,6 +177,21 @@ def __init__( self._virtual_env_context: Optional[SimpleNamespace] = virtual_env_context + # Check the current event loop policy if on windows. + if sys.platform == "win32": + current_policy = asyncio.get_event_loop_policy() + if hasattr(asyncio, "WindowsProactorEventLoopPolicy") and not isinstance( + current_policy, asyncio.WindowsProactorEventLoopPolicy + ): + warnings.warn( + "The current event loop policy is not WindowsProactorEventLoopPolicy. " + "This may cause issues with subprocesses. " + "Try setting the event loop policy to WindowsProactorEventLoopPolicy. " + "For example: `asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())`. " + "See https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.ProactorEventLoop.", + stacklevel=2, + ) + def format_functions_for_prompt(self, prompt_template: str = FUNCTION_PROMPT_TEMPLATE) -> str: """(Experimental) Format the functions for a prompt.