跳转到主要内容

通过流程控制 AI 工作流

CrewAI 流程代表了 AI 编排的下一个层次——它将 AI 代理团队的协作能力与过程化编程的精确性和灵活性相结合。虽然团队擅长代理协作,但流程让你可以精细控制 AI 系统的不同组件如何以及何时进行交互。 在本指南中,我们将逐步创建一个强大的 CrewAI 流程,用于生成任何主题的综合学习指南。本教程将演示流程如何通过结合常规代码、直接 LLM 调用和基于团队的处理,提供对 AI 工作流的结构化、事件驱动的控制。

流程的强大之处

流程使您能够
  1. 结合不同的 AI 交互模式 - 将团队用于复杂的协作任务,将直接 LLM 调用用于简单操作,将常规代码用于程序逻辑
  2. 构建事件驱动系统 - 定义组件如何响应特定事件和数据变化
  3. 在组件之间保持状态 - 在应用程序的不同部分之间共享和转换数据
  4. 与外部系统集成 - 将您的 AI 工作流与数据库、API 和用户界面无缝连接
  5. 创建复杂的执行路径 - 设计条件分支、并行处理和动态工作流

您将构建和学习什么

通过本指南,您将
  1. 创建一个复杂的开箱即用内容生成系统,它结合了用户输入、AI 规划和多代理内容创建
  2. 编排系统不同组件之间的信息流
  3. 实现事件驱动架构,其中每个步骤都响应前一步骤的完成
  4. 为更复杂的 AI 应用程序奠定基础,您可以对其进行扩展和自定义
本指南创建者流程演示了可应用于创建更高级应用程序的基本模式,例如
  • 结合多个专业子系统的交互式 AI 助手
  • 具有 AI 增强转换的复杂数据处理管道
  • 与外部服务和 API 集成的自主代理
  • 具有人工参与过程的多阶段决策系统
让我们深入了解并构建你的第一个流程!

先决条件

开始之前,请确保您已
  1. 按照安装指南安装了 CrewAI
  2. 按照LLM 设置指南在您的环境中设置了 LLM API 密钥
  3. 对 Python 有基本了解

步骤 1:创建一个新的 CrewAI 流程项目

首先,让我们使用 CLI 创建一个新的 CrewAI 流程项目。此命令将设置一个包含所有必要的目录和模板文件的脚手架项目,用于您的流程。
crewai create flow guide_creator_flow
cd guide_creator_flow
这将生成一个具有流程所需基本结构的项目。
CrewAI Framework Overview

CrewAI 框架概述

步骤 2:了解项目结构

生成的项目具有以下结构。花点时间熟悉它,因为了解此结构将帮助您将来创建更复杂的流程。
guide_creator_flow/
├── .gitignore
├── pyproject.toml
├── README.md
├── .env
├── main.py
├── crews/
│   └── poem_crew/
│       ├── config/
│       │   ├── agents.yaml
│       │   └── tasks.yaml
│       └── poem_crew.py
└── tools/
    └── custom_tool.py
此结构为流程的不同组件提供了清晰的分离
  • main.py 文件中的主要流程逻辑
  • crews 目录中的专用团队
  • tools 目录中的自定义工具
我们将修改此结构以创建我们的指南创建者流程,它将编排生成综合学习指南的过程。

步骤 3:添加内容撰写团队

我们的流程将需要一个专门的团队来处理内容创建过程。让我们使用 CrewAI CLI 添加一个内容撰写团队
crewai flow add-crew content-crew
此命令会自动为您的团队创建必要的目录和模板文件。内容撰写团队将负责撰写和审阅我们指南的各个部分,并在由我们的主应用程序编排的整体流程中工作。

步骤 4:配置内容撰写团队

现在,让我们修改为内容撰写团队生成的D文件。我们将设置两个专门的代理——一个撰写者和一个审阅者——他们将协作创建高质量的指南内容。
  1. 首先,更新代理配置文件以定义我们的内容创建团队: 请记住将 llm 设置为您正在使用的提供商。
# src/guide_creator_flow/crews/content_crew/config/agents.yaml
content_writer:
  role: >
    Educational Content Writer
  goal: >
    Create engaging, informative content that thoroughly explains the assigned topic
    and provides valuable insights to the reader
  backstory: >
    You are a talented educational writer with expertise in creating clear, engaging
    content. You have a gift for explaining complex concepts in accessible language
    and organizing information in a way that helps readers build their understanding.
  llm: provider/model-id  # e.g. openai/gpt-4o, google/gemini-2.0-flash, anthropic/claude...

content_reviewer:
  role: >
    Educational Content Reviewer and Editor
  goal: >
    Ensure content is accurate, comprehensive, well-structured, and maintains
    consistency with previously written sections
  backstory: >
    You are a meticulous editor with years of experience reviewing educational
    content. You have an eye for detail, clarity, and coherence. You excel at
    improving content while maintaining the original author's voice and ensuring
    consistent quality across multiple sections.
  llm: provider/model-id  # e.g. openai/gpt-4o, google/gemini-2.0-flash, anthropic/claude...
这些代理定义建立了专门的角色和视角,将塑造我们的 AI 代理如何进行内容创建。请注意,每个代理都有不同的目的和专业知识。
  1. 接下来,更新任务配置文件以定义具体的撰写和审阅任务
# src/guide_creator_flow/crews/content_crew/config/tasks.yaml
write_section_task:
  description: >
    Write a comprehensive section on the topic: "{section_title}"

    Section description: {section_description}
    Target audience: {audience_level} level learners

    Your content should:
    1. Begin with a brief introduction to the section topic
    2. Explain all key concepts clearly with examples
    3. Include practical applications or exercises where appropriate
    4. End with a summary of key points
    5. Be approximately 500-800 words in length

    Format your content in Markdown with appropriate headings, lists, and emphasis.

    Previously written sections:
    {previous_sections}

    Make sure your content maintains consistency with previously written sections
    and builds upon concepts that have already been explained.
  expected_output: >
    A well-structured, comprehensive section in Markdown format that thoroughly
    explains the topic and is appropriate for the target audience.
  agent: content_writer

review_section_task:
  description: >
    Review and improve the following section on "{section_title}":

    {draft_content}

    Target audience: {audience_level} level learners

    Previously written sections:
    {previous_sections}

    Your review should:
    1. Fix any grammatical or spelling errors
    2. Improve clarity and readability
    3. Ensure content is comprehensive and accurate
    4. Verify consistency with previously written sections
    5. Enhance the structure and flow
    6. Add any missing key information

    Provide the improved version of the section in Markdown format.
  expected_output: >
    An improved, polished version of the section that maintains the original
    structure but enhances clarity, accuracy, and consistency.
  agent: content_reviewer
  context:
    - write_section_task
这些任务定义为我们的代理提供了详细说明,确保他们生成的内容符合我们的质量标准。请注意,审阅任务中的 context 参数如何创建一个工作流程,使审阅者能够访问撰写者的输出。
  1. 现在,更新团队实现文件以定义我们的代理和任务如何协同工作
# src/guide_creator_flow/crews/content_crew/content_crew.py
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai.agents.agent_builder.base_agent import BaseAgent
from typing import List

@CrewBase
class ContentCrew():
    """Content writing crew"""

    agents: List[BaseAgent]
    tasks: List[Task]

    @agent
    def content_writer(self) -> Agent:
        return Agent(
            config=self.agents_config['content_writer'], # type: ignore[index]
            verbose=True
        )

    @agent
    def content_reviewer(self) -> Agent:
        return Agent(
            config=self.agents_config['content_reviewer'], # type: ignore[index]
            verbose=True
        )

    @task
    def write_section_task(self) -> Task:
        return Task(
            config=self.tasks_config['write_section_task'] # type: ignore[index]
        )

    @task
    def review_section_task(self) -> Task:
        return Task(
            config=self.tasks_config['review_section_task'], # type: ignore[index]
            context=[self.write_section_task()]
        )

    @crew
    def crew(self) -> Crew:
        """Creates the content writing crew"""
        return Crew(
            agents=self.agents,
            tasks=self.tasks,
            process=Process.sequential,
            verbose=True,
        )
此团队定义建立了我们的代理和任务之间的关系,设置了一个顺序流程,其中内容撰写者创建草稿,然后审阅者改进它。虽然此团队可以独立运作,但在我们的流程中,它将作为更大系统的一部分进行编排。

步骤 5:创建流程

现在是激动人心的部分——创建将编排整个指南创建过程的流程。在这里,我们将常规 Python 代码、直接 LLM 调用和我们的内容创建团队组合成一个有凝聚力的系统。 我们的流程将:
  1. 获取用户输入的专题和受众级别
  2. 进行直接 LLM 调用以创建结构化的指南大纲
  3. 使用内容编写团队按顺序处理每个部分
  4. 将所有内容组合成最终的综合文档
让我们在 main.py 文件中创建我们的流程
#!/usr/bin/env python
import json
import os
from typing import List, Dict
from pydantic import BaseModel, Field
from crewai import LLM
from crewai.flow.flow import Flow, listen, start
from guide_creator_flow.crews.content_crew.content_crew import ContentCrew

# Define our models for structured data
class Section(BaseModel):
    title: str = Field(description="Title of the section")
    description: str = Field(description="Brief description of what the section should cover")

class GuideOutline(BaseModel):
    title: str = Field(description="Title of the guide")
    introduction: str = Field(description="Introduction to the topic")
    target_audience: str = Field(description="Description of the target audience")
    sections: List[Section] = Field(description="List of sections in the guide")
    conclusion: str = Field(description="Conclusion or summary of the guide")

# Define our flow state
class GuideCreatorState(BaseModel):
    topic: str = ""
    audience_level: str = ""
    guide_outline: GuideOutline = None
    sections_content: Dict[str, str] = {}

class GuideCreatorFlow(Flow[GuideCreatorState]):
    """Flow for creating a comprehensive guide on any topic"""

    @start()
    def get_user_input(self):
        """Get input from the user about the guide topic and audience"""
        print("\n=== Create Your Comprehensive Guide ===\n")

        # Get user input
        self.state.topic = input("What topic would you like to create a guide for? ")

        # Get audience level with validation
        while True:
            audience = input("Who is your target audience? (beginner/intermediate/advanced) ").lower()
            if audience in ["beginner", "intermediate", "advanced"]:
                self.state.audience_level = audience
                break
            print("Please enter 'beginner', 'intermediate', or 'advanced'")

        print(f"\nCreating a guide on {self.state.topic} for {self.state.audience_level} audience...\n")
        return self.state

    @listen(get_user_input)
    def create_guide_outline(self, state):
        """Create a structured outline for the guide using a direct LLM call"""
        print("Creating guide outline...")

        # Initialize the LLM
        llm = LLM(model="openai/gpt-4o-mini", response_format=GuideOutline)

        # Create the messages for the outline
        messages = [
            {"role": "system", "content": "You are a helpful assistant designed to output JSON."},
            {"role": "user", "content": f"""
            Create a detailed outline for a comprehensive guide on "{state.topic}" for {state.audience_level} level learners.

            The outline should include:
            1. A compelling title for the guide
            2. An introduction to the topic
            3. 4-6 main sections that cover the most important aspects of the topic
            4. A conclusion or summary

            For each section, provide a clear title and a brief description of what it should cover.
            """}
        ]

        # Make the LLM call with JSON response format
        response = llm.call(messages=messages)

        # Parse the JSON response
        outline_dict = json.loads(response)
        self.state.guide_outline = GuideOutline(**outline_dict)

        # Ensure output directory exists before saving
        os.makedirs("output", exist_ok=True)

        # Save the outline to a file
        with open("output/guide_outline.json", "w") as f:
            json.dump(outline_dict, f, indent=2)

        print(f"Guide outline created with {len(self.state.guide_outline.sections)} sections")
        return self.state.guide_outline

    @listen(create_guide_outline)
    def write_and_compile_guide(self, outline):
        """Write all sections and compile the guide"""
        print("Writing guide sections and compiling...")
        completed_sections = []

        # Process sections one by one to maintain context flow
        for section in outline.sections:
            print(f"Processing section: {section.title}")

            # Build context from previous sections
            previous_sections_text = ""
            if completed_sections:
                previous_sections_text = "# Previously Written Sections\n\n"
                for title in completed_sections:
                    previous_sections_text += f"## {title}\n\n"
                    previous_sections_text += self.state.sections_content.get(title, "") + "\n\n"
            else:
                previous_sections_text = "No previous sections written yet."

            # Run the content crew for this section
            result = ContentCrew().crew().kickoff(inputs={
                "section_title": section.title,
                "section_description": section.description,
                "audience_level": self.state.audience_level,
                "previous_sections": previous_sections_text,
                "draft_content": ""
            })

            # Store the content
            self.state.sections_content[section.title] = result.raw
            completed_sections.append(section.title)
            print(f"Section completed: {section.title}")

        # Compile the final guide
        guide_content = f"# {outline.title}\n\n"
        guide_content += f"## Introduction\n\n{outline.introduction}\n\n"

        # Add each section in order
        for section in outline.sections:
            section_content = self.state.sections_content.get(section.title, "")
            guide_content += f"\n\n{section_content}\n\n"

        # Add conclusion
        guide_content += f"## Conclusion\n\n{outline.conclusion}\n\n"

        # Save the guide
        with open("output/complete_guide.md", "w") as f:
            f.write(guide_content)

        print("\nComplete guide compiled and saved to output/complete_guide.md")
        return "Guide creation completed successfully"

def kickoff():
    """Run the guide creator flow"""
    GuideCreatorFlow().kickoff()
    print("\n=== Flow Complete ===")
    print("Your comprehensive guide is ready in the output directory.")
    print("Open output/complete_guide.md to view it.")

def plot():
    """Generate a visualization of the flow"""
    flow = GuideCreatorFlow()
    flow.plot("guide_creator_flow")
    print("Flow visualization saved to guide_creator_flow.html")

if __name__ == "__main__":
    kickoff()
让我们分析一下这个流程中发生了什么
  1. 我们定义了 Pydantic 模型用于结构化数据,确保类型安全和清晰的数据表示
  2. 我们创建了一个状态类来维护流程不同步骤中的数据
  3. 我们实现了三个主要的流程步骤
    • 使用 @start() 装饰器获取用户输入
    • 通过直接 LLM 调用创建指南大纲
    • 使用我们的内容团队处理各个部分
  4. 我们使用 @listen() 装饰器来建立步骤之间的事件驱动关系
这就是流程的强大之处——将不同类型的处理(用户交互、直接 LLM 调用、基于团队的任务)组合成一个连贯的、事件驱动的系统。

步骤 6:设置您的环境变量

在项目根目录中创建一个 .env 文件,其中包含您的 API 密钥。有关配置提供商的详细信息,请参阅LLM 设置指南
.env
OPENAI_API_KEY=your_openai_api_key
# or
GEMINI_API_KEY=your_gemini_api_key
# or
ANTHROPIC_API_KEY=your_anthropic_api_key

步骤 7:安装依赖项

安装所需的依赖项
crewai install

步骤 8:运行您的流程

现在是时候让你的流程行动起来了!使用 CrewAI CLI 运行它
crewai flow kickoff
当您运行此命令时,您将看到您的流程开始运行
  1. 它会提示您输入主题和受众级别
  2. 它将为您的指南创建一个结构化大纲
  3. 它将处理每个部分,内容撰写者和审阅者将对每个部分进行协作
  4. 最后,它将所有内容编译成一个综合指南
这展示了流程协调涉及多个组件(包括 AI 和非 AI)的复杂过程的强大功能。

步骤 9:可视化您的流程

流程的强大功能之一是能够可视化其结构
crewai flow plot
这将创建一个 HTML 文件,显示您的流程结构,包括不同步骤之间的关系以及它们之间流动的数据。这种可视化对于理解和调试复杂的流程非常有价值。

步骤 10:查看输出

流程完成后,您将在 output 目录中找到两个文件
  1. guide_outline.json: 包含指南的结构化大纲
  2. complete_guide.md: 包含所有部分的综合指南
花点时间查看这些文件,并欣赏您所构建的一切——一个结合了用户输入、直接 AI 交互和协作代理工作以生成复杂、高质量输出的系统。

可能性的艺术:超越您的第一个流程

您在本指南中学到的知识为创建更复杂的 AI 系统奠定了基础。以下是一些可以扩展此基本流程的方法

增强用户交互

您可以创建更具交互性的流程,例如:
  • 用于输入和输出的网页界面
  • 实时进度更新
  • 交互式反馈和优化循环
  • 多阶段用户交互

添加更多处理步骤

您可以扩展您的流程,增加以下额外步骤:
  • 大纲创建前的研究
  • 插图图像生成
  • 技术指南的代码片段生成
  • 最终质量保证和事实核查

创建更复杂的流程

您可以实现更复杂的流模式
  • 基于用户偏好或内容类型的条件分支
  • 独立部分的并行处理
  • 带有反馈的迭代细化循环
  • 与外部 API 和服务的集成

应用于不同领域

同样的模式可以应用于创建以下流程:
  • 交互式故事讲述:根据用户输入创建个性化故事
  • 商业智能:处理数据、生成洞察并创建报告
  • 产品开发:促进构思、设计和规划
  • 教育系统:创建个性化学习体验

演示的关键特性

本指南创建者流程演示了 CrewAI 的几个强大功能
  1. 用户交互:流程直接从用户收集输入
  2. 直接 LLM 调用:使用 LLM 类进行高效、单一用途的 AI 交互
  3. 使用 Pydantic 的结构化数据:使用 Pydantic 模型确保类型安全
  4. 带有上下文的顺序处理:按顺序编写部分,提供前面部分作为上下文
  5. 多代理团队:利用专业代理(撰写者和审阅者)进行内容创建
  6. 状态管理:在流程的不同步骤中保持状态
  7. 事件驱动架构:使用 @listen 装饰器响应事件

理解流程结构

让我们分解流程的关键组件,以帮助您了解如何构建自己的流程

1. 直接 LLM 调用

当您需要简单、结构化的响应时,流程允许您直接调用语言模型
llm = LLM(
    model="model-id-here",  # gpt-4o, gemini-2.0-flash, anthropic/claude...
    response_format=GuideOutline
)
response = llm.call(messages=messages)
当您需要特定的结构化输出时,这比使用团队更高效。

2. 事件驱动架构

流程使用装饰器来建立组件之间的关系
@start()
def get_user_input(self):
    # First step in the flow
    # ...

@listen(get_user_input)
def create_guide_outline(self, state):
    # This runs when get_user_input completes
    # ...
这为您的应用程序创建了一个清晰、声明性的结构。

3. 状态管理

流程在步骤之间保持状态,使得数据共享变得容易
class GuideCreatorState(BaseModel):
    topic: str = ""
    audience_level: str = ""
    guide_outline: GuideOutline = None
    sections_content: Dict[str, str] = {}
这提供了一种类型安全的方式来跟踪和转换整个流程中的数据。

4. 团队集成

流程可以与团队无缝集成,以完成复杂的协作任务
result = ContentCrew().crew().kickoff(inputs={
    "section_title": section.title,
    # ...
})
这使您能够为应用程序的每个部分使用正确的工具——对于简单任务使用直接 LLM 调用,对于复杂协作使用团队。

后续步骤

现在您已经构建了第一个流程,您可以
  1. 尝试更复杂的流程结构和模式
  2. 尝试使用 @router() 在流程中创建条件分支
  3. 探索 and_or_ 函数以实现更复杂的并行执行
  4. 将您的流程连接到外部 API、数据库或用户界面
  5. 在一个流程中组合多个专业团队
恭喜!您已成功构建了您的第一个 CrewAI 流程,它结合了常规代码、直接 LLM 调用和基于团队的处理来创建综合指南。这些基本技能使您能够创建日益复杂的 AI 应用程序,通过程序控制和协作智能的结合来解决复杂的多阶段问题。