Skip to content

Commit dfbc993

Browse files
authored
Python: Remove orchestration persona adaptation messages (#12446)
### 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. --> We previously found that agents might get carried away from in long contexts. The persona adaptation messages were designed to steer the agents in an orchestration to respond more closely to the instructions provided (as system message). As we perform more testing with newer models, we believe that the persona adaptation messages are no longer necessary. The additional instability (because they are hardcoded messages that devs can't override) and cost (the additional token cost which is not significant, but they do pollute the context which makes debugging difficult) they introduce is not worth the benefit they provide. Closing #12294 > Ideally, we'd want to approach this more analytically. The lack of a multi-agent evaluation process makes it difficult. All samples were verified to make sure they behave the same before and after the removal of the persona adaptation messages. ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> 1. Remove the persona adaptation messages. 2. Unit tests. 3. Replace `OpenAIChatCompletion` with `AzureChatCompletion` in some of the 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 😄
1 parent eda707f commit dfbc993

File tree

8 files changed

+32
-84
lines changed

8 files changed

+32
-84
lines changed

python/samples/getting_started_with_agents/multi_agent_orchestration/step3a_group_chat_human_in_the_loop.py

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -130,35 +130,26 @@ async def main():
130130

131131
"""
132132
**Writer**
133-
"Electrify Your Drive: Affordable Fun for Everyone!"
133+
"Electrify Your Journey: Affordable Adventure Awaits!"
134134
**Reviewer**
135-
This slogan, "Electrify Your Drive: Affordable Fun for Everyone!" does a great job of conveying the core benefits
136-
of an electric SUV. Here's some feedback to consider:
137-
138-
...
139-
140-
Consider testing this slogan with focus groups or within your target market to gather insights on resonance and
141-
perception. Overall, it is a compelling and engaging statement that successfully captures the essence of your
142-
electric SUV.
143-
User: Make it rhyme
135+
Your slogan captures the essence of being both affordable and fun, which is great! However, you might want to ...
136+
User: I'd like to also make it rhyme
144137
**Writer**
145-
"Drive Electric, Feel the Thrill, Affordable Fun That Fits the Bill!"
146-
**Reviewer**
147-
The slogan, "Drive Electric, Feel the Thrill, Affordable Fun That Fits the Bill!" successfully incorporates rhyme,
148-
adding a catchy and memorable element to your marketing message. Here's some detailed feedback on this version:
138+
Sure! Here are a few rhyming slogan options for your electric SUV:
149139
150-
...
140+
1. "Zoom Through the Streets, Feel the Beats!"
141+
2. "Charge and Drive, Feel the Jive!"
142+
3. "Electrify Your Ride, Let Fun Be Your Guide!"
143+
4. "Zoom in Style, Drive with a Smile!"
151144
152-
Overall, this rhyming slogan is an improvement for making the tagline more memorable and appealing. It captures the
153-
excitement and accessibility of the product effectively. Consider checking how it resonates with your target
154-
demographic to ensure it aligns well with their preferences and expectations.
155-
User: Nice!
145+
Let me know if you'd like more options or variations!
146+
**Reviewer**
147+
These rhyming slogans are creative and energetic! They effectively capture the fun aspect while promoting ...
148+
User: Please continue with the reviewer's suggestions
156149
**Writer**
157-
Thank you! I'm glad you liked the feedback. If you need help with anything else, like tailoring the slogan for
158-
specific platforms or audiences, just let me know!
150+
Absolutely! Let's refine and expand on the reviewer's suggestions for a more polished and appealing set of rhym...
159151
***** Result *****
160-
Thank you! I'm glad you liked the feedback. If you need help with anything else, like tailoring the slogan for
161-
specific platforms or audiences, just let me know!
152+
Absolutely! Let's refine and expand on the reviewer's suggestions for a more polished and appealing set of rhym...
162153
"""
163154

164155

python/samples/getting_started_with_agents/multi_agent_orchestration/step4_handoff.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from semantic_kernel.agents import Agent, ChatCompletionAgent, HandoffOrchestration, OrchestrationHandoffs
66
from semantic_kernel.agents.runtime import InProcessRuntime
7-
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
7+
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
88
from semantic_kernel.contents import AuthorRole, ChatMessageContent
99
from semantic_kernel.functions import kernel_function
1010

@@ -61,30 +61,30 @@ def get_agents() -> tuple[list[Agent], OrchestrationHandoffs]:
6161
name="TriageAgent",
6262
description="A customer support agent that triages issues.",
6363
instructions="Handle customer requests.",
64-
service=OpenAIChatCompletion(),
64+
service=AzureChatCompletion(),
6565
)
6666

6767
refund_agent = ChatCompletionAgent(
6868
name="RefundAgent",
6969
description="A customer support agent that handles refunds.",
7070
instructions="Handle refund requests.",
71-
service=OpenAIChatCompletion(),
71+
service=AzureChatCompletion(),
7272
plugins=[OrderRefundPlugin()],
7373
)
7474

7575
order_status_agent = ChatCompletionAgent(
7676
name="OrderStatusAgent",
7777
description="A customer support agent that checks order status.",
7878
instructions="Handle order status requests.",
79-
service=OpenAIChatCompletion(),
79+
service=AzureChatCompletion(),
8080
plugins=[OrderStatusPlugin()],
8181
)
8282

8383
order_return_agent = ChatCompletionAgent(
8484
name="OrderReturnAgent",
8585
description="A customer support agent that handles order returns.",
8686
instructions="Handle order return requests.",
87-
service=OpenAIChatCompletion(),
87+
service=AzureChatCompletion(),
8888
plugins=[OrderReturnPlugin()],
8989
)
9090

python/samples/getting_started_with_agents/multi_agent_orchestration/step4a_handoff_structured_inputs.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from semantic_kernel.agents import Agent, ChatCompletionAgent, HandoffOrchestration, OrchestrationHandoffs
99
from semantic_kernel.agents.runtime import InProcessRuntime
10-
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
10+
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
1111
from semantic_kernel.contents import AuthorRole, ChatMessageContent
1212
from semantic_kernel.functions import kernel_function
1313

@@ -78,20 +78,20 @@ def get_agents() -> tuple[list[Agent], OrchestrationHandoffs]:
7878
name="TriageAgent",
7979
description="An agent that triages GitHub issues",
8080
instructions="Given a GitHub issue, triage it.",
81-
service=OpenAIChatCompletion(),
81+
service=AzureChatCompletion(),
8282
)
8383
python_agent = ChatCompletionAgent(
8484
name="PythonAgent",
8585
description="An agent that handles Python related issues",
8686
instructions="You are an agent that handles Python related GitHub issues.",
87-
service=OpenAIChatCompletion(),
87+
service=AzureChatCompletion(),
8888
plugins=[GithubPlugin()],
8989
)
9090
dotnet_agent = ChatCompletionAgent(
9191
name="DotNetAgent",
9292
description="An agent that handles .NET related issues",
9393
instructions="You are an agent that handles .NET related GitHub issues.",
94-
service=OpenAIChatCompletion(),
94+
service=AzureChatCompletion(),
9595
plugins=[GithubPlugin()],
9696
)
9797

python/semantic_kernel/agents/orchestration/group_chat.py

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -125,22 +125,8 @@ async def _handle_start_message(self, message: GroupChatStartMessage, ctx: Messa
125125
async def _handle_response_message(self, message: GroupChatResponseMessage, ctx: MessageContext) -> None:
126126
logger.debug(f"{self.id}: Received group chat response message.")
127127
if self._agent_thread is not None:
128-
if message.body.role != AuthorRole.USER:
129-
await self._agent_thread.on_new_message(
130-
ChatMessageContent(
131-
role=AuthorRole.USER,
132-
content=f"Transferred to {message.body.name}",
133-
)
134-
)
135128
await self._agent_thread.on_new_message(message.body)
136129
else:
137-
if message.body.role != AuthorRole.USER:
138-
self._chat_history.add_message(
139-
ChatMessageContent(
140-
role=AuthorRole.USER,
141-
content=f"Transferred to {message.body.name}",
142-
)
143-
)
144130
self._chat_history.add_message(message.body)
145131

146132
@message_handler
@@ -150,11 +136,7 @@ async def _handle_request_message(self, message: GroupChatRequestMessage, ctx: M
150136

151137
logger.debug(f"{self.id}: Received group chat request message.")
152138

153-
persona_adoption_message = ChatMessageContent(
154-
role=AuthorRole.USER,
155-
content=f"Transferred to {self._agent.name}, adopt the persona immediately.",
156-
)
157-
response = await self._invoke_agent(additional_messages=persona_adoption_message)
139+
response = await self._invoke_agent()
158140

159141
logger.debug(f"{self.id} responded with {response}.")
160142

python/semantic_kernel/agents/orchestration/handoffs.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -279,14 +279,7 @@ async def _handle_request_message(self, message: HandoffRequestMessage, cts: Mes
279279
return
280280
logger.debug(f"{self.id}: Received handoff request message.")
281281

282-
persona_adoption_message = ChatMessageContent(
283-
role=AuthorRole.USER,
284-
content=f"Transferred to {self._agent.name}, adopt the persona immediately.",
285-
)
286-
response = await self._invoke_agent_with_potentially_no_response(
287-
additional_messages=persona_adoption_message,
288-
kernel=self._kernel,
289-
)
282+
response = await self._invoke_agent_with_potentially_no_response(kernel=self._kernel)
290283

291284
while not self._task_completed:
292285
if self._handoff_agent_name:

python/semantic_kernel/agents/orchestration/magentic.py

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -678,22 +678,8 @@ class MagenticAgentActor(AgentActorBase):
678678
async def _handle_response_message(self, message: MagenticResponseMessage, ctx: MessageContext) -> None:
679679
logger.debug(f"{self.id}: Received response message.")
680680
if self._agent_thread is not None:
681-
if message.body.role != AuthorRole.USER:
682-
await self._agent_thread.on_new_message(
683-
ChatMessageContent(
684-
role=AuthorRole.USER,
685-
content=f"Transferred to {message.body.name}",
686-
)
687-
)
688681
await self._agent_thread.on_new_message(message.body)
689682
else:
690-
if message.body.role != AuthorRole.USER:
691-
self._chat_history.add_message(
692-
ChatMessageContent(
693-
role=AuthorRole.USER,
694-
content=f"Transferred to {message.body.name}",
695-
)
696-
)
697683
self._chat_history.add_message(message.body)
698684

699685
@message_handler
@@ -703,11 +689,7 @@ async def _handle_request_message(self, message: MagenticRequestMessage, ctx: Me
703689

704690
logger.debug(f"{self.id}: Received request message.")
705691

706-
persona_adoption_message = ChatMessageContent(
707-
role=AuthorRole.USER,
708-
content=f"Transferred to {self._agent.name}, adopt the persona immediately.",
709-
)
710-
response = await self._invoke_agent(additional_messages=persona_adoption_message)
692+
response = await self._invoke_agent()
711693

712694
logger.debug(f"{self.id} responded with {response}.")
713695

python/tests/unit/agents/orchestration/test_group_chat.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,10 @@ async def test_invoke_with_list():
133133
await runtime.stop_when_idle()
134134

135135
assert mock_invoke_stream.call_count == 2
136-
# Two messages + one message added internally to steer the conversation
137-
assert len(mock_invoke_stream.call_args_list[0][1]["messages"]) == 3
138-
# Two messages + two message added internally to steer the conversation + response from agent A
139-
assert len(mock_invoke_stream.call_args_list[1][1]["messages"]) == 5
136+
# Two messages
137+
assert len(mock_invoke_stream.call_args_list[0][1]["messages"]) == 2
138+
# Two messages + response from agent A
139+
assert len(mock_invoke_stream.call_args_list[1][1]["messages"]) == 3
140140

141141

142142
async def test_invoke_with_response_callback():

python/tests/unit/agents/orchestration/test_handoff.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,8 @@ async def test_invoke_with_list():
402402
await runtime.stop_when_idle()
403403

404404
assert mock_invoke_stream.call_count == 1
405-
# Two messages + one message added internally to steer the conversation
406-
assert len(mock_invoke_stream.call_args_list[0][1]["messages"]) == 3
405+
# Two messages
406+
assert len(mock_invoke_stream.call_args_list[0][1]["messages"]) == 2
407407
# The kernel in the agent should not be modified
408408
assert len(agent_a.kernel.plugins) == 0
409409
assert len(agent_b.kernel.plugins) == 0

0 commit comments

Comments
 (0)