.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "tutorial/workflow_multiagent_debate.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_tutorial_workflow_multiagent_debate.py: .. _multiagent-debate: Multi-Agent Debate ======================== Multi-Agent debate 模拟不同智能体之间的多轮讨论场景,通常包括几个 solver 和一个 aggregator。 典型情况下,solver 生成并交换他们的答案,而 aggregator 收集并总结答案。 我们实现了 `EMNLP 2024`_ 中的示例,其中两个 solver 智能体将按固定顺序讨论一个话题,根据先前的辩论历史表达他们的论点。 在每一轮中,主持人智能体将决定是否可以在当前轮获得最终的正确答案。 .. GENERATED FROM PYTHON SOURCE LINES 14-120 .. code-block:: Python 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()) .. rst-class:: sphx-glr-script-out .. code-block:: none Alice: 正方认为当圆A绕着圆B滚动一圈回到起点时,圆A会旋转4次。 这里的关键在于理解“绕着圆B滚动一圈”意味着什么。它指的是圆A的中心围绕圆B的中心走过了一个完整的圆周长。由于圆A和圆B是外切的,并且没有相对滑动,那么圆A沿着圆B外缘所走过的路径长度就是圆B的周长加上两倍的圆A半径(因为圆A在圆B的一侧接触)。但因为我们讨论的是圆心轨迹,所以实际上我们只关心圆B的周长,即2πR_B,其中R_B是圆B的半径。 现在,圆A的半径为R_A = R_B/3,因此圆A的周长是2πR_A = 2π(R_B/3)。 当圆A的中心走过距离等于圆B周长的距离时,它必须旋转的次数是该距离除以圆A自己的周长: \[ \text{旋转次数} = \frac{\text{圆B的周长}}{\text{圆A的周长}} = \frac{2\pi R_B}{2\pi (R_B/3)} = \frac{R_B}{(R_B/3)} = 3 \] 然而,这仅考虑了圆A绕圆B公转的情况。此外,每当圆A沿着圆B边缘移动时,它也会自转。由于圆A与圆B之间的无滑动条件,每前进圆A自身的一个周长,它就会完成一次自转。因此,除了上述的3次旋转之外,圆A还会因为其自身的滚动而额外旋转1次,总共是4次旋转。 综上所述,当圆A绕圆B滚动一圈回到起点时,圆A会旋转4次。 Alice: 总结一下我的观点:当较小的圆A绕着较大的圆B滚动一圈并且回到起点时,它不仅会因为绕行圆B一周而旋转3次,还会因为它自身的滚动而额外旋转1次。因此,圆A总共会旋转4次。接下来,请反方发言。 Bob: 感谢Alice的总结。我不同意圆A总共会旋转4次的观点。让我们来仔细分析一下这个问题。 当圆A绕着圆B滚动时,确实存在两个运动:一个是沿着圆B周长的公转,另一个是圆A自身的自转。但关键在于如何计算这些转动。 1. 公转部分:圆A绕圆B一周的距离等于圆B的周长,即2πR_B。因为圆A与圆B外切且没有相对滑动,所以圆A走过的弧长也是2πR_B。考虑到圆A的半径是圆B的1/3,即R_A = R_B / 3,那么这段距离对于圆A而言相当于其自身周长的3倍(2πR_B = 3 * 2πR_A)。因此,仅从公转角度来看,圆A需要旋转3圈才能完成这一路径。 2. 自转部分:然而,这里有一个常见的误解——认为除了这3圈之外,圆A还需要额外自转一圈。实际上,在这个过程中,并不存在所谓的'额外'一圈自转。当圆A完成围绕圆B的一周旅行回到起点时,它的总自转数已经包含了所有必要的转动。这是因为,每当圆A沿着圆B边缘前进一段距离,它同时也在进行等量的自转以保持接触点不变。最终结果就是,整个过程中的自转次数正好匹配了上述公转所需的圈数。 综上所述,我的结论是:当圆A绕圆B滚动一圈并且回到起点时,它总共只旋转了3次,而非4次。 Aggregator: 双方都提出了各自的论点,Alice认为圆A绕圆B滚动一圈回到起点时会总共旋转4次,而Bob则认为是3次。从数学上讲,当一个小圆沿着一个大圆的外侧无滑动地滚动时,小圆的自转圈数等于它所走过的路径长度除以自己的周长。由于圆A的半径是圆B的1/3,所以圆A绕圆B一周的距离相当于圆A自身周长的3倍。因此,仅考虑公转部分,圆A需要旋转3圈才能完成这一路径。 然而,这里有一个关键点:当圆A完成围绕圆B的一周旅行回到起点时,实际上它已经完成了额外的一圈自转。这是因为圆A不仅在沿圆B边缘移动(公转),同时也在进行等量的自转以保持接触点不变。因此,在整个过程中,除了那3圈之外,确实存在额外的一圈自转。 综上所述,正确的答案是圆A总共会旋转4次。 辩论结束,正确答案是: 4 .. GENERATED FROM PYTHON SOURCE LINES 121-129 进一步阅读 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - :ref:`pipeline` .. _EMNLP 2024: Encouraging Divergent Thinking in Large Language Models through Multi-Agent Debate. EMNLP 2024. .. rst-class:: sphx-glr-timing **Total running time of the script:** (1 minutes 8.910 seconds) .. _sphx_glr_download_tutorial_workflow_multiagent_debate.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: workflow_multiagent_debate.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: workflow_multiagent_debate.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: workflow_multiagent_debate.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_