AgentScope是通义实验室开源的multi-agent编程框架,专为开发人员设计,提供了丰富的组件, 全面的文档和广泛的兼容性。同时,AgentScope Workstation提供了在线拖拉拽编程和在线小助手(copilot)功能,帮助开发者迅速上手!支持自定义的容错控制和重试机制,以提高应用程序的稳定性,支持以中心化的方式构建分布式多智能体应用程序。
github链接
:https://github.com/modelscope/agentscope论文链接
:AgentScope: A Flexible yet Robust Multi-Agent Platform更多介绍参考:
- 打造可靠的多智能体生态系统:从集成到部署AgentScope为多智能体应用提供的全面支持方案
- 解决多Agent信息传递难题:AgentScope实现分布式架构下的高效协作与优化跨机器通信与任务调度,扩展性提升
多智能体群聊——在这个群聊中,你可以直接"@"提及某个智能体来引发对话。
主循环的工作流程:
- 获取用户输入
- 检查是否退出指令
- 解析用户消息中的 @ 标记
根据以下规则选择下一个发言者:
- 如果有被 @ 的角色,从队列中取出第一个
- 否则随机选择一个 NPC 角色
- 处理选中角色的回复
- 继续解析新回复中的 @ 标记
这个系统实现了一个互动性强的多智能体群聊系统,支持:
- 多角色互动
- @ 功能实现定向对话
- 角色之间的复杂关系演绎
- 自然的对话流转机制
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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。