Files
AIclinicalresearch/docs/03-业务模块/IIT Manager Agent/04-开发计划/IIT Manager Agent V2.5 综合开发计划.md
HaHafeng 0c590854b5 docs(iit): Add IIT Manager Agent V2.9 development plan with multi-agent architecture
Features:
- Add V2.9 enhancements: Cron Skill, User Profiling, Feedback Loop, Multi-Intent Handling
- Create modular development plan documents (database, engines, services, memory, tasks)
- Add V2.5/V2.6/V2.8/V2.9 design documents for architecture evolution
- Add system design white papers and implementation guides

Architecture:
- Dual-Brain Architecture (SOP + ReAct engines)
- Three-layer memory system (Flow Log, Hot Memory, History Book)
- ProfilerService for personalized responses
- SchedulerService with Cron Skill support

Also includes:
- Frontend nginx config updates
- Backend test scripts for WeChat signature
- Database backup files

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-05 22:33:26 +08:00

55 KiB
Raw Blame History

IIT Manager Agent V2.6 综合开发计划

版本: V2.6(极简架构 + SOP状态机 + 双脑路由)
日期: 2026-02-02
团队规模: 2人
预估周期: 6周
核心目标: 实现数据质控 Agent 的完整闭环 + 智能化交互 + 扩展能力层


0. 架构适配性评估

本架构设计充分考虑了临床研究的多种业务场景,通过 SOP状态机 + 双引擎 + 可扩展工具层 的设计,实现了良好的适配性和扩展性。

0.1 目标场景覆盖度

场景 覆盖度 核心支撑组件 备注
1. 拍照识别 + 自动录入 🟡 60% VisionService + ToolsService 需新增视觉能力
2. 数据质控 🟢 95% HardRuleEngine + SoftRuleEngine 核心场景,完全覆盖
3. 入排标准判断 🟢 90% SopEngine + 硬规则配置 配置 Skill 即可
4. 方案偏离检测 🟢 80% SoftRuleEngine + search_protocol 需配置访视窗口规则
5. AE事件检测 🟢 80% 硬规则触发 + 软指令评估 需配置AE识别规则
6. 伦理合规检测 🟢 80% HardRuleEngine 配置伦理规则即可
7. 定期报告生成 🟡 50% SchedulerService + ReportService 需新增定时任务

0.2 架构扩展性评价

为什么说这套架构适配性强?

扩展维度 实现方式 复杂度
新增质控规则 iit_skills 表插入 JSON 配置
新增业务场景 新增 Skill 类型 + 配置 SOP 流程 中低
新增工具能力 在 ToolsService 增加工具定义 中低
新增数据源 新增 Adapter如 OdmAdapter
新增交互入口 复用 ChatService 路由逻辑 中低

核心优势

  1. 配置驱动:新业务场景主要是"写配置"而非"写代码"
  2. 插件式工具ToolsService 支持动态注册新工具
  3. 引擎复用:所有场景共享 HardRuleEngine / SoftRuleEngine
  4. SOP 状态机:流程可配置、可追溯、可审计

0.3 完整架构图(含扩展能力)

┌─────────────────────────────────────────────────────────────────────┐
│                        入口层 (Multi-Channel)                        │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────┐ │
│  │ 企业微信文本  │  │ 企业微信图片  │  │  PC Workbench │  │ 定时触发 │ │
│  └──────────────┘  └──────────────┘  └──────────────┘  └──────────┘ │
└─────────────────────────────────────────────────────────────────────┘
          │                  │                  │              │
          ▼                  ▼                  ▼              ▼
┌─────────────────────────────────────────────────────────────────────┐
│                        路由层 (Router)                               │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────┐ │
│  │ ChatService  │  │VisionService │  │  API Routes  │  │Scheduler │ │
│  │  (文本路由)   │  │  (图片识别)   │  │  (REST API)  │  │ (定时)   │ │
│  └──────────────┘  └──────────────┘  └──────────────┘  └──────────┘ │
└─────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────┐
│                     调度层 (SopEngine)                               │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │                    Skill 配置 (Postgres)                        │ │
│  │  • qc_process (质控流程)    • ae_detection (AE检测)             │ │
│  │  • inclusion_check (入排)   • protocol_deviation (方案偏离)     │ │
│  │  • ethics_check (伦理)      • weekly_report (周报)              │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                              │                                       │
│           ┌──────────────────┼──────────────────┐                   │
│           ▼                  ▼                  ▼                   │
│  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐            │
│  │HardRuleEngine│   │SoftRuleEngine│   │ReportService │            │
│  │  (CPU规则)    │   │  (LLM推理)   │   │  (报告生成)   │            │
│  └──────────────┘   └──────────────┘   └──────────────┘            │
└─────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────┐
│                     工具层 (ToolsService)                            │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐      │
│  │read_clinical_data│  │write_clinical_data│ │search_protocol  │      │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘      │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐      │
│  │check_visit_window│ │assess_ae_causality│ │check_ethics     │      │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘      │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐      │
│  │get_project_stats │ │manage_issue      │  │send_notification│      │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘      │
└─────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────┐
│                     适配器层 (Adapters)                              │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────┐ │
│  │RedcapAdapter │  │ DifyClient   │  │WechatAdapter │  │VLMAdapter│ │
│  │  (EDC数据)   │  │  (知识库)    │  │  (消息推送)   │  │ (视觉)   │ │
│  └──────────────┘  └──────────────┘  └──────────────┘  └──────────┘ │
└─────────────────────────────────────────────────────────────────────┘

1. 架构决策总结

本计划基于以下 5 份架构设计文档的综合审查:

文档 核心观点 状态
架构决策白皮书 放弃 MCP/复杂框架,采用 Postgres-Only + Service-First 认可
V2.2 实施指南 混合双引擎(硬规则 + 软指令)+ 用户偏好 认可
V2.2 工具泛化 3-5 个"瑞士军刀"通用工具替代 100 个专用工具 认可
V2.3 健壮性设计 三层防御(模糊映射 + 容错重试 + 空结果兜底) 认可
V2.4 SOP状态机 粗粒度 SOP 节点 + 节点内 ReAct 认可

1.1 最终架构选型:双脑路由模型

核心理念:左脑(SOP) 保证严谨合规,右脑(ReAct) 提供灵活智能

┌─────────────────────────────────────────────────────────────────────┐
│                        企业微信 / 前端入口                            │
│                    [文本消息]  [图片消息]  [定时触发]                   │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│                    🧠 意图路由层 (IntentService)                      │
│                         LLM 驱动,非正则匹配                          │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  输入: "帮我查下那个发烧的病人是谁?"                             │ │
│  │  输出: { type: "QA_QUERY", entities: {...}, needsClarification } │ │
│  └────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
          │                    │                    │
          ▼                    ▼                    ▼
┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
│ 📐 左脑 (SOP)     │  │ 🎨 右脑 (ReAct)  │  │ ❓ 追问机制       │
│   结构化任务      │  │   开放性查询     │  │   信息不全        │
│   写操作必经      │  │   只读不写       │  │   主动澄清        │
│                  │  │                  │  │                  │
│ • 质控流程       │  │ • 多步推理       │  │ • "请问您指的是   │
│ • 入排判断       │  │ • 模糊查询       │  │    哪位患者?"    │
│ • 数据录入       │  │ • 统计分析       │  │                  │
└──────────────────┘  └──────────────────┘  └──────────────────┘
          │                    │
          ▼                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│                         SopEngine (状态机)                           │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │ 节点A: HardRuleEngine  →  节点B: SoftRuleEngine  →  节点C: ... │ │
│  └────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│                     ToolsService (工具层)                            │
│  ┌─────────────────────────────────────────────────────────────┐    │
│  │  🔓 只读工具 (ReAct 可用)        │  🔒 读写工具 (仅 SOP 可用) │    │
│  │  • read_clinical_data           │  • write_clinical_data    │    │
│  │  • search_protocol              │  • manage_issue           │    │
│  │  • get_project_stats            │  • update_record          │    │
│  └─────────────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│                         适配器层 (Adapters)                          │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────┐ │
│  │RedcapAdapter │  │ DifyClient   │  │WechatAdapter │  │VLMAdapter│ │
│  └──────────────┘  └──────────────┘  └──────────────┘  └──────────┘ │
└─────────────────────────────────────────────────────────────────────┘

双脑对比

维度 左脑 (SOP 状态机) 右脑 (ReAct Agent)
擅长 执行标准流程、合规检查 处理模糊提问、多步查询
典型指令 "对 P001 进行入排质控" "帮我查下最近那个发烧的病人"
思维方式 线性执行 (Step 1 → Step 2) 循环推理 (思考→查库→再思考)
数据权限 读写皆可 只读 (Read-Only)
用户评价 "靠谱但死板" "聪明但不可控"

1.2 核心设计原则

原则 描述
Postgres-Only 无 Redis用 pg-boss 替代队列,用 Postgres 存储 Skill 配置
Service-First 不用 MCP Server用 Service Class 实现工具调用
混合双引擎 硬规则(CPU) + 软指令(LLM),能用规则的不用 AI
SOP 状态机 粗粒度节点控制流程,节点内 ReAct 保持灵活性
三层防御 字段映射 + 自我修正 + 空结果兜底

2. 现有代码资产盘点

2.1 已完成的组件

组件 路径 状态 备注
ChatService services/ChatService.ts 可复用 需扩展路由逻辑
SessionMemory agents/SessionMemory.ts 可复用 内存存储,支持过期清理
RedcapAdapter adapters/RedcapAdapter.ts 可复用 核心数据访问层
WechatService services/WechatService.ts 可复用 企业微信消息推送
DifyClient common/rag/DifyClient.ts 可复用 知识库检索
LLMFactory common/llm/adapters/LLMFactory.ts 可复用 统一 LLM 调用

2.2 待开发的组件

组件 优先级 说明
iit_skills P0 Skill 配置存储
iit_field_mapping P0 字段名映射字典
ToolsService P0 统一工具管理
HardRuleEngine P0 JSON Logic 执行器
SoftRuleEngine P1 LLM 推理 + 自我修正
SopEngine P1 状态机调度器
iit_user_preferences P2 用户偏好存储

3. 开发阶段规划

Phase 1基础设施层Week 1

Day 1-2数据库 Schema 扩展

目标:创建 Skill 配置和字段映射表

任务清单
  • T1.1 设计 iit_skills 表结构

    model IitSkill {
      id          String   @id @default(uuid())
      projectId   String   // 绑定项目
      skillType   String   // qc_process | daily_briefing | general_chat
      name        String   // 技能名称
      config      Json     // 核心配置 JSON
      isActive    Boolean  @default(true)
      version     Int      @default(1)
      createdAt   DateTime @default(now())
      updatedAt   DateTime @updatedAt
    
      @@unique([projectId, skillType])
      @@map("iit_skills")
      @@schema("iit_schema")
    }
    
  • T1.2 设计 iit_field_mapping 表结构

    model IitFieldMapping {
      id          String   @id @default(uuid())
      projectId   String   // 项目级别映射
      aliasName   String   // LLM 可能传的名称(如 "gender", "性别"
      actualName  String   // REDCap 实际字段名(如 "sex"
      createdAt   DateTime @default(now())
    
      @@unique([projectId, aliasName])
      @@map("iit_field_mapping")
      @@schema("iit_schema")
    }
    
  • T1.3 执行数据库迁移

    npx prisma db push
    npx prisma generate
    
  • T1.4 插入测试数据(第一个 Skill 配置)

验收标准

  • 表创建成功
  • 能正常 CRUD 操作
  • 测试 Skill 配置可查询

Day 3-4ToolsService 实现

目标:创建统一的工具管理层

任务清单
  • T2.1 创建 ToolsService.ts

    backend/src/modules/iit-manager/services/ToolsService.ts
    
  • T2.2 实现工具定义TOOL_DEFINITIONS

    export const TOOL_DEFINITIONS = [
      {
        name: "read_clinical_data",
        description: "读取 REDCap 临床数据",
        parameters: {
          type: "object",
          properties: {
            record_id: { type: "string" },
            fields: { type: "array", items: { type: "string" } }
          },
          required: ["record_id", "fields"]
        }
      },
      {
        name: "search_protocol",
        description: "检索研究方案文档",
        parameters: { ... }
      },
      {
        name: "manage_issue",
        description: "提出质疑或发送通知",
        parameters: { ... }
      },
      {
        name: "get_project_stats",
        description: "获取项目统计数据",
        parameters: { ... }
      }
    ];
    
  • T2.3 实现字段映射逻辑(第一层防御)

    private async mapFields(projectId: string, fields: string[]): Promise<string[]> {
      const mappings = await prisma.iitFieldMapping.findMany({
        where: { projectId }
      });
      const mappingDict = Object.fromEntries(
        mappings.map(m => [m.aliasName.toLowerCase(), m.actualName])
      );
      return fields.map(f => mappingDict[f.toLowerCase()] || f);
    }
    
  • T2.4 实现 executeTool() 统一入口

  • T2.5 实现空结果兜底(第三层防御)

验收标准

  • 4 个工具定义完成
  • 字段映射逻辑生效
  • 空结果返回友好消息

Day 5HardRuleEngine 实现

目标:创建 CPU 执行的硬规则引擎

任务清单
  • T3.1 安装 json-logic-js

    npm install json-logic-js
    npm install -D @types/json-logic-js
    
  • T3.2 创建 HardRuleEngine.ts

    backend/src/modules/iit-manager/engines/HardRuleEngine.ts
    
  • T3.3 实现规则执行逻辑

    import jsonLogic from 'json-logic-js';
    
    export class HardRuleEngine {
      run(rules: HardRule[], data: Record<string, any>): RuleResult[] {
        const errors: RuleResult[] = [];
    
        for (const rule of rules) {
          const passed = jsonLogic.apply(rule.logic, data);
          if (!passed) {
            errors.push({
              field: rule.field,
              message: rule.message,
              severity: rule.severity || 'error'
            });
          }
        }
    
        return errors;
      }
    }
    
  • T3.4 编写单元测试

验收标准

  • 能正确执行 { ">=": [{ "var": "age" }, 18] } 类规则
  • 返回结构化错误列表
  • 单元测试覆盖主要场景

Phase 2引擎层实现Week 2

Day 6-7SoftRuleEngine 实现

目标:创建 LLM 推理引擎(含自我修正)

任务清单
  • T4.1 创建 SoftRuleEngine.ts

    backend/src/modules/iit-manager/engines/SoftRuleEngine.ts
    
  • T4.2 实现自我修正回路(第二层防御)

    async runWithRetry(
      instruction: string,
      context: any,
      maxRetries: number = 3
    ): Promise<SoftRuleResult> {
      let history: Message[] = [...];
    
      for (let i = 0; i < maxRetries; i++) {
        const response = await this.llm.chat(history);
    
        if (response.hasToolCall) {
          try {
            const result = await this.tools.executeTool(
              response.toolName,
              response.args
            );
            history.push({ role: 'tool', content: JSON.stringify(result) });
          } catch (error) {
            // 自我修正:告诉 LLM 它错了
            history.push({
              role: 'user',
              content: `工具调用失败: ${error.message}。请检查参数并重试。`
            });
            continue;
          }
        } else {
          return this.parseResult(response.content);
        }
      }
    
      return { passed: false, reason: '多次重试后仍失败' };
    }
    
  • T4.3 实现结果解析(要求 LLM 返回结构化 JSON

  • T4.4 编写单元测试

验收标准

  • 能调用工具并获取结果
  • 工具失败时能自动重试
  • 返回结构化判断结果

Day 8-9SopEngine 实现

目标:创建 SOP 状态机调度器

任务清单
  • T5.1 创建 SopEngine.ts

    backend/src/modules/iit-manager/engines/SopEngine.ts
    
  • T5.2 定义 Skill 配置格式SOP 流程图)

    interface SopConfig {
      name: string;
      start_node: string;
      nodes: {
        [nodeId: string]: {
          type: 'hard_rule' | 'soft_instruction';
          // hard_rule 类型
          rules?: HardRule[];
          // soft_instruction 类型
          instruction?: string;
          tools?: string[];
          // 流转
          on_pass: string;
          on_fail: string;
          on_error?: string;
        }
      }
    }
    
  • T5.3 实现状态机执行逻辑

    async run(skillConfig: SopConfig, data: any): Promise<SopResult> {
      let currentNodeId = skillConfig.start_node;
      let context = { ...data };
      const trace: TraceItem[] = [];
    
      while (currentNodeId && !currentNodeId.startsWith('end')) {
        const node = skillConfig.nodes[currentNodeId];
        trace.push({ node: currentNodeId, timestamp: new Date() });
    
        let result: NodeResult;
    
        if (node.type === 'hard_rule') {
          result = this.hardEngine.run(node.rules, context);
        } else {
          result = await this.softEngine.runWithRetry(node.instruction, context);
        }
    
        // 状态流转
        currentNodeId = result.passed ? node.on_pass : node.on_fail;
    
        // 记录违规
        if (!result.passed) {
          await this.savePendingAction(result);
        }
      }
    
      return { trace, finalState: currentNodeId };
    }
    
  • T5.4 实现违规记录保存Shadow State

  • T5.5 编写集成测试

验收标准

  • 能按流程图顺序执行节点
  • 硬规则和软指令都能正确调度
  • 违规记录保存到 iit_pending_actions

Day 10ChatService 集成

目标:将 SopEngine 集成到现有 ChatService

任务清单
  • T6.1 扩展意图识别逻辑

    private detectIntent(message: string): Intent {
      // 识别质控任务
      if (/质控|检查|校验|QC/.test(message)) {
        return { type: 'qc_task', ... };
      }
      // 其他意图...
    }
    
  • T6.2 增加质控任务路由

    async handleMessage(userId: string, message: string): Promise<string> {
      const intent = this.detectIntent(message);
    
      if (intent.type === 'qc_task') {
        // 路由到 SopEngine
        return this.handleQcTask(userId, intent);
      }
    
      // 普通问答继续走原有逻辑
      return this.handleGeneralChat(userId, message);
    }
    
  • T6.3 实现 handleQcTask() 方法

验收标准

  • 质控任务走 SopEngine
  • 普通问答走原有 LLM 逻辑
  • 两条路径互不干扰

Phase 3配置与测试Week 3

Day 11-12第一个完整 Skill 配置

目标:配置第一个项目的质控流程

任务清单
  • T7.1 设计肺癌研究质控流程(示例)

    {
      "name": "肺癌研究入组质控",
      "start_node": "baseline_check",
      "nodes": {
        "baseline_check": {
          "type": "hard_rule",
          "rules": [
            { "field": "age", "logic": { ">=": [{"var":"age"}, 18] }, "message": "年龄<18岁" },
            { "field": "age", "logic": { "<=": [{"var":"age"}, 75] }, "message": "年龄>75岁" },
            { "field": "ecog", "logic": { "<=": [{"var":"ecog"}, 2] }, "message": "ECOG>2" }
          ],
          "on_pass": "history_check",
          "on_fail": "end_with_violation"
        },
        "history_check": {
          "type": "soft_instruction",
          "instruction": "检查既往史,排除间质性肺炎、活动性感染、严重心血管疾病。",
          "tools": ["read_clinical_data"],
          "on_pass": "medication_check",
          "on_fail": "end_review_required"
        },
        "medication_check": {
          "type": "soft_instruction",
          "instruction": "检查合并用药,排除其他抗肿瘤药物。",
          "tools": ["read_clinical_data"],
          "on_pass": "end_success",
          "on_fail": "end_review_required"
        }
      }
    }
    
  • T7.2 插入 Skill 配置到数据库

  • T7.3 配置字段映射

    INSERT INTO iit_field_mapping (project_id, alias_name, actual_name) VALUES
    ('project-uuid', 'age', 'age_calculated'),
    ('project-uuid', '年龄', 'age_calculated'),
    ('project-uuid', 'ecog', 'ecog_score'),
    ('project-uuid', '既往史', 'medical_history_text'),
    ('project-uuid', 'history', 'medical_history_text');
    

验收标准

  • Skill 配置存储成功
  • 字段映射配置完成

Day 13-14端到端测试

目标:完整流程测试

测试场景
场景 输入 期望输出
场景1年龄不合规 { "age": 16, "ecog": 1 } 触发硬规则违规,记录到 pending_actions
场景2病史违规 { "age": 30, "ecog": 1, "history": "间质性肺炎" } AI 识别违规,转人工复核
场景3全部通过 { "age": 45, "ecog": 0, "history": "无特殊" } 流程正常结束
场景4字段名映射 Agent 传 fields=["年龄"] 自动映射为 age_calculated
场景5工具失败重试 REDCap 返回空 Agent 收到友好提示,正确回复用户
任务清单
  • T8.1 编写端到端测试脚本
  • T8.2 通过企业微信发送测试消息
  • T8.3 验证 pending_actions 记录
  • T8.4 验证 audit_log 记录
  • T8.5 性能测试(目标 < 5秒响应

验收标准

  • 5 个测试场景全部通过
  • 响应时间 < 5秒
  • 日志完整可追溯

Day 15文档与收尾

任务清单
  • T9.1 更新 API 文档
  • T9.2 更新模块状态文档
  • T9.3 记录技术债务
  • T9.4 代码 Review 与合并

Phase 4定时任务与高级工具Week 4 前半)

目标:实现定时报告、高级质控工具

Day 16-17定时任务与报告生成

目标:实现每周自动生成研究进度报告

任务清单
  • T10.1 创建 SchedulerService.ts(基于 pg-boss

    backend/src/modules/iit-manager/services/SchedulerService.ts
    
  • T10.2 实现定时任务调度

    import PgBoss from 'pg-boss';
    
    export class SchedulerService {
      private boss: PgBoss;
    
      async init() {
        this.boss = new PgBoss(process.env.DATABASE_URL);
        await this.boss.start();
    
        // 注册周报任务处理器
        await this.boss.work('weekly-report', this.handleWeeklyReport.bind(this));
    
        // 每周一早上9点执行
        await this.boss.schedule('weekly-report', '0 9 * * 1', { projectId: 'all' });
      }
    
      private async handleWeeklyReport(job: Job) {
        const report = await this.reportService.generateWeeklyReport(job.data.projectId);
        await this.wechatService.sendToAdmins(report);
      }
    }
    
  • T10.3 创建 ReportService.ts

    backend/src/modules/iit-manager/services/ReportService.ts
    
  • T10.4 实现周报生成逻辑

    export class ReportService {
      async generateWeeklyReport(projectId: string): Promise<string> {
        const stats = await this.getProjectStats(projectId);
    
        const report = `
    

📊 ${stats.projectName} 周报 📅 ${stats.weekRange}

入组进度

  • 本周新入组:${stats.newEnrollments} 例
  • 累计入组:${stats.totalEnrollments} / ${stats.targetEnrollments} 例
  • 完成率:${stats.completionRate}%

数据质量

  • 待处理质疑:${stats.pendingQueries} 条
  • 本周关闭质疑:${stats.closedQueries} 条
  • 方案偏离:${stats.protocolDeviations} 例

AE/SAE

  • 本周新增 AE${stats.newAEs} 例
  • 本周新增 SAE${stats.newSAEs} 例

下周重点 ${stats.upcomingVisits.map(v => - ${v.patientId}: ${v.visitName} (${v.dueDate})).join('\n')} `;

  return report;
}

}


- [ ] **T10.5** 配置周报 Skill
```json
{
  "skillType": "weekly_report",
  "config": {
    "schedule": "0 9 * * 1",
    "recipients": ["admin_group"],
    "sections": ["enrollment", "data_quality", "ae_summary", "upcoming_visits"]
  }
}

验收标准

  • 每周一自动生成周报
  • 周报通过企业微信发送给管理员
  • 周报内容完整、格式美观

Day 18-19高级质控工具扩展

目标新增方案偏离、AE评估、伦理检查工具

任务清单
  • T11.1 新增 check_visit_window 工具(方案偏离检测)

    {
      name: "check_visit_window",
      description: "检查访视是否在方案允许的时间窗口内",
      parameters: {
        record_id: { type: "string" },
        visit_id: { type: "string" },
        actual_date: { type: "string", format: "date" }
      },
      handler: async (args) => {
        const baseline = await this.getBaselineDate(args.record_id);
        const window = await this.getVisitWindow(args.visit_id);
        const actualDays = this.daysBetween(baseline, args.actual_date);
    
        const inWindow = actualDays >= window.minDays && actualDays <= window.maxDays;
        return {
          inWindow,
          expectedRange: `Day ${window.minDays} - Day ${window.maxDays}`,
          actualDay: actualDays,
          deviation: inWindow ? 0 : Math.min(
            Math.abs(actualDays - window.minDays),
            Math.abs(actualDays - window.maxDays)
          )
        };
      }
    }
    
  • T11.2 新增 assess_ae_causality 工具AE因果关系评估

    {
      name: "assess_ae_causality",
      description: "评估不良事件与研究药物的因果关系",
      parameters: {
        record_id: { type: "string" },
        ae_id: { type: "string" }
      },
      handler: async (args) => {
        const ae = await this.getAEDetails(args.record_id, args.ae_id);
        const drugInfo = await this.getDrugExposure(args.record_id);
    
        // 使用 SoftRuleEngine 评估
        const assessment = await this.softEngine.runWithRetry(
          `根据以下信息评估AE与研究药物的因果关系
          AE信息${JSON.stringify(ae)}
          用药信息:${JSON.stringify(drugInfo)}
          请给出:肯定相关/可能相关/可能无关/肯定无关/无法评估`,
          { ae, drugInfo }
        );
    
        return assessment;
      }
    }
    
  • T11.3 新增 check_ethics_compliance 工具(伦理合规检查)

    {
      name: "check_ethics_compliance",
      description: "检查是否符合伦理要求",
      parameters: {
        record_id: { type: "string" },
        check_type: { 
          type: "string", 
          enum: ["informed_consent", "age_requirement", "vulnerable_population"]
        }
      },
      handler: async (args) => {
        const rules = {
          informed_consent: {
            logic: { "<=": [{ "var": "icf_date" }, { "var": "enrollment_date" }] },
            message: "入组日期早于知情同意签署日期"
          },
          age_requirement: {
            logic: { ">=": [{ "var": "age" }, 18] },
            message: "未成年受试者需要法定监护人签署同意书"
          }
        };
    
        const data = await this.getRecordData(args.record_id);
        return this.hardEngine.run([rules[args.check_type]], data);
      }
    }
    
  • T11.4 更新 ToolsService 工具列表

验收标准

  • 访视超窗能被正确检测
  • AE 因果关系能给出评估结论
  • 伦理违规能被识别

Phase 5智能化增强 - 双脑架构Week 4 后半 - Week 5

目标:实现 LLM 意图路由 + ReAct 多步推理 + 追问机制,让 Agent "懂人话"

优先级调整说明:智能化交互比视觉识别更影响用户留存,优先实现

Day 20-21意图路由层实现

目标:用 LLM 替代正则匹配,实现智能意图识别

任务清单
  • T12.1 创建 IntentService.ts

    backend/src/modules/iit-manager/services/IntentService.ts
    
  • T12.2 实现 LLM 驱动的意图识别

    export class IntentService {
      private llm;
    
      async detect(message: string, history: Message[]): Promise<IntentResult> {
        const prompt = `
    

你是一个临床研究助手的"分诊台"。请分析用户输入,返回 JSON。

用户输入: "${message}"

分类标准:

  1. QC_TASK: 明确的质控、检查、录入指令(如"检查P001的入排标准"
  2. QA_QUERY: 模糊的查询、分析、统计问题(如"查下那个发烧的病人是谁"
  3. PROTOCOL_QA: 关于研究方案的问题(如"访视窗口是多少天"
  4. UNCLEAR: 指代不清,缺少关键信息(如"他怎么样了?"

返回格式: { "type": "QC_TASK" | "QA_QUERY" | "PROTOCOL_QA" | "UNCLEAR", "confidence": 0.0-1.0, "entities": { "record_id": "...", "visit": "..." }, "missing_info": "如果 UNCLEAR说明缺什么信息", "clarification_question": "如果 UNCLEAR生成追问句" }`;

  const response = await this.llm.chat([
    { role: 'system', content: prompt },
    ...history.slice(-3),
    { role: 'user', content: message }
  ]);
  
  return JSON.parse(response.content);
}

}


- [ ] **T12.3** 实现降级策略LLM 不可用时回退关键词匹配)
```typescript
async detectWithFallback(message: string, history: Message[]): Promise<IntentResult> {
  try {
    return await this.detect(message, history);
  } catch (error) {
    logger.warn('[IntentService] LLM 不可用,回退到关键词匹配');
    return this.keywordFallback(message);
  }
}

private keywordFallback(message: string): IntentResult {
  if (/质控|检查|校验|QC|入排/.test(message)) {
    return { type: 'QC_TASK', confidence: 0.6, entities: {} };
  }
  return { type: 'QA_QUERY', confidence: 0.5, entities: {} };
}
  • T12.4 集成到 ChatService 路由层

验收标准

  • "查下那个发烧的病人" → 识别为 QA_QUERY
  • "对 P001 进行入排质控" → 识别为 QC_TASK
  • "他怎么样了" → 识别为 UNCLEAR生成追问句
  • LLM 服务中断时自动降级

Day 22-23ReAct Agent 实现

目标:创建多步推理引擎,支持循环思考和工具调用

任务清单
  • T13.1 创建 ReActEngine.ts

    backend/src/modules/iit-manager/engines/ReActEngine.ts
    
  • T13.2 实现 ReAct 循环(思考→行动→观察→再思考)

    export class ReActEngine {
      private maxIterations = 5;  // 防止死循环
      private maxTokens = 4000;   // Token 预算限制
      private tokenCounter = 0;
    
      // 工具白名单ReAct 只能调用只读工具
      private readonly READONLY_TOOLS = [
        'read_clinical_data',
        'search_protocol', 
        'get_project_stats',
        'check_visit_window'
      ];
    
      async run(query: string, context: AgentContext): Promise<ReActResult> {
        const systemPrompt = `你是一个临床研究智能助手。你可以使用以下工具回答问题:
    

${this.formatToolDescriptions(this.READONLY_TOOLS)}

请按照 ReAct 模式思考:

  1. 思考:分析问题,决定下一步
  2. 行动:调用工具获取信息
  3. 观察:查看工具返回结果
  4. 重复以上步骤,直到能回答用户问题

注意:你只能查询数据,不能修改数据。如果用户需要修改操作,请引导他们使用正式的质控流程。`;

  let messages: Message[] = [
    { role: 'system', content: systemPrompt },
    { role: 'user', content: query }
  ];
  
  const trace: TraceItem[] = [];
  
  for (let i = 0; i < this.maxIterations; i++) {
    // Token 预算检查
    if (this.tokenCounter > this.maxTokens) {
      return { 
        success: false, 
        content: '抱歉,这个问题比较复杂,请尝试更具体的描述。',
        trace 
      };
    }
    
    const response = await this.llm.chat(messages, { 
      tools: this.getReadonlyToolDefinitions() 
    });
    
    this.tokenCounter += response.usage?.total_tokens || 0;
    trace.push({ iteration: i, response: response.content });
    
    // AI 决定结束
    if (!response.toolCalls || response.toolCalls.length === 0) {
      return { success: true, content: response.content, trace };
    }
    
    // 执行工具调用
    let errorCount = 0;
    for (const toolCall of response.toolCalls) {
      // 安全检查:只允许只读工具
      if (!this.READONLY_TOOLS.includes(toolCall.name)) {
        messages.push({
          role: 'tool',
          toolCallId: toolCall.id,
          content: `错误:工具 ${toolCall.name} 不在允许列表中。你只能使用只读工具。`
        });
        errorCount++;
        continue;
      }
      
      try {
        const result = await this.tools.executeTool(toolCall.name, toolCall.args);
        messages.push({
          role: 'tool',
          toolCallId: toolCall.id,
          content: JSON.stringify(result)
        });
      } catch (error) {
        errorCount++;
        messages.push({
          role: 'tool',
          toolCallId: toolCall.id,
          content: `工具调用失败: ${error.message}`
        });
      }
    }
    
    // 幻觉熔断:连续 2 次工具调用全部失败
    if (errorCount >= 2) {
      return {
        success: false,
        content: '抱歉,我遇到了一些技术问题,无法获取相关信息。请稍后重试或联系管理员。',
        trace
      };
    }
  }
  
  return { 
    success: false, 
    content: '抱歉,我无法在有限步骤内完成这个查询。请尝试更具体的问题。',
    trace 
  };
}

}


- [ ] **T13.3** 实现 trace 日志记录(调试用)
```typescript
private async saveTrace(userId: string, query: string, trace: TraceItem[]) {
  await prisma.iitAgentTrace.create({
    data: {
      userId,
      query,
      trace: JSON.stringify(trace),
      createdAt: new Date()
    }
  });
}
  • T13.4 编写单元测试

验收标准

  • "最近入组的女性患者平均年龄" → 自动调用工具查询并计算
  • 连续工具失败时触发熔断
  • Token 超预算时优雅终止
  • 尝试调用写工具时被拦截

Day 24追问机制与上下文增强

目标:信息不全时主动追问,增强上下文记忆

任务清单
  • T14.1 实现追问机制

    // ChatService 中的追问逻辑
    async handleMessage(userId: string, message: string): Promise<string> {
      const history = this.sessionMemory.getHistory(userId);
      const intent = await this.intentService.detect(message, history);
    
      // 信息不全,主动追问
      if (intent.type === 'UNCLEAR') {
        const clarification = intent.clarification_question 
          || `请问您能具体说明一下吗?例如:${this.getSuggestions(intent)}`;
    
        this.sessionMemory.addMessage(userId, 'assistant', clarification);
        return clarification;
      }
    
      // 根据意图路由
      if (intent.type === 'QC_TASK') {
        return this.sopEngine.run(intent);
      } else {
        return this.reactEngine.run(message, { history, intent });
      }
    }
    
  • T14.2 增强 SessionMemory支持实体记忆

    export class SessionMemory {
      // 新增:记住对话中提到的实体
      private entityMemory: Map<string, EntityContext> = new Map();
    
      addEntityContext(userId: string, entities: Record<string, any>) {
        const existing = this.entityMemory.get(userId) || {};
        this.entityMemory.set(userId, { ...existing, ...entities });
      }
    
      resolveReference(userId: string, reference: string): string | null {
        const context = this.entityMemory.get(userId);
        if (!context) return null;
    
        // 解析 "他"、"这个患者" 等指代
        if (['他', '她', '这个患者', '那个病人'].includes(reference)) {
          return context.lastMentionedPatient;
        }
        return null;
      }
    }
    
  • T14.3 实现指代消解

    // 在处理消息前,先解析指代
    private resolveReferences(userId: string, message: string): string {
      const pronouns = ['他', '她', '这个患者', '那个病人'];
      let resolved = message;
    
      for (const pronoun of pronouns) {
        if (message.includes(pronoun)) {
          const actual = this.sessionMemory.resolveReference(userId, pronoun);
          if (actual) {
            resolved = resolved.replace(pronoun, actual);
          }
        }
      }
    
      return resolved;
    }
    

验收标准

  • "他怎么样了" → 回复 "请问您指的是哪位患者?"
  • 如果上文提到 P001"他怎么样了" → 自动解析为 P001
  • 对话上下文在会话内保持连贯

Day 25集成测试与优化

目标:完成双脑架构的完整测试

测试场景Phase 5
场景 输入 期望输出
场景6模糊查询 "查下最近入组的病人" ReAct 自动查询并返回列表
场景7多步推理 "最近入组的女性平均年龄" 多步工具调用 + 计算结果
场景8追问 "他怎么样了" "请问您指的是哪位患者?"
场景9指代消解 (上文提到P001) "他的入排状态" 自动识别为 P001
场景10写操作拦截 (ReAct中) 尝试修改数据 被拦截并引导到 SOP 流程
场景11熔断 连续工具失败 优雅终止并提示
任务清单
  • T15.1 编写 Phase 5 测试脚本
  • T15.2 验证意图识别准确率(目标 > 85%
  • T15.3 验证 ReAct 多步推理成功率
  • T15.4 验证追问机制用户体验

验收标准

  • 11 个测试场景全部通过
  • 意图识别准确率 > 85%
  • ReAct 平均迭代次数 < 3
  • 用户反馈"不再觉得像傻子"

Phase 6视觉能力Week 6

目标:支持拍照上传 → 识别 → 自动录入 REDCap

Day 26-27视觉能力集成

目标:支持拍照上传 → 识别 → 自动录入 REDCap

任务清单
  • T16.1 创建 VisionService.ts

    backend/src/modules/iit-manager/services/VisionService.ts
    
  • T16.2 集成视觉大模型(推荐 Qwen-VL / GPT-4V

    export class VisionService {
      private vlmAdapter: VLMAdapter;
    
      async extractFromImage(imageUrl: string, projectId: string): Promise<ExtractedData> {
        // 1. 调用视觉模型识别内容
        const rawText = await this.vlmAdapter.recognize(imageUrl);
    
        // 2. 结构化提取
        const structured = await this.structureData(rawText, projectId);
    
        // 3. 匹配表单
        const formMatch = await this.matchForm(structured, projectId);
    
        return { rawText, structured, formMatch };
      }
    }
    
  • T16.3 创建表单模板表 iit_form_templates

    model IitFormTemplate {
      id          String   @id @default(uuid())
      projectId   String
      formName    String   // REDCap 表单名称
      fieldSchema Json     // 表单字段结构
      keywords    String[] // 用于匹配的关键词
      createdAt   DateTime @default(now())
    
      @@map("iit_form_templates")
      @@schema("iit_schema")
    }
    
  • T16.4 扩展 RedcapAdapter.writeRecord() 写入能力

  • T16.5 ChatService 增加图片消息路由

验收标准

  • 上传化验单图片能识别内容
  • 自动匹配到正确的 REDCap 表单
  • 高置信度时自动录入,低置信度时人工确认

Day 28最终集成测试

目标:完成全部场景测试

测试场景(全量)
场景 输入 期望输出
场景12拍照识别 上传化验单图片 识别内容,匹配表单,自动录入
场景13访视超窗 V3 访视超出窗口期 5 天 检测到方案偏离
场景14AE评估 SAE 事件数据 给出因果关系评估
场景15伦理违规 ICF 日期晚于入组日期 识别伦理违规
场景16周报生成 触发定时任务 生成并发送周报
任务清单
  • T17.1 编写全量测试脚本
  • T17.2 验证视觉识别准确率(目标 > 85%
  • T17.3 性能优化(图片处理 < 10s
  • T17.4 更新文档和部署指南

验收标准

  • 16 个测试场景全部通过
  • 图片识别准确率 > 85%
  • 定时任务连续运行 7 天无故障

4. 风险与应对

4.1 基础架构风险

风险 影响 应对措施
JSON Logic 表达能力不足 复杂规则无法配置 支持 function_name 模式,调用预定义函数
LLM 响应慢 用户体验差 硬规则先行,减少 LLM 调用
字段映射字典不全 工具调用失败 自我修正回路 + 日志记录 + 运营补充
REDCap 不可用 流程中断 增加 on_error 分支,友好提示

4.2 双脑架构风险 (Phase 5)

风险 影响 应对措施
意图识别错误 路由到错误分支 置信度阈值 + 低置信度时追问确认
ReAct 死循环 烧钱、用户等待 最大迭代次数 = 5Token 预算 = 4000
ReAct 调用写工具 数据被误改 工具白名单,只允许只读工具
LLM 幻觉 返回错误信息 连续 2 次工具失败触发熔断
LLM 服务中断 无法响应 降级到关键词匹配 + 友好提示
Token 成本失控 费用超预算 Token 计数 + 单次查询预算限制

4.3 扩展能力风险 (Phase 4 & 6)

风险 影响 应对措施
视觉模型识别错误 录入错误数据 低置信度人工确认,高置信度才自动录入
定时任务失败 周报未发送 pg-boss 自动重试 + 失败告警
图片处理超时 用户体验差 异步处理 + 进度提示

5. 成功标准

Phase 1-3 验收标准(核心质控)

  • 企业微信发送"质控 ID=001"3秒内收到回复
  • 硬规则违规能自动识别并记录
  • 软指令能正确调用工具并判断
  • 字段名映射生效
  • 工具失败能自动重试
  • 违规记录可在后台查看

Phase 4 验收标准(定时任务与高级工具)

  • 访视超窗能被自动检测并记录
  • AE 事件能给出因果关系评估
  • 伦理违规能被识别并告警
  • 每周一自动生成并发送周报
  • 定时任务连续运行 7 天无故障

Phase 5 验收标准(双脑架构)

  • 自然语言意图识别准确率 > 85%
  • "查下最近入组的病人" → ReAct 自动查询返回
  • "他怎么样了" → 主动追问 "请问您指的是哪位患者?"
  • 上文提到 P001 后,"他的状态" → 自动识别为 P001
  • ReAct 尝试调用写工具 → 被拦截并引导到 SOP
  • LLM 服务中断 → 自动降级到关键词匹配
  • 用户反馈:"不再觉得 Agent 像个傻子"

Phase 6 验收标准(视觉能力)

  • 拍照上传化验单,自动识别并录入 REDCap
  • 图片识别准确率 > 85%
  • 低置信度时要求人工确认

性能指标

指标 目标值
硬规则执行时间 < 100ms
软指令执行时间 < 3s
端到端响应时间 < 5s
意图识别时间 < 1s
ReAct 平均迭代次数 < 3
图片识别+录入时间 < 10s
视觉识别准确率 > 85%
意图识别准确率 > 85%
自我修正成功率 > 80%

6. 附录:文件路径清单

backend/src/modules/iit-manager/
├── services/
│   ├── ChatService.ts          # 扩展路由逻辑(双脑路由)
│   ├── IntentService.ts        # 新建LLM 意图识别 (Phase 5)
│   ├── ToolsService.ts         # 新建:统一工具管理
│   ├── SchedulerService.ts     # 新建:定时任务调度 (Phase 4)
│   ├── ReportService.ts        # 新建:报告生成服务 (Phase 4)
│   ├── VisionService.ts        # 新建:视觉识别服务 (Phase 6)
│   └── WechatService.ts        # 已存在
├── engines/
│   ├── HardRuleEngine.ts       # 新建JSON Logic 执行器
│   ├── SoftRuleEngine.ts       # 新建LLM 推理引擎
│   ├── SopEngine.ts            # 新建:状态机调度器
│   └── ReActEngine.ts          # 新建:多步推理引擎 (Phase 5)
├── agents/
│   └── SessionMemory.ts        # 已存在,扩展实体记忆 (Phase 5)
├── adapters/
│   ├── RedcapAdapter.ts        # 已存在,扩展 writeRecord()
│   └── VLMAdapter.ts           # 新建:视觉大模型适配器 (Phase 6)
└── types/
    └── index.ts                # 扩展类型定义

数据库新增表

iit_schema.iit_skills           # Skill 配置存储
iit_schema.iit_field_mapping    # 字段名映射
iit_schema.iit_agent_trace      # ReAct 推理轨迹 (Phase 5)
iit_schema.iit_form_templates   # 表单模板 (Phase 6)

7. 参考文档

  1. 架构决策白皮书:极简主义的胜利
  2. V2.2 落地实施指南
  3. V2.2 工具泛化与灵活性提升指南
  4. V2.3 健壮性设计与最佳实践
  5. V2.4 架构模式选型与 SOP 状态机推荐
  6. V2.6 智能化升级方案:双脑架构

文档维护人AI Agent
最后更新2026-02-02V2.6 整合双脑架构)