备注
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半径的1/3。当圆A绕着圆B滚动一圈回到起点时,我们需要计算出圆A自转了多少圈。
首先,我们知道圆A和圆B接触点之间的距离始终等于两圆半径之和,即\(R_B + R_A = R_B + \frac{1}{3}R_B = \frac{4}{3}R_B\)。这意味着圆A绕圆B一周所走过的路径长度为圆B周长加上自身直径长度影响下的额外旋转,具体来说就是圆B的周长\(2\pi R_B\)。
但是,由于圆A同时也在自转,它完成这一圈移动的过程中,其自身的转动量不仅仅取决于外部轨迹(即沿着圆B边缘的路径),还包括了因为与圆B接触而产生的额外旋转。考虑到圆A在不打滑的情况下绕着圆B运动,我们可以将整个过程视为一个复合运动:一方面是圆A中心围绕圆B中心做圆周运动;另一方面则是圆A相对于该圆周轨迹的自转。
对于圆A来说,它绕圆B完整一圈(即圆B的周长)的同时,实际上相当于它自己也转了一圈。但由于圆A的半径只有圆B的1/3,所以每当圆A沿圆B外围移动的距离达到自身周长\(2\pi R_A = 2\pi(\frac{1}{3}R_B)\)时,它就已经完成了相对于接触点的一次完整自转。因此,在整个过程中,除了跟随圆B外围形成的那一次自转外,根据比例关系还可以得出额外的两次自转(因为圆B的周长是圆A周长的3倍)。
综上所述,当圆A绕着圆B滚动一圈回到起点时,它总共会旋转4次。这包括了随着圆B外围形成的1次自转以及额外的3次自转。
Bob: 谢谢。我将从反方的角度出发来阐述我的观点。题目中提到的是两个圆外切且没有相对滑动,其中圆A的半径是圆B半径的1/3。当圆A绕着圆B滚动一圈回到起点时,我们需要计算出圆A自转了多少圈。
首先,让我们明确一点:圆A绕圆B一周所走过的路径长度确实是圆B的周长\(2\pi R_B\)。然而,关键在于理解圆A在这一过程中是如何旋转的。
圆A绕圆B一周的过程中,它不仅沿着圆B的边缘移动,还因为与圆B接触而产生了自转。根据题目条件,圆A和圆B之间没有相对滑动,这意味着圆A在接触点处的速度必须与圆B边缘的速度相等。因此,每当圆A沿圆B外围移动的距离达到自身周长\(2\pi R_A = 2\pi(\frac{1}{3}R_B)\)时,它就已经完成了相对于接触点的一次完整自转。
由于圆B的周长是圆A周长的3倍(即\(2\pi R_B = 3 \times 2\pi R_A\)),所以当圆A绕圆B一周时,它实际上会完成3次相对于接触点的自转。此外,还需要考虑圆A中心围绕圆B中心做圆周运动所带来的额外一次自转。
综上所述,当圆A绕着圆B滚动一圈回到起点时,它总共会旋转4次。这包括了随着圆B外围形成的3次自转以及额外的1次自转(圆心绕圆B中心的转动)。不过,需要注意的是,这里的4次旋转是由3次接触点自转加上1次整体转动构成的,并非正方所认为的“除了跟随圆B外围形成的那一次自转外,根据比例关系还可以得出额外的两次自转”。实际上,圆A在绕圆B一周的过程中,其相对于接触点的自转次数为3次,加上整体的1次转动,总计为4次。
/home/runner/work/agentscope/agentscope/src/agentscope/model/_dashscope_model.py:194: 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": "当圆A绕着圆B滚动一圈回到起点时,它总共会旋转4次。这包括了3次接触点自转加上1次整体转动。"
},
"id": "call_80dcbc00b95a4e45b548cb"
}
system: {
"type": "tool_result",
"id": "call_80dcbc00b95a4e45b548cb",
"name": "generate_response",
"output": [
{
"type": "text",
"text": "Successfully generated response."
}
]
}
Aggregator: 感谢两位辩论者的精彩发言。经过讨论,我们可以得出结论:当圆A绕着圆B滚动一圈回到起点时,它总共会旋转4次。这包括了3次接触点自转加上1次整体转动。
因此,本场辩论结束,正确答案是:圆A总共会旋转4次。再次感谢Alice和Bob的参与!
辩论结束,正确答案是: 当圆A绕着圆B滚动一圈回到起点时,它总共会旋转4次。这包括了3次接触点自转加上1次整体转动。
进一步阅读¶
Encouraging Divergent Thinking in Large Language Models through Multi-Agent Debate. EMNLP 2024.
Total running time of the script: (0 minutes 35.676 seconds)