本章内容包括:
- 使用 AutoGen Studio 构建多智能体系统
- 构建一个简单的多智能体系统
- 创建能够通过群聊协同工作的智能体
- 使用 CrewAI 构建智能体团队和多智能体系统
- 扩展智能体数量并探索 CrewAI 的处理模式
现在,让我们一起探索两个成熟的多智能体平台——AutoGen 和 CrewAI。我们先从微软的项目 AutoGen 开始,它支持多智能体,并提供了一个工作室环境,方便你快速上手智能体的开发。我们将通过微软的 AutoGen 项目学习如何通过对话和群聊协作来解决任务,进行实际编码操作。
随后,我们将转向 CrewAI,这是一套自研的企业级智能体系统,采用不同的设计思路。CrewAI 在基于角色的智能体与自主智能体之间取得平衡,支持灵活的顺序和层级任务管理。我们将探讨 CrewAI 如何解决多样且复杂的问题。
多智能体系统包含了许多单智能体系统使用的工具,但它们的优势在于能够内部提供外部反馈与评估,从而提升智能体整体的解决能力。正是这种支持与批判能力赋予了多智能体系统更强的实力。接下来,我们将从 AutoGen Studio 开始,介绍多智能体系统的基础知识。
4.1 AutoGen Studio 多智能体系统简介
AutoGen Studio 是一款强大的工具,后台通过多个智能体协同工作,解决用户指派的任务和问题。本书中部分复杂代码的开发正是基于该工具。因此,它是学习实用多智能体系统的极佳入门选择。
图 4.1 展示了 AutoGen 所采用的智能体连接与通信模式示意图。AutoGen 是一个基于对话的多智能体平台,因为它通过自然语言进行通信。自然语言对话似乎是智能体沟通最自然的方式,但这并非唯一方法,后续章节中你会看到更多不同的通信方式。
AutoGen 支持多种对话模式,包括群组式、层级式以及更常见且简单的代理通信模式。在代理通信中,一个智能体充当代理人,负责将沟通指令传达给相关智能体以完成任务。这个代理角色类似于餐厅的服务员:服务员接收顾客点单,将订单传给厨房,厨房烹饪食物,然后服务员将做好的菜送到顾客手中。
AutoGen 中的基本模式采用了 UserProxy(用户代理)和一个或多个助手智能体。图 4.2 展示了用户代理接收人类指令,然后指挥具备编写代码能力的助手智能体执行任务。每当助手完成一个任务时,代理智能体会对结果进行审核、评估并向助手反馈。这个迭代循环会持续进行,直到代理对结果满意为止。
代理模式的好处在于,它替代了对人工反馈和评估的需求,而且在大多数情况下表现良好。虽然它并不能完全取代人工的反馈和评估,但整体上能产出更完整的结果。虽然迭代循环耗时,但这段时间你完全可以用来喝杯咖啡或处理其他工作。
AutoGen Studio 是由 AutoGen 团队开发的工具,为对话型智能体提供了友好的入门环境。在接下来的练习中,我们将安装 Studio 并运行一些实验,看看这个平台的表现如何。这些工具还处于快速迭代开发阶段,如果遇到问题,可以参考 AutoGen GitHub 仓库中的文档。
4.1.1 安装和使用 AutoGen Studio
打开 Visual Studio Code(VS Code)中的 chapter_04 文件夹,创建一个本地 Python 虚拟环境,并安装 requirements.txt 文件中列出的依赖。如果需要帮助,请参考附录 B,里面有本章练习的环境安装指导。
在 VS Code 中打开终端(快捷键 Ctrl+ 或 Cmd+),切换到你的虚拟环境,然后使用示例 4.1 中的命令启动 AutoGen Studio。你首先需要设置一个环境变量,填入你的 OpenAI API 密钥。由于 8080 和 8081 端口比较常用,如果你机器上已有服务占用这些端口,可以改用 8082 或你选择的其他端口。
示例 4.1 启动 AutoGen Studio
# 在 Bash(Git Bash)中设置环境变量
export OPENAI_API_KEY="<你的 API 密钥>" #1
# 在 PowerShell 中设置环境变量
$env:VAR_NAME = "<你的 API 密钥>" #1
autogenstudio ui --port 8081 #2
#1 根据你的终端类型使用相应命令。
#2 如果机器端口冲突,请更换端口号。
打开浏览器,访问 AutoGen Studio 界面(如图 4.3 所示,截止本文撰写时)。虽然界面可能有所变化,但主要交互界面依然是聊天窗口。输入一个需要编程的复杂任务,示例为“创建一张图表,展示 GPT Agents 这一术语在谷歌搜索中的受欢迎程度”。
示例中,代理助手会生成代码片段以执行或完成各种子任务,多个智能体协同推进任务。然后,用户代理智能体尝试执行这些代码片段并评估输出结果。在多数情况下,只要代码能运行且产生预期结果,用户代理智能体就会认可任务完成。
如果你遇到助手智能体请求执行出错的问题,可以让代理智能体尝试其他方法或换一个问题。这也暴露了智能体系统依赖的某些包或库过期且无法正常工作的问题。因此,通常更建议让智能体直接执行动作,而不是先生成代码再用代码去执行操作。
技巧:建议使用 Docker 运行 AutoGen 和 AutoGen Studio,特别是在处理可能影响操作系统的代码时。Docker 能够隔离并虚拟化智能体的运行环境,从而隔离潜在的有害代码。使用 Docker 还能避免出现弹出窗口或网页阻止智能体进程运行的问题。
图 4.4 展示了智能体完成任务的界面。代理智能体会收集所有生成的代码片段、图片或其他文档,并附加到消息中。你还可以通过展开“Agent Messages”面板查看智能体的对话内容。在很多情况下,如果你让智能体生成图表或应用,系统会自动弹出二级窗口展示这些结果。
令人惊讶的是,智能体通常能够很好地完成大部分任务。根据任务的复杂程度,你可能需要与代理智能体进一步迭代。有时,某个智能体因缺乏所需技能,可能只能完成部分任务。下一节我们将探讨如何为智能体添加技能。
4.1.2 在 AutoGen Studio 中添加技能
本书中所说的技能和工具,也称为动作,是智能体扩展自身能力的主要手段。动作赋予智能体执行代码、调用 API,甚至对生成的结果进行进一步评估和检查的能力。AutoGen Studio 目前仅配备了一套基础工具,如抓取网页内容或生成图像。
注释
许多智能体系统允许智能体通过编写代码来解决目标,但我们发现代码容易出错、需要维护且变化快。因此,正如后续章节将讨论的那样,最好为智能体提供技能/动作/工具来解决问题。
在接下来的练习中,我们将添加一个技能/动作,利用 OpenAI 的视觉模型对图像进行检测。这将使代理智能体在我们要求助手生成特定内容的图像时,能够提供反馈。
启动 AutoGen Studio,进入“Build”标签页,点击“Skills”(技能),如图 4.5 所示。然后点击“New Skill”(新建技能)按钮,打开代码编辑面板,你可以在这里复制粘贴代码。在这个标签页里,还可以配置模型、智能体及智能体工作流。
输入清单4.2中展示的代码,代码文件名为 describe_image.py,已经包含在本书的源码中。将此代码复制粘贴到编辑器窗口,然后点击底部的保存按钮。
清单4.2 describe_image.py
import base64
import requests
import os
def describe_image(image_path='animals.png') -> str:
"""
使用 GPT-4 Vision 模型检查并描述图片内容。
:param input_path: str,待描述的 PNG 文件名。
"""
api_key = os.environ['OPEN_API_KEY']
# 将图片编码为 Base64 字符串的函数
def encode_image(image_path): #1
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode('utf-8')
# 获取 Base64 字符串
base64_image = encode_image(image_path)
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}"
}
payload = {
"model": "gpt-4-turbo",
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "What’s in this image?"
},
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{base64_image}" #2
}
}
]
}
],
"max_tokens": 300
}
response = requests.post(
"https://api.openai.com/v1/chat/completions",
headers=headers,
json=payload)
return response.json()["choices"][0]["message"]["content"] #3
注释说明:
#1 将图片加载并编码为 Base64 字符串的函数。
#2 将图片的 Base64 字符串包含在 JSON 请求体中发送。
#3 解析响应,返回回复内容。
describe_image 函数使用 OpenAI GPT-4 Vision 模型来描述图片中的内容。这个技能可以与已有的 generate_image 技能配合,用于质量评估。智能体可以确认生成的图片是否符合用户需求。
添加技能后,需要将其加入具体的智能体工作流和智能体中使用。图 4.6 展示了如何将新技能添加到默认或通用智能体工作流中的主助手智能体。
现在技能已经添加到主助手中,我们可以指派智能体创建特定的图像,并使用新增的 describe_image 技能对其进行验证。由于图像生成器在正确显示文字方面通常存在困难,我们将设计一个练习任务来专门解决这个问题。
输入清单4.3中的文本,提示智能体为《GPT Agents In Action》这本书创建封面。我们会明确要求封面上的书名拼写正确,并坚持让智能体使用 describe_image 函数来验证生成的图像。
清单4.3 生成书籍封面的提示语
Please create a cover for the book GPT Agents In Action, use the
describe_image skill to make sure the title of the book is spelled
correctly on the cover
输入提示后,等待一段时间,你可能会看到智能体之间围绕图像生成与验证过程的对话交流。最终,如果一切正常,智能体将返回如图4.7所示的结果。
令人惊讶的是,智能体协调仅用了几轮迭代就完成了任务。除了图片之外,你还能看到为辅助完成任务生成的各种代码片段。AutoGen Studio 在整合技能方面表现出色,智能体能够灵活适应这些技能来完成目标。接下来的章节将展示这些强大智能体的代码实现方式。
4.2 探索 AutoGen
虽然 AutoGen Studio 是理解多智能体系统的绝佳工具,但我们还需要深入代码层面。幸运的是,使用 AutoGen 编写多个智能体的示例代码既简单又易于运行。下一节我们将介绍 AutoGen 的基本设置。
4.2.1 安装和使用 AutoGen
接下来的练习会涉及编写一个使用用户代理和可对话智能体的基础多智能体系统。在此之前,我们先确保 AutoGen 已正确安装和配置。
在 VS Code 中打开终端,按照附录 B 中的章节 4 安装说明执行全部步骤,或者直接运行清单 4.4 中的 pip 命令。如果你已安装 requirements.txt 依赖,也可直接运行 AutoGen。
清单 4.4 安装 AutoGen
pip install pyautogen
接着,将 chapter_04/OAI_CONFIG_LIST.example 文件复制一份,并重命名为 OAI_CONFIG_LIST,去掉 .example 后缀。然后,在 VS Code 中打开新文件,按清单 4.5 填写你的 OpenAI 或 Azure 配置。根据你的 API 服务需求,填写 API 密钥、模型及其他详情。AutoGen 支持任何符合 OpenAI 客户端规范的模型,也就是说,你可以通过 LM Studio 使用本地 LLM,或者连接 Groq、Hugging Face 等其他服务。
清单 4.5 OAI_CONFIG_LIST
[
{
"model": "gpt-4", #1
"api_key": "<your OpenAI API key here>", #2
"tags": ["gpt-4", "tool"]
},
{
"model": "<your Azure OpenAI deployment name>", #3
"api_key": "<your Azure OpenAI API key here>", #4
"base_url": "<your Azure OpenAI API base here>", #5
"api_type": "azure",
"api_version": "2024-02-15-preview"
}
]
- #1 选择模型,推荐 GPT-4。
- #2 使用你通常使用的服务密钥。
- #3 选择模型,推荐 GPT-4。
- #4 使用你通常使用的服务密钥。
- #5 更改 base URL 以连接其他服务,不限于 Azure OpenAI。
现在我们来看看使用开箱即用的 UserProxy 和 ConversableAgent 智能体构建基础多智能体聊天的代码。打开 VS Code 中的 autogen_start.py,代码见清单 4.6,先阅读代码再运行。
清单 4.6 autogen_start.py
from autogen import ConversableAgent, UserProxyAgent, config_list_from_json
config_list = config_list_from_json(
env_or_file="OAI_CONFIG_LIST") #1
assistant = ConversableAgent(
"agent",
llm_config={"config_list": config_list}) #2
user_proxy = UserProxyAgent( #3
"user",
code_execution_config={
"work_dir": "working",
"use_docker": False,
},
human_input_mode="ALWAYS",
is_termination_msg=lambda x: x.get("content", "")
.rstrip()
.endswith("TERMINATE"), #4
)
user_proxy.initiate_chat(assistant, message="write a solution for fizz buzz in one line?") #5
- #1 从 JSON 文件
OAI_CONFIG_LIST加载 LLM 配置。 - #2 该智能体直接与 LLM 通信。
- #3 该智能体作为用户代理,将对话转发给助手智能体。
- #4 设置终止消息,控制智能体迭代结束。
- #5 通过用户代理发起与助手的对话,完成指定任务。
在 VS Code 调试器中运行此代码(按 F5)。清单 4.6 使用了一个简单的编程任务演示代码编写能力。清单 4.7 列出了一些可选示例,这些任务也是作者常用来测试 LLM 编程能力的基准。
清单 4.7 简单编程任务示例
write a Python function to check if a number is prime
code a classic snake game using Pygame #1
code a classic asteroids game in Python using Pygame #1
- #1 想要享受这些任务的迭代效果,Windows 用户推荐使用 Windows Subsystem for Linux (WSL) 或 Docker。
代码启动几秒后,助手智能体会回复代理一个解决方案。这时代理会提示你给出反馈,直接按回车即可(表示无反馈),代理就会运行代码验证其是否按预期工作。
令人印象深刻的是,代理智能体还能自动安装所需的包,比如 Pygame。随后它会运行代码,你会在终端或者新弹出的窗口/浏览器中看到结果。如果代码打开了窗口或浏览器,你可以玩游戏或使用界面。
注意,Windows 下弹出的窗口或浏览器不会自动关闭,需要手动退出整个程序。为避免此问题,建议通过 WSL 或 Docker 运行代码。AutoGen 明确推荐使用 Docker 运行代码执行智能体,熟悉容器技术的用户尤为适合。
无论哪种方式,代理生成并运行代码后,之前在清单 4.6 中指定的 working_dir 目录下会出现一个包含代码的 Python 文件。你可以随时运行该代码、修改或请求改进,后续章节会详细讲解。
下一节我们将探讨如何提升编码智能体的能力。
4.2.2 通过智能体评审提升代码输出质量
多智能体系统的一大强大优势是能自动分配多种角色或人格来完成任务。生成或协助编写代码对开发者非常有利,但如果代码还能被审查和测试,那效果会更好。在接下来的练习中,我们将为智能体系统添加一个评审智能体,帮助处理编码任务。打开 autogen_coding_critic.py 文件,代码如下:
from autogen import AssistantAgent, UserProxyAgent, config_list_from_json
config_list = config_list_from_json(env_or_file="OAI_CONFIG_LIST")
user_proxy = UserProxyAgent(
"user",
code_execution_config={
"work_dir": "working",
"use_docker": False,
"last_n_messages": 1,
},
human_input_mode="ALWAYS",
is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"),
)
engineer = AssistantAgent(
name="Engineer",
llm_config={"config_list": config_list},
system_message="""
You are a professional Python engineer, known for your expertise in
software development.
You use your skills to create software applications, tools, and
games that are both functional and efficient.
Your preference is to write clean, well-structured code that is easy
to read and maintain.
""", #1
)
critic = AssistantAgent(
name="Reviewer",
llm_config={"config_list": config_list},
system_message="""
You are a code reviewer, known for your thoroughness and commitment
to standards.
Your task is to scrutinize code content for any harmful or
substandard elements.
You ensure that the code is secure, efficient, and adheres to best
practices.
You will identify any issues or areas for improvement in the code
and output them as a list.
""", #2
)
def review_code(recipient, messages, sender, config): #3
return f"""
Review and critique the following code.
{recipient.chat_messages_for_summary(sender)[-1]['content']}
""" #3
user_proxy.register_nested_chats( #4
[
{
"recipient": critic,
"message": review_code,
"summary_method": "last_msg",
"max_turns": 1,
}
],
trigger=engineer, #4
)
task = """Write a snake game using Pygame."""
res = user_proxy.initiate_chat(
recipient=engineer,
message=task,
max_turns=2,
summary_method="last_msg" #5
)
- #1 本次助手被赋予专业的系统/人格消息。
- #2 创建了第二个助手——评审智能体,具有审查背景。
- #3 自定义函数帮助提取代码供评审智能体审查。
- #4 在评审智能体和工程师智能体之间创建嵌套对话。
- #5 代理智能体发起对话,设置最大对话轮数和显式摘要方法。
在 VS Code 中以调试模式运行 autogen_coding_critic.py,观察智能体之间的对话。这次代码返回后,评审智能体会被触发,添加改进代码的评论和建议。
嵌套对话适合支持和控制智能体交互,但下一节我们会看到更优方案。在此之前,我们先来了解 AutoGen 的缓存机制。
4.2.3 理解 AutoGen 缓存机制
作为一个对话式多智能体平台,AutoGen 在多轮聊天过程中会消耗大量 token。当你让 AutoGen 处理复杂或新颖问题时,可能会遇到 LLM 的 token 限制。为此,AutoGen 支持多种减少 token 使用的方法。
AutoGen 默认启用缓存,用于存储进度并减少 token 消耗。你可能已经注意到当前工作目录下存在一个 .cache 文件夹(见图 4.8)。缓存机制允许智能体在对话中断时继续会话,避免重复处理。
在代码中,你可以控制智能体运行时的缓存文件夹,如清单4.9所示。通过使用 with 语句包装 initiate_chat 调用,你可以指定缓存的位置和种子(seed)。这样,只需设置之前缓存的 cache_seed,你就能保存并在未来恢复之前的长时间运行任务。
清单4.9 设置缓存文件夹示例
with Cache.disk(cache_seed=42) as cache: #1
res = user_proxy.initiate_chat(
recipient=engineer,
message=task,
max_turns=2,
summary_method="last_msg",
cache=cache, #2
)
- #1 通过设置
cache_seed来指定缓存位置的唯一标识。 - #2 将缓存作为参数传递。
这种缓存机制使你能够从之前的缓存位置继续操作,捕获之前的运行状态。它也是演示和检查智能体对话如何生成结果的好方法。下一节我们将探讨 AutoGen 支持的另一种对话模式——群聊。
4.3 AutoGen 中的智能体群聊
聊天委派和嵌套对话的问题之一是信息传递。你如果玩过“传话游戏”,就会深刻体会信息在反复传递过程中是如何快速变化的。智能体间的嵌套或顺序对话同样存在这个问题,可能导致任务目标或期望结果发生偏差。
传话游戏(The Telephone Game)
传话游戏是一个寓教于乐的游戏,用来展示信息丢失和连贯性下降的现象。孩子们排成一列,第一个孩子听到一句话后,依次口头传给下一个孩子,最后一个孩子将听到的内容大声告诉全体。通常,最终传出的信息与最初完全不同。
为了解决这一问题,AutoGen 提供了群聊机制,让智能体参与共享对话。这样,智能体可以查看全部历史对话,更好地协作完成长期且复杂的任务。
图4.9展示了嵌套对话和协作式群聊的区别。上一节我们用嵌套聊天实现了多智能体嵌套对话,本节将通过群聊机制提供更具协作性的对话体验。
打开 autogen_coding_group.py 文件,查看相关代码片段,如清单4.10所示。代码与前一个练习类似,但引入了 GroupChat 和 GroupChatManager。智能体和消息由群聊对象管理,类似于 Slack 或 Discord 这样的应用中的消息频道。聊天管理器负责协调消息回复,避免对话重叠。
清单4.10 autogen_coding_group.py(相关部分)
user_proxy = UserProxyAgent(
"user",
code_execution_config={
"work_dir": "working",
"use_docker": False,
"last_n_messages": 3,
},
human_input_mode="NEVER", #1
)
llm_config = {"config_list": config_list}
engineer = AssistantAgent(… #2
critic = AssistantAgent(… #2
groupchat = GroupChat(agents=[user_proxy,
engineer,
critic],
messages=[],
max_round=20) #3
manager = GroupChatManager(groupchat=groupchat,
llm_config=llm_config) #4
task = """Write a snake game using Pygame."""
with Cache.disk(cache_seed=43) as cache:
res = user_proxy.initiate_chat(
recipient=manager,
message=task,
cache=cache,
)
- #1 现在设置为不接受人工输入,因此无人工反馈。
- #2 代码省略,具体可查看文件中 persona 的相关更改。
- #3 该对象管理所有智能体的连接并存储消息。
- #4 管理器负责协调对话,就像一个主持人一样。
运行此练习,你将看到智能体如何协作。工程师智能体会接受评审智能体的反馈,并执行操作以改进代码。代理智能体可以参与整个对话过程。
群聊是一种极佳的方式,用来增强智能体的协作能力,帮助它们共同完成任务。不过,这种方式也会带来更高的冗长度和 token 消耗。当然,随着大语言模型(LLM)技术的成熟,其上下文窗口(token window)和处理 token 的成本都会有所提升,未来对 token 消耗的顾虑可能逐渐减少。
AutoGen 是一个强大的多智能体平台,你可以通过网页界面或代码体验它。无论你喜欢哪种方式,这个智能体协作工具都是构建代码或其他复杂任务的绝佳平台。当然,这并不是唯一的平台,下一节我们将介绍一个新兴的多智能体系统——CrewAI。
4.4 使用 CrewAI 构建智能体团队
CrewAI 是多智能体系统领域中的新秀。相比 AutoGen 最初源于研究并逐步扩展,CrewAI 则是从企业系统的实际需求出发设计构建的。因此,该平台更加健壮,但在某些方面的可扩展性相对较弱。
使用 CrewAI,你可以组建一个智能体团队,专注于任务目标的特定领域。与 AutoGen 不同,CrewAI 不依赖用户代理(user proxy agent),而是假设智能体仅在团队内部协作。
图4.10 展示了 CrewAI 平台的主要组成元素、它们的连接方式及核心功能。图中体现了一个顺序处理的智能体系统,包含通用的研究者(researcher)和撰写者(writer)智能体。每个智能体被分配具体任务,且可能配备工具或记忆功能以辅助完成任务。
CrewAI 支持两种主要的处理方式:顺序处理和分层处理。图 4.10 展示了通过迭代给定的代理(agents)及其相关任务来实现的顺序处理流程。下一节中,我们将深入代码,演示如何搭建一个团队(crew),并用它来完成一个目标,同时创作一个有趣的笑话。
4.4.1 创建一个由 CrewAI 代理组成的“笑话制造者”团队
CrewAI 的配置比 AutoGen 复杂一些,但也因此提供了更多的控制能力和额外的引导功能,可以为代理提供更具体的上下文,从而引导它们完成指定任务。这虽然带来了一些复杂性,但相比 AutoGen 默认的即用型方案,确实提供了更细粒度的控制。
打开 VS Code 中的 crewai_introduction.py 文件,看看文件开头部分,如列表 4.11 所示。配置一个代理需要许多设置,包括角色(role)、目标(goal)、详细程度(verbose)、记忆(memory)、背景故事(backstory)、委派权限(delegation)乃至工具(未展示)。在此示例中,我们使用了两个代理:一个高级笑话研究员和一个笑话作家。
列表 4.11 crewai_introduction.py(代理部分)
from crewai import Agent, Crew, Process, Task
from dotenv import load_dotenv
load_dotenv()
joke_researcher = Agent( #1
role="Senior Joke Researcher",
goal="Research what makes things funny about the following {topic}",
verbose=True, #2
memory=True, #3
backstory=( #4
"Driven by slapstick humor, you are a seasoned joke researcher"
"who knows what makes people laugh. You have a knack for finding"
"the funny in everyday situations and can turn a dull moment into"
"a laugh riot."
),
allow_delegation=True, #5
)
joke_writer = Agent( #6
role="Joke Writer",
goal="Write a humourous and funny joke on the following {topic}",
verbose=True, #7
memory=True, #8
backstory=( #9
"You are a joke writer with a flair for humor. You can turn a"
"simple idea into a laugh riot. You have a way with words and"
"can make people laugh with just a few lines."
),
allow_delegation=False, #5
)
- #1 创建代理并赋予其目标
- #2 verbose 表示代理是否输出详细信息到终端
- #3 支持代理使用记忆功能
- #4 backstory 是代理的背景故事或角色设定
- #5 代理是否允许委派任务;True 表示允许委派
- #6 同 #1,为第二个代理创建并赋予目标
- #7 同 #2,详细输出控制
- #8 同 #3,记忆支持
- #9 同 #4,背景故事
继续往下看代码,我们看到任务定义,如列表 4.12 所示。任务表示代理完成系统主要目标所需执行的流程。它还会关联代理与具体任务,定义任务输出,并可包含任务执行方式。
列表 4.12 crewai_introduction.py(任务部分)
research_task = Task( #1
description=(
"Identify what makes the following topic:{topic} so funny."
"Be sure to include the key elements that make it humourous."
"Also, provide an analysis of the current social trends,"
"and how it impacts the perception of humor."
),
expected_output="A comprehensive 3 paragraphs long report on the latest jokes.", #2
agent=joke_researcher, #3
)
write_task = Task( #4
description=(
"Compose an insightful, humourous and socially aware joke on {topic}."
"Be sure to include the key elements that make it funny and"
"relevant to the current social trends."
),
expected_output="A joke on {topic}.", #5
agent=joke_writer, #3
async_execution=False, #6
output_file="the_best_joke.md", #7
)
- #1 任务描述,定义代理如何完成任务
- #2 明确规定完成任务后期望的输出
- #3 指派执行任务的代理
- #4 同 #1,另一个任务的描述
- #5 期望输出为一则关于主题的笑话
- #6 是否异步执行任务
- #7 任务输出文件名
接下来,可以看到文件底部如何将所有部分组装成一个 Crew(团队),如列表 4.13 所示。构建 Crew 时可以配置许多选项,包括代理、任务、处理流程类型、记忆、缓存、最大请求数(max_rpm)以及是否允许团队共享信息。
列表 4.13 crewai_introduction.py(团队部分)
crew = Crew(
agents=[joke_researcher, joke_writer], #1
tasks=[research_task, write_task], #2
process=Process.sequential, #3
memory=True, #4
cache=True, #5
max_rpm=100, #6
share_crew=True, #7
)
result = crew.kickoff(inputs={"topic": "AI engineer jokes"})
print(result)
- #1 组建的代理团队
- #2 团队可执行的任务列表
- #3 定义代理间的交互方式
- #4 是否启用记忆功能,需与代理和任务设置对应
- #5 是否启用缓存,类似 AutoGen 功能
- #6 系统限制的最大请求数/分钟
- #7 团队内部是否共享信息,类似群聊模式
看完后,在 VS Code 中运行此文件(按 F5),终端会显示团队间的对话和消息。如你所见,这个代理系统的目标是创作与 AI 工程师相关的笑话。以下是几次运行产生的一些有趣笑话示例:
- 为什么电脑会觉得冷?因为它把 Windows 窗户开着了。
- 为什么 AI 工程师不和算法玩捉迷藏?因为无论藏在哪里,算法总能在“过拟合”房间找到他们!
- AI 工程师最喜欢的歌是什么?“我只是打电话来说我爱你……顺便收集更多语音识别软件的数据。”
- 为什么 AI 工程师总是没钱?因为他花光了钱买“cookies”,但浏览器一直在吃掉它们。
在继续运行笑话团队进行更多迭代之前,建议先阅读下一节内容,介绍如何为多代理系统添加可观测性功能。
4.4.2 使用 AgentOps 观察代理工作情况
观察像多代理系统这样复杂的组合,对于理解可能出现的各种问题至关重要。通过应用追踪实现可观测性,是任何复杂系统的关键要素,尤其是在企业应用场景中。
CrewAI 支持连接一个专门的代理运维平台,恰如其名,称为 AgentOps。这个可观测性平台是通用的,旨在支持与任何针对大型语言模型(LLM)使用的代理平台的可观测性对接。目前,AgentOps 尚无公开的价格或商业化细节。
连接 AgentOps 非常简单,只需安装对应的软件包,获取 API 密钥,并在你的 Crew 配置中添加一行代码。接下来的练习将演示连接和运行 AgentOps 的步骤。
列表 4.14 安装 agentops 包
pip install agentops
或者作为 CrewAI 的附加组件安装:
pip install crewai[agentops]
请记住,AgentOps 也可以连接到其他代理平台以实现可观测性。
使用 AgentOps 之前,你需要注册获取一个 API 密钥。以下是撰写本文时获取密钥的一般步骤:
- 在浏览器中访问 app.agentops.ai
- 注册账户
- 创建一个项目,或者使用默认项目
- 进入 设置 > 项目与 API 密钥
- 复制或生成新的 API 密钥,这会将密钥复制到剪贴板
- 将密钥粘贴到你项目中的
.env文件内
API 密钥复制后,格式类似如下示例:
列表 4.15 .env 文件:添加 AgentOps 密钥
AGENTOPS_API_KEY="your API key"
接下来,我们需要在 CrewAI 脚本中添加几行代码。列表 4.16 展示了在 crewai_agentops.py 文件中添加的内容。创建你自己的脚本时,只需引入 agentops 包并在使用 CrewAI 时初始化它即可。
列表 4.16 crewai_agentops.py(AgentOps 相关代码添加)
import agentops #1
from crewai import Agent, Crew, Process, Task
from dotenv import load_dotenv
load_dotenv()
agentops.init() #2
- #1 引入必需的 agentops 包
- #2 确保在加载环境变量后初始化 agentops
在 VS Code 中运行 crewai_agentops.py 文件(按 F5),观察代理的工作过程,与之前相同。但现在你可以打开 AgentOps 控制台,查看代理在多个层级的交互情况。
图 4.11 展示了用于运行笑话团队创建最佳笑话的 AgentOps 控制台界面。该界面显示了多项统计数据,包括总耗时、运行环境、提示词和完成词令牌数、LLM 调用时间以及估算费用。看到费用数据可能让人警醒,同时也反映出代理对话可能产生的冗长内容。
AgentOps 平台是任何代理平台的极佳补充。虽然它内置于 CrewAI 中,但可观测性功能同样可以添加到 AutoGen 或其他框架中。AgentOps 的另一个吸引人之处在于,它专注于观察代理间的交互,而非从机器学习运维平台转型而来。未来,我们很可能会看到更多专注于代理可观测性的模式涌现。
不可忽视的一个好处是,可观测性平台能提供成本监控。你有没有注意到图 4.11 中创建一个笑话的费用略高于 50 美分?代理虽强大,但成本也可能非常高,因此务必关注这些成本在实际和商业化上的表现。
本章最后一节,我们将回到 CrewAI,重新探讨构建会编写游戏代码的代理。这将很好地对比 AutoGen 和 CrewAI 的能力。
4.5 使用 CrewAI 重新探索编码代理
比较多代理平台能力的一个好方法是实现类似的任务。在接下来的练习中,我们将使用 CrewAI 作为一个游戏编程团队。当然,这也可以适配到其他编码任务。
打开 VS Code 中的 crewai_coding_crew.py 文件,先看列表 4.17 中的代理部分。这里我们创建了高级工程师、测试工程师和首席测试工程师三个代理,分别设定了角色、目标和背景故事。
列表 4.17 crewai_coding_crew.py(代理部分)
print("## Welcome to the Game Crew") #1
print("-------------------------------")
game = input("What is the game you would like to build? What will be the mechanics?\n")
senior_engineer_agent = Agent(
role="Senior Software Engineer",
goal="Create software as needed",
backstory=dedent(
"""
You are a Senior Software Engineer at a leading tech think tank.
Your expertise in programming in python. and do your best to
produce perfect code
"""
),
allow_delegation=False,
verbose=True,
)
qa_engineer_agent = Agent(
role="Software Quality Control Engineer",
goal="create prefect code, by analizing the code that is given for errors",
backstory=dedent(
"""
You are a software engineer that specializes in checking code
for errors. You have an eye for detail and a knack for finding
hidden bugs.
You check for missing imports, variable declarations, mismatched
brackets and syntax errors.
You also check for security vulnerabilities, and logic errors
"""
),
allow_delegation=False,
verbose=True,
)
chief_qa_engineer_agent = Agent(
role="Chief Software Quality Control Engineer",
goal="Ensure that the code does the job that it is supposed to do",
backstory=dedent(
"""
You are a Chief Software Quality Control Engineer at a leading
tech think tank. You are responsible for ensuring that the code
that is written does the job that it is supposed to do.
You are responsible for checking the code for errors and ensuring
that it is of the highest quality.
"""
),
allow_delegation=True, #2
verbose=True,
)
- #1 允许用户输入他们想要构建的游戏及其机制说明
- #2 只有首席测试工程师允许委派任务
继续往下看文件,会显示代理的任务定义,如列表 4.18。任务描述和期望输出都很清晰。每个代理都有特定任务,以便更好地提供上下文帮助完成工作。
列表 4.18 crewai_coding_crew.py(任务部分)
code_task = Task(
description=f"""
You will create a game using python, these are the instructions:
Instructions
------------
{game} #1
You will write the code for the game using python.""",
expected_output="Your Final answer must be the full python code, only the python code and nothing else.",
agent=senior_engineer_agent,
)
qa_task = Task(
description=f"""You are helping create a game using python, these are the instructions:
Instructions
------------
{game} #1
Using the code you got, check for errors. Check for logic errors,
syntax errors, missing imports, variable declarations, mismatched brackets,
and security vulnerabilities.""",
expected_output="Output a list of issues you found in the code.",
agent=qa_engineer_agent,
)
evaluate_task = Task(
description=f"""You are helping create a game using python, these are the instructions:
Instructions
------------
{game} #1
You will look over the code to insure that it is complete and
does the job that it is supposed to do. """,
expected_output="Your Final answer must be the corrected a full python code, only the python code and nothing else.",
agent=chief_qa_engineer_agent,
)
- #1 使用 Python 格式化将游戏指令插入到提示中
最后,列表 4.19 展示了如何将这些内容组合到文件底部。该团队配置与之前类似,添加了所有代理和任务,以及 verbose 和 process 属性。示例中继续使用顺序处理方式。
列表 4.19 crewai_coding_crew.py(团队部分)
crew = Crew(
agents=[senior_engineer_agent,
qa_engineer_agent,
chief_qa_engineer_agent],
tasks=[code_task, qa_task, evaluate_task],
verbose=2,
process=Process.sequential, #1
)
result = crew.kickoff() #2
print("######################")
print(result)
- #1 处理流程为顺序执行
- #2 启动团队工作,不提供额外上下文
运行 VS Code 中的文件(按 F5),系统会提示你输入编写游戏的指令。你可以输入贪吃蛇游戏或其他你选择的游戏。然后观察代理的工作成果。
有了首席测试工程师的加入,生成的结果一般会比 AutoGen 默认产出更好。审查代码时,你会发现它通常遵循良好编码规范,有时甚至包含测试和单元测试。
在本章结束前,我们将对团队的处理流程做最后一次修改。之前我们采用的是顺序处理,如图 4.10 所示。图 4.12 展示了 CrewAI 中分层处理的样貌。
添加这个管理者(manager)是一个相对简单的过程。列表 4.20 展示了对一个新文件所做的额外代码改动,该文件使用层级(hierarchical)方法运行编码团队。除了从 LangChain 导入连接 OpenAI 的类外,另一个新增内容是将该类作为团队管理者(manager_llm)传入。
列表 4.20 crewai_hierarchy.py(团队管理者部分)
from langchain_openai import ChatOpenAI #1
crew = Crew(
agents=[senior_engineer_agent,
qa_engineer_agent,
chief_qa_engineer_agent],
tasks=[code_task, qa_task, evaluate_task],
verbose=2,
process=Process.hierarchical, #2
manager_llm=ChatOpenAI( #3
temperature=0, model="gpt-4" #3
), #4
) #4
- #1 从 LangChain 导入 LLM 连接器
- #2 选择层级处理时,必须设置团队管理者
- #3 将团队管理者设置为该 LLM 连接器
- #4 选择层级处理时,必须设置团队管理者
在 VS Code 中运行此文件(按 F5)。提示时,输入你想创建的游戏。你可以使用之前在 AutoGen 里试过的游戏,比如贪吃蛇,这也是一个不错的基准例子。观察代理如何完成代码的编写,并反复检查其中的问题。
运行完后,你还可以登录 AgentOps 查看此次运行的成本。很可能,这次的费用会超过没有使用管理者时的两倍以上。而输出结果通常也不会显著更好。这正是构建代理系统时常见的陷阱——不了解系统复杂度如何迅速失控。
一个常见的失控例子是代理不断重复相同动作,陷入频繁重复任务。你可以在 AgentOps 中通过查看“Repeat Thoughts”(重复思考)图表来发现这个问题,如图 4.13 所示。
AgentOps 中的“Repeat Thoughts”(重复思考)图是衡量你的代理系统中重复行为的极佳工具。过度重复的思考模式通常意味着代理缺乏足够的决断力,而是不断尝试生成不同的答案。如果你遇到这个问题,就需要调整代理的处理模式、任务和目标。甚至可能需要改变系统中代理的类型和数量。
多代理系统是将工作按照岗位和任务的工作模式拆分开的极佳方案。通常,工作职责会分配给特定的代理角色或人物设定,而它们需要完成的任务可能是隐式的(如 AutoGen 中),也可能是更显式的(如 CrewAI 中)。
本章我们介绍了许多实用的工具和平台,你可以立即使用它们来提升工作、生活等多个方面。这也标志着我们多代理平台之旅的结束,但多代理的探索和应用还远未结束,后续章节中我们将继续深入发现和学习。
总结
- AutoGen 由微软开发,是一个基于对话的多代理平台,采用多种代理类型,如用户代理和助理代理,通过自然语言交互来促进任务执行。
- AutoGen Studio 是一个开发环境,允许用户创建、测试和管理多代理系统,提高了 AutoGen 的易用性。
- AutoGen 支持多种通信模式,包括群聊、层级通信和代理通信。代理通信中,主代理(代理人)作为用户与其他代理之间的接口,以简化任务完成流程。
- CrewAI 提供了一种结构化构建多代理系统的方法,重点面向企业应用,强调基于角色和自治的代理功能,支持灵活的顺序或层级任务管理。
- 本章通过实操演示如何搭建和使用 AutoGen Studio,包括安装必要组件和运行基础多代理系统。
- AutoGen 中的代理可以配备特定技能,用于完成代码生成、图像分析和数据检索等任务,拓展其应用范围。
- CrewAI 的特点是能够比 AutoGen 更加严格地构建代理交互,在需要精确和受控代理行为的场景中更具优势。
- CrewAI 支持为代理集成记忆和工具,以便代理通过完成任务进行信息消费。
- CrewAI 支持与可观测性工具如 AgentOps 集成,提供对代理性能、交互效率和成本管理的洞察。
- AgentOps 是一个代理可观测性平台,可以帮助你轻松监控大量代理间的交互情况。