【智能体漫游】AI应用开发的“四大门派“,你看懂了吗?

0 阅读12分钟

看完这篇,你再也不会把Workflow和Agent搞混了


开篇:AI圈的第一大悬案

image.png 作为一个在AI圈摸爬滚打多年的老兵,我见过最离谱的事情是什么?

是产品经理和研发吵架,吵了半天发现:俩人说的"Agent"根本不是一个东西。

产品经理说的Agent:能自主决策、能调用工具、能自己完成任务的智能体。

研发说的Agent:一个工作流里串了三个Prompt节点,号称"智能客服Agent"。

然后产品经理急了:"你这个Workflow跟Agent有什么关系?"

研发也急了:"我这就是Agent啊!我调用了大模型!"

啪!巴别塔塌了。

今天这篇文章,就是来给你们"统一度量衡"的。看完之后,保证你对AI应用开发的四种架构范式门儿清,再也不会被忽悠。


一、先搞清楚:我们为什么要学"设计模式"?

先问一个问题:你学设计模式是为了什么?

image.png

是为了面试能背出来?"单例模式、工厂模式、观察者模式"念得滚瓜烂熟,结果实际写代码的时候还是CRUD一把梭?

错!设计模式是为了让你"少踩坑"。

前人花了几十年时间,总结出一套"特定场景下的最佳实践"。当你遇到相似的问题时,直接套用这些已经被验证的成熟方案,就能事半功倍。

在AI应用开发领域,这套逻辑同样成立。

可惜的是,很多AI开发者还处于"野路子"阶段。拿到一个需求,上来就问:"用LangChain还是CrewAI?"、"要不要上RAG?"

兄弟,你连问题是什么都没搞清楚,上什么框架?

真正的架构师思维是:先分析业务本质,再选择合适的范式,最后才是具体框架和工具。


二、AI应用开发的"四大门派"

让我们先上一张图,建立整体认知:

flowchart TD
    subgraph AI应用四大门派
        A["🧘 Prompt派<br/>一切交给模型"] 
        B["🏭 Workflow派<br/>代码预先编排"]
        C["🤖 Agent派<br/>模型决定下一步"]
        D["👥 Multi-Agent派<br/>组织的力量"]
    end
    
    A -->|"自主性低"| A1["复杂度:低"]
    B -->|"自主性中"| B1["复杂度:中"]
    C -->|"自主性高"| C1["复杂度:高"]
    D -->|"自主性最高"| D1["复杂度:最高"]
    
    style A fill:#e1f5fe,color:#000
    style B fill:#fff3e0,color:#000
    style C fill:#f3e5f5,color:#000
    style D fill:#e8f5e9,color:#000

一句话总结:

  • Prompt派:你说什么,模型做什么,简单直接
  • Workflow派:我设计好流程,模型按部就班执行
  • Agent派:我只告诉你目标,模型自己想办法
  • Multi-Agent派:我一个不够用,那就一群来干!

接下来,我们用"生成竞品分析报告"这个任务,带你逐一拆解每个门派。


三、第一派:Prompt Engineering(提示词工程)

image.png 核心理念:一切交给模型。

这是最简单的模式,也是大多数人的起点。

flowchart LR
    A["📄 竞品数据"] --> B["🤖 大模型"]
    C["📋 任务要求"] --> B
    B --> D["📊 分析报告"]

什么是Prompt Engineering?

简单来说,就是你构建一个"超级Prompt",把所有东西都塞进去,然后让模型一次性给你输出结果。

核心工作就一件事:写好那个Prompt。

代码示例

# ============================================
# Prompt Engineering 的"精髓"
# 就是把你想说的全塞进一个Prompt里
# 然后祈祷模型能理解 😅
# ============================================

class PromptEngineer:
    """
    提示词工程师
    
    工作内容:
    1. 写系统提示词(定义角色)
    2. 写上下文(塞数据)
    3. 写任务要求(告诉模型要什么)
    
    理想场景:
    - 数据量不大(<3万字)
    - 任务简单明确
    - 输出格式固定
    """
    
    def generate_report(self, data: str, requirement: str) -> str:
        """
        生成报告
        
        参数说明:
        - data: 竞品数据(静态文本)
        - requirement: 你的要求(目标+格式+风格)
        
        典型用法:
        """
        # 构建"超级Prompt"
        # 把数据、要求、格式全塞进去
        prompt = f"""
# 系统提示:定义你的角色
你是一位资深行业分析师,擅长从数据中提炼洞察。

# 背景数据
{data}

# 任务要求
{requirement}

# 输出格式
请按以下格式输出:
1. 竞品概览
2. 核心洞察
3. 趋势分析
4. 建议
"""
        
        # 调用模型,一次性输出
        return self.model.complete(prompt)

Prompt派的"三大原罪"

罪状症状后果
上下文膨胀数据一多,模型就开始"选择性失忆"关键信息被忽略
效果不稳定换个大模型,Prompt要重写维护成本爆炸
无法应对意外用户问了个Prompt里没覆盖的系统直接崩溃

什么时候用Prompt派?

简单场景,数据量可控,边界明确。比如:

  • 写一封邮件润色
  • 翻译一段文字
  • 按模板生成文案

什么时候不用Prompt派?

长链路任务、数据量大、边界不确定的任务。硬上的结果就是:Debug到怀疑人生。


四、第二派:Workflow / Chain(代码驱动的流水线)

image.png 核心理念:预先编排,稳定执行。

这是目前工业界落地最多的模式。扣子(Coze)、Dify 这些平台,本质上都是Workflow模式。

什么是Workflow?

简单来说,就是你设计好流程图,模型按照你设计的步骤一步一步执行。

核心理念:程序员决定下一步,模型只是在特定节点"打工"。

flowchart TB
    A["📥 输入"] --> B["🔍 爬虫"]
    B --> C["🧹 清洗"]
    C --> D["🧠 LLM分析"]
    D --> E["📝 LLM总结"]
    E --> F["✅ LLM审核"]
    F --> G["💾 输出PDF"]
    
    style A fill:#e1f5fe
    style B fill:#fff8e1
    style C fill:#fff8e1
    style D fill:#e8f5e9
    style E fill:#e8f5e9
    style F fill:#e8f5e9
    style G fill:#fce4ec

代码示例

# ============================================
# Workflow 模式:程序员是导演,模型是演员
# ============================================

class WorkflowEngine:
    """
    工作流引擎
    
    核心思路:
    1. 定义好处理节点(节点是固定的)
    2. 定义好执行顺序(顺序是硬编码的)
    3. 模型只在特定节点被调用
    
    优势:
    - 极其稳定(代码写死了,不会乱来)
    - 易于调试(哪个节点出问题,一目了然)
    - 适合工程落地(生产环境首选)
    
    局限:
    - 不灵活(遇到没设计过的场景就抓瞎)
    - 枚举成本高(异常分支太多,代码写不下)
    """
    
    def __init__(self):
        # 定义处理流程(顺序是死的)
        self.nodes = [
            CrawlerNode(),      # 节点1:爬虫
            CleanerNode(),      # 节点2:清洗
            AnalyzerNode(),     # 节点3:分析(调用LLM)
            SummarizerNode(),   # 节点4:总结(调用LLM)
            ReviewerNode(),     # 节点5:审核(调用LLM)
            WriterNode()        # 节点6:输出
        ]
    
    def run(self, input_data):
        """
        按顺序执行
        
        执行逻辑:
        1. 从节点1开始
        2. 每个节点处理后传给下一个
        3. 直到最后一个节点输出结果
        """
        result = input_data
        for node in self.nodes:
            result = node.execute(result)
        return result

# 节点基类
class WorkflowNode:
    """
    每个节点都要实现 execute 方法
    输入 -> 处理 -> 输出
    """
    
    def execute(self, input_data):
        # 子类实现具体逻辑
        pass

Workflow vs Agent:傻傻分不清?

很多人搞不清Workflow和Agent的区别。我来给你画个重点:

flowchart LR
    subgraph Workflow
        A["程序员"] -->|"决定|下一步"| B["执行节点"]
    end
    
    subgraph Agent
        C["程序员"] -->|"给目标|工具"| D["模型自主"]
        D -->|"自己决定|下一步"| E["执行动作"]
    end
    
    style A fill:#fff3e0
    style D fill:#e8f5e9

判断标准:

  • Workflow:LLM只是决定"调什么工具",整个流程是程序员设计好的
  • Agent:LLM决定"下一步做什么",模型有真正的自主决策权

一个经典的误区:

"我用扣子搭了一个工作流,里面有LLM节点,这算不算Agent?"

不算。 你这个叫Workflow,不叫Agent。因为下一步做什么,是你设计好的,不是模型决定的。


五、第三派:Single Agent(五脏俱全的数字生命)

image.png 核心理念:模型决定下一步。

这是真正让程序员"失业"的模式——不是让你失业,而是让你从"写代码"变成"设计系统"。

什么是Agent?

简单来说,就是你给模型一个目标,加上工具箱和记忆,然后模型自己想办法完成。

核心变化:从"程序员控制流程"变成"模型自主决策"。

flowchart TB
    A["🎯 目标"] --> B["🧠 规划器"]
    B -->|"调用工具"| C["🔧 工具箱"]
    B -->|"查询记忆"| D["💾 记忆"]
    C -->|"结果"| E["👁️ 观察"]
    E --> B
    D -->|"历史"| B

ReAct范式:Agent的"大脑"

ReAct = Reasoning + Acting,即"思考 + 行动"。

这是目前最主流的Agent实现范式。让我用图解的方式解释:

flowchart TB
    subgraph ReAct循环
        A["🧠 Thought<br/>思考"] -->|"下一步行动"| B["🎬 Action<br/>执行"]
        B -->|"观察结果"| C["👁️ Observation<br/>观察"]
        C -->|"更新推理"| A
    end
    
    A -."|反思|改进".-> A

循环执行,直到任务完成。

ReAct的数学公式

这是本文的核心公式,看懂了这个,你就真正理解了Agent

初始化:M0,t1循环直到完成:τt=LLM(format(Mt1))// 生成思考at={parse_action(τt),如果是工具调用final_answer(τt),否则输出答案ot={ToolExec(at),执行工具null,如果是最终答案Mt=Mt1{(τt,at,ot)}// 更新记忆tt+1\begin{aligned} 初始化: & \quad M_0 \leftarrow \emptyset, \quad t \leftarrow 1 \\ 循环直到完成: & \\ & \tau_t = LLM(format(M_{t-1})) \quad \text{// 生成思考} \\ & a_t = \begin{cases} parse\_action(\tau_t), & \text{如果是工具调用} \\ final\_answer(\tau_t), & \text{否则输出答案} \end{cases} \\ & o_t = \begin{cases} ToolExec(a_t), & \text{执行工具} \\ null, & \text{如果是最终答案} \end{cases} \\ & M_t = M_{t-1} \cup \{(\tau_t, a_t, o_t)\} \quad \text{// 更新记忆} \\ & t \leftarrow t + 1 \end{aligned}

公式变量详解:

符号定义类比
MtM_t时刻t的完整记忆Agent的"经验簿"
τt\tau_t时刻t的推理/思考Agent的"脑子"
ata_t时刻t要执行的动作Agent的"决定"
oto_t时刻t的观察结果Agent的"收获"
LLM()LLM()大语言模型Agent的"大脑"
parse_action()parse\_action()解析动作类型判断要做什么
ToolExec()ToolExec()执行工具真正干活

代码实现

# ============================================
# ReAct Agent:从零实现一个会"思考"的Agent
# ====================================

class ReActAgent:
    """
    ReAct智能体
    
    核心理念:
    - 思考(Reasoning):我当前知道什么,下一步该做什么?
    - 行动(Acting):执行工具,获取结果
    - 观察(Observation):根据结果更新认知
    
    循环执行,直到输出最终答案
    """
    
    def __init__(self, model, tools: dict, max_loops: int = 10):
        """
        初始化
        
        参数:
            model: 大语言模型(GPT-4、Claude等)
            tools: 可用工具字典 {工具名: 工具函数}
            max_loops: 最大循环次数(防止无限循环)
        """
        self.model = model
        self.tools = tools
        self.max_loops = max_loops
        
        # 记忆:存储(思考, 动作, 结果)元组
        self.memory = []
    
    def run(self, task: str) -> str:
        """
        执行任务
        
        执行流程:
        1. 根据记忆生成提示词
        2. 调用LLM获取思考
        3. 解析动作类型
        4. 执行工具或输出答案
        5. 更新记忆
        6. 重复直到完成
        """
        loop_count = 0
        
        while loop_count < self.max_loops:
            # Step 1: 生成思考
            # 这是公式中 τ_t = LLM(format(M_{t-1}))
            prompt = self._build_prompt(task)
            thought = self.model.think(prompt)
            
            # Step 2: 解析动作
            # 这是公式中 a_t = parse_action(τ_t)
            action_type, action_data = self._parse_action(thought)
            
            # 如果是最终答案,直接返回
            if action_type == "final_answer":
                return action_data
            
            # 如果是工具调用,执行工具
            # 这是公式中 o_t = ToolExec(a_t)
            observation = self._execute_tool(action_data)
            
            # Step 3: 更新记忆
            # 这是公式中 M_t = M_{t-1} ∪ {(τ_t, a_t, o_t)}
            self.memory.append({
                "thought": thought,
                "action": action_data,
                "observation": observation
            })
            
            loop_count += 1
        
        return "超出最大循环次数,任务失败"
    
    def _build_prompt(self, task: str) -> str:
        """
        构建提示词
        
        提示词结构:
        1. 原始任务
        2. 可用工具
        3. 历史记录(思考-动作-结果)
        4. 输出格式要求
        """
        prompt_parts = [f"任务:{task}\n"]
        prompt_parts.append("可用工具:")
        for name, tool in self.tools.items():
            prompt_parts.append(f"- {name}: {tool.description}")
        
        prompt_parts.append("\n格式要求:")
        prompt_parts.append("Thought: [你的思考]")
        prompt_parts.append("Action: [工具名[参数]] 或 Answer: [最终答案]")
        
        # 添加历史记录
        if self.memory:
            prompt_parts.append("\n历史记录:")
            for i, record in enumerate(self.memory):
                prompt_parts.append(f"第{i+1}轮:")
                prompt_parts.append(f"  思考:{record['thought']}")
                prompt_parts.append(f"  动作:{record['action']}")
                prompt_parts.append(f"  结果:{record['observation']}")
        
        return "\n".join(prompt_parts)
    
    def _parse_action(self, thought: str) -> tuple:
        """
        解析动作
        
        判断逻辑:
        - 如果包含"Answer:" -> 最终答案
        - 如果包含"Action:" -> 工具调用
        """
        if "Answer:" in thought:
            answer = thought.split("Answer:")[1].strip()
            return ("final_answer", answer)
        
        if "Action:" in thought:
            action_str = thought.split("Action:")[1].strip()
            # 解析 tool_name[params] 格式
            if "[" in action_str:
                tool_name = action_str.split("[")[0].strip()
                params = action_str.split("[")[1].split("]")[0].strip()
                return ("tool_call", (tool_name, params))
        
        # 无法解析,按最终答案处理
        return ("final_answer", thought)
    
    def _execute_tool(self, tool_call: tuple) -> str:
        """
        执行工具
        
        参数:
            tool_call: (工具名, 参数) 元组
        """
        tool_name, params = tool_call
        
        if tool_name not in self.tools:
            return f"错误:未找到工具 {tool_name}"
        
        tool = self.tools[tool_name]
        result = tool.execute(params)
        
        return str(result)

Agent的痛点

很多人用Agent会遇到一个问题:上下文爆炸

flowchart LR
    A["搜索1"] -->|"塞入|上下文"| B["🧠 上下文"]
    C["搜索2"] -->|"塞入|上下文"| B
    D["搜索3"] -->|"塞入|上下文"| B
    E["分析结果"] -->|"塞入|上下文"| B
    F["...几十个|调用..."] -->|"塞入|上下文"| B
    
    B -->|"太长|爆炸"| G["💥 上下文爆炸<br/>模型开始幻觉"]

症状:

  • Agent执行任务时,越来越慢
  • 输出质量越来越差
  • 开始出现明显的逻辑错误

根本原因: 每次工具调用的结果都会积累在上下文中,长链路任务会把上下文塞满。

解决方案: 上下文压缩、摘要,或者——Multi-Agent


六、第四派:Multi-Agent System(组织的力量)

image.png 核心理念:一个不够用,一群来干!

什么是Multi-Agent?

简单来说,就是多个Agent协同工作,每个Agent负责一部分任务,通过分工合作完成复杂目标。

核心价值:上下文隔离 + 专业分工

flowchart TB
    A["🎯 任务"] --> B["👔 Manager<br/>主管"]
    
    B -->|"分派|研究"| C["🔍 Researcher<br/>研究员"]
    B -->|"分派|分析"| D["📊 Analyst<br/>分析师"]
    B -->|"分派|审核"| E["✅ Reviewer<br/>审核员"]
    
    C -->|"精炼数据"| D
    D -->|"分析结论"| E
    E -->|"通过|输出"| F["📄 最终报告"]
    E -.->|"不通过|回退"| B
    
    style A fill:#e1f5fe
    style B fill:#fff3e0
    style C fill:#e8f5e9
    style D fill:#e8f5e9
    style E fill:#e8f5e9

Multi-Agent的四大架构

根据不同的协作模式,Multi-Agent可以分为四种架构:

flowchart LR
    subgraph 四大架构
        A["🏭 串行架构"]
        B["👔 分层架构"]
        C["⚡ 并行架构"]
        D["🔗 网络架构"]
    end
    
    A -->|"顺序执行<br/>A→B→C"| A1["流水线模式"]
    B -->|"中央协调<br/>Manager分配"| B1["主管-员工模式"]
    C -->|"并行执行<br/>同时干活"| C1["Map-Reduce模式"]
    D -->|"对等协作<br/>自由通信"| D1["点对点模式<br/>⚠️慎用"]

代码实现:分层架构

# ============================================
# Multi-Agent:分层架构实现
# 核心思想:专业化分工 + 上下文隔离
# ====================================

class MultiAgentSystem:
    """
    多智能体系统
    
    为什么需要Multi-Agent?
    1. 上下文隔离:每个Agent只处理一部分
    2. 专业分工:研究员只搜索,分析师只分析
    3. 质量保证:审核员负责质检,不合格就回退
    """
    
    def __init__(self):
        # 主管:负责协调,不干具体活
        self.manager = ManagerAgent()
        
        # 研究员:只负责搜索
        self.researcher = SpecialistAgent(
            role="研究员",
            tools=[SearchTool(), CrawlerTool()]
        )
        
        # 分析师:只负责分析
        self.analyst = SpecialistAgent(
            role="分析师", 
            tools=[AnalysisTool(), ChartTool()]
        )
        
        # 审核员:只负责判断
        self.reviewer = ReviewerAgent()
    
    def run(self, task: str) -> str:
        """
        多Agent协作执行
        
        执行流程:
        1. Manager分析任务,决定下一步
        2. Researcher收集数据(独立的上下文)
        3. Analyst分析数据(独立的上下文)
        4. Reviewer审核结果
        5. 不合格则回退给Manager重新分配
        """
        state = {"phase": "start", "task": task}
        
        while True:
            decision = self.manager.decide(state)
            
            if decision["type"] == "research":
                # 研究员独立工作(上下文隔离)
                data = self.researcher.research(task)
                # 精炼数据传给下一个Agent
                refined_data = self._refine(data)
                state = {"phase": "analyze", "data": refined_data}
            
            elif decision["type"] == "analyze":
                # 分析师独立工作(上下文隔离)
                analysis = self.analyst.analyze(state["data"])
                refined_analysis = self._refine(analysis)
                state = {"phase": "review", "analysis": refined_analysis}
            
            elif decision["type"] == "review":
                # 审核员判断
                verdict = self.reviewer.judge(state["analysis"])
                
                if verdict["pass"]:
                    return verdict["report"]
                else:
                    # 不合格,回退!
                    state = {"phase": "retry", "feedback": verdict["feedback"]}
    
    def _refine(self, data: Any) -> str:
        """
        跨Agent数据精炼
        
        关键设计:不在Agent间传递完整上下文
        而是精炼后只传递下一个Agent需要的信息
        """
        # 用LLM摘要,精简数据
        return self.manager.llm.summarize(data)

Multi-Agent vs 工作流:有什么区别?

维度WorkflowMulti-Agent
决策者程序员(硬编码)模型(自主决策)
节点类型固定功能节点具备自主能力的Agent
上下文共享上下文每个Agent独立上下文
灵活性低(流程固定)高(动态决策)
复杂度
适用场景边界清晰复杂长链路

一句话区分:

  • Workflow:你设计好剧本,演员按剧本来
  • Multi-Agent:你请了一群各有专长的演员,让他们自己商量着来

七、架构选型指南:别把洗衣机当冰箱用

终于到了最关键的问题:我该用哪种范式?

image.png

这里要引入一个核心概念:阿什比定律

"Only variety can destroy variety." —— 只有多样性才能对抗多样性。

翻译成人话:业务有多复杂,系统就得有多复杂。

业务不确定性分析

业务的不确定性来自三个方面:

flowchart TB
    A["业务不确定性"] --> B["输入不确定性"]
    A --> C["过程不确定性"]
    A --> D["结果不确定性"]
    
    B -->|"用户说什么不确定"| E["智能客服"]
    C -->|"如何解决不确定"| F["代码调试"]
    D -->|"输出什么不确定"| G["创意写作"]

熵-架构匹配矩阵

选型决策表

image.png

业务特征推荐范式典型场景
规则固定、数据简单Prompt邮件润色、翻译、模板生成
流程固定、边界清晰Workflow扣子工作流、内容处理流水线
开放问题、需要决策Single Agent智能客服、代码调试
超长链路、复杂协作Multi-Agent竞品分析、研究报告

常见误区

误区真相
"我用了LangChain,就是Agent了"不一定,可能是Workflow
"Agent一定比Workflow好"看场景!杀鸡焉用牛刀
"Multi-Agent就是多个LLM节点"错!每个节点都得是能自主决策的Agent
"AI越贵越好"不一定,适合最重要

八、总结:一张图记住四种范式

mindmap
  root((AI应用开发<br/>四大范式))
    Prompt Engineering
      你说啥我做啥
      简单直接
      上下文是瓶颈
    Workflow
      流程我设计
      模型按部就班
      稳定可靠
    Single Agent
      目标给你
      工具给你
      模型自己想办法
    Multi-Agent
      一群Agent协作
      分工专业
      上下文隔离

记住四句话:

  1. Prompt:简单够用,不要over engineering
  2. Workflow:工程落地首选,稳定压倒一切
  3. Agent:模型当大脑,程序员当设计师
  4. Multi-Agent:组织的力量,给模型减负

image.png