总部位于巴西圣保罗的 João Moura 拥有超过 20 年的软件工程师经验。他曾在 Clearbit、Urdog 和 Toptal 等初创公司工作过,期间使用过 Ruby、JavaScript、TypeScript、Elixir 和 Python 等多种编程语言开发系统。同时,他在机器学习和人工智能领域也有扎实的背景。
2023 年,他推出了 CrewAI,这是一个基于 Python 的库,已发布在 GitHub 上,地址为:github.com/crewAIInc/c…。
激发他兴趣的是“由 AI 支持的全自动化部门”这一理念。CrewAI 主要致力于构建基于角色扮演的系统。
这一框架很快受到关注。João 表示:
“过去几周我一直在亲自测试 CrewAI,获得的结果令人印象深刻。就像拼图逐渐拼成完整图案,每个智能体都为整体贡献力量。”
目前该框架已有超过 18,000 个星标和 115 名贡献者。
本章将带你了解该框架的背景知识。
基础知识
在 AI 智能体框架中,CrewAI 是相对容易上手的一款。它设计合理、直观易用,但功能依然强大。
另一个重要优势是 CrewAI 构建于 LangChain 框架之上,这意味着它能够利用 LangChain 丰富的集成和功能。同时,CrewAI 还与 LangSmith 相连,支持生成式 AI 应用的测试与监控。
至于 CrewAI,本身包含多个核心概念,如智能体(agents)、任务(tasks)、工具(tools)、流程(processes)、团队(crews)和记忆(memory)。接下来,我们将逐一探讨这些内容。
智能体(Agents)
在 CrewAI 中,智能体是自主实体,负责执行任务、做出决策,并在协作团队环境中与其他智能体互动。每个智能体就像团队中的专业成员,具备特定技能,能够支持团队整体目标的实现。例如,一个智能体可以是数据分析师、内容创作者或技术支持专家,每个角色都是为有效支持团队目标而设计的。
下面是一个智能体的示例代码:
agent = Agent(
role='Content Creator',
goal='Develop engaging marketing content',
backstory="""You're a content creator at a digital marketing agency.
Your main responsibility is to create compelling content that resonates with the target audience and drives engagement.
You're currently working on a campaign to promote a new product launch across social media platforms.""",
tools=[content_tool1, content_tool2], # 可选,默认为空列表
llm=my_llm, # 可选
function_calling_llm=my_llm, # 可选
max_iter=15, # 可选
verbose=True, # 可选
allow_delegation=True, # 可选
callbacks=[callback1, callback2], # 可选
)
智能体的行为和能力由以下几个关键属性定义:
- role(角色) :定义智能体在团队中的具体职责。此例中,智能体扮演“内容创作者”,负责生成符合品牌信息和目标的营销内容。
- goal(目标) :指导智能体行动的主要目标。此处为“开发引人入胜的营销内容”,促使智能体专注于创作能够吸引受众并促进互动的内容。
- backstory(背景故事) :为智能体的角色和目标提供叙事上下文。该背景设定智能体为数字营销机构的内容创作者,当前任务是推广新产品发布活动。这有助于智能体做出符合其职责的决策。
- tools(工具) :智能体为实现目标可使用的具体能力或资源。
- llm:驱动智能体生成和理解文本的语言模型实例,例如 GPT-4,通过该模型智能体能够进行内容创作和决策。
- function_calling_llm:专门负责管理智能体调用工具或函数的语言模型。如果指定,负责执行函数调用,确保智能体有效利用工具生成内容。
- max_iter(最大迭代次数) :限定智能体在最终输出之前可对任务迭代的次数。此例中最多迭代 15 次,以不断完善内容。
- verbose(详细模式) :启用时,智能体会在运行过程中提供详细的反馈或日志,方便跟踪内容创作流程和理解决策过程。
- allow_delegation(允许委派) :决定智能体是否可以将任务或查询委派给其他智能体。设置为 True 时,如果智能体认为其他更专业的智能体更适合处理某些任务,它可以进行委派,以保证内容创作的高效性。
- callbacks(回调函数) :在智能体运行的特定时刻触发的函数,用于根据运行结果执行通知或其他操作。
任务(Tasks)
任务是由智能体管理的独立分配,设计有详细指令以确保成功完成。每个任务提供智能体完成工作所需的一切,包括描述、指定角色、所需工具及其他资源。这样的全面设置使智能体能够精准地处理不同复杂度的任务。
在 CrewAI 中,任务也可以是协作性质,通常涉及多个智能体共同完成。任务属性经过配置以促进有效协作,团队(Crew)的流程确保协作高效顺畅。
以下是一个任务的示例代码:
task = Task(
description='Research and compile a list of best practices for cybersecurity in cloud environments',
expected_output='A detailed report outlining the top 10 best practices for securing cloud environments, including explanations and examples.',
agent=cybersecurity_agent,
tools=[cloud_security_tool, research_tool]
)
任务结构中各属性及说明如下:
- description(描述) :简要且全面地说明任务内容,阐明主要目标或目的,确保智能体理解需要完成的工作。
- expected_output(预期输出) :定义任务完成后应达到的结果,详细说明成功完成任务的标准,帮助智能体明确期望。
- agent(智能体) :负责执行任务的具体实体或个体,可以是指定的智能体,也可能由系统内部流程确定。
与智能体类似,你也可以为任务设置以下属性:
- max_iter(最大迭代次数)
- verbose(详细模式)
- allow_delegation(允许委派)
- callbacks(回调函数)
此外,任务还有一些额外属性:
- async_execution(异步执行) :允许任务异步运行,不会阻塞其他进程,适合长时间运行或多任务并行执行的场景。
- context(上下文) :添加其他任务的输出,作为当前任务执行的补充上下文信息。
- config(配置) :提供额外配置细节,用于进一步定制任务。
- output_json:任务生成 JSON 格式输出,方便结构化数据的处理和传输,需配合 OpenAI 客户端使用。
- output_pydantic:类似 JSON 输出,任务以 Pydantic 模型对象形式输出,适用于需遵守特定数据模型的任务,也需 OpenAI 客户端支持。
- output_file(输出文件) :将任务结果保存到文件中。如果结合 JSON 或 Pydantic 输出,决定结果的存储方式和位置,便于后续访问或审阅。每个任务只能设置一种输出格式。
- human_input(人工输入) :指定任务完成后是否需要人工反馈,适合需要人工监督的任务,默认值为 False。
- callback(回调) :根据任务运行结果调用方法或函数,执行通知或其他操作。
工具(Tools)
在 CrewAI 中,工具是智能体用来执行各种任务的能力或功能,范围涵盖从简单搜索到复杂交互,支持无缝的团队协作。这些工具是提升智能体协作效率的重要组成部分,来源包括 CrewAI 工具包和 LangChain 工具。它们针对特定任务设计,如网页搜索、数据分析、内容生成和智能体协作,使工具具有高度实用性和多功能性。
这些工具直接集成在智能体的工作流程中,大幅增强了智能体执行任务的效率。此外,工具具备高度可定制性,开发者可以创建自定义工具或使用现有工具,以满足智能体的具体需求。为确保操作流畅,工具内置了健壮的错误处理机制,并采用智能缓存优化性能,减少重复任务。这种实用性、集成度、可定制性与性能优化的结合,使工具成为 CrewAI 生态系统的重要组成部分。本书基于 CrewAI 版本 0.51.0 进行介绍。
以下是部分 CrewAI 工具示例:
- BrowserbaseLoadTool:用于与网页浏览器交互并提取数据的工具
- CodeDocsSearchTool:专为浏览代码文档和技术手册设计的搜索工具
- CSVSearchTool:针对结构化数据高效搜索 CSV 文件的专用工具
- DALL-E Tool:通过 DALL-E API 生成图像的工具
- DOCXSearchTool:用于搜索 DOCX 文件,便于处理和提取 Word 文档信息
- PDFSearchTool:专门用于搜索 PDF 文档,适合处理扫描件或复杂文件
- ScrapeWebsiteTool:用于抓取整个网站内容,适合从网页收集全面数据
- XMLSearchTool:设计用于搜索 XML 文件,针对结构化数据格式优化
团队(Crews)
团队是由多个智能体协作组成的集合,共同完成一系列任务。每个团队负责制定任务执行策略,协调智能体之间的互动,并管理整体工作流程,以确保操作高效且有效。
以下是一个团队的示例代码:
project_team = Crew(
agents=[data_analyst, report_creator],
tasks=[data_analysis_task, generate_report_task],
process=Process.sequential,
full_output=True,
verbose=True,
)
这里可以设置运行的智能体(agents)和任务(tasks)。还有一个属性是 process,它定义了智能体的执行顺序,我们将在后面详细讨论。
接下来是 full_output 属性,用于控制团队是返回所有任务的输出还是仅返回最终结果。
其他一些属性包括:
- share_crew:允许你将团队的执行数据和结果分享给 CrewAI 团队。这有助于改进库的功能和支持模型训练。
- output_log_file:如果你想保存团队的完整执行日志,可以将此属性设置为 True,或指定一个具体文件路径来保存日志。
- planning:启用此属性后,团队会在每次迭代前进行规划。你也可以通过
planning_llm属性为规划设置使用的语言模型。
流程(Processes)
在 CrewAI 中,流程是任务管理的核心支柱,就像项目经理在团队中组织和分配工作一样。这些流程确保任务能够根据既定策略有效地分配和执行。
常见的流程类型包括:
- 顺序流程(Sequential Process) :任务按预定顺序依次执行,保证每个任务按特定顺序完成。
- 分层流程(Hierarchical Process) :任务在结构化的层级体系中管理。一个管理者(可以是语言模型
manager_llm或自定义智能体manager_agent)负责任务的分配与监督。该设置使管理者能够根据需要创建和分派任务,确保任务与团队整体目标保持一致。 - 共识流程(Consensual Process) :设计用于让智能体协作决策任务执行,采用民主方式管理任务。目前此流程计划未来开发,尚未在现有代码中实现。
以下是顺序流程的示例代码:
crew = Crew(
agents=my_agents,
tasks=my_tasks,
process=Process.sequential
)
这是分层流程的示例代码:
crew = Crew(
agents=my_agents,
tasks=my_tasks,
process=Process.hierarchical,
manager_llm=ChatOpenAI(model="gpt-4")
)
记忆(Memory)
CrewAI 框架包含一个先进的记忆系统,极大地增强了 AI 智能体记忆、推理和从过去经验中学习的能力。该记忆系统由几个关键组成部分构成,每个部分都针对性地提升智能体在特定方面的表现:
- 短期记忆(Short-Term Memory) :临时存储最近的交互和结果,使智能体能够在当前任务中访问并应用相关信息。这种即时回忆对保持操作的连续性和相关性至关重要。
- 长期记忆(Long-Term Memory) :保存过去执行中的宝贵见解,使智能体随着时间积累知识库,优化决策流程。这种累积的智慧使智能体能借鉴以往经验,指导未来行动。
- 实体记忆(Entity Memory) :专注于捕捉和组织与任务相关的实体信息,如人物、地点和概念。通过提供详细的关键元素知识,增强智能体理解能力和应对复杂场景的能力。
- 上下文记忆(Contextual Memory) :整合短期、长期和实体记忆功能,在多个任务或对话中保持一致的上下文,确保智能体在扩展交互范围时依然能提供连贯且贴切的响应。
通过组合这些记忆组件,CrewAI 系统赋予智能体上下文感知能力、累积和学习经验的能力,以及对关键实体的深度理解。这个全面的记忆系统使智能体在交互中更有效、更智能,能够以更高的复杂性和适应性处理任务。
本章剩余部分将通过多个 CrewAI 应用实例来说明这些核心概念。
备注
CrewAI+ 是 CrewAI 的企业版,支持将任何团队快速转化为 API,通过 hooks、REST、gRPC 等方式与应用集成。它还提供模板和自定义工具,但截至目前,CrewAI+ 仍处于私测阶段。
财务规划智能体
我们将创建一个预算智能体,通过分析用户的收入和支出,帮助制定详细的月度预算,确保所有必要的开销得到覆盖,同时优化储蓄。
这涉及多智能体协作。首先是预算智能体(Budgeting Agent),它分析用户的收入和支出,制定详细的月度预算。其次是投资顾问智能体(Investment Advisor Agent),根据用户的财务目标和风险承受能力,提供定制化的投资建议,帮助用户通过明智的决策实现财富增长。最后是债务管理智能体(Debt Management Agent),专注于帮助用户管理和减少债务,制定有效的还款策略,并提供债务合并和利率谈判方面的建议。
下面是代码示例:
!pip install crewai
!pip install crewai crewai-tools
首先安装核心的 CrewAI 包,它包含了在 Python 中创建和管理多智能体系统所需的基本类和函数。然后安装工具包,工具包包括管理特定类型智能体、连接外部 API 或实现多智能体框架高级功能的专用组件。
导入相关模块:
from crewai import Agent, Task, Crew
接下来定义各个智能体。首先是预算智能体:
budgeting_agent = Agent(
role="Budgeting Advisor",
goal="Create a monthly budget to help users manage their income and expenses effectively.",
backstory=(
"You are an experienced financial advisor specializing in personal finance. "
"Your goal is to help users allocate their income efficiently, ensuring they cover "
"all necessary expenses while also saving for the future."
),
allow_delegation=False,
verbose=True
)
Agent 类通过多个关键参数定义智能体的角色、目标和行为。此处智能体角色为“预算顾问”,目标是帮助用户有效管理收入和支出,制定月度预算。backstory 参数为智能体提供上下文,描绘其为专注于个人理财的经验丰富财务顾问,帮助智能体作出与其专业相符的响应和决策。allow_delegation=False 表示该智能体不将任务委托给其他智能体,保持职责专一。verbose=True 允许详细日志记录,方便跟踪智能体的操作过程。
接着是投资顾问智能体:
investment_agent = Agent(
role="Investment Advisor",
goal="Recommend suitable investment options based on the user's financial goals and risk tolerance.",
backstory=(
"You are an investment expert with years of experience in the financial markets. "
"Your goal is to help users grow their wealth by providing sound investment advice "
"tailored to their risk tolerance and financial objectives."
),
allow_delegation=False,
verbose=True
)
backstory 强调智能体作为经验丰富的投资专家,具备深厚的金融市场知识,确保给出相关且专业的投资建议。
最后是债务管理智能体:
debt_management_agent = Agent(
role="Debt Management Specialist",
goal="Help users manage and reduce their debt through effective strategies.",
backstory=(
"You specialize in helping individuals overcome debt by creating personalized repayment plans. "
"Your focus is on reducing interest payments and improving the user's financial health."
),
allow_delegation=False,
verbose=True
)
该智能体专注于制定个性化还款计划,减少利息支出,改善用户整体财务状况,从而提供切实可行的债务管理建议。
接下来定义三项任务:
预算任务:
budgeting_task = Task(
description=(
"1. Analyze the user's income and expenses. Financial Data: {financialdata}\n"
"2. Create a detailed monthly budget that includes essential expenses, savings, and discretionary spending.\n"
"3. Provide tips for optimizing spending and increasing savings."
),
expected_output="A comprehensive monthly budget with recommendations for optimizing spending and savings.",
agent=budgeting_agent
)
任务描述清晰列出了步骤:分析财务数据,制定包含必要支出、储蓄及可自由支配开销的详细预算,并提供优化建议。expected_output 明确了任务成果,即一个全面的月度预算及节省支出的建议。
投资任务:
investment_task = Task(
description=(
"1. Assess the user's financial goals and risk tolerance.\n"
"2. Recommend suitable investment options such as stocks, bonds, mutual funds, or ETFs.\n"
"3. Provide a brief overview of each recommended investment's potential risks and returns."
),
expected_output="A personalized investment plan with recommendations and risk assessments.",
agent=investment_agent
)
描述强调评估用户目标与风险承受度,推荐符合需求的投资选项,并说明风险及回报,确保提供个性化的投资方案。
债务管理任务:
debt_management_task = Task(
description=(
"1. Analyze the user's current debts, including interest rates and balances.\n"
"2. Develop a repayment plan that prioritizes high-interest debt and suggests strategies for paying off balances faster.\n"
"3. Provide advice on consolidating debt or negotiating lower interest rates."
),
expected_output="A debt management plan with actionable steps to reduce and eliminate debt.",
agent=debt_management_agent
)
任务聚焦于债务分析、制定优先还清高利息债务的计划以及提供合并债务和降低利率的建议。
最后将智能体和任务关联起来:
crew = Crew(
agents=[budgeting_agent, investment_agent, debt_management_agent],
tasks=[budgeting_task, investment_task, debt_management_task],
verbose=True # 设置为 True 以获得详细日志,False 则减少输出
)
此 Crew 对象将三个智能体和对应任务整合,确保每个智能体完成其分配的职责。
运行示例:
user_financial_data = dict({
"financialdata": {
"income": 5000, # 月收入,美元
"expenses": {
"rent": 1500,
"utilities": 300,
"groceries": 400,
"transportation": 200,
"entertainment": 150,
"other": 450
},
"debts": {
"credit_card": {
"balance": 2000,
"interest_rate": 0.18 # 18% 利率
},
"student_loan": {
"balance": 15000,
"interest_rate": 0.045 # 4.5% 利率
}
},
"savings_goal": 500 # 月储蓄目标,美元
}
})
# 运行智能体组,传入用户财务数据
result = crew.kickoff(inputs=user_financial_data)
# 提取原始文本结果
raw_result = result.raw
# 以 Markdown 格式显示结果
from IPython.display import Markdown
Markdown(raw_result)
变量 user_financial_data 被定义用来表示用户的财务状况,包含财务规划所需的各项内容。用户的月收入设定为 5000 美元。支出细分为多个类别,包括房租(1500 美元)、水电费(300 美元)、食品杂货(400 美元)、交通费(200 美元)、娱乐费(150 美元)以及其他杂项支出共计 450 美元。此外,用户的债务情况也被详细列出,包括信用卡余额 2000 美元,利率为 18%,以及学生贷款余额 15000 美元,利率为 4.5%。用户还有每月储蓄目标 500 美元。这份全面的财务数据随后传入 crew.kickoff 函数,启动多个 AI 智能体协同工作的流程,以生成财务建议。该流程的结果以原始文本形式提取,随后通过 Markdown 格式进行展示,方便阅读和理解,如图 6-1 所示。
产品发布协调者
我们将创建一个更高级的 AI 智能体,称之为 LaunchMaster。它旨在简化产品发布的复杂流程,确保每个环节都被精心管理以确保成功。通过利用专业的子智能体,LaunchMaster 负责关键任务,比如深入的市场调研以确定目标人群和竞争对手,为各类营销渠道制作引人入胜且有说服力的内容,并执行针对网红和媒体的精准推广。
本程序引入了 CrewAI 框架中的一些新概念。例如,我们使用了新工具,如 SerperDevTool 和 ScrapeWebsiteTool,还演示了如何创建自定义工具。
该智能体允许人工输入,并支持将数据保存到你的电脑。
让我们来看程序的工作流程。
我们导入以下库:
from crewai_tools import ScrapeWebsiteTool, SerperDevTool
from pydantic import BaseModel
ScrapeWebsiteTool 用于从网站抓取数据,使 AI 智能体能够动态收集和分析网页内容。SerperDevTool 用于互联网搜索,使用该工具需要在 serper.dev 注册获取 API 密钥。
从 pydantic 导入的 BaseModel 是 Python 中用于定义带有验证规则的数据模型的类,接下来会用它为自定义工具提供结构。
接着,我们创建三个智能体:
market_researcher = Agent(
role="Market Researcher",
goal="Conduct thorough market research to identify target demographics and competitors.",
tools=[search_tool, scrape_tool],
verbose=True,
backstory=(
"Analytical and detail-oriented, you excel at gathering insights about the market, "
"analyzing competitors, and identifying the best strategies to target the desired audience."
)
)
content_creator = Agent(
role='Content Creator',
goal="Develop engaging content for the product launch, including blogs, social media posts, and videos.",
tools=[search_tool, scrape_tool],
verbose=True,
backstory=(
"Creative and persuasive, you craft content that resonates with the audience, "
"driving engagement and excitement for the product launch."
)
)
pr_outreach_specialist = Agent(
role="PR and Outreach Specialist",
goal="Reach out to influencers, media outlets, and key opinion leaders to promote the product launch.",
tools=[search_tool, scrape_tool],
verbose=True,
backstory=(
"With strong networking skills, you connect with influencers and media outlets to ensure "
"the product launch gains maximum visibility and coverage."
)
)
市场调研员(Market Researcher)智能体专注于收集和分析市场数据,确定目标人群和竞争对手,使用搜索和网页抓取工具。内容创作者(Content Creator)负责为产品发布开发引人入胜的内容,如博客和社交媒体帖子,激发用户兴趣和参与度。公关与推广专家(PR and Outreach Specialist)则通过联系网红、媒体和关键意见领袖,最大化产品发布的曝光率和媒体覆盖率,同样利用强大的社交网络和工具来提高推广效率。
基础数据模型定义如下:
class MarketResearchData(BaseModel):
target_demographics: str
competitor_analysis: str
key_findings: str
MarketResearchData 类是结构化数据模型,用于捕获市场调研智能体分析的输出。该模型包括目标受众、竞争者分析和关键发现字段,确保以一致的格式存储和验证调研成果。
接下来定义几个任务:
market_research_task = Task(
description="Conduct market research for the {product_name} launch, focusing on target demographics and competitors.",
expected_output="A detailed report on market research findings, including target demographics and competitor analysis.",
human_input=True,
output_json=MarketResearchData,
output_file="market_research.json",
agent=market_researcher
)
该任务要求市场调研智能体针对产品发布进行市场研究,重点关注目标人群和竞争对手。description 参数说明了任务步骤,expected_output 明确期望输出一份详细报告,human_input=True 允许人类反馈确认结果,结果以 JSON 格式保存到 market_research.json 文件,方便分享与整合。
内容创建任务如下:
content_creation_task = Task(
description="Create content for the {product_name} launch, including blog posts, social media updates, and promotional videos.",
expected_output="A collection of content pieces ready for publication.",
human_input=True,
async_execution=False,
output_file="content_plan.txt",
agent=content_creator
)
内容创作者智能体负责为产品发布准备博客文章、社交媒体更新和宣传视频等内容。任务要求输出一套可发布的内容集,并支持人工反馈。任务执行为同步,输出保存为 content_plan.txt。
公关推广任务定义:
pr_outreach_task = Task(
description="Contact influencers, media outlets, and key opinion leaders to promote the {product_name} launch.",
expected_output="A report on outreach efforts, including responses from influencers and media coverage.",
async_execution=False,
output_file="outreach_report.md",
agent=pr_outreach_specialist
)
该任务由公关与推广专家执行,联系网红、媒体及意见领袖推广产品发布。输出为一份详细报告,包含反馈和媒体报道,保存为 Markdown 格式文件 outreach_report.md。
组建团队代码:
product_launch_crew = Crew(
agents=[market_researcher, content_creator, pr_outreach_specialist],
tasks=[market_research_task, content_creation_task, pr_outreach_task],
verbose=True
)
团队由市场调研员、内容创作者和公关推广专家组成,任务参数保证每位智能体承担相应职责。
运行团队示例输入:
launch_details = {
'product_name': "SmartHome 360",
'product_description': "A cutting-edge smart home system that integrates with all your devices.",
'launch_date': "2024-10-01",
'target_market': "Tech-savvy homeowners",
'budget': 50000
}
result = product_launch_crew.kickoff(inputs=launch_details)
launch_details 字典包含产品发布的关键信息,介绍了 “SmartHome 360” 智能家居系统,描述其整合多设备的先进功能,发布于 2024 年 10 月 1 日,目标市场为技术达人家庭,预算为 5 万美元。将这些信息传入团队的 kickoff 方法后,AI 智能体团队将开始执行市场调研、内容制作和公关推广任务,针对该发布方案量身定制。
输出内容将非常丰富,示例中生成了超过 162 页的报告!程序会访问互联网收集数据,用于撰写报告和分析。
然后,我们将这些信息整理为更简明的格式:
import json
from pprint import pprint
from IPython.display import Markdown # 导入 Markdown 函数
# 显示生成的 market_research.json 文件
with open('market_research.json') as f:
data = json.load(f)
pprint(data)
# 显示生成的 content_plan.txt 文件
with open('content_plan.txt') as f:
content = f.read()
print(content)
# 显示生成的 outreach_report.md 文件
Markdown("outreach_report.md")
首先导入 json 模块用于加载和解析 JSON 数据,使用 pprint 模块中的 pprint 函数美化打印复杂数据结构。
代码打开并加载市场调研报告 market_research.json,用 pprint 打印清晰有序的数据结构。接着打开并读取内容创作计划 content_plan.txt,打印显示产品发布的内容规划。最后,调用 Markdown 函数呈现公关推广报告 outreach_report.md,以格式良好的形式展示推广成果,便于审阅。
这一系列步骤确保了 AI 智能体所有关键输出均可访问,且以用户友好的格式呈现。
客户呼叫中心处理
我们来看一个使用 CrewAI 的更复杂示例,该示例将自动化呼叫中心的任务。这里我们将采用分层流程(hierarchical process)。
典型的客户服务中心是客户通过电话、邮件或聊天等方式沟通的服务枢纽。客户的来电会根据问题的性质被转发给不同的智能体,问题类型可能是账单查询、技术支持或一般咨询等。智能体会直接为客户解决问题,或将复杂问题升级给专家处理。复杂问题会通过工单系统进行跟踪并持续跟进直到解决。交互结束后,客户通常会被邀请提供反馈,以进一步提升服务质量。
图 6-2 展示了该系统的层级结构。以下是各智能体的职责:
- 客户服务经理(Customer Service Manager):监督多个专门负责具体任务的智能体
- 呼叫处理智能体(Call Handling Agent):管理来电分配、问题解决及升级流程
- 技术支持智能体(Technical Support Agent):负责故障排查、远程协助及工单创建
- 账单与支付智能体(Billing and Payments Agent):处理发票生成、付款处理及争议解决
- 客户反馈与调查智能体(Customer Feedback and Surveys Agent):负责问卷派发、反馈收集及情感分析
来看程序是如何工作的。
我们引入以下库:
from langchain_openai import ChatOpenAI
from crewai import Crew, Process, Agent
根据上文定义的层级结构,我们创建以下四个智能体:
呼叫处理智能体(Call Handling Agent):
call_handling_agent = Agent(
role="Call Handling Agent",
goal="管理并解决客户电话咨询,包括来电分配和问题处理:{call_action_taken}",
tools=[],
allow_delegation=True, # 该智能体可委派任务
verbose=True,
backstory=("擅长处理来电,将客户引导至正确部门,并高效解决基础问题。")
)
上述代码描述了呼叫处理智能体的职责,例如呼叫分配、简单查询回复和问题升级。这里的 goal 使用了动态参数 {call_action_taken} 来反映电话处理中采取的具体操作。此智能体还可将任务转交给其他智能体或部门以处理更复杂的问题。
技术支持智能体(Technical Support Agent):
tech_support_agent = Agent(
role="Technical Support Agent",
goal="排查并解决客户报告的技术问题:{technical_action_taken}",
tools=[],
allow_delegation=True, # 可委派任务或升级问题
verbose=True,
backstory=("经验丰富,擅长远程技术支持、故障排查和工单管理,确保问题得到解决。")
)
此智能体的 goal 同样动态包含了解决过程中采取的操作 {technical_action_taken}。它可以委派任务或将问题升级。描述强调其在远程技术支持和全流程工单管理中的丰富经验。
账单与支付智能体(Billing & Payments Agent):
billing_agent = Agent(
role="Billing & Payments Agent",
goal="处理客户账单查询、付款及纠纷解决:{billing_action_taken}",
tools=[],
allow_delegation=False, # 不委派任务
verbose=True,
backstory=("专注于管理账单相关问题,确保发票准确、付款及时,并处理客户争议。")
)
该智能体的 goal 动态包含账单处理操作 {billing_action_taken}。不同于其他智能体,它不支持任务委派(allow_delegation=False)。描述突出了其在账单准确性、付款处理和纠纷解决方面的专业能力。
客户反馈与调查智能体(Customer Feedback & Surveys Agent):
feedback_agent = Agent(
role="Customer Feedback & Surveys Agent",
goal="通过调查收集并分析客户反馈及情感数据:{customer_feedback}",
tools=[],
allow_delegation=False, # 不委派任务
verbose=True,
backstory=("专长于收集客户反馈、执行调查并进行情感分析,以提升整体服务质量。")
)
该智能体利用 {customer_feedback} 来分析客户反馈,且不支持委派任务。其背景说明了专注于客户反馈收集与情感分析,旨在提升服务质量。
以下是各智能体任务的代码示例:
呼叫处理任务(含上下文、智能体及回调函数):
call_handling_task = Task(
description="处理客户来电,解决基本查询或必要时升级处理。",
expected_output="一份详尽的呼叫处理报告,包括解决的查询和升级情况。",
human_input=True,
output_json=CallHandlingData,
output_file="call_handling_report.json",
context={'priority': 'high', 'expected_resolution_time': '15 minutes'}, # 额外任务上下文
agent=call_handling_agent,
callback=lambda result: print(f"任务完成:{call_handling_agent.role},结果:{result}"),
)
技术支持任务:
tech_support_task = Task(
description="排查客户反馈的技术问题,并按需解决或升级,依据{troubleshooting_steps}",
expected_output="技术问题处理总结报告及未解决工单。",
human_input=True,
output_json=TechSupportData,
output_file="tech_support_report.json",
context={'priority': 'medium', 'expected_resolution_time': '30 minutes'},
agent=tech_support_agent,
callback=lambda result: print(f"任务完成:{tech_support_agent.role},结果:{result}"),
)
账单与支付任务:
billing_task = Task(
description="处理客户发票,解决付款问题及纠纷。",
expected_output="发票处理、付款完成及纠纷解决报告。",
human_input=True,
output_json=BillingData,
output_file="billing_report.json",
context={'priority': 'low', 'expected_resolution_time': '45 minutes'},
agent=billing_agent,
callback=lambda result: print(f"任务完成:{billing_agent.role},结果:{result}"),
)
客户反馈与调查任务:
feedback_task = Task(
description="发放客户满意度调查,分析反馈中的情感信息。",
expected_output="调查结果总结及客户情感分析报告。",
human_input=True,
output_json=FeedbackData,
output_file="feedback_report.json",
context={'priority': 'low', 'expected_resolution_time': '60 minutes'},
agent=feedback_agent,
callback=lambda result: print(f"任务完成:{feedback_agent.role},结果:{result}"),
)
呼叫处理智能体负责处理客户来电、解决查询以及复杂问题的升级,预计在15分钟内解决。技术支持智能体负责排查技术问题并准备报告,预计在30分钟内完成。账单智能体处理发票、付款问题或纠纷,整体优先级较低,解决时限约45分钟。客户反馈智能体通过调查收集客户反馈,任务优先级也较低,预计完成时间为60分钟。
callback 属性接收一个函数,该函数在任务执行完成后被调用,通过记录日志消息显示智能体已完成任务。这对于实时跟踪任务执行和管理非常有用,能保证流程顺畅且结果被妥善记录。
为了存储智能体执行任务相关的数据,我们可以创建如下基础类:
class CallHandlingData(BaseModel):
call_summary: str
resolved_queries: str
escalated_issues: str
class TechSupportData(BaseModel):
troubleshooting_steps: str
resolved_issues: str
open_tickets: str
class BillingData(BaseModel):
invoice_details: str
processed_payments: str
resolved_disputes: str
class FeedbackData(BaseModel):
survey_results: str
customer_feedback: str
sentiment_summary: str
下面的代码片段展示了由四个智能体组成的团队(Crew):
customer_service_crew = Crew(
agents=[call_handling_agent, tech_support_agent, billing_agent, feedback_agent],
tasks=[call_handling_task, tech_support_task, billing_task, feedback_task],
manager_llm=ChatOpenAI(temperature=0, model="gpt-4o"), # 管理整体任务分配的语言模型
process=Process.hierarchical, # 分层任务委派
memory=True, # 启用记忆功能以保持任务执行的连续性
planning=True, # 启用规划以策略性地分配资源和管理任务
)
设置 memory=True 允许存储先前任务的信息,以便任务执行时保持连续性;planning=True 使系统能通过资源分配进行战略规划。
层级流程结构使得团队像一个有组织、协调良好的团队,每个智能体执行自身角色,系统负责整体流程和任务分配。
接下来获取用户输入数据:
customer_service_details = dict({
'call_handling': {
'queries_to_resolve': [
'Account update request, need to update phone number', # 客户账户更新请求
'Complaint about slow service on previous calls'
],
'call_action_taken': 'Account update request is completed. Call transferred to technical support'
},
'escalations': {
'technical_support': {
'issue': 'Product malfunction after software update',
'technical_action_taken': 'noted the issues faced by the customer and ticket created for further investigation, call transferred to billing for resolution of overcharges'
},
'billing': {
'issue': 'Overcharged on most recent invoice',
'priority': 'High',
'billing_action_taken': 'The overcharges are dropped and customer was sent to take survey with end of the call'
}
},
'technical_support': {
'troubleshooting_steps': [
'Check for software compatibility issues',
'Remote assistance to reinstall/update software'
],
},
'billing_payments': {
'priority': 'High',
'dispute_resolution_steps': [
'Review the invoice for overcharges',
'Calculate and issue refund if overcharge is confirmed'
]
},
'customer_feedback': {
'feedback_sentiment': {
'positive': '50%', # 客户对账单处理满意
'neutral': '30%', # 对整体服务持中立态度
'negative': '20%' # 因技术问题未解决表示不满
}
}
})
最后,用以上用户输入启动团队执行任务:
task_result = customer_service_crew.kickoff(inputs=customer_service_details)
任务完成后,打印执行结果:
# 任务完成回调示例
def handle_task_completion(task_result):
# 提取原始文本结果
raw_result = task_result.raw
# 以Markdown格式展示结果
from IPython.display import Markdown
print("任务完成:")
Markdown(raw_result)
这样,客户服务团队的各智能体就会根据用户输入协同工作,完成呼叫处理、技术支持、账单处理及客户反馈收集等任务,并输出对应的详细报告。
检索增强生成(RAG)
CrewAI 提供了多种用于检索增强生成(RAG)的类,以下是一些示例:
- CSVSearchTool:允许智能体高效地从 CSV 文件中检索特定数据。
- DOCXSearchTool:在 DOCX 文档中搜索,根据查询上下文提取相关文本部分。
- PDFSearchTool:支持在 PDF 文件中搜索,提取并利用相关内容生成回答。
- WebsiteSearchTool:在指定网站中搜索,从网页中提取相关信息以增强生成过程。
下面我们来看一个示例,使用 WebsiteSearchTool。
首先导入所需库:
from crewai import Agent, Task, Crew, Process
from crewai_tools import WebsiteSearchTool
配置 WebsiteSearchTool,指定网址:
WebsiteSearchTool(website='https://en.wikipedia.org/wiki/Alan_Turing')
这是关于艾伦·图灵的传记页面。
我们创建一个执行搜索的智能体:
search_agent = Agent(
role='Website Researcher',
goal='Search and extract relevant information from a specific website.',
verbose=True,
memory=True,
backstory='You are an expert in searching websites for the most relevant and up-to-date information.',
tools=[search_tool]
)
智能体被赋予“网站研究员”的角色,明确目标是从指定网站识别并提取相关数据。其背景故事将其定位为网络搜索专家,强调其查找最相关、最新信息的能力。最后,智能体配备了执行搜索任务所需的工具(此处为 search_tool)。
定义该智能体的任务:
search_task = Task(
description=(
"Use the provided website to find information on the topic '{topic}'. "
"Make sure to gather all the relevant data available on this site."
),
expected_output='A detailed summary of the information found on the website.',
tools=[search_tool],
agent=search_agent,
)
任务描述指导智能体利用给定网址针对 {topic} 主题收集信息,强调需获取网站上所有相关数据。期望输出为该主题的详细总结,由智能体根据搜索结果生成。任务配备了所需的 search_tool,并分配给 search_agent 来执行。
接下来创建团队(Crew):
research_crew = Crew(
agents=[search_agent],
tasks=[search_task],
process=Process.sequential # 顺序执行任务
)
团队配置为顺序执行任务。search_agent 确保有专门的专家执行研究工作,而 search_task 明确需要完成的任务。这样组织流程,使研究团队能够高效处理任务流程。
启动团队,输入主题“Artificial intelligence”,并打印 RAG 结果:
result = research_crew.kickoff(inputs={'topic': 'Artificial intelligence'})
print(result)
输出将显示从网页中检索到的与“人工智能”主题相关的内容部分。
连接大语言模型(LLMs)
目前,CrewAI 默认使用的 LLM 是 GPT-4o,但该框架支持多种其他模型。
我们先来看如何使用 Hugging Face 的模型:
from langchain.llms import HuggingFaceHub
然后创建其实例:
llm = HuggingFaceHub(
repo_id="HuggingFaceH4/zephyr-7b-beta",
huggingfacehub_api_token="<HF_TOKEN_HERE>",
task="text-generation",
)
参数说明:
repo_id:指定你想从 Hugging Face Hub 使用的模型。huggingfacehub_api_token:你的 Hugging Face API 令牌,可以在 HuggingFace.co 免费获取。task:指定模型的任务类型,这里是“text-generation”,表示用于文本生成。
另一个选择是 Cohere,使用时需要导入:
from langchain_community.chat_models import ChatCohere
然后设置环境变量以存储 Cohere API 密钥(可在 cohere.com 获取):
import os
os.environ["COHERE_API_KEY"] = "your-cohere-api-key"
接着创建 Cohere LLM 实例:
llm = ChatCohere()
如果使用 Azure LLM,可以这样导入并创建实例:
from langchain_openai import AzureChatOpenAI
azure_llm = AzureChatOpenAI(
azure_endpoint=os.environ.get("AZURE_OPENAI_ENDPOINT"),
api_key=os.environ.get("AZURE_OPENAI_KEY")
)
本地 LLM 有多种使用方法,其中推荐使用 Ollama。
导入 Ollama:
from langchain_ollama import ChatOllama
然后用以下参数创建 llm 对象:
llm = ChatOllama(
model="llama3.1",
base_url="http://localhost:11434"
)
此配置将连接运行在本地 11434 端口的 Ollama 实例。
结论
CrewAI 构建于强大的 LangChain 框架之上,通过专注于角色扮演场景,简化了多智能体系统的创建与管理,使各智能体能够有效协作,实现复杂目标。该框架灵活多变,能够集成包括网页搜索、数据分析和内容生成等多种工具,因而在不同应用场景中表现出极高的适用性。随着贡献者社区的不断壮大,CrewAI 有望成为 AI 开发领域的重要力量。