配套笔记:Agent 架构如何设计 · PE与PEV架构 · 如何防止幻觉

本文用图说话,把 V1(过度设计)与 V2(重构后)的架构差异可视化,便于面试白板讲解。


一、V1:过度设计的 PE 状态机(翻车现场)

链路Planner → Executor → Gatekeeper → Verifier → Composer

5 个 LLM 节点 + 全量状态传递,看起来职责清晰,实则是"用编排复杂性掩盖推理能力不足"。

flowchart TD
    U1([用户输入诊断请求]) --> Planner

    subgraph LLM["LLM 节点(均消耗推理)"]
        Planner["Planner<br/>宏观规划排查路径"]
        Executor["Executor<br/>调用工具执行"]
        Gatekeeper["Gatekeeper<br/>(LLM) 参数校验"]
        Verifier["Verifier<br/>(LLM) 结果审查"]
        Composer["Composer<br/>(LLM) 总结报告"]
    end

    Planner -->|"规划路径(猜)"| Executor
    Executor -->|"结果踢回重规划"| Planner
    Executor --> Gatekeeper
    Gatekeeper -->|"通过"| Verifier
    Verifier -.->|"打回:结论不行"| Executor
    Verifier -->|"通过"| Composer
    Composer --> R1([诊断报告])

    %% 翻车点标注
    Planner -.- x1["❌ 宏观规划 vs 微观试探错位<br/>踢皮球割裂推理连贯性"]
    Verifier -.- x2["❌ LLM 审查 LLM<br/>死循环 + 双重幻觉"]
    Executor -.- x3["❌ 1000 行脏日志全量塞入<br/>上下文腐烂 → 过度输出"]
    Gatekeeper -.- x4["❌ 确定性逻辑做成 LLM 节点<br/>浪费一次推理 + 不可靠"]

    classDef llm fill:#fce4ec,stroke:#c2185b,stroke-width:1px
    classDef bad fill:#fff3e0,stroke:#e65100,stroke-width:1px,stroke-dasharray:4 3
    class Planner,Executor,Gatekeeper,Verifier,Composer llm
    class x1,x2,x3,x4 bad

三大致命弊端

  1. 踢皮球:诊断是数据驱动的"走一步看一步",PE 强行前置宏观 Plan,Planner 要么瞎猜路径,要么 Executor 出结果就踢回重规划。
  2. 死循环 + 双重幻觉:LLM 审 LLM,Verifier 打回 Executor 改了还打回,Token 烧穿;Verifier 自己也产生"审查幻觉"。
  3. 上下文断裂/膨胀:全量传 → 上下文爆炸;摘要传 → 丢失关键线索。

二、V2:单 ReAct Agent + 强 Harness + 分层 Verify(重构后)

核心思想:把推理还给 ReAct,把校验还给代码。

flowchart TD
    U2([用户输入诊断请求]) --> Router{"命中已知 SOP?"}

    Router -->|"是(80% 高频)"| Highway["🛣️ Highway 流水线<br/>专家固化 SOP = 离线 Plan<br/>固定 PE,不走推理"]
    Highway --> Sec["秒级出结果"]

    Router -->|"否(长尾复杂)"| Agent["🧠 单 ReAct DiagnosisAgent<br/>While 循环:感知-决策-行动-反馈<br/>边查边想,过程流式输出"]

    subgraph Harness["Harness 代码层(0 LLM)"]
        direction TB
        RTK["① 工具层 RTK 清洗<br/>1000 行日志 → 只留 ERROR±5 行<br/>DB 记录 → 聚合为指标"]
        Schema["② JSON Schema 契约<br/>thought≤50字 / 格式校验<br/>不合格直接打回"]
        Assert["③ 物理门禁<br/>evidence_id 真实存在?<br/>raw_path 文件存在?"]
    end

    Tools[("工具集<br/>查日志 / 指标 / Trace / DB")]
    Agent <-->|调用 + 清洗后返回| RTK
    RTK --> Tools
    Agent -->|每步输出| Schema
    Schema -.->|不合格打回| Agent

    Agent -->|"结构化草稿报告"| Assert
    Assert -.->|失败:假证据/格式错| Agent
    Assert -->|成功:写入暂存区<br/>状态 PENDING| UI["前端过渡态<br/>'正在安全校验…'"]

    UI -.->|后台异步触发| Verifier2["🔍 独立 Verifier Agent<br/>隔离上下文(仅看证据+草稿)<br/>语义校验:时间线对齐?"]

    Verifier2 -->|输出置信度分数| Push{"基于置信度<br/>WebSocket 二次推送"}

    Push -->|">=0.7 高置信"| R2["推送强诊断结论"]
    Push -->|"0.4~0.7 中置信"| R3["结论 + '建议人工复核'"]
    Push -->|"<0.4 低置信"| R4["只推原始日志/时间线<br/>不编结论"]
    Push -->|"异步 >8s 未返回"| R5["降级:推草稿 + 超时提示"]

    classDef react fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    classDef code fill:#e8f5e9,stroke:#2e7d32,stroke-width:1px
    classDef async fill:#fff8e1,stroke:#f9a825,stroke-width:1px,stroke-dasharray:5 3
    classDef highway fill:#f3e5f5,stroke:#8e24aa,stroke-width:1px
    class Agent react
    class RTK,Schema,Assert code
    class Verifier2,Push,UI async
    class Highway highway

三、V1 → V2 的降维对照表

维度 V1(过度设计) V2(重构后) 核心动作
主推理 Planner + Executor 拆成 2 个 LLM 节点 单 ReAct DiagnosisAgent 合并
总结 独立 Composer 节点 ReAct 终点直接输出结构化报告 砍掉
参数校验 LLM Gatekeeper 节点 代码层 JSON Schema Linter(0 LLM) 下沉为代码
数据清洗 没有 工具层 RTK 机制 新增代码层
结果审查 主链路同步 Verifier(LLM)→ 死循环 物理验真(代码同步) + 语义校验(异步 Agent) 分层 + 脱链
高频场景 全走 ReAct Highway 流水线旁路 旁路 PE
防幻觉 靠"多加监工" 上下文干净 + 契约 + 物理门禁 + 负反馈 治源

四、单 Agent vs 多 Agent 选型决策图

终极拷问的答案:不要为"拆"而拆,看任务拓扑 + 两条硬指标。

flowchart TD
    Start([要不要引入多 Agent / Graph?]) --> Q1{"任务拓扑?"}

    Q1 -->|"线性深挖<br/>前一步决定后一步查什么"| Single["✅ 单 Agent + 强 Harness<br/>拆了会丢上下文连贯性"]
    Q1 -->|"扇出汇聚<br/>子任务互不依赖可并行"| Q2{"单 Agent 还撑得住?"}

    Q2 -->|"工具 ≤10 且上下文可压"| Single2["✅ 仍用单 Agent"]
    Q2 -->|"工具 >10 或上下文物理爆炸"| Multi["✅ Supervisor 多 Agent<br/>子 Agent 并行跑<br/>各自消化原始数据,只传结论摘要"]

    Single --> CheckHard{"需要状态外化 / 可中断恢复?"}
    Single2 --> CheckHard
    CheckHard -->|"否"| NoGraph["✅ 普通 While 循环即可<br/>不需要 Graph 框架"]
    CheckHard -->|"是(跑到一半存档/等人审)"| Graph["⚠️ 才引入 LangGraph<br/>仅为 状态外化 + 断点续跑"]

    classDef keep fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px
    classDef warn fill:#fff3e0,stroke:#e65100,stroke-width:1px
    class Single,Single2,NoGraph keep
    class Multi warn
    class Graph warn

两条硬性触发线(触发其一才演进多 Agent)

  1. 单 Agent 工具数 > 10,工具选择准确率断崖式下降。
  2. 即便 RTK 清洗 + 文件卸载,上下文仍物理装不下。

五、防幻觉"四层防线"因果链(数据面细节)

flowchart LR
    Input[("工具原始返回<br/>1000 行脏日志 / 大表")] --> L1

    L1["防线1<br/>RTK 清洗<br/>切断脏数据输入<br/>只留 ERROR±5 / 聚合指标"]
    L1 -->|干净数据| Brain["🧠 Agent 推理"]

    Brain -->|每步输出| L2["防线2<br/>JSON Schema 契约<br/>锁死输出格式<br/>超50字/格式错直接打回(0 LLM)"]
    L2 -.->|不合格| Brain

    Brain -->|最终报告| L3["防线3<br/>物理门禁<br/>evidence_id 查会话历史<br/>raw_path 查文件系统<br/>绝不靠 LLM 验真"]
    L3 -.->|不合法| Brain

    L3 -->|通过| L4["防线4<br/>交叉验证(异步)<br/>日志结论 vs 指标结论<br/>日志时间线 vs Trace时间线<br/>需≥2独立证据支持"]
    L4 -->|不一致| Low["低置信度报告<br/>不强行缝合"]
    L4 -->|一致| High["高置信度结论"]

    Bonus["附加:闭环负反馈<br/>配置回滚先 Dry-run<br/>真报错喂回当 Observation<br/>打破真空自圆其说"]
    Brain -.->|有副作用动作| Bonus
    Bonus -.->|物理阻力| Brain

    classDef defense fill:#e8f5e9,stroke:#2e7d32,stroke-width:1px
    classDef brain fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    class L1,L2,L3,L4,Bonus defense
    class Brain brain

六、一句话方法论(面试收尾)

把推理还给 ReAct,把校验还给代码,把上下文洗干净。

成熟的 Agent 架构,标志不是组件多丰富、Graph 多复杂,而是把模型能力接入可交付的工程运行时——用 While 循环驱动大脑,用 Harness 代码锁住手脚。