diff --git a/docs/sphinx_doc/en/source/tutorial/208-distribute.md b/docs/sphinx_doc/en/source/tutorial/208-distribute.md index e9dbbb5d9..234ddb5fa 100644 --- a/docs/sphinx_doc/en/source/tutorial/208-distribute.md +++ b/docs/sphinx_doc/en/source/tutorial/208-distribute.md @@ -291,7 +291,7 @@ In addition to providing the `to_dist` method, `RpcMeta` also records callable m The decorator {func}`async_func` is implemented in `src/agentscope/rpc/rpc_meta.py`. The `__call__` and `reply` methods of `AgentBase` and all its subclasses are marked with `async_func` to avoid blocking. -In contrast to `async_func`, there is also the {func}`sync_func` decorator, used to indicate synchronous methods. However, since synchronous methods are the default, it is generally not used. +In contrast to `async_func`, there is also the {func}`sync_func` decorator, which is used to mark synchronous methods. However, since synchronous methods are the default, they generally do not need to be explicitly marked. Below is a simple example where we declare a class `Example`. In this class, `sync_method` is a synchronous method, `async_method_basic` and `async_method_complex` are marked as asynchronous methods, and `_protected_method` is a private method. @@ -446,7 +446,7 @@ as_server start --host localhost --port 12345 --model-config-path model_config_p ##### `result_pool` -The `ResultPool` implementation is located in `src/agentscope/server/async_result_pool.py` and is used for managing the execution results of asynchronous methods. There are currently two implementations: `local` and `redis`. The `local` implementation is based on Python's dictionary type (`dict`), whereas the `redis` implementation is based on Redis. Both implementations include automatic deletion mechanisms to prevent results from consuming too much memory. The `local` implementation allows for timeout-based deletion (`max_expire`) or deletion when a certain number of items is exceeded (`max_len`), while the `redis` implementation only supports timeout-based deletion (`max_expire`). +The `ResultPool` implementation is located in `src/agentscope/server/async_result_pool.py` and is used for managing the execution results of asynchronous methods. There are currently two implementations: `local` and `redis`. The `local` implementation is based on Python's dictionary type (`dict`), whereas the `redis` implementation is based on Redis. Both implementations include automatic deletion mechanisms to prevent results from consuming too much memory. The `local` implementation allows for timeout-based deletion (`max_expire_time`) or deletion when a certain number of items is exceeded (`max_len`), while the `redis` implementation only supports timeout-based deletion (`max_expire_time`). During the startup of `AgentServerLauncher`, you can specify which implementation to use by passing in the `pool_type` parameter, with the default being `local`. If `redis` is specified, you must also provide the `redis_url`. Below are examples of code and command-line usage. diff --git a/docs/sphinx_doc/zh_CN/source/tutorial/208-distribute.md b/docs/sphinx_doc/zh_CN/source/tutorial/208-distribute.md index 805df4ab0..a8999a4b5 100644 --- a/docs/sphinx_doc/zh_CN/source/tutorial/208-distribute.md +++ b/docs/sphinx_doc/zh_CN/source/tutorial/208-distribute.md @@ -142,7 +142,7 @@ if __name__ == "__main__": - **智能体服务器进程 (Agent Server Process)**: AgentScope 智能体服务器进程是分布式模式下 Agent 所运行的进程。例如上一节的例子中 `dist_agents` 中的所有 Agent 的本体实际上都运行于智能体服务器进程中。AgentScope 智能体服务器进程可以存在多个。智能体服务器进程可以运行在任意网络可达的机器上,并且每个智能体服务器进程中都可以同时运行多个 Agent。 - **子进程模式 (Child Mode)**: 在子进程模式下,智能体服务器进程由主进程启动的子进程。例如上一节的例子中,`dist_agents` 中的每个 Agent 实际上都是主进程的子进程。该模式是 AgentScope 分布式的默认运行模式,即直接调用 `to_dist` 函数不给定任何参数时会默认使用该模式,[基础用法](#basic_usage-zh)部分采用的就是这种模式。 -- **独立进程模式 (Indpendent Mode)**: 在独立进程模式下,智能体进程相对主进程来说是独立的,需要预先在机器上启动智能体进程,并向 `to_dist` 函数传入一些特定的参数。如果需要实现 Agent 跨机器部署,必须使用该模式,另外如果对性能要求较高或是 Agent 数量较多也建议使用该模式。 +- **独立进程模式 (Independent Mode)**: 在独立进程模式下,智能体进程相对主进程来说是独立的,需要预先在机器上启动智能体进程,并向 `to_dist` 函数传入一些特定的参数。如果需要实现 Agent 跨机器部署,必须使用该模式,另外如果对性能要求较高或是 Agent 数量较多也建议使用该模式。 ### 使用独立进程模式 @@ -291,9 +291,9 @@ Client 主要包含 `RpcMeta`、`RpcObject` 两个主要类,其中 `RpcMeta` #### `async_func` 和 `AsyncResult` -{func}`async_func` 装饰器的实现位于 `src/agentscope/rpc/rpc_meta.py``AgentBase` 及其所有子类的 `__call__` 以及 `reply` 方法都被标记为了 `async_func` 以避免阻塞。 +{func}`async_func` 装饰器的实现位于 `src/agentscope/rpc/rpc_meta.py`。`AgentBase` 及其所有子类的 `__call__` 以及 `reply` 方法都被标记为了 `async_func` 以避免阻塞。 -与 `async_func` 相对的还有 {func}`sync_func` 装饰器,用于标识同步方法。但由于同步方法为默认情况,因此一般不使用。 +与 `async_func` 相对的还有 {func}`sync_func` 装饰器,用于标识同步方法。但由于同步方法为默认情况,因此一般不需要显式标注。 如下是一个简单的示例,这里声明了一个 `Example` 类,其中 `sync_method` 是同步方法,`async_method_basic` 以及 `async_method_complex` 被标记为了异步方法,`_protected_method` 是私有方法。 @@ -417,7 +417,7 @@ Server 端主要基于 gRPC 实现,主要包含 `AgentServerServicer` 和 `Rpc ```{warning} `AgentServerLauncher` 会加载并执行自定义的 Python 对象,在使用前请仔细检查被加载的对象,如果其中包含恶意代码可能会对系统造成严重损害。 -`AgentServerLauncer` 类还存在一个 `local_mode` 参数用于表示是否只允许本地访问,默认为 `True`,如果需要允许其他机器访问,则需要设置为 `False`。为了避免网络攻击,建议仅在可信的网络环境下使用。 +`AgentServerLauncher` 类还存在一个 `local_mode` 参数用于表示是否只允许本地访问,默认为 `True`,如果需要允许其他机器访问,则需要设置为 `False`。为了避免网络攻击,建议仅在可信的网络环境下使用。 ``` #### `AgentServerServicer` @@ -433,7 +433,7 @@ Server 端主要基于 gRPC 实现,主要包含 `AgentServerServicer` 和 `Rpc ##### `executor` executor 是一个线程池 (`concurrent.futures.ThreadPoolExecutor`),其中的线程数量由 `capacity` 参数决定,`capacity` 的设置对运行效率的影响巨大,需要根据具体任务来针对性设置。 -为了让 Server 中的各个 Agent 能够并发执行,最好保证 `capacity` 大于 `AgentServerServicer` 中同时运行的 Agent 的数量,否则可能会导致运行时间成倍增加,甚至在一些特殊场景 (多个agent 之间进行递归调用) 中出现死锁现象。 +为了让 Server 中的各个 Agent 能够并发执行,最好保证 `capacity` 大于 `AgentServerServicer` 中同时运行的 Agent 的数量,否则可能会导致运行时间成倍增加,甚至在一些特殊场景 (多个 agent 之间进行递归调用) 中出现死锁现象。 `capacity` 参数可以在 `as_server` 命令中通过 `--capacity` 指定,或是直接在 `RpcAgentServerLauncher` 初始化时指定。 @@ -453,7 +453,7 @@ as_server start --host localhost --port 12345 --model-config-path model_config_p ##### `result_pool` -`ResultPool` 的实现位于 `src/agentscope/server/async_result_pool.py`,用于管理异步方法的执行结果,目前有两种实现分别为 `local` 和 `redis`。其中 `local` 基于 Python 的字典类型 (`dict`) 实现,而 `redis` 则是基于 Redis 实现。为了避免结果占用过多内存两种实现都包含了过期自动删除机制,其中 `local` 可以设置超时删除 (`max_expire`) 或超过条数删除 (`max_len`),而 `redis` 则仅支持超时删除 (`max_expire`)。 +`ResultPool` 的实现位于 `src/agentscope/server/async_result_pool.py`,用于管理异步方法的执行结果,目前有两种实现分别为 `local` 和 `redis`。其中 `local` 基于 Python 的字典类型 (`dict`) 实现,而 `redis` 则是基于 Redis 实现。为了避免结果占用过多内存两种实现都包含了过期自动删除机制,其中 `local` 可以设置超时删除 (`max_expire_time`) 或超过条数删除 (`max_len`),而 `redis` 则仅支持超时删除 (`max_expire_time`)。 在启动 `AgentServerLauncher` 时可以通过传入 `pool_type` 来指定使用哪种实现,默认为`local`。 如果指定为 `redis` 则还必须传入 `redis_url`,如下是代码以及命令行的使用案例。 diff --git a/examples/environments/chatroom/chatroom_example.py b/examples/environments/chatroom/chatroom_example.py index f552f6c17..636b473a0 100644 --- a/examples/environments/chatroom/chatroom_example.py +++ b/examples/environments/chatroom/chatroom_example.py @@ -39,7 +39,7 @@ def main(args: argparse.Namespace) -> None: "model_type": "dashscope_chat", "config_name": "dash", "model_name": "qwen-turbo", - "api_key": os.environ.get("DASH_API_KEY", ""), + "api_key": os.environ.get("DASHSCOPE_API_KEY", ""), }, ] diff --git a/examples/environments/chatroom/chatroom_with_assistant_example.py b/examples/environments/chatroom/chatroom_with_assistant_example.py index 3983a2711..1ed80c639 100644 --- a/examples/environments/chatroom/chatroom_with_assistant_example.py +++ b/examples/environments/chatroom/chatroom_with_assistant_example.py @@ -44,7 +44,7 @@ def main(args: argparse.Namespace) -> None: "model_type": "dashscope_chat", "config_name": "dash", "model_name": "qwen-turbo", - "api_key": os.environ.get("DASH_API_KEY", ""), + "api_key": os.environ.get("DASHSCOPE_API_KEY", ""), }, ] diff --git a/examples/paper_large_scale_simulation/tools/persona_generator.py b/examples/paper_large_scale_simulation/tools/persona_generator.py index 9adb044e5..02c015daa 100644 --- a/examples/paper_large_scale_simulation/tools/persona_generator.py +++ b/examples/paper_large_scale_simulation/tools/persona_generator.py @@ -19,7 +19,7 @@ "model_type": "dashscope_chat", "config_name": MODEL_CONFIG_NAME, "model_name": "qwen-max", - "api_key": os.environ.get("DASH_API_KEY", ""), + "api_key": os.environ.get("DASHSCOPE_API_KEY", ""), } BEGIN_TAG = "[PERSONA BEGIN]" diff --git a/examples/parallel_service/parallel_service.py b/examples/parallel_service/parallel_service.py index 2ead87b82..d484f47b5 100644 --- a/examples/parallel_service/parallel_service.py +++ b/examples/parallel_service/parallel_service.py @@ -203,7 +203,7 @@ def main() -> None: "model_type": "dashscope_chat", "config_name": "dash", "model_name": "qwen-turbo", - "api_key": os.environ.get("DASH_API_KEY", ""), + "api_key": os.environ.get("DASHSCOPE_API_KEY", ""), }, ] diff --git a/src/agentscope/agents/agent.py b/src/agentscope/agents/agent.py index 85d3fba5f..6cabace3d 100644 --- a/src/agentscope/agents/agent.py +++ b/src/agentscope/agents/agent.py @@ -52,7 +52,7 @@ def __init__( Whether the agent has memory. to_dist (`Optional[Union[DistConf, bool]]`, default to `False`): The configurations passed to :py:meth:`to_dist` method. Used in - :py:class:`_AgentMeta`, when this parameter is provided, + :py:class:`RpcMeta`, when this parameter is provided, the agent will automatically be converted into its distributed version. Below are some examples: diff --git a/src/agentscope/environment/env.py b/src/agentscope/environment/env.py index ff1cc6601..7e274deb4 100644 --- a/src/agentscope/environment/env.py +++ b/src/agentscope/environment/env.py @@ -30,7 +30,15 @@ def trigger_listener(env: "Env", event: Event) -> None: def event_func(func: Callable) -> Callable: - """A decorator to register an event function. + """A decorator to register an event function in `Env` and its + subclasses. + + Note: + + This decorator is only available in the subclasses of `Env`. + If a function is decorated with `@event_func`, at the end of + the function, all listeners bound to the function will be + triggered automatically. Args: func (`Callable`): The event function. @@ -65,8 +73,22 @@ def wrapper( # type: ignore[no-untyped-def] class EventListener(ABC): - """A class representing a listener for listening the event of an - env.""" + """A base class representing a listener for listening the event of an + environment. The actions of the listener should be implemented in the + `__call__` method. + + Args: + env (`Env`): The environment instance who trigger the listener. + event (`Event`): The event information, which contains the event + function name (`name`: `str`), the arguments of the event function + (`args`: `dict`), and the return value of the event function + (`returns`: `Any`). + + Note: + + `EventListener` can only be bound to event functions (decorated + with `@event_func`). + """ def __init__(self, name: str) -> None: """Init a EventListener instance. @@ -128,8 +150,7 @@ def add_child(self, child: Env) -> bool: """Add a child env to the current env. Args: - child (`Env`): The children - envs. + child (`Env`): The children envs. Returns: `bool`: Whether the children were added successfully. @@ -200,6 +221,7 @@ class BasicEnv(Env): and cannot get value. Note: + `BasicEnv` is used as the base class to implement other envs. Application developers should not use this class. """ diff --git a/src/agentscope/rpc/retry_strategy.py b/src/agentscope/rpc/retry_strategy.py index 2646e0fd3..b01931556 100644 --- a/src/agentscope/rpc/retry_strategy.py +++ b/src/agentscope/rpc/retry_strategy.py @@ -86,11 +86,12 @@ def retry( # pylint: disable=R1710 ) file_name = frame_info.filename line_number = frame_info.lineno - logger.info( + logger.debug( f"Attempt {attempt + 1} at [{file_name}:{line_number}] failed:" f"\n{e}.\nRetrying in {random_delay:.2f} seconds...", ) time.sleep(random_delay) + logger.error(f"Max timeout exceeded at [{file_name}:{line_number}].") raise TimeoutError("Max retry exceeded.") @@ -157,12 +158,13 @@ def retry( # pylint: disable=R1710 ) file_name = frame_info.filename line_number = frame_info.lineno - logger.info( + logger.debug( f"Attempt {attempt + 1} at [{file_name}:{line_number}] failed:" f"\n{e}.\nRetrying in {random_delay:.2f} seconds...", ) time.sleep(random_delay) delay *= 2 + logger.error(f"Max timeout exceeded at [{file_name}:{line_number}].") raise TimeoutError("Max retry exceeded.") diff --git a/src/agentscope/rpc/rpc_client.py b/src/agentscope/rpc/rpc_client.py index cb8a471cf..021f0d620 100644 --- a/src/agentscope/rpc/rpc_client.py +++ b/src/agentscope/rpc/rpc_client.py @@ -162,7 +162,7 @@ def create_agent( Args: agent_configs (`dict`): Init configs of the agent, generated by - `_AgentMeta`. + `RpcMeta`. agent_id (`str`): agent_id of the created agent. Returns: @@ -315,8 +315,8 @@ def download_file(self, path: str) -> str: """Download a file from a remote server to the local machine. Args: - path (`str`): The path of the file to be downloaded. Note that - it is the path on the remote server. + path (`str`): The path of the file to be downloaded. Note that + it is the path on the remote server. Returns: `str`: The path of the downloaded file. Note that it is the path diff --git a/src/agentscope/server/__init__.py b/src/agentscope/server/__init__.py index 8b69a542a..2cbf37d0c 100644 --- a/src/agentscope/server/__init__.py +++ b/src/agentscope/server/__init__.py @@ -1,10 +1,8 @@ # -*- coding: utf-8 -*- """Import all server related modules in the package.""" from .launcher import RpcAgentServerLauncher, as_server -from .servicer import AgentServerServicer __all__ = [ "RpcAgentServerLauncher", - "AgentServerServicer", "as_server", ] diff --git a/src/agentscope/server/launcher.py b/src/agentscope/server/launcher.py index 21d2347a6..00b94f09b 100644 --- a/src/agentscope/server/launcher.py +++ b/src/agentscope/server/launcher.py @@ -75,11 +75,11 @@ def _setup_agent_server( Only listen to local requests. capacity (`int`, default to `32`): The number of concurrent agents in the server. - pool-type (`str`, defaults to `"local"`): The type of the async + pool_type (`str`, defaults to `"local"`): The type of the async message pool, which can be `local` or `redis`. If `redis` is specified, you need to start a redis server before launching the server. - redis-url (`str`, defaults to `"redis://localhost:6379"`): The + redis_url (`str`, defaults to `"redis://localhost:6379"`): The url of the redis server. max_pool_size (`int`, defaults to `8192`): Max number of agent replies that the server can accommodate. @@ -161,11 +161,11 @@ async def _setup_agent_server_async( # pylint: disable=R0912 listen to requests from all hosts. capacity (`int`, default to `32`): The number of concurrent agents in the server. - pool-type (`str`, defaults to `"local"`): The type of the async + pool_type (`str`, defaults to `"local"`): The type of the async message pool, which can be `local` or `redis`. If `redis` is specified, you need to start a redis server before launching the server. - redis-url (`str`, defaults to `"redis://localhost:6379"`): The url + redis_url (`str`, defaults to `"redis://localhost:6379"`): The url of the redis server. max_pool_size (`int`, defaults to `8192`): The max number of agent reply messages that the server can @@ -355,12 +355,12 @@ def __init__( Socket port of the agent server. capacity (`int`, default to `32`): The number of concurrent agents in the server. - pool-type (`str`, defaults to `"local"`): The type of the async + pool_type (`str`, defaults to `"local"`): The type of the async message pool, which can be `local` or `redis`. If `redis` is specified, you need to start a redis server before launching the server. - redis-url (`str`, defaults to `"redis://localhost:6379"`): The - address of the redis server. + redis_url (`str`): The address of the redis server. + Defaults to `redis://localhost:6379`. max_pool_size (`int`, defaults to `8192`): The max number of async results that the server can accommodate. Note that the oldest result will be deleted @@ -547,9 +547,9 @@ def as_server() -> None: .. code-block:: shell - as_server start --host localhost \ - --port 12345 \ - --model-config-path config.json \ + as_server start --host localhost \\ + --port 12345 \\ + --model-config-path config.json \\ --agent-dir ./my_agents """ parser = argparse.ArgumentParser()