Note
Go to the end to download the full example code.
Multi-Agent Debate¶
Debate workflow simulates a multi-turn discussion between different agents, mostly several solvers and an aggregator. Typically, the solvers generate and exchange their answers, while the aggregator collects and summarizes the answers.
We implement the examples in EMNLP 2024, where two debater agents will discuss a topic in a fixed order, and express their arguments based on the previous debate history. At each round a moderator agent will decide whether the correct answer can be obtained in the current iteration.
import asyncio
import os
from pydantic import Field, BaseModel
from agentscope.agent import ReActAgent
from agentscope.formatter import (
DashScopeMultiAgentFormatter,
DashScopeChatFormatter,
)
from agentscope.message import Msg
from agentscope.model import DashScopeChatModel
from agentscope.pipeline import MsgHub
# Prepare a topic
topic = (
"The two circles are externally tangent and there is no relative sliding. "
"The radius of circle A is 1/3 the radius of circle B. Circle A rolls "
"around circle B one trip back to its starting point. How many times will "
"circle A revolve in total?"
)
# Create two debater agents, Alice and Bob, who will discuss the topic.
def create_solver_agent(name: str) -> ReActAgent:
"""Get a solver agent."""
return ReActAgent(
name=name,
sys_prompt=f"You're a debater named {name}. Hello and welcome to the "
"debate competition. It's unnecessary to fully agree with "
"each other's perspectives, as our objective is to find "
"the correct answer. The debate topic is stated as "
f"follows: {topic}.",
model=DashScopeChatModel(
model_name="qwen-max",
api_key=os.environ["DASHSCOPE_API_KEY"],
stream=False,
),
formatter=DashScopeMultiAgentFormatter(),
)
alice, bob = [create_solver_agent(name) for name in ["Alice", "Bob"]]
# Create a moderator agent
moderator = ReActAgent(
name="Aggregator",
sys_prompt=f"""You're a moderator. There will be two debaters involved in a debate competition. They will present their answer and discuss their perspectives on the topic:
``````
{topic}
``````
At the end of each round, you will evaluate both sides' answers and decide which one is correct.""",
model=DashScopeChatModel(
model_name="qwen-max",
api_key=os.environ["DASHSCOPE_API_KEY"],
stream=False,
),
# Use multiagent formatter because the moderator will receive messages from more than a user and an assistant
formatter=DashScopeMultiAgentFormatter(),
)
# A structured output model for the moderator
class JudgeModel(BaseModel):
"""The structured output model for the moderator."""
finished: bool = Field(
description="Whether the debate is finished.",
)
correct_answer: str | None = Field(
description="The correct answer to the debate topic, only if the debate is finished. Otherwise, leave it as None.",
default=None,
)
async def run_multiagent_debate() -> None:
"""Run the multi-agent debate workflow."""
while True:
# The reply messages in MsgHub from the participants will be broadcasted to all participants.
async with MsgHub(participants=[alice, bob, moderator]):
await alice(
Msg(
"user",
"You are affirmative side, Please express your viewpoints.",
"user",
),
)
await bob(
Msg(
"user",
"You are negative side. You disagree with the affirmative side. Provide your reason and answer.",
"user",
),
)
# Alice and Bob doesn't need to know the moderator's message, so moderator is called outside the MsgHub.
msg_judge = await moderator(
Msg(
"user",
"Now you have heard the answers from the others, have the debate finished, and can you get the correct answer?",
"user",
),
structured_model=JudgeModel,
)
if msg_judge.metadata.get("finished"):
print(
"\nThe debate is finished, and the correct answer is: ",
msg_judge.metadata.get("correct_answer"),
)
break
asyncio.run(run_multiagent_debate())
Alice: Thank you, and I appreciate the opportunity to present the affirmative side of this debate. The topic at hand is to determine how many times circle A, with a radius 1/3 that of circle B, will revolve as it rolls around the circumference of circle B without sliding.
To solve this, we need to consider the relationship between the circumferences of the two circles and the number of revolutions circle A makes as it travels around circle B.
Let's denote:
- The radius of circle B as \( R \).
- The radius of circle A as \( r = \frac{1}{3}R \).
The circumference of a circle is given by \( 2\pi \) times the radius. Therefore, the circumferences are:
- Circumference of circle B: \( 2\pi R \)
- Circumference of circle A: \( 2\pi r = 2\pi \left(\frac{1}{3}R\right) = \frac{2\pi R}{3} \)
When circle A rolls around circle B, it travels a distance equal to the circumference of circle B. The number of revolutions circle A makes is the total distance traveled divided by its own circumference. Thus, the number of revolutions \( N \) is:
\[ N = \frac{\text{Circumference of circle B}}{\text{Circumference of circle A}} = \frac{2\pi R}{\frac{2\pi R}{3}} = \frac{2\pi R \cdot 3}{2\pi R} = 3 \]
Therefore, circle A will make 3 complete revolutions as it rolls around circle B one time. This is the core of my argument, and I look forward to hearing the opposing viewpoint.
Bob: Thank you, and I appreciate the opportunity to present the negative side of this debate. While Alice's calculations are mathematically correct in terms of the ratio of the circumferences, the scenario described involves a more complex interaction between the two circles.
When circle A rolls around circle B without sliding, it is not just traveling along the circumference of circle B; it is also rotating due to the curvature of circle B. This means that we must consider the additional rotation caused by the change in orientation as circle A moves around circle B.
Let's denote:
- The radius of circle B as \( R \).
- The radius of circle A as \( r = \frac{1}{3}R \).
The total distance traveled by the center of circle A as it rolls around circle B is the circumference of the path traced by the center of circle A, which is the circumference of a circle with radius \( R + r \). Therefore, the distance traveled by the center of circle A is:
\[ 2\pi (R + r) = 2\pi \left(R + \frac{1}{3}R\right) = 2\pi \left(\frac{4}{3}R\right) = \frac{8\pi R}{3} \]
The number of revolutions \( N \) that circle A makes is the total distance traveled by its center divided by its own circumference:
\[ N = \frac{\text{Distance traveled by the center of circle A}}{\text{Circumference of circle A}} = \frac{\frac{8\pi R}{3}}{\frac{2\pi R}{3}} = \frac{\frac{8\pi R}{3} \cdot 3}{2\pi R} = \frac{8\pi R}{2\pi R} = 4 \]
Therefore, circle A will make 4 complete revolutions as it rolls around circle B one time. This accounts for both the linear travel along the path and the rotational movement due to the curvature of circle B.
/home/runner/work/agentscope/agentscope/src/agentscope/model/_dashscope_model.py:182: DeprecationWarning: 'required' is not supported by DashScope API. It will be converted to 'auto'.
warnings.warn(
Aggregator: {
"type": "tool_use",
"name": "generate_response",
"input": {
"correct_answer": "3",
"finished": true
},
"id": "call_8514a14462ce4d2c80d1c4"
}
system: {
"type": "tool_result",
"id": "call_8514a14462ce4d2c80d1c4",
"name": "generate_response",
"output": [
{
"type": "text",
"text": "Successfully generated response."
}
]
}
Aggregator: Thank you, Alice and Bob, for your detailed presentations. After carefully considering both arguments, the correct answer is that circle A will make 3 complete revolutions as it rolls around circle B one time.
Alice's argument correctly calculates the number of revolutions by considering the ratio of the circumferences of the two circles. When circle A rolls around circle B without sliding, the distance it travels (the circumference of circle B) divided by its own circumference gives the number of revolutions, which is 3.
Bob's argument introduces an additional consideration of the path traced by the center of circle A, but this does not change the number of rotations of circle A itself. The additional rotation due to the curvature of circle B is already accounted for in the calculation of the distance traveled by the point of contact on circle A.
Therefore, Alice's answer is correct. Circle A will make 3 complete revolutions as it rolls around circle B.
The debate is finished, and the correct answer is: 3
Further Reading¶
Encouraging Divergent Thinking in Large Language Models through Multi-Agent Debate. EMNLP 2024.
Total running time of the script: (0 minutes 41.934 seconds)