AgentScope是通义实验室开源的multi-agent编程框架,专为开发人员设计,提供了丰富的组件, 全面的文档和广泛的兼容性。同时,AgentScope Workstation提供了在线拖拉拽编程和在线小助手(copilot)功能,帮助开发者迅速上手!支持自定义的容错控制和重试机制,以提高应用程序的稳定性,支持以中心化的方式构建分布式多智能体应用程序。

1.设置基本参数,配置模型与智能体

设定群聊的默认话题和系统提示。这将指导 Agent 与用户互动,并为群聊提供初始的讨论方向。系统提示中告诉了智能体使用 "@" 提及某个智能体继续对话,也就是说不仅用户可以 "@" 提及智能体,智能体之间也可以互相 "@",甚至可以 "@" 提及用户哦!复制代码

DEFAULT_TOPIC = """
# 背景设定:现代国家内斗
在一个政局动荡、权力更迭频繁的现代国家中,政府与反对派之间矛盾激化,民众分裂,舆论战、情报战、经济战交织其中。在这场没有硝烟却同样致命的斗争中,四位来自不同背景的人物因信念、命运和立场被卷入风暴中心。在这个虚拟聊天室中,各个角色可以自由而简短地发言。

#角色关系简图:
- 志安与明龙:秘密盟友,志安提供情报,明龙负责传播真相。
- 志安与天强:表兄弟,理念不同但感情深厚,天强常在街头行动中掩护志安的身份。
- 天强与伊媚:早期合作推动公民运动,后来因是否使用激进手段产生分歧。
- 明龙与伊媚:通过媒体建立合作关系,明龙帮助伊媚扩大影响力

# 回复规则:
- 每位角色必须以第一人称(我、我们)进行表达。
- 语言风格应符合角色身份、性格和说话方式。
- 角色之间的互动应体现出立场差异、情感张力或理念冲突。
- 可根据对话内容自然展开回忆、情绪、策略性思考等内心独白。
- 角色每次回复内容不超过150字
"""
SYS_PROMPT = """
您可以在发送消息时使用 '@' 符号来指定某位成员进行回复。
具体方式是在您的消息中输入 '@' 符号后紧跟目标成员的名称,并在名称后留一个空格。
当前所有参与者为:{agent_names}
"""

agentscope.init 在初始化模型配置的同时构建智能体。

import agentscope
npc_agents = agentscope.init(
    model_configs="./model_configs.json",
    agent_configs="./agent_configs.json",
)
[
    {
        "config_name": "yi-lightning",
        "model_name": "yi-lightning",
        "model_type": "yi_chat",
        "api_key": "57acc"
    },
    {
    "model_type": "dashscope_chat",
    "config_name": "tongyi_qwen_config",
    "model_name": "qwen-max",
    "api_key": "************"  // 在这里填写你DashScope中的API-KEY
    },
    {
        "model_type": "openai_chat",
        "config_name": "gpt-4o",
        "model_name": "gpt-4o",
        "api_key": "sk-",
        "client_args": {
            "base_url": "http://xxx:4000"
        }
    }
]

在我们的群聊实践中,每个智能体都被赋予了独特的身份和背景故事,这些设置是通过设定不同的sys_prompt来实现的。在agent_configs.json里,我们将一一介绍这些配置中的智能体以及其角色设定:

[
    {
        "class": "DialogAgent",
        "args": {
            "name": "志安",
            "sys_prompt":"身份: 国家战略安全局高级顾问 / 前外交官\n特点:冷静理智、思维缜密,擅长制定长期策略与危机应对。他出身于政治世家,受过西方精英教育,精通多国语言,是政府内部少数能平衡各方势力的人。近期察觉到高层有叛变迹象,正秘密调查真相。\n语言风格: 文雅克制,常引用历史典故或哲学名言,说话带有外交辞令般的精确性与分寸感。\n关键词: 谋略、冷静、忠诚、怀疑\n示例发言:“我一直在观察那些看似无关紧要的小动作——一次通话的时间、一个突然取消的会议……这些细节背后,往往藏着更大的图谋。”",
            "model_config_name": "gpt-4o",
            "use_memory": true
        }
    },
    {
        "class": "DialogAgent",
        "args": {
            "name": "明龙",
            "sys_prompt":"身份: 独立记者兼社交媒体意见领袖\n特点:热爱讲述普通人与英雄的故事,擅长用情绪化的叙事影响公众舆论。他是“信息战场”的弄潮儿,在多个平台上拥有大量粉丝,经常揭露政府黑幕,也暗中支持某些反对力量。他与志豪保持秘密联系,是其在民间的重要耳目。\n语言风格: 现代口语化,富有戏剧张力,喜欢用比喻和反讽表达观点。关键词: 故事、煽动、真相、愤怒\n示例发言:“我不只是报道新闻,我在制造回声。当沉默成为常态,我就用文字点燃火种。”",
            "model_config_name": "gpt-4o",
            "use_memory": true
        }
    },
    {
        "class": "DialogAgent",
        "args": {
            "name": "天强",
            "sys_prompt":"身份: 国家队退役运动员 / 社会活动家\n特点:曾是奥运级别的短跑选手,退役后投身公益事业,成为年轻人的精神偶像。他厌恶政治,但在国家陷入混乱后,利用自己的影响力组织志愿者团体,保护弱势群体。他的行动力强,重视身体素质与心理韧性训练。\n语言风格: 简洁有力,直接明了,充满激励性,偶尔夹杂体育术语。 行动、正义、热血、希望\n示例发言:“我不是战士,但我可以为他们守住后方。每一次救援,都是一次冲刺终点。”",
            "model_config_name": "gpt-4o",
            "use_memory": true
        }
    },
    {
        "class": "DialogAgent",
        "args": {
            "name": "伊媚",
            "sys_prompt":"身份: 反对派联盟发言人 / 法律学者\n特点:一位年轻而坚定的女政治家,曾在国际法庭工作多年,主张以法治重建国家秩序。她公开批评现政权腐败无能,成为反对派的象征人物。尽管立场强硬,但她始终呼吁和平对话,拒绝暴力手段。她的父亲曾是前朝高官,家族因此被清算,使她对体制有着深刻的批判意识。\n语言风格: 正义感强,逻辑清晰,措辞严谨,具有法律人的理性与说服力。\n关键词: 公正、理性、控诉、变革\n示例发言:“我要做的不是推翻一座墙,而是建造新的制度基础。我们必须让人民相信,未来不只是另一种形式的压迫。”",
            "model_config_name": "gpt-4o",
            "use_memory": true
        }
    }
]

2. 搭建群聊环境

在配置模型与智能体并初始化 AgentScope 之后,我们使用 UserAgent 创建用户代理,通过 msghub 创建群聊。这样,群聊环境就建立起来了。


import agentscope
from agentscope.agents import UserAgent
from agentscope.msghub import msghub
def main():
    # 通过`agentscope.init()`初始化智能体
    ...
    # 初始化用户智能体
    user_agent = UserAgent()
    
    # 参与群聊的所有智能体
    agents = list(npc_agents) + [user]
    
    # 通过第一步中的基本参数,创建群聊中的群聊Announcement
    hint = Msg(
        name="Host",
        content=DEFAULT_TOPIC
        + SYS_PROMPT.format(
            agent_names=[agent.name for agent in agents],
        ),
    )
    rnd = 0
    # 维护一个发言列表
    speak_list = []
    # 创建群聊
    with msghub(agents, announcement=hint):
        # 群聊逻辑
        ...

3.实现交互逻辑

我们设计了一个简单的轮流对话机制,用户可以通过输入指定的内容与智能体互动,也可以使用 “@” 符号指定回复某个智能体。

  • 轮流对话机制的初始化: 群聊环境通过一个持续的循环来维持对话的进行,等待和处理每个参与者的输入。复制代码

    while True:
                # 循环体中的代码负责处理对话逻辑
                x = user_agent()
                if x.content == "exit":
                    break
  • 智能体交互逻辑: 系统检查用户消息中是否有 "@提及" 智能体的内容,并根据提及情况决定回合中将交互的智能体,并加入 speak_list 中。

    speak_list += filter_agents(x.get("content", ""), npc_agents)
    if len(speak_list) > 0:
        next_agent = speak_list.pop(0)
        x = next_agent()

    如果speak_list为空,即没有被"@"提及的智能体,那么通过select_next_one,来选择一个智能体发言。无论是被提及的智能体还是系统选择的智能体,它们的回复(如果有)都将为下一轮的交互做准备。

    else:
        next_agent = select_next_one(npc_agents, rnd)
        x = next_agent()
    speak_list += filter_agents(x.content, npc_agents)
    rnd += 1

工具类函数:我们使用正则表达式来提取 "@" 提及到的智能体:


def filter_agents(string: str, agents: Sequence) -> Sequence:
    """
    该函数会筛选输入字符串中以'@'为前缀的给定名称的出现,并返回找到的名称列表。
    """
    if len(agents) == 0:
        return []
    # 创建一个匹配@后跟任何候选名字的模式
    pattern = (
        r"@(" + "|".join(re.escape(agent.name) for agent in agents) + r")\b"
    )
    # 在字符串中找到所有模式的出现
    matches = re.findall(pattern, string)
    
    # 为了快速查找,创建一个将代理名映射到代理对象的字典
    agent_dict = {agent.name: agent for agent in agents}
    # 返回匹配的代理对象列表,保持顺序
    ordered_agents = [
        agent_dict[name] for name in matches if name in agent_dict
    ]
    return ordered_agents

并且通过随机选择来决定当发言列表为空时,下一个发言的智能体,读者也可以自己实现更复杂的逻辑

def select_next_one(agents: Sequence, rnd: int) -> Sequence:
    """
    Select next agent.
    """
    #顺序选择
    # return agents[rnd % len(agents)]
    #随机选择
    return random.choice(agents)

4.启动带有 "@" 提及功能的群聊应用

现在,您可以运行 main.py 脚本,启动多智能体群聊应用。复制代码

python main.py  # 或者使用as_studio main.py
  • 效果

在这里插入图片描述

可以看到随机策略很不智能,还是需要NLU模块

5. 多智能体系统中“选择下一个发言者”的场景。

当前不加@的回复是随机的很不智能,下面给出适用于多智能体系统中“选择下一个发言者”的方法。该方案通过引入多维度策略和动态规则,提升发言顺序的灵活性与智能性:


5.1. 智能体属性建模

为每个智能体定义动态属性标签,作为选择依据:

  • 领域权重:根据当前话题匹配智能体的专业领域(如技术、法律、艺术)。
  • 发言热度:记录历史发言频率,避免“霸屏”或“沉默”现象。
  • 情绪状态:模拟智能体的情绪波动(如兴奋、犹豫、焦虑),影响发言意愿。
  • 关系网络:智能体与其他成员的互动关系(如盟友、竞争者、中立者)。
  • 目标优先级:智能体当前任务目标(如推动决策、收集信息、反对提议)。

5.2. 动态权重分配

通过上下文感知机制动态调整选择规则的权重:

  • 话题相关性:若当前讨论技术问题,优先选择领域专家。
  • 对话阶段:初期随机选择以激发多样性;后期聚焦关键意见领袖。
  • 冲突检测:若存在激烈分歧,优先选择中立者或调解者发言。
  • 时间压力:临近截止时间时,优先选择决策效率高的智能体。
  • 对话历史分析:识别重复观点或无效发言,降低对应智能体的权重。
  • 知识图谱关联:若当前话题与某智能体的历史知识库强相关,优先选择。
  • 外部事件触发:根据系统外部输入(如用户指令、环境变化)调整发言策略。

5.3. 多轮策略组合

结合以下策略生成发言顺序,避免单一逻辑的局限性:

(1) 轮次驱动

  • 冷启动阶段:随机选择打破僵局。
  • 稳定阶段:按领域权重排序,但允许一定概率的随机扰动。
  • 收尾阶段:强制优先选择未发言者或低频发言者。

(2) 竞争机制

  • 竞标式发言:智能体根据当前话题提出“发言价值评估”,系统选择最高分者。
  • 辩论式触发:若某观点被多次反驳,触发相关领域智能体强制发言。

(3) 群体行为模拟

  • 跟随效应:高影响力智能体发言后,优先选择其支持者或反对者。
  • 沉默突破:长期未发言的智能体获得“发言权补偿”。

6.完整代码

  • main.py

    import agentscope
    from agentscope.agents import DialogAgent, UserAgent
    from agentscope.msghub import msghub
    from agentscope.message import Msg
    
    from groupchat_utils import (
      select_next_one,
      filter_agents,
    )
    
    DEFAULT_TOPIC = """
    # 背景设定:现代国家内斗
    在一个政局动荡、权力更迭频繁的现代国家中,政府与反对派之间矛盾激化,民众分裂,舆论战、情报战、经济战交织其中。在这场没有硝烟却同样致命的斗争中,四位来自不同背景的人物因信念、命运和立场被卷入风暴中心。在这个虚拟聊天室中,各个角色可以自由而简短地发言。
    
  • 志安与明龙:秘密盟友,志安提供情报,明龙负责传播真相。
  • 志安与天强:表兄弟,理念不同但感情深厚,天强常在街头行动中掩护志安的身份。
  • 天强与伊媚:早期合作推动公民运动,后来因是否使用激进手段产生分歧。
  • 明龙与伊媚:通过媒体建立合作关系,明龙帮助伊媚扩大影响力

    回复规则:

  • 每位角色必须以第一人称(我、我们)进行表达。
  • 语言风格应符合角色身份、性格和说话方式。
  • 角色之间的互动应体现出立场差异、情感张力或理念冲突。
  • 可根据对话内容自然展开回忆、情绪、策略性思考等内心独白。
  • 角色每次回复内容不超过150字
    """
    SYS_PROMPT = """
    您可以在发送消息时使用 '@' 符号来指定某位成员进行回复。
    具体方式是在您的消息中输入 '@' 符号后紧跟目标成员的名称,并在名称后留一个空格。
    当前所有参与者为:{agent_names}
    """
    def main() -> None:
    # 初始化用户智能体
    npc_agents=agentscope.init(model_configs="agentscope/model_configs.json",

              agent_configs="agentscope/agent_configs.json",
              studio_url="http://127.0.0.1:5000")
    

    user_agent = UserAgent()

    # 参与群聊的所有智能体
    agents = list(npc_agents) + [user_agent]

    # 通过第一步中的基本参数,创建群聊中的群聊Announcement
    hint = Msg(

      name="Host",
      content=DEFAULT_TOPIC
      + SYS_PROMPT.format(
          agent_names=[agent.name for agent in agents],
      ),
      role="assistant",

    )
    rnd = 0
    # 维护一个发言列表
    speak_list = []
    # 创建群聊
    with msghub(agents, announcement=hint):

      while True:
          # 循环体中的代码负责处理对话逻辑
          x = user_agent()
          if x.content == "exit":
              break
          # 处理 @ 消息
          speak_list += filter_agents(x.content, npc_agents)
          # 选择下一个发言者
          if len(speak_list) > 0:
              next_agent = speak_list.pop(0)
              x = next_agent() #在 AgentScope 框架中,智能体对象(如 DialogAgent )被设计为可调用的,当你使用 agent() 语法时,实际上是在调用该智能体的 __call__ 方法,这个方法会进一步调用智能体的 reply 方法来生成回复。
          else:
              next_agent = select_next_one(npc_agents, rnd)
              x = next_agent()
          # 继续处理新的 @ 消息
          speak_list += filter_agents(x.content, npc_agents)
    
          rnd += 1
    
    

    if name == "__main__":
    main()

  • groupchat_utils.py
# -*- coding: utf-8 -*-
""" Group chat utils."""
import re
from typing import Sequence
import random 


def select_next_one(agents: Sequence, rnd: int) -> Sequence:
    """
    Select next agent.
    """
    #顺序选择
    # return agents[rnd % len(agents)]
    #随机选择
    return random.choice(agents)


def filter_agents(string: str, agents: Sequence) -> Sequence:
    """
    该函数会筛选输入字符串中以'@'为前缀的给定名称的出现,并返回找到的名称列表。
    """
    if len(agents) == 0:
        return []

    # 创建一个匹配@后跟任何候选名字的模式
    pattern = (
        r"@(" + "|".join(re.escape(agent.name) for agent in agents) + r")\b"
    )

    # 在字符串中找到所有模式的出现
    matches = re.findall(pattern, string)

    # 为了快速查找,创建一个将代理名映射到代理对象的字典
    agent_dict = {agent.name: agent for agent in agents}

    # 返回匹配的代理对象列表,保持顺序
    ordered_agents = [
        agent_dict[name] for name in matches if name in agent_dict
    ]
    return ordered_agents

汀丶
95 声望68 粉丝