# **IIT Manager Agent V2.4:架构模式选型与 SOP 状态机推荐** **核心议题:** ReAct vs Planner vs State Machine —— 谁更适合医疗质控? **结论前置:** 弃用纯 Planner,限制使用 ReAct,全面拥抱 **SOP 状态机**。 ## **1\. 深度解析:ReAct 与 Planner 适合我们吗?** ### **1.1 ReAct (Reasoning \+ Acting)** * **原理**:Agent 像人一样“自言自语”。 * *Thought*: "我需要查患者年龄。" \-\> *Action*: read\_data \-\> *Observation*: "16岁" \-\> *Thought*: "太小了,报错。" * **在 IIT 中的地位**:**它就是你的 Engine B**。 * 你现有的 runAgentLoop 代码本质上就是一个 ReAct 循环。 * **优点**:灵活,能处理突发情况(比如发现数据缺了,它知道先去查)。 * **缺点**:容易陷入死循环(反复查同一个数据),或者在思考步骤中消耗大量 Token。 * **结论**:**保留使用**,但必须加“紧箍咒”(最大步数限制)。 ### **1.2 Planner (Query-Planner-Execute-Reflect)** * **原理**:先写大纲,再干活。 * *Plan*: 1\. 查总人数; 2\. 算脱落率; 3\. 写周报; 4\. 反思哪里写得不好。 * **在 IIT 中的地位**:**仅适合“项目管理 Agent” (周报/统计)**。 * 对于“数据质控”这种秒级响应的任务,Planner 太慢了(光生成计划就要 5-10 秒)。 * **缺点**:对于 2 人团队,实现一个稳定的 Planner 很难(需要维护计划状态、断点恢复)。 * **结论**:**质控场景禁用,报表场景可选**。 ## **2\. 终极推荐:SOP 状态机 (SOP-Driven State Machine)** 为什么医疗行业(GCP)最看重 Protocol(方案)?因为临床研究本质上就是一个**巨大的流程图**。 我们应该让 Agent **“照着流程图走”**,而不是让它“只有个模糊目标自己瞎想”。 ### **2.1 什么是 SOP 状态机架构?** 把你的 Skills JSON 进化成一个**有向图 (DAG)** 或 **流程图**。 * **节点 (Node)**:一个具体的检查步骤(可以是硬规则,也可以是软指令)。 * **边 (Edge)**:下一步走哪里(通过了走 A,没通过走 B)。 ### **2.2 为什么它既稳又活?** * **稳 (Stability)**:流程是写死的(先查年龄,再查病史,最后查合并用药)。Agent 不会乱跳步骤,不会漏查。 * **活 (Flexibility)**:每个节点内部可以用 AI(Engine B)来灵活判断。 ## **3\. 落地实施:如何改造 Skills JSON?** 我们将 V2.1 的扁平配置升级为**流程配置**。 ### **3.1 新的 Skill 结构 (qc\_process.json)** { "name": "肺癌入排质控流程", "start\_node": "check\_age", // 入口 "nodes": { // 节点 1: 硬规则 (CPU 执行) "check\_age": { "type": "hard\_rule", "logic": { "\>=": \[{ "var": "age" }, 18\] }, "on\_pass": "check\_history", // 通过了,去查病史 "on\_fail": "end\_with\_error" // 没通过,直接结束 }, // 节点 2: 软指令 (AI 执行 \- ReAct 模式) "check\_history": { "type": "soft\_instruction", "instruction": "检查病史描述,排除'间质性肺炎'。", "tools": \["read\_clinical\_data"\], "on\_pass": "check\_meds", "on\_fail": "review\_required" // AI 觉得有问题,转人工复核 }, // 节点 3: 复杂逻辑 (AI 执行) "check\_meds": { "type": "soft\_instruction", "instruction": "检查合并用药,排除靶向药。", "on\_pass": "end\_success", "on\_fail": "review\_required" } } } ## **4\. 代码实现:极简状态机引擎** 不要引入 XState 这种复杂库,2 人团队自己写个 while 循环就够了。 // backend/src/modules/iit-manager/services/SopEngine.ts class SopEngine { async run(skillConfig: any, data: any) { let currentNodeId \= skillConfig.start\_node; let context \= { ...data }; // 共享上下文 while (currentNodeId && currentNodeId \!== 'end') { const node \= skillConfig.nodes\[currentNodeId\]; console.log(\`\[SOP\] Executing node: ${currentNodeId}\`); let result; if (node.type \=== 'hard\_rule') { // 调用 Engine A (V2.1 的逻辑) result \= this.runHardRule(node, context); } else if (node.type \=== 'soft\_instruction') { // 调用 Engine B (ReAct 模式) result \= await this.runSoftAgent(node, context); } // 状态流转 if (result.passed) { currentNodeId \= node.on\_pass; } else { if (node.on\_fail \=== 'end\_with\_error') { await this.saveShadowQuery(result.message); return; } currentNodeId \= node.on\_fail; } } } } ## **5\. 架构对比总结表** | 架构模式 | 稳定性 | 灵活性 | 复杂度 | 适用场景 | 推荐指数 | | :---- | :---- | :---- | :---- | :---- | :---- | | **ReAct (V2.1 Engine B)** | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 中 | 单点模糊判断 (如: 这段话是不是病史) | ✅ **局部使用** | | **Planner** | ⭐⭐ | ⭐⭐⭐⭐ | 高 | 复杂任务规划 (如: 生成全项目总结) | ❌ **质控不用** | | **SOP 状态机 (V2.4)** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 低 | **临床试验全流程控制** (SOP 落地) | 👑 **核心架构** | ## **6\. 深度释疑:SOP 会导致僵化吗?(Flexibility Check)** 针对你担心的“每个字段都要配流程”和“浪费 LLM 能力”的问题,我们需要纠正一个认知误区。 ### **6.1 误区:SOP \= 细粒度代码逻辑** * **错误做法**:把 400 个变量写成 400 个节点。节点1: 查年龄 \-\> 节点2: 查性别 \-\> 节点3: 查身高... * **后果**:配置地狱,灵活性为零。 ### **6.2 正解:SOP \= 粗粒度业务阶段 (Phases)** 我们通过 **“粗颗粒度节点”** 来充分释放 LLM 的能力。一个 SOP 可能只有 3 个节点,但涵盖了无数逻辑。 * **节点 A (基线硬扫描)**: * **类型**:硬规则(Hard Rule) * **内容**:一次性加载 50 条 JSON Logic 规则。 * **执行**:CPU 毫秒级跑完所有数值校验(年龄、身高、体重、化验值范围)。 * **配置**:这是一个列表,不是流程图,配置很简单。 * **节点 B (AI 综合研判)**: * **类型**:软指令(Soft Instruction / ReAct) * **Prompt**:“请作为医学专家,阅读患者的‘现病史’、‘既往史’和‘手术史’。请综合判断是否存在:严重心血管疾病、未控制的高血压或活动性感染。如果有,请引用原文说明。” * **LLM 的灵活性**: * 在这个节点**内部**,LLM 是完全自由的。 * 它可以自己决定先看现病史还是既往史。 * 它可以自己判断“高血压二级”算不算“未控制”。 * **它依然在用 ReAct 调用工具**,只是我们把它限制在了“检查病史”这个大阶段里,不让它跑去“检查知情同意书”。 ### **6.3 实战推演:如何拆解一个 400 变量的项目?** 假设你的项目有 10 个表,400 个变量。 | 数据类型 | 变量数量 | 举例 | 处理策略 | 节点归属 | | :---- | :---- | :---- | :---- | :---- | | **人口学/基线** | 20 个 | 年龄、性别、身高、体重 | **Hard Rule** | **节点 A (基线检查)** | | **实验室检查** | 300 个 | 血常规、生化、尿常规 | **Hard Rule** | **节点 A (基线检查)** | | **体格检查** | 50 个 | 心率、血压、体温 | **Hard Rule** | **节点 A (基线检查)** | | **既往病史** | 5 个 | 自由文本描述 | **Soft Instruction** | **节点 B (病史研判)** | | **合并用药** | 5 个 | 自由文本药名 | **Soft Instruction** | **节点 C (用药研判)** | | **不良事件** | 20 个 | 严重程度、转归情况 | **Soft Instruction** | **节点 D (安全监控)** | **结论**: * 尽管有 400 个变量,**SOP 流程图里其实只有 4 个节点**。 * 你只需要写 **3 条** AI 指令(针对节点 B, C, D)。 * 剩下的 370 个变量,全部用简单的 JSON 规则批量处理。 **这不仅没有浪费 LLM 的能力,反而让它更专注(只处理那 30 个最难的变量),并帮你省下了巨额的 Token 费用。** ## **7\. 给 2 人团队的行动指南** 1. **宏观上用 SOP**: * 临床研究最讲究 SOP。用 JSON 定义好“先查A,再查B,最后查C”的流程。这能保证你的系统像瑞士钟表一样稳定。 * 这解决了“不知道 AI 会不会乱跑”的恐惧。 2. **微观上用 ReAct**: * 在 SOP 的某个具体节点(比如“检查病史”节点)里,允许 AI 使用 ReAct 模式(思考-查库-判断)。 * 这保留了处理非结构化数据的灵活性。 3. **实现路径**: * Phase 2.1: 先把之前的 hard\_rules 列表改成简单的 nodes 结构(线性执行)。 * Phase 2.2: 在 nodes 里增加 on\_pass / on\_fail 跳转逻辑。 **一句话总结:用 SOP (状态机) 管住 Agent 的腿(流程),用 ReAct 管住 Agent 的嘴(推理)。这就是既稳定又灵活的最佳实践。**