备注
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总共会旋转3次。
首先,我们知道圆A的半径是圆B的1/3,这意味着圆A的周长也是圆B周长的1/3。当圆A围绕圆B外切滚动一圈时,它所走过的路径长度等于圆B的周长。由于圆A和圆B之间没有相对滑动,所以圆A在滚动过程中覆盖的距离应该等于其自身周长乘以其旋转次数。
设圆B的半径为R,则其周长为\(2\pi R\);圆A的半径为\(R/3\),则其周长为\(2\pi (R/3) = 2\pi R / 3\)。为了让圆A能够完整地绕圆B一周(即走过\(2\pi R\)的距离),根据距离=周长×转数的关系,我们可以得出:
\[2\pi R = (2\pi R / 3) \times 转数\]
解这个等式得到转数=3。因此,我们得出结论:当圆A绕圆B滚动一圈回到起点时,它总共旋转了3次。这不仅符合数学上的计算逻辑,也直观地反映了两个不同大小圆形物体相互作用时的物理现象。
Bob: 谢谢。我方认为当圆A绕着圆B滚动一圈回到起点时,圆A总共会旋转4次,而不是3次。
首先,让我们重新审视这个问题。圆A的半径是圆B的1/3,这意味着如果将圆B的周长记为\(2\pi R\),那么圆A的周长就是\(2\pi (R/3) = 2\pi R / 3\)。当圆A围绕圆B外切滚动一圈时,它确实走过了一个等于圆B周长的距离,即\(2\pi R\)。
然而,关键在于理解圆A是如何完成这一圈移动的。当我们说圆A“绕”圆B转了一圈时,实际上包含了两部分运动:一是沿着圆B外围的平移;二是自身相对于这个路径的旋转。因此,计算圆A总的旋转次数时,我们需要考虑这两方面的贡献。
- **由于路径长度而产生的旋转**:根据正方提供的分析,这部分确实是3次。
- **额外的一次旋转**:这是许多人容易忽略的部分。想象一下,当你用手指沿着另一个物体的边缘画圈时,除了随着路径移动之外,你的手指也会因为要保持与该物体接触而额外转动一圈。同样地,圆A在绕着圆B移动的同时,为了始终保持与圆B接触(即没有相对滑动),它还需要额外进行一次自转。
因此,综合以上两点,圆A总共需要旋转4次才能完成绕圆B一周的动作。这不仅符合几何学上的推理,也准确反映了物理现象的本质。
/home/runner/work/agentscope/agentscope/src/agentscope/model/_dashscope_model.py:232: 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滚动一圈回到起点时,圆A总共会旋转4次。除了因为路径长度而产生的3次旋转外,还有额外的一次自转,以保持与圆B接触且没有相对滑动。"
},
"id": "call_c0c715c85c1a49cbbf68fa"
}
system: {
"type": "tool_result",
"id": "call_c0c715c85c1a49cbbf68fa",
"name": "generate_response",
"output": [
{
"type": "text",
"text": "Successfully generated response."
}
]
}
Aggregator: 感谢Alice和Bob的精彩辩论。经过仔细考虑,我们可以得出结论:当圆A绕着圆B滚动一圈回到起点时,圆A总共会旋转4次。
首先,根据路径长度计算出的旋转次数确实是3次,这与Alice的观点一致。然而,正如Bob所指出的,我们还需要考虑到额外的一次自转,这是为了保持圆A始终与圆B接触且没有相对滑动。因此,总的旋转次数为4次。
所以,正确答案是:当圆A绕着圆B滚动一圈回到起点时,圆A总共会旋转4次。再次感谢两位辩手的参与!
辩论结束,正确答案是: 当圆A绕着圆B滚动一圈回到起点时,圆A总共会旋转4次。除了因为路径长度而产生的3次旋转外,还有额外的一次自转,以保持与圆B接触且没有相对滑动。
进一步阅读¶
Encouraging Divergent Thinking in Large Language Models through Multi-Agent Debate. EMNLP 2024.
Total running time of the script: (1 minutes 12.522 seconds)