备注
Go to the end to download the full example code.
Multi-Agent Debate¶
Multi-Agent debate 模拟不同智能体之间的多轮讨论场景,通常包括几个 solver 和一个 aggregator。 典型情况下,solver 生成并交换他们的答案,而 aggregator 收集并总结答案。
我们实现了 EMNLP 2024 中的示例,其中两个 solver 智能体将按固定顺序讨论一个话题,根据先前的辩论历史表达他们的论点。 在每一轮中,主持人智能体将决定是否可以在当前轮获得最终的正确答案。
import asyncio
import os
from pydantic import Field, BaseModel
from agentscope.agent import ReActAgent
from agentscope.formatter import (
DashScopeMultiAgentFormatter,
)
from agentscope.message import Msg
from agentscope.model import DashScopeChatModel
from agentscope.pipeline import MsgHub
# 准备一个话题
topic = "两个圆外切且没有相对滑动。圆A的半径是圆B半径的1/3。圆A绕圆B滚动一圈回到起点。圆A总共会旋转多少次?"
# 创建两个辩论者智能体,Alice 和 Bob,他们将讨论这个话题。
def create_solver_agent(name: str) -> ReActAgent:
"""获取一个解决者智能体。"""
return ReActAgent(
name=name,
sys_prompt=f"你是一个名为 {name} 的辩论者。你好,欢迎来到"
"辩论比赛。我们的目标是找到正确答案,因此你没有必要完全同意对方"
f"的观点。辩论话题如下所述:{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"]]
# 创建主持人智能体
moderator = ReActAgent(
name="Aggregator",
sys_prompt=f"""你是一个主持人。将有两个辩论者参与辩论比赛。他们将就以下话题提出观点并进行讨论:
``````
{topic}
``````
在每轮讨论结束时,你将评估辩论是否结束,以及话题正确的答案。""",
model=DashScopeChatModel(
model_name="qwen-max",
api_key=os.environ["DASHSCOPE_API_KEY"],
stream=False,
),
# 使用多智能体格式化器,因为主持人将接收来自多于用户和助手的消息
formatter=DashScopeMultiAgentFormatter(),
)
# 主持人的结构化输出模型
class JudgeModel(BaseModel):
"""主持人的结构化输出模型。"""
finished: bool = Field(description="辩论是否结束。")
correct_answer: str | None = Field(
description="辩论话题的正确答案,仅当辩论结束时提供该字段。否则保留为 None。",
default=None,
)
async def run_multiagent_debate() -> None:
"""运行多智能体辩论工作流。"""
while True:
# MsgHub 中参与者的回复消息将广播给所有参与者。
async with MsgHub(participants=[alice, bob, moderator]):
await alice(
Msg(
"user",
"你是正方,请表达你的观点。",
"user",
),
)
await bob(
Msg(
"user",
"你是反方。你不同意正方的观点。请表达你的观点和理由。",
"user",
),
)
# Alice 和 Bob 不需要知道主持人的消息,所以主持人在 MsgHub 外部调用。
msg_judge = await moderator(
Msg(
"user",
"现在你已经听到了他们的辩论,现在判断辩论是否结束,以及你能得到正确答案吗?",
"user",
),
structured_model=JudgeModel,
)
if msg_judge.metadata.get("finished"):
print(
"\n辩论结束,正确答案是:",
msg_judge.metadata.get("correct_answer"),
)
break
asyncio.run(run_multiagent_debate())
Alice: 感谢你的提问。我是正方,我的观点是当圆A绕着圆B滚动一圈回到起点时,圆A总共会旋转4次。
首先,我们来明确几个关键点:
- 圆A的半径为r, 则圆B的半径为3r。
- 两个圆外切且没有相对滑动意味着在接触点处两者的线速度相等。
- 当圆A完成一次绕圆B的完整旋转(即回到初始位置)时,它沿着圆B的周长移动了一圈的距离。
接下来分析:
1. 圆B的周长 = 2π * (3r) = 6πr
2. 圆A自身的周长 = 2π * r
当圆A绕着圆B滚动一圈时,它实际上是在一条长度为6πr的路径上移动。由于圆A没有打滑,这意味着它的边缘也必须走过相同的距离。因此,圆A自转的次数可以通过将这条路径长度除以圆A自己的周长来计算:
\[ \text{自转次数} = \frac{\text{路径长度}}{\text{圆A的周长}} = \frac{6\pi r}{2\pi r} = 3 \]
但是这里有一个容易被忽略的关键点:除了沿大圆路径移动导致的自转外,每当圆A绕过圆B一周时,它还会因为相对于自身中心的旋转而额外增加一次完整的自转。这是因为当我们考虑圆A围绕圆B中心运动时,可以想象成一个点同时进行公转和自转。因此,总自转数为路径引起的3次加上额外的一次自转,总计4次。
综上所述,当圆A绕圆B滚动一圈并回到起点时,圆A总共会旋转4次。
Bob: 感谢Alice的详细解释。我是反方,我的观点是当圆A绕着圆B滚动一圈回到起点时,圆A总共会旋转3次。
首先,我同意Alice提到的关键点:
- 圆A的半径为r, 则圆B的半径为3r。
- 两个圆外切且没有相对滑动意味着在接触点处两者的线速度相等。
- 当圆A完成一次绕圆B的完整旋转(即回到初始位置)时,它沿着圆B的周长移动了一圈的距离。
接下来分析:
1. 圆B的周长 = 2π * (3r) = 6πr
2. 圆A自身的周长 = 2π * r
当圆A绕着圆B滚动一圈时,它实际上是在一条长度为6πr的路径上移动。由于圆A没有打滑,这意味着它的边缘也必须走过相同的距离。因此,圆A自转的次数可以通过将这条路径长度除以圆A自己的周长来计算:
\[ \text{自转次数} = \frac{\text{路径长度}}{\text{圆A的周长}} = \frac{6\pi r}{2\pi r} = 3 \]
这里需要注意的是,当我们考虑圆A绕圆B滚动一圈时,我们只需要关注圆A沿路径移动导致的自转。圆A绕圆B一周的过程中,确实存在一个公转和自转的现象,但这里的自转已经包含在了上述计算中。额外的一次自转实际上是重复计算了圆A绕圆B一周的自转。
因此,当圆A绕圆B滚动一圈并回到起点时,圆A总共会旋转3次。
/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": {
"finished": true,
"correct_answer": "3次"
},
"id": "call_96f13c9075c04c3e97dcad"
}
system: {
"type": "tool_result",
"id": "call_96f13c9075c04c3e97dcad",
"name": "generate_response",
"output": [
{
"type": "text",
"text": "Successfully generated response."
}
]
}
Aggregator: 感谢Alice和Bob的精彩辩论。从双方的讨论中,我们可以看到对于这个问题有着不同的理解。然而,根据几何学中的滚动问题原理,当一个圆沿着另一个圆外切滚动且没有相对滑动时,小圆绕大圆一周所经历的自转次数等于两圆半径之比加1。在这个案例里,圆A的半径是圆B半径的1/3,因此圆A绕圆B滚动一圈回到起点时,圆A总共会旋转3次。
所以,正确答案是圆A总共会旋转3次。这意味着Bob的观点更符合实际情况。再次感谢两位辩手为我们带来的深入分析!
辩论结束,正确答案是: 3次
进一步阅读¶
Encouraging Divergent Thinking in Large Language Models through Multi-Agent Debate. EMNLP 2024.
Total running time of the script: (0 minutes 53.477 seconds)