* fix doc on distributed runtime

* Fix references

* Update references

* Fix import paths in user guide notebooks for code executor components
This commit is contained in:
Eric Zhu 2024-12-06 01:23:05 -08:00 committed by GitHub
parent 8707729da9
commit fa550c2c36
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 2256 additions and 2256 deletions

View File

@ -17,7 +17,7 @@ from autogen_core.components.models import (
LLMMessage,
)
from autogen_core import DefaultSubscription, DefaultTopicId
from autogen_core.components.code_executor import LocalCommandLineCodeExecutor
from autogen_ext.code_executors.local import LocalCommandLineCodeExecutor
from autogen_core.components.models import AssistantMessage
from autogen_magentic_one.markdown_browser import MarkdownConverter, UnsupportedFormatException

View File

@ -18,7 +18,7 @@ from autogen_core.components.models import (
LLMMessage,
)
from autogen_core import DefaultSubscription, DefaultTopicId
from autogen_core.components.code_executor import LocalCommandLineCodeExecutor
from autogen_ext.code_executors.local import LocalCommandLineCodeExecutor
from autogen_core.components.models import AssistantMessage
from autogen_magentic_one.markdown_browser import MarkdownConverter, UnsupportedFormatException

View File

@ -5,7 +5,7 @@ from autogen_core import AgentId, AgentProxy, TopicId
from autogen_core import SingleThreadedAgentRuntime
from autogen_core.application.logging import EVENT_LOGGER_NAME
from autogen_core import DefaultSubscription, DefaultTopicId
from autogen_core.components.code_executor import LocalCommandLineCodeExecutor
from autogen_ext.code_executors.local import LocalCommandLineCodeExecutor
from autogen_core.components.models import (
UserMessage,
)

View File

@ -11,7 +11,7 @@ from autogen_core import AgentId, AgentProxy, TopicId
from autogen_core import SingleThreadedAgentRuntime
from autogen_core.application.logging import EVENT_LOGGER_NAME
from autogen_core import DefaultSubscription, DefaultTopicId
from autogen_core.components.code_executor import LocalCommandLineCodeExecutor
from autogen_ext.code_executors.local import LocalCommandLineCodeExecutor
from autogen_core.components.models import (
ChatCompletionClient,
UserMessage,

View File

@ -28,7 +28,7 @@ class UserProxyAgent(BaseChatAgent):
Using :class:`UserProxyAgent` puts a running team in a temporary blocked
state until the user responds. So it is important to time out the user input
function and cancel using the :class:`~autogen_core.base.CancellationToken` if the user does not respond.
function and cancel using the :class:`~autogen_core.CancellationToken` if the user does not respond.
The input function should also handle exceptions and return a default response if needed.
For typical use cases that involve

View File

@ -210,7 +210,7 @@ class BaseGroupChat(Team, ABC):
asyncio.run(main())
Example using the :class:`~autogen_core.base.CancellationToken` to cancel the task:
Example using the :class:`~autogen_core.CancellationToken` to cancel the task:
.. code-block:: python
@ -310,7 +310,7 @@ class BaseGroupChat(Team, ABC):
asyncio.run(main())
Example using the :class:`~autogen_core.base.CancellationToken` to cancel the task:
Example using the :class:`~autogen_core.CancellationToken` to cancel the task:
.. code-block:: python

View File

@ -35,7 +35,7 @@ class FIFOLock:
class SequentialRoutedAgent(RoutedAgent):
"""A subclass of :class:`autogen_core.components.RoutedAgent` that ensures
"""A subclass of :class:`autogen_core.RoutedAgent` that ensures
messages are handled sequentially in the order they arrive."""
def __init__(self, description: str) -> None:

View File

@ -163,7 +163,7 @@
"source": [
"In this example, we will use a tool for Python code execution.\n",
"First, we create a Docker-based command-line code executor\n",
"using {py:class}`~autogen_core.components.code_executor.docker_executorCommandLineCodeExecutor`,\n",
"using {py:class}`~autogen_ext.code_executors.docker.DockerCommandLineCodeExecutor`,\n",
"and then use it to instantiate a built-in Python code execution tool\n",
"{py:class}`~autogen_core.components.tools.PythonCodeExecutionTool`\n",
"that runs code in a Docker container."

View File

@ -2,7 +2,7 @@
## How do I get the underlying agent instance?
Agents might be distributed across multiple machines, so the underlying agent instance is intentionally discouraged from being accessed. If the agent is definitely running on the same machine, you can access the agent instance by calling {py:meth}`autogen_core.base.AgentRuntime.try_get_underlying_agent_instance` on the `AgentRuntime`. If the agent is not available this will throw an exception.
Agents might be distributed across multiple machines, so the underlying agent instance is intentionally discouraged from being accessed. If the agent is definitely running on the same machine, you can access the agent instance by calling {py:meth}`autogen_core.AgentRuntime.try_get_underlying_agent_instance` on the `AgentRuntime`. If the agent is not available this will throw an exception.
## How do I call call a function on an agent?
@ -12,7 +12,7 @@ This allows your agent to work in a distributed environment a well as a local on
## Why do I need to use a factory to register an agent?
An {py:class}`autogen_core.base.AgentId` is composed of a `type` and a `key`. The type corresponds to the factory that created the agent, and the key is a runtime, data dependent key for this instance.
An {py:class}`autogen_core.AgentId` is composed of a `type` and a `key`. The type corresponds to the factory that created the agent, and the key is a runtime, data dependent key for this instance.
The key can correspond to a user id, a session id, or could just be "default" if you don't need to differentiate between instances. Each unique key will create a new instance of the agent, based on the factory provided. This allows the system to automatically scale to different instances of the same agent, and to manage the lifecycle of each instance independently based on how you choose to handle keys in your application.
@ -57,4 +57,4 @@ client = OpenAIChatCompletionClient(
"json_output": False,
}
)
```
```

View File

@ -1,276 +1,276 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Agent and Agent Runtime\n",
"\n",
"In this and the following section, we focus on the core concepts of AutoGen:\n",
"agents, agent runtime, messages, and communication.\n",
"You will not find any AI models or tools here, just the foundational\n",
"building blocks for building multi-agent applications."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"An agent in AutoGen is an entity defined by the base class {py:class}`autogen_core.base.BaseAgent`.\n",
"It has a unique identifier of the type {py:class}`autogen_core.base.AgentId`,\n",
"a metadata dictionary of the type {py:class}`autogen_core.base.AgentMetadata`,\n",
"and method for handling messages {py:meth}`autogen_core.base.BaseAgent.on_message_impl`.\n",
"\n",
"An agent runtime is the execution environment for agents in AutoGen.\n",
"Similar to the runtime environment of a programming language,\n",
"an agent runtime provides the necessary infrastructure to facilitate communication\n",
"between agents, manage agent lifecycles, enforce security boundaries, and support monitoring and\n",
"debugging.\n",
"For local development, developers can use {py:class}`~autogen_core.application.SingleThreadedAgentRuntime`,\n",
"which can be embedded in a Python application.\n",
"\n",
"```{note}\n",
"Agents are not directly instantiated and managed by application code.\n",
"Instead, they are created by the runtime when needed and managed by the runtime.\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Implementing an Agent\n",
"\n",
"To implement an agent, the developer must subclass the {py:class}`~autogen_core.base.BaseAgent` class\n",
"and implement the {py:meth}`~autogen_core.base.BaseAgent.on_message_impl` method.\n",
"This method is invoked when the agent receives a message. For example,\n",
"the following agent handles a simple message type and prints the message it receives:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from dataclasses import dataclass\n",
"\n",
"from autogen_core import AgentId, BaseAgent, MessageContext\n",
"\n",
"\n",
"@dataclass\n",
"class MyMessageType:\n",
" content: str\n",
"\n",
"\n",
"class MyAgent(BaseAgent):\n",
" def __init__(self) -> None:\n",
" super().__init__(\"MyAgent\")\n",
"\n",
" async def on_message_impl(self, message: MyMessageType, ctx: MessageContext) -> None:\n",
" print(f\"Received message: {message.content}\") # type: ignore"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This agent only handles `MyMessageType` messages. \n",
"To handle multiple message types, developers can subclass the {py:class}`~autogen_core.components.RoutedAgent` class\n",
"which provides an easy-to use API to implement different message handlers for different message types.\n",
"See the next section on [message and communication](./message-and-communication.ipynb)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Registering Agent Type\n",
"\n",
"To make agents available to the runtime, developers can use the\n",
"{py:meth}`~autogen_core.base.BaseAgent.register` class method of the\n",
"{py:class}`~autogen_core.base.BaseAgent` class.\n",
"The process of registration associates an agent type, which is uniquely identified by a string, \n",
"and a factory function\n",
"that creates an instance of the agent type of the given class.\n",
"The factory function is used to allow automatic creation of agent instances \n",
"when they are needed.\n",
"\n",
"Agent type ({py:class}`~autogen_core.base.AgentType`) is not the same as the agent class. In this example,\n",
"the agent type is `AgentType(\"my_agent\")` and the agent class is the Python class `MyAgent`.\n",
"The factory function is expected to return an instance of the agent class \n",
"on which the {py:meth}`~autogen_core.base.BaseAgent.register` class method is invoked.\n",
"Read [Agent Identity and Lifecycles](../core-concepts/agent-identity-and-lifecycle.md)\n",
"to learn more about agent type and identity.\n",
"\n",
"```{note}\n",
"Different agent types can be registered with factory functions that return \n",
"the same agent class. For example, in the factory functions, \n",
"variations of the constructor parameters\n",
"can be used to create different instances of the same agent class.\n",
"```\n",
"\n",
"To register an agent type with the \n",
"{py:class}`~autogen_core.application.SingleThreadedAgentRuntime`,\n",
"the following code can be used:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AgentType(type='my_agent')"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from autogen_core import SingleThreadedAgentRuntime\n",
"\n",
"runtime = SingleThreadedAgentRuntime()\n",
"await MyAgent.register(runtime, \"my_agent\", lambda: MyAgent())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Once an agent type is registered, we can send a direct message to an agent instance\n",
"using an {py:class}`~autogen_core.base.AgentId`.\n",
"The runtime will create the instance the first time it delivers a\n",
"message to this instance."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Received message: Hello, World!\n"
]
}
],
"source": [
"agent_id = AgentId(\"my_agent\", \"default\")\n",
"runtime.start() # Start processing messages in the background.\n",
"await runtime.send_message(MyMessageType(\"Hello, World!\"), agent_id)\n",
"await runtime.stop() # Stop processing messages in the background."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```{note}\n",
"Because the runtime manages the lifecycle of agents, an {py:class}`~autogen_core.base.AgentId`\n",
"is only used to communicate with the agent or retrieve its metadata (e.g., description).\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Running the Single-Threaded Agent Runtime\n",
"\n",
"The above code snippet uses `runtime.start()` to start a background task\n",
"to process and deliver messages to recepients' message handlers.\n",
"This is a feature of the\n",
"local embedded runtime {py:class}`~autogen_core.application.SingleThreadedAgentRuntime`.\n",
"\n",
"To stop the background task immediately, use the `stop()` method:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"runtime.start()\n",
"# ... Send messages, publish messages, etc.\n",
"await runtime.stop() # This will return immediately but will not cancel\n",
"# any in-progress message handling."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can resume the background task by calling `start()` again.\n",
"\n",
"For batch scenarios such as running benchmarks for evaluating agents,\n",
"you may want to wait for the background task to stop automatically when\n",
"there are no unprocessed messages and no agent is handling messages --\n",
"the batch may considered complete.\n",
"You can achieve this by using the `stop_when_idle()` method:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"runtime.start()\n",
"# ... Send messages, publish messages, etc.\n",
"await runtime.stop_when_idle() # This will block until the runtime is idle."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can also directly process messages one-by-one without a background task using:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"await runtime.process_next()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Other runtime implementations will have their own ways of running the runtime."
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Agent and Agent Runtime\n",
"\n",
"In this and the following section, we focus on the core concepts of AutoGen:\n",
"agents, agent runtime, messages, and communication.\n",
"You will not find any AI models or tools here, just the foundational\n",
"building blocks for building multi-agent applications."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"An agent in AutoGen is an entity defined by the base class {py:class}`autogen_core.Agent`.\n",
"It has a unique identifier of the type {py:class}`autogen_core.AgentId`,\n",
"a metadata dictionary of the type {py:class}`autogen_core.AgentMetadata`,\n",
"and method for handling messages {py:meth}`autogen_core.BaseAgent.on_message_impl`.\n",
"\n",
"An agent runtime is the execution environment for agents in AutoGen.\n",
"Similar to the runtime environment of a programming language,\n",
"an agent runtime provides the necessary infrastructure to facilitate communication\n",
"between agents, manage agent lifecycles, enforce security boundaries, and support monitoring and\n",
"debugging.\n",
"For local development, developers can use {py:class}`~autogen_core.application.SingleThreadedAgentRuntime`,\n",
"which can be embedded in a Python application.\n",
"\n",
"```{note}\n",
"Agents are not directly instantiated and managed by application code.\n",
"Instead, they are created by the runtime when needed and managed by the runtime.\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Implementing an Agent\n",
"\n",
"To implement an agent, the developer must subclass the {py:class}`~autogen_core.BaseAgent` class\n",
"and implement the {py:meth}`~autogen_core.BaseAgent.on_message_impl` method.\n",
"This method is invoked when the agent receives a message. For example,\n",
"the following agent handles a simple message type and prints the message it receives:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from dataclasses import dataclass\n",
"\n",
"from autogen_core import AgentId, BaseAgent, MessageContext\n",
"\n",
"\n",
"@dataclass\n",
"class MyMessageType:\n",
" content: str\n",
"\n",
"\n",
"class MyAgent(BaseAgent):\n",
" def __init__(self) -> None:\n",
" super().__init__(\"MyAgent\")\n",
"\n",
" async def on_message_impl(self, message: MyMessageType, ctx: MessageContext) -> None:\n",
" print(f\"Received message: {message.content}\") # type: ignore"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This agent only handles `MyMessageType` messages. \n",
"To handle multiple message types, developers can subclass the {py:class}`~autogen_core.RoutedAgent` class\n",
"which provides an easy-to use API to implement different message handlers for different message types.\n",
"See the next section on [message and communication](./message-and-communication.ipynb)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Registering Agent Type\n",
"\n",
"To make agents available to the runtime, developers can use the\n",
"{py:meth}`~autogen_core.BaseAgent.register` class method of the\n",
"{py:class}`~autogen_core.BaseAgent` class.\n",
"The process of registration associates an agent type, which is uniquely identified by a string, \n",
"and a factory function\n",
"that creates an instance of the agent type of the given class.\n",
"The factory function is used to allow automatic creation of agent instances \n",
"when they are needed.\n",
"\n",
"Agent type ({py:class}`~autogen_core.AgentType`) is not the same as the agent class. In this example,\n",
"the agent type is `AgentType(\"my_agent\")` and the agent class is the Python class `MyAgent`.\n",
"The factory function is expected to return an instance of the agent class \n",
"on which the {py:meth}`~autogen_core.BaseAgent.register` class method is invoked.\n",
"Read [Agent Identity and Lifecycles](../core-concepts/agent-identity-and-lifecycle.md)\n",
"to learn more about agent type and identity.\n",
"\n",
"```{note}\n",
"Different agent types can be registered with factory functions that return \n",
"the same agent class. For example, in the factory functions, \n",
"variations of the constructor parameters\n",
"can be used to create different instances of the same agent class.\n",
"```\n",
"\n",
"To register an agent type with the \n",
"{py:class}`~autogen_core.application.SingleThreadedAgentRuntime`,\n",
"the following code can be used:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AgentType(type='my_agent')"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from autogen_core import SingleThreadedAgentRuntime\n",
"\n",
"runtime = SingleThreadedAgentRuntime()\n",
"await MyAgent.register(runtime, \"my_agent\", lambda: MyAgent())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Once an agent type is registered, we can send a direct message to an agent instance\n",
"using an {py:class}`~autogen_core.AgentId`.\n",
"The runtime will create the instance the first time it delivers a\n",
"message to this instance."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Received message: Hello, World!\n"
]
}
],
"source": [
"agent_id = AgentId(\"my_agent\", \"default\")\n",
"runtime.start() # Start processing messages in the background.\n",
"await runtime.send_message(MyMessageType(\"Hello, World!\"), agent_id)\n",
"await runtime.stop() # Stop processing messages in the background."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```{note}\n",
"Because the runtime manages the lifecycle of agents, an {py:class}`~autogen_core.AgentId`\n",
"is only used to communicate with the agent or retrieve its metadata (e.g., description).\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Running the Single-Threaded Agent Runtime\n",
"\n",
"The above code snippet uses `runtime.start()` to start a background task\n",
"to process and deliver messages to recepients' message handlers.\n",
"This is a feature of the\n",
"local embedded runtime {py:class}`~autogen_core.application.SingleThreadedAgentRuntime`.\n",
"\n",
"To stop the background task immediately, use the `stop()` method:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"runtime.start()\n",
"# ... Send messages, publish messages, etc.\n",
"await runtime.stop() # This will return immediately but will not cancel\n",
"# any in-progress message handling."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can resume the background task by calling `start()` again.\n",
"\n",
"For batch scenarios such as running benchmarks for evaluating agents,\n",
"you may want to wait for the background task to stop automatically when\n",
"there are no unprocessed messages and no agent is handling messages --\n",
"the batch may considered complete.\n",
"You can achieve this by using the `stop_when_idle()` method:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"runtime.start()\n",
"# ... Send messages, publish messages, etc.\n",
"await runtime.stop_when_idle() # This will block until the runtime is idle."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can also directly process messages one-by-one without a background task using:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"await runtime.process_next()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Other runtime implementations will have their own ways of running the runtime."
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -10,17 +10,17 @@
"Generally speaking, it will save each code block to a file and then execute that file.\n",
"This means that each code block is executed in a new process. There are two forms of this executor:\n",
"\n",
"- Docker ({py:class}`~autogen_ext.code_executor.docker_executor.DockerCommandLineCodeExecutor`) - this is where all commands are executed in a Docker container\n",
"- Local ({py:class}`~autogen_core.code_executor.local.LocalCommandLineCodeExecutor`) - this is where all commands are executed on the host machine\n",
"- Docker ({py:class}`~autogen_ext.code_executors.docker.DockerCommandLineCodeExecutor`) - this is where all commands are executed in a Docker container\n",
"- Local ({py:class}`~autogen_ext.code_executors.local.LocalCommandLineCodeExecutor`) - this is where all commands are executed on the host machine\n",
"\n",
"## Docker\n",
"\n",
"```{note}\n",
"To use `DockerCommandLineCodeExecutor`, ensure the `autogen-ext[docker]` package is installed. For more details, see the [Packages Documentation](https://microsoft.github.io/autogen/dev/packages/index.html).\n",
"To use {py:class}`~autogen_ext.code_executors.docker.DockerCommandLineCodeExecutor`, ensure the `autogen-ext[docker]` package is installed. For more details, see the [Packages Documentation](https://microsoft.github.io/autogen/dev/packages/index.html).\n",
"\n",
"```\n",
"\n",
"The {py:class}`~autogen_ext.code_executor.docker_executor.DockerCommandLineCodeExecutor` will create a Docker container and run all commands within that container. \n",
"The {py:class}`~autogen_ext.code_executors.docker.DockerCommandLineCodeExecutor` will create a Docker container and run all commands within that container. \n",
"The default image that is used is `python:3-slim`, this can be customized by passing the `image` parameter to the constructor. \n",
"If the image is not found locally then the class will try to pull it. \n",
"Therefore, having built the image locally is enough. The only thing required for this image to be compatible with the executor is to have `sh` and `python` installed. \n",
@ -104,7 +104,7 @@
"The local version will run code on your local system. Use it with caution.\n",
"```\n",
"\n",
"To execute code on the host machine, as in the machine running your application, {py:class}`~autogen_core.components.code_executor.LocalCommandLineCodeExecutor` can be used.\n",
"To execute code on the host machine, as in the machine running your application, {py:class}`~autogen_ext.code_executors.local.LocalCommandLineCodeExecutor` can be used.\n",
"\n",
"### Example"
]
@ -149,7 +149,7 @@
"source": [
"## Local within a Virtual Environment\n",
"\n",
"If you want the code to run within a virtual environment created as part of the applications setup, you can specify a directory for the newly created environment and pass its context to {py:class}`~autogen_core.components.code_executor.LocalCommandLineCodeExecutor`. This setup allows the executor to use the specified virtual environment consistently throughout the application's lifetime, ensuring isolated dependencies and a controlled runtime environment."
"If you want the code to run within a virtual environment created as part of the applications setup, you can specify a directory for the newly created environment and pass its context to {py:class}`~autogen_ext.code_executors.local.LocalCommandLineCodeExecutor`. This setup allows the executor to use the specified virtual environment consistently throughout the application's lifetime, ensuring isolated dependencies and a controlled runtime environment."
]
},
{

View File

@ -1,222 +1,222 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Distributed Agent Runtime\n",
"\n",
"```{attention}\n",
"The distributed agent runtime is an experimental feature. Expect breaking changes\n",
"to the API.\n",
"```\n",
"\n",
"A distributed agent runtime facilitates communication and agent lifecycle management\n",
"across process boundaries.\n",
"It consists of a host service and at least one worker runtime.\n",
"\n",
"The host service maintains connections to all active worker runtimes,\n",
"facilitates message delivery, and keeps sessions for all direct messages (i.e., RPCs).\n",
"A worker runtime processes application code (agents) and connects to the host service.\n",
"It also advertises the agents which they support to the host service,\n",
"so the host service can deliver messages to the correct worker.\n",
"\n",
"````{note}\n",
"The distributed agent runtime requires extra dependencies, install them using:\n",
"```bash\n",
"pip install autogen-core[grpc]==0.4.0.dev9\n",
"```\n",
"````\n",
"\n",
"We can start a host service using {py:class}`~autogen_core.application.GrpcWorkerAgentRuntimeHost`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from autogen_ext.runtimes.grpc import GrpcWorkerAgentRuntimeHost\n",
"\n",
"host = GrpcWorkerAgentRuntimeHost(address=\"localhost:50051\")\n",
"host.start() # Start a host service in the background."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The above code starts the host service in the background and accepts\n",
"worker connections on port 50051.\n",
"\n",
"Before running worker runtimes, let's define our agent.\n",
"The agent will publish a new message on every message it receives.\n",
"It also keeps track of how many messages it has published, and \n",
"stops publishing new messages once it has published 5 messages."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from dataclasses import dataclass\n",
"\n",
"from autogen_core import DefaultTopicId, MessageContext, RoutedAgent, default_subscription, message_handler\n",
"\n",
"\n",
"@dataclass\n",
"class MyMessage:\n",
" content: str\n",
"\n",
"\n",
"@default_subscription\n",
"class MyAgent(RoutedAgent):\n",
" def __init__(self, name: str) -> None:\n",
" super().__init__(\"My agent\")\n",
" self._name = name\n",
" self._counter = 0\n",
"\n",
" @message_handler\n",
" async def my_message_handler(self, message: MyMessage, ctx: MessageContext) -> None:\n",
" self._counter += 1\n",
" if self._counter > 5:\n",
" return\n",
" content = f\"{self._name}: Hello x {self._counter}\"\n",
" print(content)\n",
" await self.publish_message(MyMessage(content=content), DefaultTopicId())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can set up the worker agent runtimes.\n",
"We use {py:class}`~autogen_core.application.GrpcWorkerAgentRuntime`.\n",
"We set up two worker runtimes. Each runtime hosts one agent.\n",
"All agents publish and subscribe to the default topic, so they can see all\n",
"messages being published.\n",
"\n",
"To run the agents, we publishes a message from a worker."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"worker1: Hello x 1\n",
"worker2: Hello x 1\n",
"worker2: Hello x 2\n",
"worker1: Hello x 2\n",
"worker1: Hello x 3\n",
"worker2: Hello x 3\n",
"worker2: Hello x 4\n",
"worker1: Hello x 4\n",
"worker1: Hello x 5\n",
"worker2: Hello x 5\n"
]
}
],
"source": [
"import asyncio\n",
"\n",
"from autogen_ext.runtimes.grpc import GrpcWorkerAgentRuntime\n",
"\n",
"worker1 = GrpcWorkerAgentRuntime(host_address=\"localhost:50051\")\n",
"worker1.start()\n",
"await MyAgent.register(worker1, \"worker1\", lambda: MyAgent(\"worker1\"))\n",
"\n",
"worker2 = GrpcWorkerAgentRuntime(host_address=\"localhost:50051\")\n",
"worker2.start()\n",
"await MyAgent.register(worker2, \"worker2\", lambda: MyAgent(\"worker2\"))\n",
"\n",
"await worker2.publish_message(MyMessage(content=\"Hello!\"), DefaultTopicId())\n",
"\n",
"# Let the agents run for a while.\n",
"await asyncio.sleep(5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can see each agent published exactly 5 messages.\n",
"\n",
"To stop the worker runtimes, we can call {py:meth}`~autogen_core.application.GrpcWorkerAgentRuntime.stop`."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"await worker1.stop()\n",
"await worker2.stop()\n",
"\n",
"# To keep the worker running until a termination signal is received (e.g., SIGTERM).\n",
"# await worker1.stop_when_signal()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can call {py:meth}`~autogen_core.application.GrpcWorkerAgentRuntimeHost.stop`\n",
"to stop the host service."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"await host.stop()\n",
"\n",
"# To keep the host service running until a termination signal (e.g., SIGTERM)\n",
"# await host.stop_when_signal()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Next Steps\n",
"To see complete examples of using distributed runtime, please take a look at the following samples:\n",
"\n",
"- [Distributed Workers](https://github.com/microsoft/autogen/tree/main/python/packages/autogen-core/samples/worker) \n",
"- [Distributed Semantic Router](https://github.com/microsoft/autogen/tree/main/python/packages/autogen-core/samples/semantic_router) \n",
"- [Distributed Group Chat](https://github.com/microsoft/autogen/tree/main/python/packages/autogen-core/samples/distributed-group-chat) \n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "agnext",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Distributed Agent Runtime\n",
"\n",
"```{attention}\n",
"The distributed agent runtime is an experimental feature. Expect breaking changes\n",
"to the API.\n",
"```\n",
"\n",
"A distributed agent runtime facilitates communication and agent lifecycle management\n",
"across process boundaries.\n",
"It consists of a host service and at least one worker runtime.\n",
"\n",
"The host service maintains connections to all active worker runtimes,\n",
"facilitates message delivery, and keeps sessions for all direct messages (i.e., RPCs).\n",
"A worker runtime processes application code (agents) and connects to the host service.\n",
"It also advertises the agents which they support to the host service,\n",
"so the host service can deliver messages to the correct worker.\n",
"\n",
"````{note}\n",
"The distributed agent runtime requires extra dependencies, install them using:\n",
"```bash\n",
"pip install \"autogen-ext[grpc]==0.4.0.dev9\"\n",
"```\n",
"````\n",
"\n",
"We can start a host service using {py:class}`~autogen_ext.runtimes.grpc.GrpcWorkerAgentRuntimeHost`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from autogen_ext.runtimes.grpc import GrpcWorkerAgentRuntimeHost\n",
"\n",
"host = GrpcWorkerAgentRuntimeHost(address=\"localhost:50051\")\n",
"host.start() # Start a host service in the background."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The above code starts the host service in the background and accepts\n",
"worker connections on port 50051.\n",
"\n",
"Before running worker runtimes, let's define our agent.\n",
"The agent will publish a new message on every message it receives.\n",
"It also keeps track of how many messages it has published, and \n",
"stops publishing new messages once it has published 5 messages."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from dataclasses import dataclass\n",
"\n",
"from autogen_core import DefaultTopicId, MessageContext, RoutedAgent, default_subscription, message_handler\n",
"\n",
"\n",
"@dataclass\n",
"class MyMessage:\n",
" content: str\n",
"\n",
"\n",
"@default_subscription\n",
"class MyAgent(RoutedAgent):\n",
" def __init__(self, name: str) -> None:\n",
" super().__init__(\"My agent\")\n",
" self._name = name\n",
" self._counter = 0\n",
"\n",
" @message_handler\n",
" async def my_message_handler(self, message: MyMessage, ctx: MessageContext) -> None:\n",
" self._counter += 1\n",
" if self._counter > 5:\n",
" return\n",
" content = f\"{self._name}: Hello x {self._counter}\"\n",
" print(content)\n",
" await self.publish_message(MyMessage(content=content), DefaultTopicId())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can set up the worker agent runtimes.\n",
"We use {py:class}`~autogen_core.application.GrpcWorkerAgentRuntime`.\n",
"We set up two worker runtimes. Each runtime hosts one agent.\n",
"All agents publish and subscribe to the default topic, so they can see all\n",
"messages being published.\n",
"\n",
"To run the agents, we publishes a message from a worker."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"worker1: Hello x 1\n",
"worker2: Hello x 1\n",
"worker2: Hello x 2\n",
"worker1: Hello x 2\n",
"worker1: Hello x 3\n",
"worker2: Hello x 3\n",
"worker2: Hello x 4\n",
"worker1: Hello x 4\n",
"worker1: Hello x 5\n",
"worker2: Hello x 5\n"
]
}
],
"source": [
"import asyncio\n",
"\n",
"from autogen_ext.runtimes.grpc import GrpcWorkerAgentRuntime\n",
"\n",
"worker1 = GrpcWorkerAgentRuntime(host_address=\"localhost:50051\")\n",
"worker1.start()\n",
"await MyAgent.register(worker1, \"worker1\", lambda: MyAgent(\"worker1\"))\n",
"\n",
"worker2 = GrpcWorkerAgentRuntime(host_address=\"localhost:50051\")\n",
"worker2.start()\n",
"await MyAgent.register(worker2, \"worker2\", lambda: MyAgent(\"worker2\"))\n",
"\n",
"await worker2.publish_message(MyMessage(content=\"Hello!\"), DefaultTopicId())\n",
"\n",
"# Let the agents run for a while.\n",
"await asyncio.sleep(5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can see each agent published exactly 5 messages.\n",
"\n",
"To stop the worker runtimes, we can call {py:meth}`~autogen_ext.runtimes.grpc.GrpcWorkerAgentRuntime.stop`."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"await worker1.stop()\n",
"await worker2.stop()\n",
"\n",
"# To keep the worker running until a termination signal is received (e.g., SIGTERM).\n",
"# await worker1.stop_when_signal()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can call {py:meth}`~autogen_ext.runtimes.grpc.GrpcWorkerAgentRuntimeHost.stop`\n",
"to stop the host service."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"await host.stop()\n",
"\n",
"# To keep the host service running until a termination signal (e.g., SIGTERM)\n",
"# await host.stop_when_signal()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Next Steps\n",
"To see complete examples of using distributed runtime, please take a look at the following samples:\n",
"\n",
"- [Distributed Workers](https://github.com/microsoft/autogen/tree/main/python/packages/autogen-core/samples/worker) \n",
"- [Distributed Semantic Router](https://github.com/microsoft/autogen/tree/main/python/packages/autogen-core/samples/semantic_router) \n",
"- [Distributed Group Chat](https://github.com/microsoft/autogen/tree/main/python/packages/autogen-core/samples/distributed-group-chat) \n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "agnext",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -365,12 +365,12 @@
"metadata": {},
"source": [
"The `SimpleAgent` class is a subclass of the\n",
"{py:class}`autogen_core.components.RoutedAgent` class for the convenience of automatically routing messages to the appropriate handlers.\n",
"{py:class}`autogen_core.RoutedAgent` class for the convenience of automatically routing messages to the appropriate handlers.\n",
"It has a single handler, `handle_user_message`, which handles message from the user. It uses the `ChatCompletionClient` to generate a response to the message.\n",
"It then returns the response to the user, following the direct communication model.\n",
"\n",
"```{note}\n",
"The `cancellation_token` of the type {py:class}`autogen_core.base.CancellationToken` is used to cancel\n",
"The `cancellation_token` of the type {py:class}`autogen_core.CancellationToken` is used to cancel\n",
"asynchronous operations. It is linked to async calls inside the message handlers\n",
"and can be used by the caller to cancel the handlers.\n",
"```"

View File

@ -70,9 +70,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The {py:class}`~autogen_core.components.code_executor.docker_executorCommandLineCodeExecutor`\n",
"The {py:class}`~autogen_ext.code_executors.docker.DockerCommandLineCodeExecutor`\n",
"class is a built-in code executor that runs Python code snippets in a subprocess\n",
"in the local command line environment.\n",
"in the command line environment of a docker container.\n",
"The {py:class}`~autogen_core.components.tools.PythonCodeExecutionTool` class wraps the code executor\n",
"and provides a simple interface to execute Python code snippets.\n",
"\n",

View File

@ -21,7 +21,7 @@
"the agents.\n",
"\n",
"```{attention}\n",
"Code generated in this example is run within a [Docker](https://www.docker.com/) container. Please ensure Docker is [installed](https://docs.docker.com/get-started/get-docker/) and running prior to running the example. Local code execution is available ({py:class}`~autogen_core.components.code_executor.LocalCommandLineCodeExecutor`) but is not recommended due to the risk of running LLM generated code in your local environment.\n",
"Code generated in this example is run within a [Docker](https://www.docker.com/) container. Please ensure Docker is [installed](https://docs.docker.com/get-started/get-docker/) and running prior to running the example. Local code execution is available ({py:class}`~autogen_ext.code_executors.local.LocalCommandLineCodeExecutor`) but is not recommended due to the risk of running LLM generated code in your local environment.\n",
"```"
]
},
@ -36,7 +36,7 @@
"from typing import List\n",
"\n",
"from autogen_core import DefaultTopicId, MessageContext, RoutedAgent, default_subscription, message_handler\n",
"from autogen_core.components.code_executor import CodeBlock, CodeExecutor\n",
"from autogen_core.code_executor import CodeBlock, CodeExecutor\n",
"from autogen_core.components.models import (\n",
" AssistantMessage,\n",
" ChatCompletionClient,\n",

View File

@ -24,7 +24,7 @@
"\n",
"### Initialization\n",
"\n",
"First, you will need to find or create a credentialing object that implements the {py:class}`~autogen_core.components.code_executor.TokenProvider` interface. This is any object that implements the following function\n",
"First, you will need to find or create a credentialing object that implements the {py:class}`~autogen_ext.code_executors.azure.TokenProvider` interface. This is any object that implements the following function\n",
"```python\n",
"def get_token(\n",
" self, *scopes: str, claims: Optional[str] = None, tenant_id: Optional[str] = None, **kwargs: Any\n",
@ -208,7 +208,7 @@
"source": [
"### New Sessions\n",
"\n",
"Every instance of the {py:class}`~autogen_core.components.code_executor.AzureContainerCodeExecutor` class will have a unique session ID. Every call to a particular code executor will be executed on the same session until the {py:meth}`~autogen_core.components.code_executor.AzureContainerCodeExecutor.restart` function is called on it. Previous sessions cannot be reused.\n",
"Every instance of the {py:class}`~autogen_ext.code_executors.azure.AzureContainerCodeExecutor` class will have a unique session ID. Every call to a particular code executor will be executed on the same session until the {py:meth}`~autogen_ext.code_executors.azure.AzureContainerCodeExecutor.restart` function is called on it. Previous sessions cannot be reused.\n",
"\n",
"Here we'll run some code on the code session, restart it, then verify that a new session has been opened."
]
@ -243,7 +243,7 @@
"source": [
"### Available Packages\n",
"\n",
"Each code execution instance is pre-installed with most of the commonly used packages. However, the list of available packages and versions are not available outside of the execution environment. The packages list on the environment can be retrieved by calling the {py:meth}`~autogen_core.components.code_executor.AzureContainerCodeExecutor.get_available_packages` function on the code executor."
"Each code execution instance is pre-installed with most of the commonly used packages. However, the list of available packages and versions are not available outside of the execution environment. The packages list on the environment can be retrieved by calling the {py:meth}`~autogen_ext.code_executors.azure.AzureContainerCodeExecutor.get_available_packages` function on the code executor."
]
},
{

View File

@ -91,7 +91,7 @@ class AgentRuntime(Protocol):
Args:
type (str): The type of agent this factory creates. It is not the same as agent class name. The `type` parameter is used to differentiate between different factory functions rather than agent classes.
agent_factory (Callable[[], T]): The factory that creates the agent, where T is a concrete Agent type. Inside the factory, use `autogen_core.base.AgentInstantiationContext` to access variables like the current runtime and agent ID.
agent_factory (Callable[[], T]): The factory that creates the agent, where T is a concrete Agent type. Inside the factory, use `autogen_core.AgentInstantiationContext` to access variables like the current runtime and agent ID.
subscriptions (Callable[[], list[Subscription]] | list[Subscription] | None, optional): The subscriptions that the agent should be subscribed to. Defaults to None.
"""
@ -108,7 +108,7 @@ class AgentRuntime(Protocol):
Args:
type (str): The type of agent this factory creates. It is not the same as agent class name. The `type` parameter is used to differentiate between different factory functions rather than agent classes.
agent_factory (Callable[[], T]): The factory that creates the agent, where T is a concrete Agent type. Inside the factory, use `autogen_core.base.AgentInstantiationContext` to access variables like the current runtime and agent ID.
agent_factory (Callable[[], T]): The factory that creates the agent, where T is a concrete Agent type. Inside the factory, use `autogen_core.AgentInstantiationContext` to access variables like the current runtime and agent ID.
"""
...

View File

@ -122,7 +122,7 @@ class BaseAgent(ABC, Agent):
*,
cancellation_token: CancellationToken | None = None,
) -> Any:
"""See :py:meth:`autogen_core.base.AgentRuntime.send_message` for more information."""
"""See :py:meth:`autogen_core.AgentRuntime.send_message` for more information."""
if cancellation_token is None:
cancellation_token = CancellationToken()

View File

@ -104,7 +104,7 @@ def message_handler(
- The method must have exactly 3 arguments:
1. `self`
2. `message`: The message to be handled, this must be type-hinted with the message type that it is intended to handle.
3. `ctx`: A :class:`autogen_core.base.MessageContext` object.
3. `ctx`: A :class:`autogen_core.MessageContext` object.
- The method must be type hinted with what message types it can return as a response, or it can return `None` if it does not return anything.
Handlers can handle more than one message type by accepting a Union of the message types. It can also return more than one message type by returning a Union of the message types.
@ -224,7 +224,7 @@ def event(
- The method must have exactly 3 arguments:
1. `self`
2. `message`: The event message to be handled, this must be type-hinted with the message type that it is intended to handle.
3. `ctx`: A :class:`autogen_core.base.MessageContext` object.
3. `ctx`: A :class:`autogen_core.MessageContext` object.
- The method must return `None`.
Handlers can handle more than one message type by accepting a Union of the message types.
@ -344,7 +344,7 @@ def rpc(
- The method must have exactly 3 arguments:
1. `self`
2. `message`: The message to be handled, this must be type-hinted with the message type that it is intended to handle.
3. `ctx`: A :class:`autogen_core.base.MessageContext` object.
3. `ctx`: A :class:`autogen_core.MessageContext` object.
- The method must be type hinted with what message types it can return as a response, or it can return `None` if it does not return anything.
Handlers can handle more than one message type by accepting a Union of the message types. It can also return more than one message type by returning a Union of the message types.

View File

@ -10,9 +10,9 @@ from autogen_core import SingleThreadedAgentRuntime
from autogen_core.application.logging import EVENT_LOGGER_NAME
from autogen_core import AgentId, AgentProxy
from autogen_core import DefaultTopicId
from autogen_core.components.code_executor import LocalCommandLineCodeExecutor
from autogen_ext.code_executors.local import LocalCommandLineCodeExecutor
from autogen_ext.code_executor.docker_executor import DockerCommandLineCodeExecutor
from autogen_core.components.code_executor import CodeBlock
from autogen_core.code_executor import CodeBlock
from autogen_magentic_one.agents.coder import Coder, Executor
from autogen_magentic_one.agents.file_surfer import FileSurfer
from autogen_magentic_one.agents.multimodal_web_surfer import MultimodalWebSurfer