Note
Go to the end to download the full example code.
Conversation¶
Conversation is a design pattern that agents exchange and share information between each other, most commonly in game playing, chatbot, and multi-agent discussion scenarios.
In AgentScope, the conversation is built upon the explicit message exchange. In this tutorial, we will demonstrate how to build a conversation
between a user and an agent (chatbot)
between multiple agents (game playing, discussion, etc.)
Their main difference lies in
how the prompt is constructed, and
how the information is propagated/shared among agents.
import asyncio
import json
import os
from agentscope.agent import ReActAgent, UserAgent
from agentscope.memory import InMemoryMemory
from agentscope.formatter import (
DashScopeChatFormatter,
DashScopeMultiAgentFormatter,
)
from agentscope.model import DashScopeChatModel
from agentscope.message import Msg
from agentscope.pipeline import MsgHub
from agentscope.tool import Toolkit
User-Agent Conversation¶
User-agent conversation, also known as chatbot, is the most common usage scenario of LLM-empowered agents, and the design target of most LLM APIs. Such conversation features only two participants: a user and an agent.
In AgentScope, the formatters with “Chat” in its name are designed for
user-agent conversation, such as DashScopeChatFormatter
,
AnthropicChatFormatter
, etc.
They use the role
field in the message to distinguish the user and the
agent, and format the messages accordingly.
Here we build a simple conversation between agent Friday
and user.
Tip
AgentScope provides a built-in UserAgent
class for human-in-the-loop (HITL) interaction. Refer to user-agent for more details.
friday = ReActAgent(
name="Friday",
sys_prompt="You're a helpful assistant named Friday",
model=DashScopeChatModel(
model_name="qwen-max",
api_key=os.environ["DASHSCOPE_API_KEY"],
),
formatter=DashScopeChatFormatter(), # The formatter for user-agent conversation
memory=InMemoryMemory(),
toolkit=Toolkit(),
)
# Create a user agent
user = UserAgent(name="User")
Now, we can program the conversation by exchanging messages between these two agents until the user types “exit” to end the conversation.
async def run_conversation() -> None:
"""Run a simple conversation between Friday and User."""
msg = None
while True:
msg = await friday(msg)
msg = await user(msg)
if msg.get_text_content() == "exit":
break
asyncio.run(run_conversation())
More than Two Agents¶
As stated in the beginning, we demonstrate how to build conversation with multiple agents in terms of prompt construction and information sharing.
Prompt Construction¶
In AgentScope, we provide built-in formatters for multi-agent conversation, featuring “MultiAgent” in their names, such as DashScopeMultiAgentFormatter
, AnthropicMultiAgentFormatter
, etc.
Specifically, they use the name
field in the message to distinguish different agents, and format the conversation history into a single user message.
Taking DashScopeMultiAgentFormatter
as an example:
Tip
More details about the formatter can be found in Prompt Formatter.
async def example_multi_agent_prompt() -> None:
msgs = [
Msg("system", "You're a helpful assistant named Bob.", "system"),
Msg("Alice", "Hi!", "user"),
Msg("Bob", "Hi! Nice to meet you guys.", "assistant"),
Msg("Charlie", "Me too! I'm Charlie, by the way.", "assistant"),
]
formatter = DashScopeMultiAgentFormatter()
prompt = await formatter.format(msgs)
print("Formatted prompt:")
print(json.dumps(prompt, indent=4, ensure_ascii=False))
# We print the content of the combined user message here for better
# understanding:
print("-------------")
print("Combined message")
print(prompt[1]["content"])
asyncio.run(example_multi_agent_prompt())
Formatted prompt:
[
{
"role": "system",
"content": "You're a helpful assistant named Bob."
},
{
"role": "user",
"content": "# Conversation History\nThe content between <history></history> tags contains your conversation history\n<history>\nAlice: Hi!\nBob: Hi! Nice to meet you guys.\nCharlie: Me too! I'm Charlie, by the way.\n</history>"
}
]
-------------
Combined message
# Conversation History
The content between <history></history> tags contains your conversation history
<history>
Alice: Hi!
Bob: Hi! Nice to meet you guys.
Charlie: Me too! I'm Charlie, by the way.
</history>
Message Sharing¶
In multi-agent conversation, exchanging messages explicitly may not be efficient and convenient, especially when broadcasting messages among multiple agents.
Therefore, AgentScope provides an async context manager named MsgHub
to simplify the operation of broadcasting messages.
Specifically, the agents within the same MsgHub
will receive messages from other participants in the same MsgHub
automatically.
model = DashScopeChatModel(
model_name="qwen-max",
api_key=os.environ["DASHSCOPE_API_KEY"],
)
formatter = DashScopeMultiAgentFormatter()
alice = ReActAgent(
name="Alice",
sys_prompt="You're a student named Alice.",
model=model,
formatter=formatter,
toolkit=Toolkit(),
memory=InMemoryMemory(),
)
bob = ReActAgent(
name="Bob",
sys_prompt="You're a student named Bob.",
model=model,
formatter=formatter,
toolkit=Toolkit(),
memory=InMemoryMemory(),
)
charlie = ReActAgent(
name="Charlie",
sys_prompt="You're a student named Charlie.",
model=model,
formatter=formatter,
toolkit=Toolkit(),
memory=InMemoryMemory(),
)
async def example_msghub() -> None:
"""Example of using MsgHub for multi-agent conversation."""
async with MsgHub(
[alice, bob, charlie],
announcement=Msg(
"system",
"Now you meet each other with a brief self-introduction.",
"system",
),
):
await alice()
await bob()
await charlie()
asyncio.run(example_msghub())
Alice: Hello! I'm Alice, a student who's always eager to learn new things and engage in interesting discussions. Nice to meet you! Could you tell me a bit about yourself?
Bob: Hello Alice, I'm Bob. It's great to meet you as well! I'm also a student and like diving into all sorts of topics. What kind of discussions do you enjoy the most?
Charlie: Alice: I really enjoy discussions that challenge my way of thinking, especially those about philosophy and ethics. It's fascinating to explore different viewpoints and the reasons behind them. What about you, Bob? What topics do you find most engaging?
Charlie: I'm quite the same, Alice. I also find philosophical debates intriguing, but I have a soft spot for science and technology topics as well. It's amazing how much they can change our lives and the world around us. Do you follow any scientific or tech news?
Now we print the memory of Alice to check if her memory is updated correctly.
async def example_memory() -> None:
"""Print the memory of Alice."""
print("Memory of Alice:")
for msg in await alice.memory.get_memory():
print(f"{msg.name}: {msg.get_text_content()}")
asyncio.run(example_memory())
Memory of Alice:
system: Now you meet each other with a brief self-introduction.
Alice: None
system: None
Alice: Hello! I'm Alice, a student who's always eager to learn new things and engage in interesting discussions. Nice to meet you! Could you tell me a bit about yourself?
Bob: Hello Alice, I'm Bob. It's great to meet you as well! I'm also a student and like diving into all sorts of topics. What kind of discussions do you enjoy the most?
Charlie: I'm quite the same, Alice. I also find philosophical debates intriguing, but I have a soft spot for science and technology topics as well. It's amazing how much they can change our lives and the world around us. Do you follow any scientific or tech news?
Further Reading¶
Total running time of the script: (0 minutes 11.872 seconds)