备注
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次。
理由如下:
首先,我们设圆B的半径为R,则圆A的半径为r = R/3。当圆A绕着圆B无滑动地滚动一周时,它走过的路径长度等于圆B的周长加上两倍的圆A的半径(因为是外切关系),即\[2\pi R + 2r = 2\pi R + \frac{2}{3}R = \frac{8}{3}R\]。
但是,考虑到圆A是在绕着圆B滚动的同时也在自转,实际上圆A中心移动的距离就是圆B的周长,即\[2\pi R\]。因此,对于圆A来说,它沿着这条路径滚动了一圈,相当于其自身周长的几倍呢?我们知道圆A的周长是\[2\pi r = 2\pi (R/3) = \frac{2}{3}\pi R\]。
要计算圆A相对于自身旋转了多少圈,我们需要用圆A中心行进的距离除以圆A的周长:
\[\frac{2\pi R}{\frac{2}{3}\pi R} = 3\]
这表示如果只考虑圆A沿圆B外围滚动而不考虑它们之间的相对位置变化的话,圆A应该旋转3次。然而,由于圆A在绕圆B旋转的同时也经历了整体的旋转(即绕着圆B中心公转),根据几何分析,在完成一次完整的绕行后,圆A还需要额外旋转1次来调整方向,以确保最终能够准确对接到起始位置。因此,总的旋转次数为\(3+1=4\)次。
Bob: 反方观点:圆A绕圆B滚动一圈回到起点时,圆A总共会旋转3次。
理由如下:
根据题目条件,圆A的半径是圆B半径的1/3。设圆B的半径为R,则圆A的半径为r = R/3。当圆A绕着圆B无滑动地滚动一周时,它走过的路径长度等于圆B的周长,即\[2\pi R\]。这是因为圆A与圆B外切并且没有相对滑动,所以圆A中心移动的距离正好等于圆B的周长。
接下来计算圆A相对于自身旋转了多少圈。我们知道圆A的周长是\[2\pi r = 2\pi (R/3) = \frac{2}{3}\pi R\]。要确定圆A沿这条路径滚动了多少圈,我们需要用圆A中心行进的距离除以圆A的周长:
\[\frac{2\pi R}{\frac{2}{3}\pi R} = 3\]
这表明,在圆A沿着圆B外围滚动一圈的过程中,它相对于自身轴线恰好旋转了3次。这里需要注意的是,虽然圆A在绕圆B运动时确实经历了一种公转,但这种公转并不额外增加自转次数。也就是说,圆A在完成一次完整的绕行后,并不需要再进行额外的一次自转来调整方向,因为其自转已经足够使得它能够准确对接到起始位置了。
因此,总的旋转次数为3次,而不是4次。
/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_61cc4f7c29a24e5eaea207"
}
system: {
"type": "tool_result",
"id": "call_61cc4f7c29a24e5eaea207",
"name": "generate_response",
"output": [
{
"type": "text",
"text": "Successfully generated response."
}
]
}
Aggregator: 感谢两位辩论者的精彩论述。根据双方的讨论,我们可以得出结论:当圆A绕着圆B无滑动地滚动一圈回到起点时,圆A总共会旋转3次。
正方提出了一个观点认为圆A在完成一次完整的绕行后还需要额外旋转1次来调整方向以确保最终能够准确对接到起始位置,从而得到4次旋转的结果。然而,反方正确地指出了,在这种情况下,圆A在绕圆B运动时经历的公转并不额外增加自转次数。因此,仅需考虑圆A沿路径移动的距离与它自身周长的比例关系,即\[2\pi R / (\frac{2}{3}\pi R) = 3\]次旋转就足够了。
综上所述,正确的答案是圆A总共会旋转3次。再次感谢Alice和Bob为我们带来的深入分析!如果还有其他问题或需要进一步探讨的话题,请随时告诉我。
辩论结束,正确答案是: 3次
进一步阅读¶
Encouraging Divergent Thinking in Large Language Models through Multi-Agent Debate. EMNLP 2024.
Total running time of the script: (0 minutes 39.512 seconds)