前言
在上一期的文章《Multi-Agent实践第1期:5分钟上手AgentScope》中,我们简要介绍了如何使用AgentScope快速构建一个多智能体聊天应用。本期,我们将带你体验如何实现一个更具互动性的多智能体群聊——在这个群聊中,你可以直接"@"提及某个智能体来引发对话。
欢迎关注AgentScope,在github上(https://github.com/modelscope/agentscope) 为我们star 🌟。我们会在接下来几天,继续推出一系列教程,让大家每天花5~10分钟,搭建出不同的由简单到复杂的有趣的多智能体应用!
准备工作与智能体配置
第一步:设置基本参数
为了实现我们的群聊环境,第一步是设置一些基本参数。USER_TIME_TO_SPEAK定义了用户在回合中发言的时间限制,这里我们给用户设置了10秒钟的时间来输入他们的消息。
USER_TIME_TO_SPEAK = 10
接下来,我们设定群聊的默认话题和系统提示。这将指导Agent与用户互动,并为群聊提供初始的讨论方向。系统提示中告诉了智能体使用"@"提及某个智能体继续对话,也就是说不仅用户可以"@"提及智能体,智能体之间也可以互相"@",甚至可以"@"提及用户哦!
DEFAULT_TOPIC = """ This is a chat room and you can speak freely and briefly. """ SYS_PROMPT = """ You can designate a member to reply to your message, you can use the @ symbol. This means including the @ symbol in your message, followed by that person's name, and leaving a space after the name. All participants are: {agent_names} """
第二步:配置模型与智能体
在上一期中,我们介绍了直接实例化智能体,实际上通过配置文件,我们也可以直接使用agentscope.init在初始化模型配置的同时构建智能体。
import agentscope npc_agents = agentscope.init( model_configs="./model_configs.json", agent_configs="./agent_configs.json", )
这里我们将在model_configs.json中配置模型信息,这里我们使用千问(qwen)。
// model_configs.json [ { "model_type": "dashscope_chat", "config_name": "tongyi_qwen_config", "model_name": "qwen-max", "api_key": "************" // 在这里填写你DashScope中的API-KEY } ]
在我们的群聊实践中,每个智能体都被赋予了独特的身份和背景故事,这些设置是通过设定不同的sys_prompt来实现的。在agent_configs.json里,我们将一一介绍这些配置中的智能体以及其角色设定:
- Lingfeng(凌风): 凌风是一位帝国朝廷中的贵族,以其智慧和策略眼光而闻名。他经常参与复杂的政治阴谋,最近怀疑女王的顾问有叛国行为。他的言谈举止让人想起古典文学,显示出他深厚的文化底蕴和对古代智慧的追求。
- Boyu(博宇): 博宇是凌风的朋友。他的言语现代但带有戏剧性的色彩,与他对情感故事讲述的爱好相契合。通过秘密通信,博宇紧密关注着凌风在帝国朝廷中的政治活动。
- Haotian(浩天): 浩天是凌风的表弟,相比于宫廷的拘束生活,他更喜欢自由的田野。作为一位受到赞誉的运动员,他的影响力在政治动荡时期为凌风提供了保护。浩天喜欢通过体育训练来为生活中的挑战做准备。
// agent_configs.json [ { "class": "DialogAgent", "args": { "name": "Lingfeng", "sys_prompt":"You are Lingfeng, a noble in the imperial court, known for your wisdom and strategic acumen. You often engage in complex political intrigues and have recently suspected the Queen’s adviser of treachery. Your speaking style is reminiscent of classical literature.", "model_config_name": "tongyi_qwen_config", "use_memory": true } }, { "class": "DialogAgent", "args": { "name": "Boyu", "sys_prompt":"You are Boyu, a friend of Lingfeng. Your speech is modern but with a flair for the dramatic, matching your love for emotive storytelling. You've been closely following Lingfeng’s political maneuvers in the imperial court through secret correspondence.", "model_config_name": "tongyi_qwen_config", "use_memory": true } }, { "class": "DialogAgent", "args": { "name": "Haotian", "sys_prompt":"You are Haotian, Lingfeng’s cousin who prefers the open fields to the confines of court life. As a celebrated athlete, your influence has protected Lingfeng in times of political strife. You promote physical training as a way to prepare for life's battles, often using sports metaphors in conversation.", "model_config_name": "tongyi_qwen_config", "use_memory": true } } ]
第三步:搭建群聊环境
在配置模型与智能体并初始化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): # 群聊逻辑 ...
第四步:实现交互逻辑
我们设计了一个简单的轮流对话机制,用户可以通过输入指定的内容与智能体互动,也可以使用“@”符号指定回复某个智能体。
轮流对话机制的初始化: 群聊环境通过一个持续的循环来维持对话的进行,等待和处理每个参与者的输入。
while True: # 循环体中的代码负责处理对话逻辑
等待和处理用户输入: 系统会等待用户在一定时间内(由USER_TIME_TO_SPEAK定义)输入他们的消息。如果用户及时输入了内容,则继续执行后续逻辑。
try: x = user(timeout=USER_TIME_TO_SPEAK) if x.content == "exit": break
超时处理: 如果用户没有在规定时间内进行输入,跳过捕获TimeoutError错误,系统会记录一条日志信息,表示用户超过了响应时间,并跳过用户的回合,因此用户可以在群聊中跳过当轮发言。
except TimeoutError: x = {"content": ""} logger.info( f"User has not typed text for " f"{USER_TIME_TO_SPEAK} seconds, skip.", )
智能体交互逻辑: 系统检查用户消息中是否有"@提及"智能体的内容,并根据提及情况决定回合中将交互的智能体,并加入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: return agents[rnd % len(agents)]
第五步:启动带有"@"提及功能的群聊应用
现在,您可以运行main.py脚本,启动多智能体群聊应用。
python main.py # 或者使用as_studio main.py
总结
到这里,我们已经完成了一个带有"@"提及功能的多智能体群聊的基本搭建。AgentScope提供的强大功能,让我们能够以最小的努力实现这样的多智能体应用。未来,我们还可以扩展智能体的功能,增加更丰富的交互方式,甚至接入更高级的模型,让群聊环境生动起来。完整的代码可以在链接中找到(https://github.com/modelscope/agentscope/tree/main/examples/conversation_with_mentions)。
延伸阅读和资源
- 完整的中文文档和教程:https://modelscope.github.io/agentscope/zh_CN/index.html
- AgentScope的GitHub示例库:https://github.com/modelscope/agentscope/tree/main/examples
- 论文及研究资料:https://arxiv.org/abs/2402.14034
- 加入我们的讨论组:扫描GitHub项目首页的二维码。
比赛
看到这里,如果你有好玩的想法,不如实践起来,还可以顺便参加下面的比赛~
点击即可参加赛事报名~