跳转到主要内容

理解决策框架

在使用 CrewAI 构建 AI 应用程序时,您将做出的最重要的决策之一是为您的特定用例选择正确的方法。您应该使用 Crew 吗?Flow 吗?还是两者的结合?本指南将帮助您评估需求并做出明智的架构决策。 这个决策的核心是理解应用程序中复杂性精度之间的关系:
Complexity vs. Precision Matrix

CrewAI 应用程序的复杂性与精度矩阵

该矩阵有助于形象化地展示不同方法如何与变化的复杂性和精度要求相对应。让我们来探讨每个象限的含义以及它如何指导您的架构选择。

复杂性-精度矩阵解析

什么是复杂性?

在 CrewAI 应用程序的背景下,复杂性指的是:
  • 所需的不同步骤或操作的数量
  • 需要执行的任务的多样性
  • 不同组件之间的相互依赖性
  • 对条件逻辑和分支的需求
  • 整体工作流程的复杂程度

什么是精度?

在此背景下,精度指的是:
  • 最终输出所需的准确性
  • 对结构化、可预测结果的需求
  • 可复现性的重要程度
  • 对每一步所需的控制水平
  • 对输出变化的容忍度

四个象限

1. 低复杂性,低精度

特点
  • 简单、直接的任务
  • 对输出的一些变化有容忍度
  • 步骤数量有限
  • 创意或探索性应用
推荐方法: 具有最少代理的简单 Crews 用例示例:
  • 基础内容生成
  • 创意头脑风暴
  • 简单的摘要任务
  • 创意写作辅助

2. 低复杂性,高精度

特点
  • 需要精确、结构化输出的简单工作流
  • 需要可复现的结果
  • 步骤有限但精度要求高
  • 通常涉及数据处理或转换
推荐方法: 直接调用 LLM 的 Flows 或具有结构化输出的简单 Crews 用例示例:
  • 数据提取和转换
  • 表单填写和验证
  • 结构化内容生成(JSON, XML)
  • 简单的分类任务

3. 高复杂性,低精度

特点
  • 包含多个步骤的多阶段过程
  • 创意或探索性输出
  • 组件间的复杂交互
  • 对最终结果的变化有容忍度
推荐方法: 拥有多个专业代理的复杂 Crews 用例示例:
  • 研究与分析
  • 内容创作流程
  • 探索性数据分析
  • 创造性问题解决

4. 高复杂性,高精度

特点
  • 需要结构化输出的复杂工作流
  • 多个相互依赖的步骤,具有严格的准确性要求
  • 既需要复杂的处理,也需要精确的结果
  • 通常是任务关键型应用
推荐方法: 编排多个 Crews 并带有验证步骤的 Flows 用例示例:
  • 企业决策支持系统
  • 复杂数据处理流程
  • 多阶段文档处理
  • 受监管行业的应用

在 Crews 和 Flows 之间进行选择

何时选择 Crews

Crews 在以下情况下是理想选择:
  1. 您需要协作智能 - 多个具有不同专业领域的代理需要协同工作
  2. 问题需要涌现式思维 - 解决方案能从不同视角和方法中受益
  3. 任务主要是创意性或分析性的 - 工作涉及研究、内容创作或分析
  4. 您更看重适应性而非严格的结构 - 工作流可以从代理的自主性中受益
  5. 输出格式可以有一定的灵活性 - 可以接受输出结构的一些变化
# Example: Research Crew for market analysis
from crewai import Agent, Crew, Process, Task

# Create specialized agents
researcher = Agent(
    role="Market Research Specialist",
    goal="Find comprehensive market data on emerging technologies",
    backstory="You are an expert at discovering market trends and gathering data."
)

analyst = Agent(
    role="Market Analyst",
    goal="Analyze market data and identify key opportunities",
    backstory="You excel at interpreting market data and spotting valuable insights."
)

# Define their tasks
research_task = Task(
    description="Research the current market landscape for AI-powered healthcare solutions",
    expected_output="Comprehensive market data including key players, market size, and growth trends",
    agent=researcher
)

analysis_task = Task(
    description="Analyze the market data and identify the top 3 investment opportunities",
    expected_output="Analysis report with 3 recommended investment opportunities and rationale",
    agent=analyst,
    context=[research_task]
)

# Create the crew
market_analysis_crew = Crew(
    agents=[researcher, analyst],
    tasks=[research_task, analysis_task],
    process=Process.sequential,
    verbose=True
)

# Run the crew
result = market_analysis_crew.kickoff()

何时选择 Flows

Flows 在以下情况下是理想选择:
  1. 您需要精确控制执行过程 - 工作流需要精确的顺序和状态管理
  2. 应用程序有复杂的状态要求 - 您需要在多个步骤中维护和转换状态
  3. 您需要结构化、可预测的输出 - 应用程序需要一致的、格式化的结果
  4. 工作流涉及条件逻辑 - 需要根据中间结果采取不同的路径
  5. 您需要将 AI 与程序化代码结合 - 解决方案既需要 AI 能力也需要传统编程
# Example: Customer Support Flow with structured processing
from crewai.flow.flow import Flow, listen, router, start
from pydantic import BaseModel
from typing import List, Dict

# Define structured state
class SupportTicketState(BaseModel):
    ticket_id: str = ""
    customer_name: str = ""
    issue_description: str = ""
    category: str = ""
    priority: str = "medium"
    resolution: str = ""
    satisfaction_score: int = 0

class CustomerSupportFlow(Flow[SupportTicketState]):
    @start()
    def receive_ticket(self):
        # In a real app, this might come from an API
        self.state.ticket_id = "TKT-12345"
        self.state.customer_name = "Alex Johnson"
        self.state.issue_description = "Unable to access premium features after payment"
        return "Ticket received"

    @listen(receive_ticket)
    def categorize_ticket(self, _):
        # Use a direct LLM call for categorization
        from crewai import LLM
        llm = LLM(model="openai/gpt-4o-mini")

        prompt = f"""
        Categorize the following customer support issue into one of these categories:
        - Billing
        - Account Access
        - Technical Issue
        - Feature Request
        - Other

        Issue: {self.state.issue_description}

        Return only the category name.
        """

        self.state.category = llm.call(prompt).strip()
        return self.state.category

    @router(categorize_ticket)
    def route_by_category(self, category):
        # Route to different handlers based on category
        return category.lower().replace(" ", "_")

    @listen("billing")
    def handle_billing_issue(self):
        # Handle billing-specific logic
        self.state.priority = "high"
        # More billing-specific processing...
        return "Billing issue handled"

    @listen("account_access")
    def handle_access_issue(self):
        # Handle access-specific logic
        self.state.priority = "high"
        # More access-specific processing...
        return "Access issue handled"

    # Additional category handlers...

    @listen("billing", "account_access", "technical_issue", "feature_request", "other")
    def resolve_ticket(self, resolution_info):
        # Final resolution step
        self.state.resolution = f"Issue resolved: {resolution_info}"
        return self.state.resolution

# Run the flow
support_flow = CustomerSupportFlow()
result = support_flow.kickoff()

何时结合使用 Crews 和 Flows

最复杂的应用程序通常会从结合使用 Crews 和 Flows 中受益:
  1. 复杂的多阶段过程 - 使用 Flows 来编排整个过程,使用 Crews 来处理复杂的子任务
  2. 既需要创造力又需要结构的应用 - 使用 Crews 进行创意任务,使用 Flows 进行结构化处理
  3. 企业级 AI 应用 - 使用 Flows 管理状态和流程,同时利用 Crews 进行专业工作
# Example: Content Production Pipeline combining Crews and Flows
from crewai.flow.flow import Flow, listen, start
from crewai import Agent, Crew, Process, Task
from pydantic import BaseModel
from typing import List, Dict

class ContentState(BaseModel):
    topic: str = ""
    target_audience: str = ""
    content_type: str = ""
    outline: Dict = {}
    draft_content: str = ""
    final_content: str = ""
    seo_score: int = 0

class ContentProductionFlow(Flow[ContentState]):
    @start()
    def initialize_project(self):
        # Set initial parameters
        self.state.topic = "Sustainable Investing"
        self.state.target_audience = "Millennial Investors"
        self.state.content_type = "Blog Post"
        return "Project initialized"

    @listen(initialize_project)
    def create_outline(self, _):
        # Use a research crew to create an outline
        researcher = Agent(
            role="Content Researcher",
            goal=f"Research {self.state.topic} for {self.state.target_audience}",
            backstory="You are an expert researcher with deep knowledge of content creation."
        )

        outliner = Agent(
            role="Content Strategist",
            goal=f"Create an engaging outline for a {self.state.content_type}",
            backstory="You excel at structuring content for maximum engagement."
        )

        research_task = Task(
            description=f"Research {self.state.topic} focusing on what would interest {self.state.target_audience}",
            expected_output="Comprehensive research notes with key points and statistics",
            agent=researcher
        )

        outline_task = Task(
            description=f"Create an outline for a {self.state.content_type} about {self.state.topic}",
            expected_output="Detailed content outline with sections and key points",
            agent=outliner,
            context=[research_task]
        )

        outline_crew = Crew(
            agents=[researcher, outliner],
            tasks=[research_task, outline_task],
            process=Process.sequential,
            verbose=True
        )

        # Run the crew and store the result
        result = outline_crew.kickoff()

        # Parse the outline (in a real app, you might use a more robust parsing approach)
        import json
        try:
            self.state.outline = json.loads(result.raw)
        except:
            # Fallback if not valid JSON
            self.state.outline = {"sections": result.raw}

        return "Outline created"

    @listen(create_outline)
    def write_content(self, _):
        # Use a writing crew to create the content
        writer = Agent(
            role="Content Writer",
            goal=f"Write engaging content for {self.state.target_audience}",
            backstory="You are a skilled writer who creates compelling content."
        )

        editor = Agent(
            role="Content Editor",
            goal="Ensure content is polished, accurate, and engaging",
            backstory="You have a keen eye for detail and a talent for improving content."
        )

        writing_task = Task(
            description=f"Write a {self.state.content_type} about {self.state.topic} following this outline: {self.state.outline}",
            expected_output="Complete draft content in markdown format",
            agent=writer
        )

        editing_task = Task(
            description="Edit and improve the draft content for clarity, engagement, and accuracy",
            expected_output="Polished final content in markdown format",
            agent=editor,
            context=[writing_task]
        )

        writing_crew = Crew(
            agents=[writer, editor],
            tasks=[writing_task, editing_task],
            process=Process.sequential,
            verbose=True
        )

        # Run the crew and store the result
        result = writing_crew.kickoff()
        self.state.final_content = result.raw

        return "Content created"

    @listen(write_content)
    def optimize_for_seo(self, _):
        # Use a direct LLM call for SEO optimization
        from crewai import LLM
        llm = LLM(model="openai/gpt-4o-mini")

        prompt = f"""
        Analyze this content for SEO effectiveness for the keyword "{self.state.topic}".
        Rate it on a scale of 1-100 and provide 3 specific recommendations for improvement.

        Content: {self.state.final_content[:1000]}... (truncated for brevity)

        Format your response as JSON with the following structure:
        {{
            "score": 85,
            "recommendations": [
                "Recommendation 1",
                "Recommendation 2",
                "Recommendation 3"
            ]
        }}
        """

        seo_analysis = llm.call(prompt)

        # Parse the SEO analysis
        import json
        try:
            analysis = json.loads(seo_analysis)
            self.state.seo_score = analysis.get("score", 0)
            return analysis
        except:
            self.state.seo_score = 50
            return {"score": 50, "recommendations": ["Unable to parse SEO analysis"]}

# Run the flow
content_flow = ContentProductionFlow()
result = content_flow.kickoff()

实用评估框架

要为您的特定用例确定正确的方法,请遵循以下分步评估框架:

步骤 1:评估复杂性

通过考虑以下因素,在 1-10 的范围内评估您的应用程序的复杂性:
  1. 步骤数量:需要多少个不同的操作?
    • 1-3 步:低复杂性 (1-3)
    • 4-7 步:中等复杂性 (4-7)
    • 8 步以上:高复杂性 (8-10)
  2. 相互依赖性:不同部分之间的关联程度如何?
    • 很少依赖:低复杂性 (1-3)
    • 一些依赖:中等复杂性 (4-7)
    • 许多复杂依赖:高复杂性 (8-10)
  3. 条件逻辑:需要多少分支和决策?
    • 线性过程:低复杂性 (1-3)
    • 一些分支:中等复杂性 (4-7)
    • 复杂的决策树:高复杂性 (8-10)
  4. 领域知识:所需知识的专业化程度如何?
    • 通用知识:低复杂性 (1-3)
    • 一些专业知识:中等复杂性 (4-7)
    • 多个领域的深度专业知识:高复杂性 (8-10)
计算您的平均分以确定总体复杂性。

步骤 2:评估精度要求

通过考虑以下因素,在 1-10 的范围内评估您的精度要求:
  1. 输出结构:输出必须有多结构化?
    • 自由格式文本:低精度 (1-3)
    • 半结构化:中等精度 (4-7)
    • 严格格式化(JSON, XML):高精度 (8-10)
  2. 准确性需求:事实准确性有多重要?
    • 创意内容:低精度 (1-3)
    • 信息性内容:中等精度 (4-7)
    • 关键信息:高精度 (8-10)
  3. 可复现性:每次运行结果必须有多一致?
    • 可接受变化:低精度 (1-3)
    • 需要一定一致性:中等精度 (4-7)
    • 需要完全可复现:高精度 (8-10)
  4. 错误容忍度:错误会产生什么影响?
    • 低影响:低精度 (1-3)
    • 中等影响:中等精度 (4-7)
    • 高影响:高精度 (8-10)
计算您的平均分以确定总体精度要求。

步骤 3:映射到矩阵

将您的复杂性和精度分数绘制在矩阵上:
  • 低复杂性 (1-4),低精度 (1-4):简单的 Crews
  • 低复杂性 (1-4),高精度 (5-10):直接调用 LLM 的 Flows
  • 高复杂性 (5-10),低精度 (1-4):复杂的 Crews
  • 高复杂性 (5-10),高精度 (5-10):编排 Crews 的 Flows

步骤 4:考虑其他因素

除了复杂性和精度,还要考虑:
  1. 开发时间:Crews 通常能更快地构建原型
  2. 维护需求:Flows 提供更好的长期可维护性
  3. 团队专业知识:考虑您的团队对不同方法的熟悉程度
  4. 可扩展性要求:对于复杂应用,Flows 通常扩展性更好
  5. 集成需求:考虑解决方案如何与现有系统集成

结论

选择 Crews 还是 Flows——或将它们结合使用——是一项关键的架构决策,它会影响您的 CrewAI 应用程序的有效性、可维护性和可扩展性。通过从复杂性和精度两个维度评估您的用例,您可以做出符合具体需求的明智决策。 请记住,最佳方法通常会随着应用程序的成熟而演变。从能满足您需求的最简单的解决方案开始,并准备好随着经验的积累和需求的明晰化来完善您的架构。
现在您有了一个框架,可以用来评估 CrewAI 的用例,并根据复杂性和精度的要求选择正确的方法。这将帮助您构建更有效、可维护和可扩展的 AI 应用程序。

后续步骤