使用流程控制 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 框架概述

步骤 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:配置内容编写团队

现在,让我们修改为内容编写团队生成的 文件。我们将设置两个专门的智能体——一个作家和一个评审员——他们将协作创建高质量的指南内容。

  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 系统奠定了基础。以下是一些可以扩展此基本流程的方法

增强用户交互

您可以创建更具交互性的流程,包括

  • 用于输入和输出的 Web 界面
  • 实时进度更新
  • 交互式反馈和精炼循环
  • 多阶段用户交互

添加更多处理步骤

您可以为您的流程添加额外的步骤,用于

  • 在大纲创建前进行研究
  • 为插图生成图像
  • 为技术指南生成代码片段
  • 最终质量保证和事实核查

创建更复杂的流程

您可以实现更复杂的流程模式

  • 基于用户偏好或内容类型的条件分支
  • 独立部分的并行处理
  • 包含反馈的迭代精炼循环
  • 与外部 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 应用程序,通过结合程序控制和协作智能来解决复杂的多阶段问题。