从"给电饭煲"到"全自动帮厨":从传统软件架构角度看 AI Agent 与多智能体演进

0 阅读6分钟

从"给电饭煲"到"全自动帮厨":从传统软件架构看 AI Agent 与多智能体演进

过去两年,我们见证了大模型(LLM)从"聊天玩具"艰难走向"企业级应用"的过程。早期的狂热褪去后,开发者们在业务落地时普遍遭遇了滑铁卢:让模型写首诗很容易,但让它稳定、不出错地执行一个包含 10 个步骤的自动化业务流,简直像是在走钢丝。

剥开 AI 神奇的外衣,我们会发现:AI Agent 落地的尽头,其实是向传统软件工程妥协。

今天,我们不聊玄乎的 AGI,只从传统面向对象设计(OOP)和 2025 年主流的多智能体架构出发,聊聊大模型工作流是如何一步步演进,并试图解决其致命缺陷的。


一、能力的进化:从 Function Call 到 Multi-Agent 交付

在 Agent 发展的早期,业界流行直接给大模型塞一堆 Function Call(函数调用)

🍚 电饭煲比喻:你想吃米饭,系统给了大模型一个电饭煲、一个量杯、一个水龙头。大模型需要亲自推理:"先调用 add_water(500ml) → 判断水位 → 调用 heat_on()"。结果?大模型经常在冗长的多步推理中 "迷路" ,或者把参数传错——饭烧糊了。

为了降低大模型的认知负担,Skill(技能套件) 的概念应运而生,并迅速演化为 2025 年大火的 Multi-Agent(多智能体)架构

🤖 帮厨比喻:你想吃米饭,系统直接分配一个"煮饭 Agent"。你只需把"米"这个参数传给它,它内部怎么加水、怎么控火,主控大脑不再关心。它不再交付"生数据",而是直接交付"煮好的米饭"。

📊 能力交付模式演进

graph LR
    subgraph phase1["🔧 PHASE 1 · Function Call 时代"]
        direction TB
        LLM1["🧠 LLM 逐步推理"] --> T1["add_water()"]
        LLM1 --> T2["check_level()"]
        LLM1 --> T3["heat_on()"]
        LLM1 --> T4["heat_off()"]
        T1 --> R1["⚠️ 高概率翻车"]
        T2 --> R1
        T3 --> R1
        T4 --> R1
    end

    subgraph phase2["🚀 PHASE 2 · Multi-Agent 时代 2025"]
        direction TB
        MA["🧠 Main Agent<br/>只做意图理解+任务分发"] --> SA1["🍚 煮饭 Agent"]
        MA --> SA2["🥗 炒菜 Agent"]
        MA --> SA3["🍰 甜品 Agent"]
        SA1 --> R2["✅ 直接交付最终能力"]
        SA2 --> R2
        SA3 --> R2
    end

    phase1 -- "演进 ➡️" --> phase2

    style phase1 fill:#1a1a2e,stroke:#ff6b35,color:#fff
    style phase2 fill:#1a1a2e,stroke:#00d4aa,color:#fff
    style LLM1 fill:#2d1810,stroke:#ff6b35,color:#ff6b35
    style MA fill:#0d2920,stroke:#00d4aa,color:#00d4aa
    style R1 fill:#2d1010,stroke:#ef4444,color:#ef4444
    style R2 fill:#0d2920,stroke:#00d4aa,color:#00d4aa
    style T1 fill:#141420,stroke:#a78bfa,color:#a78bfa
    style T2 fill:#141420,stroke:#a78bfa,color:#a78bfa
    style T3 fill:#141420,stroke:#a78bfa,color:#a78bfa
    style T4 fill:#141420,stroke:#a78bfa,color:#a78bfa
    style SA1 fill:#0d1a2d,stroke:#4d8fff,color:#4d8fff
    style SA2 fill:#1a1028,stroke:#a78bfa,color:#a78bfa
    style SA3 fill:#1a1a10,stroke:#fbbf24,color:#fbbf24

在 2025 年的 Multi-Agent 工作流中,每一个专门的 Sub-Agent(比如数据分析 Agent、代码审查 Agent)本质上就是一种高度封装的 Skill。它们各自为政,对外只提供"能力交付",极大地解耦了系统的复杂度。


二、用 Java 体系秒懂 Agent 架构演进

如果把现在的 AI Agent 架构映射到传统的后端开发中,那些拥有多年经验的程序员会心一笑:这不就是重做了一遍面向对象设计和微服务吗?

AI Agent 概念传统 Java/后端架构映射核心职责与特点
Tool / Function (底层工具)Method (基础方法)原子级的死板代码(如 execute_sql())。毫无智能,100% 确定性,只做最基础的数据吞吐。
Skill / Sub-Agent (专业能力/子智能体)Class / Microservice (类/微服务)封装了多个底层 Tool 和异常重试逻辑(如 DataAnalystAgent)。有边界、高内聚,只交付特定领域的业务结果。
Main Agent (主控大脑)Main Application (主程序/编排层)负责宏观意图理解、全局任务拆解、维持上下文记忆。按需"实例化"调用不同的 Sub-Agent 来拼装最终结果。

📊 架构映射:AI Agent ↔ OOP / 微服务

graph TB
    subgraph ai["🤖 AI Agent 世界"]
        direction TB
        MainAgent["🧠 Main Agent"] --> SubA["Sub-Agent A<br/>数据分析"]
        MainAgent --> SubB["Sub-Agent B<br/>代码审查"]
        MainAgent --> SubC["Sub-Agent C<br/>报告生成"]
        SubA --> ToolA1["tool: query_db()"]
        SubA --> ToolA2["tool: calc_stats()"]
        SubB --> ToolB1["tool: lint_code()"]
        SubC --> ToolC1["tool: gen_chart()"]
        SubC --> ToolC2["tool: format_doc()"]
    end

    subgraph java["☕ Java / 微服务世界"]
        direction TB
        App["⚙️ Main Application"] --> SvcA["Microservice A<br/>数据分析服务"]
        App --> SvcB["Class B<br/>代码审查模块"]
        App --> SvcC["Microservice C<br/>报告生成服务"]
        SvcA --> MA1["method: queryDB()"]
        SvcA --> MA2["method: calcStats()"]
        SvcB --> MB1["method: lintCode()"]
        SvcC --> MC1["method: genChart()"]
        SvcC --> MC2["method: formatDoc()"]
    end

    ai <-- "💡 相同的设计哲学<br/>高内聚 · 低耦合 · 单一职责" --> java

    style ai fill:#1a1a2e,stroke:#ff6b35,color:#fff
    style java fill:#1a1a2e,stroke:#4d8fff,color:#fff
    style MainAgent fill:#2d1810,stroke:#ff6b35,color:#ff6b35
    style App fill:#0d1a2d,stroke:#4d8fff,color:#4d8fff
    style SubA fill:#0d2920,stroke:#00d4aa,color:#00d4aa
    style SubB fill:#0d2920,stroke:#00d4aa,color:#00d4aa
    style SubC fill:#0d2920,stroke:#00d4aa,color:#00d4aa
    style SvcA fill:#1a1028,stroke:#a78bfa,color:#a78bfa
    style SvcB fill:#1a1028,stroke:#a78bfa,color:#a78bfa
    style SvcC fill:#1a1028,stroke:#a78bfa,color:#a78bfa

为什么要这么解耦?因为在实际的企业级开发中:写底层 Tool 的是后端工程师,封装 Skill/Sub-Agent 业务逻辑的是业务专家,而调优主控大脑 Prompt 的是算法工程师(我的理解是这样,有说不对,评论区留个现在中的例子,我学习学习)。这种架构让 AI 工程化拥有了传统软件开发的协作基础。


三、大模型的阿喀琉斯之踵:误差级联 (Cascading Errors)

为什么我们非要把架构拆得这么细?因为大模型有一个目前物理法则下无法根治的绝症:误差级联

传统软件工程是确定性的:调用 100 次 save() 方法,只要没 bug,成功率就是 100%。

但大模型是概率生成的:这遵循的是残酷的乘法法则

🧮 残酷的乘法法则

假设目前最顶尖的大模型,执行单个任务节点的准确率高达 95%

链路长度计算整体成功率评估
2 步0.95²≈ 90%非常可用
5 步0.95⁵≈ 77% ⚠️勉强接受
10 步0.95¹⁰≈ 60%接近崩溃
20 步0.95²⁰≈ 36% 💀基本不可用

📊 误差级联:幻觉被层层放大

graph LR
    S1["✅ Step 1<br/>95%"] --> S2["Step 2<br/>90%"]
    S2 --> S3["Step 3<br/>86%"]
    S3 --> S5["⚠️ Step 5<br/>77%"]
    S5 --> S8["Step 8<br/>66%"]
    S8 --> S10["❌ Step 10<br/>60%"]
    S10 --> OUT["💀 Garbage Out<br/>幻觉层层放大"]

    style S1 fill:#0d2920,stroke:#00d4aa,color:#00d4aa
    style S2 fill:#0d2920,stroke:#3dbd98,color:#3dbd98
    style S3 fill:#1a1a10,stroke:#a3c45a,color:#a3c45a
    style S5 fill:#1a1a10,stroke:#fbbf24,color:#fbbf24
    style S8 fill:#2d1810,stroke:#f97316,color:#f97316
    style S10 fill:#2d1010,stroke:#ef4444,color:#ef4444
    style OUT fill:#2d1010,stroke:#ef4444,color:#ef4444

这意味着,只要链路里有一个节点产生了哪怕极微小的"幻觉",这个错误就会作为下一个节点的输入,被无限放大(Garbage in, garbage out)。任务只要稍微复杂一点,系统就处在崩溃的边缘。


四、Software 2.0:用传统设计模式"驯服" AI

既然无法从大模型内部消灭误差,我们就只能在外部用工程手段去兜底。这也是目前主流框架(如 LangGraph、AutoGen 等)正在做的事情——用确定性的架构去包裹不确定的内核

🛡️ 四大工程兜底策略

策略一:缩短链路,大颗粒度交付

用高内聚的 Sub-Agent 代替细粒度的 Function,强行把 10 步链路压缩成 3 步,降低出错概率。

策略二:引入"拦截器"与自我反思(Actor-Critic)

在关键节点插入一个充当"裁判"的校验 Agent。一旦发现执行 Agent 产出的格式不对或逻辑有误,直接拦截并打回重做,用算力换准确率。

策略三:状态机与检查点回滚(State Machine & Checkpoints)

不再让 Agent "一条路走到黑"。系统不断保存当前图节点的状态快照。如果第 5 步失败了,直接回滚到第 4 步的安全状态重新尝试,而不是全盘崩溃。

策略四:人类在环(Human-in-the-loop)

对于高价值、高风险的节点(例如发邮件给全量客户、修改生产数据库),强制挂起线程,等待人类审批后再继续执行。

📊 工程兜底方案架构

graph LR
    A["🤖 Sub-Agent A<br/>执行任务"] --> C{"🔍 Critic<br/>校验 Agent"}
    C -- "❌ 格式/逻辑有误" --> A
    C -- "✅ 校验通过" --> CP["💾 Checkpoint<br/>保存状态快照"]
    CP --> B["🤖 Sub-Agent B<br/>执行下一步"]
    B -- "❌ 失败回滚" --> CP
    B -- "✅ 完成" --> H{"🧑 Human-in-the-Loop<br/>人工审批"}
    H -- "✅ 批准" --> OUT["🎯 最终输出"]
    H -- "❌ 驳回" --> B

    style A fill:#0d2920,stroke:#00d4aa,color:#00d4aa
    style C fill:#1a1a10,stroke:#fbbf24,color:#fbbf24
    style CP fill:#0d1a2d,stroke:#4d8fff,color:#4d8fff
    style B fill:#0d2920,stroke:#00d4aa,color:#00d4aa
    style H fill:#1a1028,stroke:#a78bfa,color:#a78bfa
    style OUT fill:#0d2920,stroke:#00d4aa,color:#00d4aa

这四大策略并非互斥,而是可以组合使用。在实际的企业级 Agent 系统中,往往是四管齐下,形成一套完整的"安全网"。


结语

AI 的发展并没有抛弃软件工程,反而越来越需要软件工程的加持。

未来的应用架构,大脑(LLM) 负责理解模糊的意图和规划,而 手脚(Tool/Skill) 负责执行严谨的、带有重试机制的确定性逻辑。

从面向对象到面向 Agent,变的是交互方式,不变的是高内聚、低耦合的系统设计哲学。

大家在实际开发 Agent 工作流时,遇到过最崩溃的"幻觉翻车"是什么?又是怎么用工程手段兜底的?欢迎在评论区交流探讨!