Skip to content

Commit d67f568

Browse files
authored
Python: Multi-agent orchestration: Magentic (microsoft#12104)
### Motivation and Context <!-- Thank you for your contribution to the semantic-kernel repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 2. What problem does it solve? 3. What scenario does it contribute to? 4. If it fixes an open issue, please link to the issue here. --> PR for Magentic multi-agent orchestration. ADR: https://github.com/microsoft/semantic-kernel/blob/main/docs/decisions/0071-multi-agent-orchestration.md Initial PR: microsoft#11993 ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> This PR includes the following: 1. Implementations for the magentic orchestrations 2. Unit tests and samples ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone 😄 --------- Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
1 parent 6f80214 commit d67f568

11 files changed

Lines changed: 2021 additions & 16 deletions

File tree

‎python/.cspell.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"logit",
4848
"logprobs",
4949
"lowlevel",
50+
"Magentic",
5051
"mistralai",
5152
"mongocluster",
5253
"nd",
@@ -77,4 +78,4 @@
7778
"vertexai",
7879
"Weaviate"
7980
]
80-
}
81+
}

‎python/samples/getting_started_with_agents/README.md‎

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,20 +49,6 @@ Example|Description
4949

5050
_Note: For details on configuring an Azure AI Agent, please see [here](../getting_started_with_agents/azure_ai_agent/README.md)._
5151

52-
## Multi Agent Orchestration
53-
54-
Example|Description
55-
---|---
56-
[step1_concurrent](../getting_started_with_agents/multi_agent_orchestration/step1_concurrent.py)|How to run multiple agents concurrently and manage their output.
57-
[step1a_concurrent_structure_output](../getting_started_with_agents/multi_agent_orchestration/step1a_concurrent_structure_output.py)|How to run concurrent agents that return structured outputs.
58-
[step2_sequential](../getting_started_with_agents/multi_agent_orchestration/step2_sequential.py)|How to run agents sequentially where each one depends on the previous.
59-
[step2a_sequential_cancellation_token](../getting_started_with_agents/multi_agent_orchestration/step2a_sequential_cancellation_token.py)|How to use cancellation tokens in a sequential agent flow.
60-
[step3_group_chat](../getting_started_with_agents/multi_agent_orchestration/step3_group_chat.py)|How to create a group chat with multiple agents interacting together.
61-
[step3a_group_chat_human_in_the_loop](../getting_started_with_agents/multi_agent_orchestration/step3a_group_chat_human_in_the_loop.py)|How to include a human participant in a group chat with agents.
62-
[step3b_group_chat_with_chat_completion_manager](../getting_started_with_agents/multi_agent_orchestration/step3b_group_chat_with_chat_completion_manager.py)|How to manage a group chat with agents using a chat completion manager.
63-
[step4_handoff](../getting_started_with_agents/multi_agent_orchestration/step4_handoff.py)|How to hand off conversation or tasks from one agent to another.
64-
[step4a_handoff_structured_inputs](../getting_started_with_agents/multi_agent_orchestration/step4a_handoff_structured_inputs.py)|How to perform structured inputs handoffs between agents.
65-
6652

6753
## OpenAI Assistant Agent
6854

@@ -86,6 +72,21 @@ Example|Description
8672
[step6_responses_agent_vision](../getting_started_with_agents/openai_responses/step6_responses_agent_vision.py)|How to provide an image as input to an OpenAI Responses agent.
8773
[step7_responses_agent_structured_outputs](../getting_started_with_agents/openai_responses/step7_responses_agent_structured_outputs.py)|How to use have an OpenAI Responses agent use structured outputs.
8874

75+
## Multi-Agent Orchestration
76+
77+
Example|Description
78+
---|---
79+
[step1_concurrent](../getting_started_with_agents/multi_agent_orchestration/step1_concurrent.py)|How to run agents in parallel on the same task.
80+
[step1a_concurrent_structure_output](../getting_started_with_agents/multi_agent_orchestration/step1a_concurrent_structure_output.py)|How to run agents in parallel on the same task and return structured output.
81+
[step2_sequential](../getting_started_with_agents/multi_agent_orchestration/step2_sequential.py)|How to run agents in sequence to complete a task.
82+
[step2a_sequential_cancellation_token](../getting_started_with_agents/multi_agent_orchestration/step2a_sequential_cancellation_token.py)|How to cancel an invocation while it is in progress.
83+
[step3_group_chat](../getting_started_with_agents/multi_agent_orchestration/step3_group_chat.py)|How to run agents in a group chat to complete a task.
84+
[step3a_group_chat_human_in_the_loop](../getting_started_with_agents/multi_agent_orchestration/step3a_group_chat_human_in_the_loop.py)|How to run agents in a group chat with human in the loop.
85+
[step3b_group_chat_with_chat_completion_manager](../getting_started_with_agents/multi_agent_orchestration/step3b_group_chat_with_chat_completion_manager.py)|How to run agents in a group chat with a more dynamic manager.
86+
[step4_handoff](../getting_started_with_agents/multi_agent_orchestration/step4_handoff.py)|How to run agents in a handoff orchestration to complete a task.
87+
[step4a_handoff_structure_input](../getting_started_with_agents/multi_agent_orchestration/step4a_handoff_structure_input.py)|How to run agents in a handoff orchestration to complete a task with structured input.
88+
[step5_magentic](../getting_started_with_agents/multi_agent_orchestration/step5_magentic.py)|How to run agents in a Magentic orchestration to complete a task.
89+
8990
## Configuring the Kernel
9091

9192
Similar to the Semantic Kernel Python concept samples, it is necessary to configure the secrets
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Multi-agent orchestration
2+
3+
The Semantic Kernel Agent Framework now supports orchestrating multiple agents to work together to complete a task.
4+
5+
## Background
6+
7+
The following samples are beneficial if you are just getting started with Semantic Kernel.
8+
9+
- [Chat Completion](../../concepts/chat_completion/)
10+
- [Auto Function Calling](../../concepts/auto_function_calling/)
11+
- [Structured Output](../../concepts/structured_output/)
12+
- [Getting Started with Agents](../../getting_started_with_agents/)
13+
- [More advanced agent samples](../../concepts/agents/)
14+
15+
## Prerequisites
16+
17+
The following environment variables are required to run the samples:
18+
19+
- OPENAI_API_KEY
20+
- OPENAI_CHAT_MODEL_ID
21+
22+
However, if you are using other model services, feel free to switch to those in the samples.
23+
Refer to [here](../../concepts/setup/README.md) on how to set up the environment variables for your model service.
24+
25+
## Orchestrations
26+
27+
| **Orchestrations** | **Description** |
28+
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
29+
| **Concurrent** | Useful for tasks that will benefit from independent analysis from multiple agents. |
30+
| **Sequential** | Useful for tasks that require a well-defined step-by-step approach. |
31+
| **Handoff** | Useful for tasks that are dynamic in nature and don't have a well-defined step-by-step approach. |
32+
| **GroupChat** | Useful for tasks that will benefit from inputs from multiple agents and a highly configurable conversation flow. |
33+
| **Magentic** | GroupChat like with a planner based manager. Inspired by [Magentic One](https://www.microsoft.com/en-us/research/articles/magentic-one-a-generalist-multi-agent-system-for-solving-complex-tasks/). |

python/samples/getting_started_with_agents/multi_agent_orchestration/step1a_concurrent_structure_output.py renamed to python/samples/getting_started_with_agents/multi_agent_orchestration/step1a_concurrent_structured_outputs.py

File renamed without changes.
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
# Copyright (c) Microsoft. All rights reserved.
2+
3+
import asyncio
4+
5+
from semantic_kernel.agents import (
6+
Agent,
7+
ChatCompletionAgent,
8+
MagenticOrchestration,
9+
OpenAIAssistantAgent,
10+
StandardMagenticManager,
11+
)
12+
from semantic_kernel.agents.runtime import InProcessRuntime
13+
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
14+
from semantic_kernel.contents import ChatMessageContent
15+
16+
"""
17+
The following sample demonstrates how to create a Magentic orchestration with two agents:
18+
- A Research agent that can perform web searches
19+
- A Coder agent that can run code using the code interpreter
20+
21+
Read more about Magentic here:
22+
https://www.microsoft.com/en-us/research/articles/magentic-one-a-generalist-multi-agent-system-for-solving-complex-tasks/
23+
24+
This sample demonstrates the basic steps of creating and starting a runtime, creating
25+
a Magentic orchestration with two agents and a Magentic manager, invoking the
26+
orchestration, and finally waiting for the results.
27+
28+
The Magentic manager requires a chat completion model that supports structured output.
29+
"""
30+
31+
32+
async def agents() -> list[Agent]:
33+
"""Return a list of agents that will participate in the Magentic orchestration.
34+
35+
Feel free to add or remove agents.
36+
"""
37+
research_agent = ChatCompletionAgent(
38+
name="ResearchAgent",
39+
description="A helpful assistant with access to web search. Ask it to perform web searches.",
40+
instructions=(
41+
"You are a Researcher. You find information without additional computation or quantitative analysis."
42+
),
43+
# This agent requires the gpt-4o-search-preview model to perform web searches.
44+
# Feel free to explore with other agents that support web search, for example,
45+
# the `OpenAIResponseAgent` or `AzureAIAgent` with bing grounding.
46+
service=OpenAIChatCompletion(ai_model_id="gpt-4o-search-preview"),
47+
)
48+
49+
# Create an OpenAI Assistant agent with code interpreter capability
50+
client, model = OpenAIAssistantAgent.setup_resources()
51+
code_interpreter_tool, code_interpreter_tool_resources = OpenAIAssistantAgent.configure_code_interpreter_tool()
52+
definition = await client.beta.assistants.create(
53+
model=model,
54+
name="CoderAgent",
55+
description="A helpful assistant that writes and executes code to process and analyze data.",
56+
instructions="You solve questions using code. Please provide detailed analysis and computation process.",
57+
tools=code_interpreter_tool,
58+
tool_resources=code_interpreter_tool_resources,
59+
)
60+
coder_agent = OpenAIAssistantAgent(
61+
client=client,
62+
definition=definition,
63+
)
64+
65+
return [research_agent, coder_agent]
66+
67+
68+
def agent_response_callback(message: ChatMessageContent) -> None:
69+
"""Observer function to print the messages from the agents."""
70+
print(f"**{message.name}**\n{message.content}")
71+
72+
73+
async def main():
74+
"""Main function to run the agents."""
75+
# 1. Create a Magentic orchestration with two agents and a Magentic manager
76+
# Note, the Standard Magentic manager uses prompts that have been tuned very
77+
# carefully but it accepts custom prompts for advanced users and scenarios.
78+
# For even more advanced scenarios, you can subclass the MagenticManagerBase
79+
# and implement your own manager logic.
80+
# The standard manager also requires a chat completion model that supports
81+
# structured output.
82+
magentic_orchestration = MagenticOrchestration(
83+
members=await agents(),
84+
manager=StandardMagenticManager(chat_completion_service=OpenAIChatCompletion()),
85+
agent_response_callback=agent_response_callback,
86+
)
87+
88+
# 2. Create a runtime and start it
89+
runtime = InProcessRuntime()
90+
runtime.start()
91+
92+
# 3. Invoke the orchestration with a task and the runtime
93+
orchestration_result = await magentic_orchestration.invoke(
94+
task=(
95+
"I am preparing a report on the energy efficiency of different machine learning model architectures. "
96+
"Compare the estimated training and inference energy consumption of ResNet-50, BERT-base, and GPT-2 "
97+
"on standard datasets (e.g., ImageNet for ResNet, GLUE for BERT, WebText for GPT-2). "
98+
"Then, estimate the CO2 emissions associated with each, assuming training on an Azure Standard_NC6s_v3 VM "
99+
"for 24 hours. Provide tables for clarity, and recommend the most energy-efficient model "
100+
"per task type (image classification, text classification, and text generation)."
101+
),
102+
runtime=runtime,
103+
)
104+
105+
# 4. Wait for the results
106+
value = await orchestration_result.get()
107+
108+
print(f"\nFinal result:\n{value}")
109+
110+
# 5. Stop the runtime when idle
111+
await runtime.stop_when_idle()
112+
113+
"""
114+
Sample output:
115+
**ResearchAgent**
116+
Estimating the energy consumption and associated CO₂ emissions for training and inference of ResNet-50, BERT-base...
117+
118+
**CoderAgent**
119+
Here is the comparison of energy consumption and CO₂ emissions for each model (ResNet-50, BERT-base, and GPT-2)
120+
over a 24-hour period:
121+
122+
| Model | Training Energy (kWh) | Inference Energy (kWh) | Total Energy (kWh) | CO₂ Emissions (kg) |
123+
|-----------|------------------------|------------------------|---------------------|---------------------|
124+
| ResNet-50 | 21.11 | 0.08232 | 21.19232 | 19.50 |
125+
| BERT-base | 0.048 | 0.23736 | 0.28536 | 0.26 |
126+
| GPT-2 | 42.22 | 0.35604 | 42.57604 | 39.17 |
127+
128+
### Recommendations:
129+
...
130+
131+
**CoderAgent**
132+
Here are the recalibrated results for energy consumption and CO₂ emissions, assuming a more conservative approach
133+
for models like GPT-2:
134+
135+
| Model | Training Energy (kWh) | Inference Energy (kWh) | Total Energy (kWh) | CO₂ Emissions (kg) |
136+
|------------------|------------------------|------------------------|---------------------|---------------------|
137+
| ResNet-50 | 21.11 | 0.08232 | 21.19232 | 19.50 |
138+
| BERT-base | 0.048 | 0.23736 | 0.28536 | 0.26 |
139+
| GPT-2 (Adjusted) | 42.22 | 0.35604 | 42.57604 | 39.17 |
140+
141+
...
142+
143+
**ResearchAgent**
144+
Estimating the energy consumption and associated CO₂ emissions for training and inference of machine learning ...
145+
146+
**ResearchAgent**
147+
Estimating the energy consumption and CO₂ emissions of training and inference for ResNet-50, BERT-base, and ...
148+
149+
**CoderAgent**
150+
Here is the estimated energy use and CO₂ emissions for a full day of operation for each model on an Azure ...
151+
152+
**ResearchAgent**
153+
Recent analyses have highlighted the substantial energy consumption and carbon emissions associated with ...
154+
155+
**CoderAgent**
156+
Here's the refined estimation for the energy use and CO₂ emissions for optimized models on an Azure ...
157+
158+
**CoderAgent**
159+
To provide precise estimates for CO₂ emissions based on Azure's regional data centers' carbon intensity, we need ...
160+
161+
**ResearchAgent**
162+
To refine the CO₂ emission estimates for training and inference of ResNet-50, BERT-base, and GPT-2 on an Azure ...
163+
164+
**CoderAgent**
165+
Here's the refined comparative table for energy consumption and CO₂ emissions for ResNet-50, BERT-base, and GPT-2,
166+
taking into account carbon intensity data for Azure's West Europe and Sweden Central regions:
167+
168+
| Model | Energy (kWh) | CO₂ Emissions West Europe (kg) | CO₂ Emissions Sweden Central (kg) |
169+
|------------|--------------|--------------------------------|-----------------------------------|
170+
| ResNet-50 | 5.76 | 0.639 | 0.086 |
171+
| BERT-base | 9.18 | 1.019 | 0.138 |
172+
| GPT-2 | 12.96 | 1.439 | 0.194 |
173+
174+
**Refined Recommendations:**
175+
176+
...
177+
178+
Final result:
179+
Here is the comprehensive report on energy efficiency and CO₂ emissions for ResNet-50, BERT-base, and GPT-2 models
180+
when trained and inferred on an Azure Standard_NC6s_v3 VM for 24 hours.
181+
182+
### Energy Consumption and CO₂ Emissions:
183+
184+
Based on refined analyses, here are the estimated energy consumption and CO₂ emissions for each model:
185+
186+
| Model | Energy (kWh) | CO₂ Emissions West Europe (kg) | CO₂ Emissions Sweden Central (kg) |
187+
|------------|--------------|--------------------------------|-----------------------------------|
188+
| ResNet-50 | 5.76 | 0.639 | 0.086 |
189+
| BERT-base | 9.18 | 1.019 | 0.138 |
190+
| GPT-2 | 12.96 | 1.439 | 0.194 |
191+
192+
### Recommendations for Energy Efficiency:
193+
194+
...
195+
"""
196+
197+
198+
if __name__ == "__main__":
199+
asyncio.run(main())

‎python/semantic_kernel/agents/__init__.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@
4040
"HandoffOrchestration": ".orchestration.handoffs",
4141
"OrchestrationHandoffs": ".orchestration.handoffs",
4242
"GroupChatOrchestration": ".orchestration.group_chat",
43+
"RoundRobinGroupChatManager": ".orchestration.group_chat",
44+
"BooleanResult": ".orchestration.group_chat",
45+
"StringResult": ".orchestration.group_chat",
46+
"MessageResult": ".orchestration.group_chat",
47+
"GroupChatManager": ".orchestration.group_chat",
48+
"MagenticOrchestration": ".orchestration.magentic",
49+
"ProgressLedger": ".orchestration.magentic",
50+
"MagenticManagerBase": ".orchestration.magentic",
51+
"StandardMagenticManager": ".orchestration.magentic",
4352
}
4453

4554

‎python/semantic_kernel/agents/__init__.pyi‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,16 @@ from .open_ai.open_ai_assistant_agent import AssistantAgentThread, OpenAIAssista
2727
from .open_ai.openai_responses_agent import OpenAIResponsesAgent, ResponsesAgentThread
2828
from .open_ai.run_polling_options import RunPollingOptions
2929
from .orchestration.concurrent import ConcurrentOrchestration
30-
from .orchestration.group_chat import GroupChatManager, GroupChatOrchestration, RoundRobinGroupChatManager
30+
from .orchestration.group_chat import (
31+
BooleanResult,
32+
GroupChatManager,
33+
GroupChatOrchestration,
34+
MessageResult,
35+
RoundRobinGroupChatManager,
36+
StringResult,
37+
)
3138
from .orchestration.handoffs import HandoffOrchestration, OrchestrationHandoffs
39+
from .orchestration.magentic import MagenticManagerBase, MagenticOrchestration, ProgressLedger, StandardMagenticManager
3240
from .orchestration.sequential import SequentialOrchestration
3341

3442
__all__ = [
@@ -49,6 +57,7 @@ __all__ = [
4957
"AzureResponsesAgent",
5058
"BedrockAgent",
5159
"BedrockAgentThread",
60+
"BooleanResult",
5261
"ChatCompletionAgent",
5362
"ChatHistoryAgentThread",
5463
"ConcurrentOrchestration",
@@ -60,15 +69,21 @@ __all__ = [
6069
"GroupChatManager",
6170
"GroupChatOrchestration",
6271
"HandoffOrchestration",
72+
"MagenticManagerBase",
73+
"MagenticOrchestration",
74+
"MessageResult",
6375
"ModelConnection",
6476
"ModelSpec",
6577
"OpenAIAssistantAgent",
6678
"OpenAIResponsesAgent",
6779
"OrchestrationHandoffs",
80+
"ProgressLedger",
6881
"ResponsesAgentThread",
6982
"RoundRobinGroupChatManager",
7083
"RunPollingOptions",
7184
"SequentialOrchestration",
85+
"StandardMagenticManager",
86+
"StringResult",
7287
"ToolSpec",
7388
"register_agent_type",
7489
]

0 commit comments

Comments
 (0)