# Protocol Agent 2.0 开发计划 — 工作流驱动的智能对话 Agent > **版本:** v2.0 > **日期:** 2026-03-01 > **核心定位:** 将 6 个验证过的子 Agent 聚合为一个工作流驱动的研究方案制定智能体 > **架构模式:** 智能拼图板(工作流编排层 + 对话智能层 双层融合) > **前置文档:** > - `00-模块当前状态与开发指南.md`(AIA 模块全貌) > - `04-Protocol_Agent开发计划/`(V1.0 MVP 设计) > - `06-开发记录/2026-01-24-Protocol_Agent_MVP开发完成.md` > - `06-开发记录/2026-01-25-Protocol_Agent_MVP完整交付.md` --- ## 1. 为什么需要 2.0 ### 1.1 V1.0 MVP 的测试反馈(11 个问题) | # | 问题 | 根因 | |---|------|------| | 0 | 段落序号全为 "1." | Markdown 渲染 Bug | | 1 | 说了队列研究,同步时还是显示 RCT | 上下文未注入已确认数据 | | 2 | 未确认参数就可以同步,内容是 AI 编造的 | 同步按钮触发逻辑依赖关键词匹配 | | 3 | 已确认的信息被重复讨论 | 历史消息注入方式低效 | | 4 | 观察指标阶段 AI 又绕回样本量 | 阶段控制完全依赖 Prompt 约束 | | 5 | 不联系对话上下文(PICO 阶段说过的数据收集时间点在研究设计又问) | 阶段间上下文未传递 | | 6 | 发送参数后又要求重复提供 | `take: 20` 历史消息截断关键信息 | | 7 | 完成样本量计算后仍然说"正式进入样本量计算阶段" | LLM 无视 system prompt 的阶段指令 | | 8 | 纠正后能回到正确方向,下一条消息又回退 | LLM 无法可靠维持阶段状态 | | 9 | 正在进行观察指标设计,又回到样本量计算 | 同上,Prompt 约束不可靠 | | 10 | 同步到右侧的内容与对话讨论内容不一致 | `condenseStageData` 二次 LLM 调用改变了数据 | ### 1.2 V1.0 架构的 5 个根本缺陷 1. **编排器被绕过**:`ProtocolAgentController.sendMessage` 直接调用 LLM,未经过 `BaseAgentOrchestrator`,Agent 框架形同虚设 2. **阶段管理 100% 靠 Prompt**:`buildSystemPrompt` 用"禁止事项"约束 LLM,LLM 经常违反 3. **`` 机制脆弱**:依赖 LLM 在对话中输出 XML 标签,前端解析后触发同步 4. **历史消息注入低效**:`take: 20` 原始消息不分阶段全部注入,浪费 Token 且丢失关键上下文 5. **未复用已验证的子 Agent 提示词**:用一个通用 `buildSystemPrompt` 取代了 6 个经过专家验证的提示词 ### 1.3 核心设计理念 > **一句话定义:** Protocol Agent 2.0 = **工作流驱动的智能对话 Agent** > > - **工作流层**(智能拼图板)定义 6 块必须完成的"拼图",但**不强制填充顺序**,用户可以从任意话题切入 > - **对话智能层**保证用户交互的自然性和灵活性(来自 SSA 模式的核心思想:用户驱动对话流,系统智能填补空白) > - **验证过的提示词**保证每个阶段的专业深度(复用已有 6 个子 Agent) > - **双层依赖模型**保证方法学严谨性(软依赖允许开始聊,硬依赖守卫最终同步) > > **核心隐喻**:6 块拼图可以任意顺序完成,但每块拼图内部由经过专家验证的 AI 专家坐诊。 --- ## 2. 架构设计 ### 2.1 智能拼图板架构 ``` ┌─────────────────────────────────────────────────────────────────────┐ │ Layer 1: 工作流编排层 — 智能拼图板 (WorkflowOrchestrator) │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ ① 科学问题│ │ ② PICO │ │ ③ 选题评价│ 第一阶:定问题 │ │ │ ██░░ 40% │ │ ████ 85%│ │ ░░░░ 0% │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ ④ 研究设计│ │ ⑤ 观察指标│ │ ⑥ 样本量 │ 第二阶:做设计 │ │ │ ██░░ 50% │ │ ░░░░ 0% │ │ ░░░░ 0% │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ SmartFocus: 当前聚焦 → ② PICO(建议,非强制) │ │ 用户可随时切换到任意阶段讨论 │ │ │ │ 依赖关系(软约束): │ │ 科学问题 ─soft→ PICO ─soft→ 选题评价 │ │ │ │ │ └─soft→ 研究设计 ─soft→ 观察指标 ─soft→ 样本量 │ │ │ │ 同步守卫(硬约束): │ │ 同步样本量 ←hard─ 研究设计已确认 + 主要指标已确认 │ └──────────────────────┬──────────────────────────────────────────────┘ │ 每次对话 ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ Layer 2: 对话智能层 (ConversationIntelligence) │ │ │ │ ┌────────────┐ ┌───────────────────┐ ┌──────────────────┐ │ │ │ Opening │ │ Intent │ │ Prompt │ │ │ │ Analyzer │→ │ Router │→ │ Selector │ │ │ │ (首条消息) │ │ (7 种意图) │ │ (依赖感知选择) │ │ │ └────────────┘ └───────────────────┘ └────────┬─────────┘ │ │ │ │ │ ▼ │ │ ┌───────────────────┐ ┌────────────────────────────────────┐ │ │ │ Conversation │ │ Post-Process Pipeline │ │ │ │ Service │→ │ GlobalExtract → CheckProgress │ │ │ │ (验证提示词 + │ │ → SmartFocus → SyncGuard? │ │ │ │ 黑板上下文注入) │ └────────────────────────────────────┘ │ │ └───────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ ProtocolBlackboard (Session 黑板 — 单一真相源) │ │ │ │ 科学问题 ██░░ 40% PICO ████ 85% 🔄 选题评价 ░░░░ 0% │ │ │ │ 研究设计 ██░░ 50% 观察指标 ░░░░ 0% 样本量 ░░░░ 0% │ │ │ └──────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────┘ ``` ### 2.2 核心组件职责 | 组件 | 层级 | 职责 | 复用来源 | |------|------|------|---------| | **WorkflowOrchestrator** | 工作流层 | 管理 6 阶段拼图板、依赖关系(软/硬)、SmartFocus 推荐 | 新建 | | **StageRegistry** | 工作流层 | 注册 6 个阶段的提示词、输出 Schema、完成标准、软硬依赖 | 新建(消费已有 Prompt) | | **OpeningAnalyzer** | 对话智能层 | 首条消息分析,判定开场模式(新手/有经验/跳阶段),初始化黑板 | 新建 | | **IntentRouter** | 对话智能层 | 轻量级意图分类(7 种意图) | 参考 SSA IntentRouterService | | **PromptSelector** | 对话智能层 | 根据 focusStage + 前提条件选择 Prompt 策略(完整模式/依赖感知模式) | 新建 | | **ConversationService** | 对话智能层 | 组装 system prompt + 黑板上下文 + 对话历史 → LLM 流式生成 | 参考 SSA ConversationService | | **ProtocolBlackboard** | 对话智能层 | 统一存储所有阶段的结构化数据(单一真相源) | 参考 SSA SessionBlackboard | | **GlobalExtractTool** | 对话智能层 | 每次 AI 回复后全域提取(可同时更新多个阶段黑板) | 新建 | | **CheckProgressTool** | 对话智能层 | 评估各阶段完整度 + 硬依赖守卫 | 新建 | | **SyncElementTool** | 对话智能层 | 用户确认后同步数据到方案(含硬依赖校验) | 重构现有 sync | ### 2.3 阶段定义与验证提示词映射 | # | 阶段 | Prompt Code | 输出 Schema | 完成标准 | |---|------|-------------|-------------|---------| | 1 | 科学问题梳理 | `AIA_SCIENTIFIC_QUESTION` | `{ content: string }` | content 非空且 ≥30 字 | | 2 | PICO 梳理 | `AIA_PICO_ANALYSIS` | `{ population, intervention, comparison, outcome }` | 4 字段均非空 | | 3 | 选题评价 | `AIA_TOPIC_EVALUATION` | `{ feasibility, novelty, significance, summary }` | summary 非空 | | 4 | 研究设计 | 新建 `PA_STUDY_DESIGN`(基于验证提示词适配) | `{ studyType, designFeatures[], details }` | studyType 非空 | | 5 | 观察指标设计 | `AIA_OUTCOME_DESIGN` | `{ outcomes: { primary[], secondary[], safety[] }, confounders[] }` | primary 至少 1 项 | | 6 | 样本量计算 | `AIA_SAMPLE_SIZE` | `{ sampleSize, calculation: { alpha, power, effectSize }, rationale }` | sampleSize > 0 | > **关键原则**:验证过的提示词从 `capability_schema.prompt_templates` 数据库加载(通过 `PromptService`),不硬编码在 TypeScript 中。进入方式变了(拼图板而非流水线),但阶段内部仍加载对应的验证提示词。 ### 2.4 意图分类(7 种) | 意图 | 触发示例 | 处理方式 | |------|---------|---------| | `chat` | "队列研究和 RCT 有什么区别" | focusStage 提示词 + 黑板上下文 → LLM 直接回答 | | `provide_info` | "研究人群是 45-75 岁冠心病患者" | LLM 回复 + 全域提取 → 更新黑板 | | `multi_stage_input` | "做老年冠心病队列研究,看出血事件发生率" | LLM 回复 + 全域提取(多阶段同时更新)→ SmartFocus 推荐聚焦 | | `ask_guidance` | "下一步该讨论什么" / "还缺什么" | check_progress → LLM 引导回复 | | `confirm_sync` | "确认" / 点击同步按钮 | sync_element(含硬依赖守卫)→ SmartFocus 切换 | | `generate` | "帮我生成完整方案" | 校验全局完整度 → 生成全文 | | `revise` | "PICO 的人群描述要改一下" | 定位目标阶段和要素 → 更新黑板 → LLM 确认 | 意图识别采用**规则优先 + LLM 兜底**策略(与 SSA 一致),规则配置放在 `intent_rules.json`。 `multi_stage_input` 与 `provide_info` 的区别:前者的用户消息涉及多个阶段的信息(通过规则或 LLM 判断消息中包含多个阶段关键词),全域提取会扫描所有阶段 Schema;后者只涉及当前 focusStage。 ### 2.5 核心对话流程(全域提取 + 智能聚焦) ``` 用户发送消息 │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 1. IntentRouter.classify(message, blackboard) │ │ → chat / provide_info / multi_stage_input / │ │ ask_guidance / confirm_sync / generate / revise │ │ │ │ 如果是会话首条消息 → 先经过 OpeningAnalyzer(见 2.8 节) │ └──────────┬──────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 2. PromptSelector.select(focusStage, blackboard) │ │ │ │ 检查 focusStage 的软依赖是否满足: │ │ │ │ 情况 A — 前提充足(软依赖满足): │ │ mode = 'full_stage' │ │ → 直接加载 focusStage 的验证提示词 │ │ → 如 AIA_SAMPLE_SIZE │ │ │ │ 情况 B — 前提不足(软依赖缺失): │ │ mode = 'dependency_aware' │ │ → 加载 focusStage 的验证提示词作为专业知识参考 │ │ → 额外注入依赖感知指令: │ │ "用户希望讨论样本量计算。以下前提信息尚未收集: │ │ - 研究设计类型 - 主要观察指标 │ │ 围绕用户目标,自然地引导收集上述信息。" │ │ │ │ 随着对话推进、黑板填充,情况 B 自然过渡到情况 A(用户无感知)│ └──────────┬──────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 3. ConversationService.buildMessages() │ │ │ │ system = PromptSelector 选择的提示词组合 │ │ + 全黑板状态摘要(每个阶段一两句话,自然语言) │ │ + focusStage 阶段内已收集的数据 │ │ │ │ history = focusStage 阶段内的对话历史 │ │ (滑动窗口 ≤15 轮,不含其他阶段的对话) │ │ │ │ user = 用户消息 │ └──────────┬──────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 4. LLM 流式生成回复(createStreamingService) │ │ 使用通用 StreamingService(OpenAI Compatible) │ └──────────┬──────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 5. 后处理管线(流式完成后执行) │ │ │ │ a. GlobalExtractTool.extract( │ │ recentMessages, │ │ allStageSchemas ← 全域扫描,非仅 focusStage │ │ ) │ │ → 独立 LLM 调用(temperature=0.1, Zod 校验) │ │ → 一次提取,多阶段黑板同时更新 │ │ → 例:用户说"做队列研究看出血事件" │ │ → study_design.data.studyType = "队列研究" │ │ → endpoints.data.primary = ["出血事件发生率"] │ │ │ │ b. CheckProgressTool.check(blackboard) │ │ → 纯规则计算(确定性逻辑,无 LLM) │ │ → 返回:每个阶段的 completeness%, readyToSync │ │ → readyToSync 需同时满足: │ │ ✅ 本阶段完整度达标(completionRules) │ │ ✅ 硬依赖的前序阶段已 confirmed │ │ │ │ c. SmartFocus.recommend(blackboard, userMessage) │ │ → 计算下一步建议聚焦的阶段(见 2.6 节) │ │ │ │ d. 如果某阶段 readyToSync == true │ │ → 前端显示该阶段的同步按钮(含预览数据,可编辑) │ │ │ │ e. 保存 AI 回复到 messages 表(metadata 含 stageCode) │ │ f. 更新 conversation.updatedAt │ └─────────────────────────────────────────────────────────────┘ ``` ### 2.6 SmartFocus 智能聚焦机制 SmartFocus 替代了 V1.0 的固定 `advanceStage`,它**建议**聚焦阶段但**不强制**。 ``` SmartFocus.recommend(blackboard, userMessage) │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 优先级规则(从高到低): │ │ │ │ P0: 用户明确要求的阶段 │ │ "我们聊聊样本量" → focusStage = sample_size │ │ "PICO 的人群描述要改" → focusStage = pico │ │ │ │ P1: 用户刚同步完的阶段的下一个推荐阶段 │ │ 刚同步完 PICO → 推荐 topic_evaluation 或 study_design │ │ │ │ P2: 完整度最低的、且软依赖已满足的阶段 │ │ 科学问题 40% + PICO 85% → 推荐先补完科学问题 │ │ │ │ P3: 完整度已高但未确认的阶段(建议确认同步) │ │ PICO 85% 且未 confirmed → "PICO 信息已较完整, │ │ 建议确认后同步到方案" │ │ │ │ → 输出: suggestedFocusStage + reason │ │ → 以系统提示的方式告知用户(非强制切换) │ │ → 用户下一条消息可以接受建议,也可以继续聊其他话题 │ └─────────────────────────────────────────────────────────────┘ ``` **focusStage 切换时机**: | 场景 | 切换行为 | |------|---------| | 用户对话内容明确指向某阶段 | 自动切换(IntentRouter 识别) | | 用户点击同步按钮 | 同步完成后,SmartFocus 推荐下一个 | | 用户说"继续"/"下一步" | SmartFocus 自动推荐 | | 用户持续在当前阶段对话 | 不切换 | ### 2.7 阶段同步与回溯机制 ``` 用户点击"同步到方案" │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ SyncElementTool.sync(stageCode, confirmedData) │ │ │ │ 1. 硬依赖守卫 canSync(): │ │ 检查该阶段的硬依赖是否全部满足 │ │ │ │ ❌ 不满足 → 返回友好提示 + 快捷操作: │ │ "样本量计算结果同步前,需先确认研究设计和主要观察指标。 │ │ [快速确认研究设计] [快速确认观察指标]" │ │ │ │ ✅ 满足 → 继续: │ │ 2. 将数据写入 ProtocolBlackboard(标记 confirmed) │ │ 3. 写入 protocol_contexts 表持久化 │ │ 4. SmartFocus.recommend() → 推荐下一个聚焦阶段 │ │ 5. 前端更新 StatePanel 进度 │ └─────────────────────────────────────────────────────────────┘ ``` **回溯机制**(与原方案一致): ``` 用户修改已确认的阶段数据(通过 StatePanel 编辑按钮或对话中 revise 意图) │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ WorkflowOrchestrator.handleRevision(targetStage) │ │ │ │ 策略 A(小修改,不影响后续阶段): │ │ → 直接更新黑板对应字段 │ │ → 不切换 focusStage │ │ → LLM 回复确认修改 │ │ │ │ 策略 B(大修改,影响后续阶段的依赖): │ │ → 更新黑板 │ │ → 将受影响的后续阶段标记为 needs_review │ │ → 提示用户: "人群范围的变化可能影响研究设计, │ │ 建议重新确认研究设计。" │ │ → 不强制回溯,由用户决定 │ └─────────────────────────────────────────────────────────────┘ ``` ### 2.8 开场模式自适应(OpeningAnalyzer) 用户的第一条消息由 OpeningAnalyzer 分析,自适应三种开场模式: ``` 用户首条消息 │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ OpeningAnalyzer.analyze(firstMessage) │ │ │ │ 模式 A: 新手 / 空白开场 │ │ 触发: "我想做一个研究" / "你好" / 消息 < 20 字且无专业术语 │ │ 处理: │ │ → focusStage = scientific_question │ │ → 引导式对话: "请先告诉我你想研究什么问题?" │ │ │ │ 模式 B: 有经验 / 信息丰富开场 │ │ 触发: "做老年冠心病患者队列研究,看出血事件发生率" │ │ 消息含多个阶段的关键信息 │ │ 处理: │ │ → GlobalExtract 全域提取 → 多阶段黑板同时填充 │ │ → focusStage = 最需要补充的阶段 │ │ → "我已记录到您的研究主题和设计方向。 │ │ 目前 PICO 中的对照组还未明确,我们来确认一下?" │ │ │ │ 模式 C: 明确跳阶段 │ │ 触发: "科学问题和 PICO 已确定,直接做研究设计" │ │ 明确表示跳过某些阶段 │ │ 处理: │ │ → 在 StatePanel 显示待确认项(快速录入界面) │ │ → focusStage = 用户指定的阶段 │ │ → 对于已跳过的阶段,提示"可在 StatePanel 中补充" │ └─────────────────────────────────────────────────────────────┘ ``` ### 2.9 双层依赖模型 **核心洞察**:方法学上的依赖关系有两种强度,不能一刀切。 #### 软依赖(Soft Dependency)— 可以开始聊 | 阶段 | 软依赖 | 含义 | |------|--------|------| | 科学问题 | 无 | 任何时候都可以聊 | | PICO | 有大致研究方向 | 知道"大概要研究什么"就能开始 | | 选题评价 | 有科学问题 | 需要评价的对象 | | 研究设计 | 有大致 P 和 O | 知道"人群和结局"就能聊设计 | | 观察指标 | 有研究设计方向 | 知道"什么研究类型"就能聊指标 | | 样本量 | 有研究类型和指标方向 | 知道"做什么研究、看什么"就能开始聊 | **软依赖不满足时**:不阻止用户,而是进入"依赖感知对话模式"(见 2.5 节 PromptSelector 情况 B),通过对话自然收集缺失的前提信息。 > **类比**:研究者说"老师我想算样本量",方法学专家不会说"请先写好 PICO 再来",而是说"好的,你打算做什么类型的研究?主要看什么指标?"——在讨论样本量的过程中自然收集前提。 #### 硬依赖(Hard Dependency)— 不能最终同步 | 阶段 | 硬依赖(同步守卫) | 含义 | |------|-------------------|------| | 科学问题 | 无 | 随时可同步 | | PICO | 无 | 随时可同步 | | 选题评价 | PICO 已 confirmed | 评价必须基于确认的 PICO | | 研究设计 | PICO 已 confirmed | 设计必须基于确认的人群和结局 | | 观察指标 | 研究设计已 confirmed | 指标必须匹配确认的设计 | | 样本量 | 研究设计 + 主要指标已 confirmed | 计算必须基于确认的设计和指标 | **硬依赖不满足时**:同步按钮不出现,或点击后返回友好提示 + 快捷操作按钮(如"快速确认研究设计")。 #### Prompt 选择策略伪代码 ```typescript function selectPromptStrategy( focusStage: ProtocolStageCode, blackboard: ProtocolBlackboard ): PromptStrategy { const softDeps = stageRegistry[focusStage].softDependencies; const missingDeps = softDeps.filter( dep => !hasSufficientData(blackboard.stages[dep.stage], dep.minimumFields) ); if (missingDeps.length === 0) { // 前提充足 → 直接用该阶段的验证提示词深度对话 return { mode: 'full_stage', promptCode: stageRegistry[focusStage].promptCode, context: buildBlackboardSummary(blackboard), }; } else { // 前提不足 → 依赖感知模式(目标导向收集前提) return { mode: 'dependency_aware', primaryPromptCode: stageRegistry[focusStage].promptCode, missingPrerequisites: missingDeps.map(formatMissing), guidanceInstruction: '围绕用户目标,自然地引导收集上述前提信息', context: buildBlackboardSummary(blackboard), }; } } ``` **关键点**:随着对话推进、全域提取不断填充黑板,`missingDeps` 逐渐清零,系统从"依赖感知模式"**自然过渡**到"完整验证提示词模式",用户完全无感知。 ### 2.10 ProtocolBlackboard 数据结构 ```typescript interface ProtocolBlackboard { sessionId: string; userId: string; conversationId: string; // 当前工作流状态 focusStage: ProtocolStageCode; // 建议聚焦的阶段(非强制锁定) stageHistory: Array<{ stage: string; enteredAt: Date; completedAt?: Date }>; // 6 个阶段的数据(每个阶段独立管理) stages: { scientific_question: StageData<{ content: string; }>; pico: StageData<{ population: string; intervention: string; comparison: string; outcome: string; }>; topic_evaluation: StageData<{ feasibility: string; novelty: string; significance: string; summary: string; }>; study_design: StageData<{ studyType: string; designFeatures: string[]; details: string; }>; endpoints: StageData<{ outcomes: { primary: string[]; secondary: string[]; safety: string[]; }; confounders: string[]; followUp: string; }>; sample_size: StageData<{ sampleSize: number; calculation: { alpha: number; power: number; effectSize: string; }; rationale: string; dropoutRate: string; }>; }; // 每个阶段的对话历史 ID(用于加载阶段内历史) stageConversationRanges: Record; } interface StageData { status: 'pending' | 'in_progress' | 'completed' | 'needs_review'; data: Partial; // 已收集的数据(可能不完整) confirmedData?: T; // 用户确认后的完整数据 completeness: number; // 0-100 confirmedAt?: Date; lastExtractedAt?: Date; } ``` **持久化策略**:ProtocolBlackboard 写入 `protocol_contexts` 表(已存在),使用 JSONB 字段存储。每次 `GlobalExtract` 和 `sync_element` 后更新。 --- ## 3. 与 V1.0 的关键差异 | 维度 | V1.0 MVP | V2.0 | |------|---------|------| | **架构模型** | 顺序流水线(必须按 1→2→3→4→5 走) | **智能拼图板**(6 块拼图任意顺序,SmartFocus 引导) | | **提示词** | 1 个通用 `buildSystemPrompt`(手写,未验证) | **6 个验证过的提示词**(从 PromptService 加载) | | **阶段控制** | Prompt 中写"禁止讨论其他阶段" | **代码控制**(WorkflowOrchestrator + SmartFocus) | | **依赖关系** | 隐含在顺序中(硬编码) | **双层依赖模型**(软依赖可聊,硬依赖守卫同步) | | **上下文管理** | `take: 20` 原始消息 + JSON.stringify 注入 | **ProtocolBlackboard** + 阶段内对话隔离 + 自然语言摘要注入 | | **数据提取** | LLM 在对话中输出 `` 标签 | **GlobalExtractTool**(独立 LLM,全域扫描多阶段,Zod 校验) | | **同步按钮** | 关键词匹配 / 前端解析 XML 标签 | **CheckProgressTool 规则计算** + **硬依赖守卫**(双重校验) | | **编排器** | `BaseAgentOrchestrator` 被绕过 | **WorkflowOrchestrator 统一入口** | | **意图识别** | 无 | **IntentRouter**(7 种意图,规则 + LLM 兜底) | | **开场方式** | 强制从科学问题开始 | **OpeningAnalyzer** 三模式自适应(新手/有经验/跳阶段) | | **跨阶段修改** | 不支持 | **回溯机制**(小修改直接更新,大修改提示用户) | --- ## 4. 工具定义(5 个) ### 4.1 Tool 1: `global_extract`(自动触发) ```typescript { name: "global_extract", trigger: "auto_after_response", description: "从最近对话中全域提取结构化数据,可同时更新多个阶段黑板", input: { recentMessages: "最近 3 轮对话", allStageSchemas: "所有 6 个阶段的 Zod Schema", currentBlackboard: "黑板当前状态" }, output: { updates: "Record", rationale: "提取依据" }, implementation: "独立 LLM 调用(非对话层),temperature=0.1,Zod 校验,jsonrepair 容错" } ``` **与 V1.0 的区别**: - V1.0 要求对话 LLM 在回复中输出 `` 标签(不可靠) - V2.0 用独立的 LLM 调用专门做提取(可靠),且是**全域扫描**而非仅 focusStage **全域提取示例**: ``` 用户: "做老年冠心病患者的队列研究,主要看 6 个月后的出血事件发生率" GlobalExtract 输出: scientific_question → { content: "老年冠心病患者...出血事件..." } pico → { population: "老年冠心病患者", outcome: "出血事件发生率" } study_design → { studyType: "前瞻性队列研究" } endpoints → { primary: ["出血事件发生率"], followUp: "6个月" } ``` ### 4.2 Tool 2: `check_progress`(自动触发 + 按需) ```typescript { name: "check_progress", trigger: "auto_after_extract | on_demand", description: "评估各阶段完整度 + 硬依赖校验", input: {}, output: { stageProgress: "Record", globalCompleteness: "number 0-100", suggestion: "string(下一步建议)" }, implementation: "纯规则计算,无 LLM 调用" } ``` **完成标准规则示例**: ```typescript const COMPLETION_RULES: Record CompletionResult> = { pico: (data) => { const fields = ['population', 'intervention', 'comparison', 'outcome']; const filled = fields.filter(f => data[f] && data[f].length >= 5); return { completeness: Math.round((filled.length / fields.length) * 100), missingFields: fields.filter(f => !filled.includes(f)), }; }, // ...其他阶段 }; ``` **readyToSync 判定(含硬依赖守卫)**: ```typescript function isReadyToSync(stageCode: ProtocolStageCode, blackboard: ProtocolBlackboard): boolean { const completion = COMPLETION_RULES[stageCode](blackboard.stages[stageCode].data); if (!completion.readyToSync) return false; const hardDeps = stageRegistry[stageCode].hardDependencies; return hardDeps.every( dep => blackboard.stages[dep.stage].status === 'completed' ); } ``` ### 4.3 Tool 3: `search_methodology`(按需) ```typescript { name: "search_methodology", trigger: "on_demand", description: "在方法学知识库中检索", input: { question: "string", topic: "string" }, output: { chunks: "RetrievalResult[]", summary: "string" }, implementation: "复用平台 RAG 引擎(pgvector)" } ``` > **Phase 1 不实现**,预留接口。Phase 2 接入知识库后启用。 ### 4.4 Tool 4: `compute_sample_size`(按需) ```typescript { name: "compute_sample_size", trigger: "on_demand(样本量阶段,参数就绪后)", description: "调用统计引擎计算样本量", input: { design, outcomeType, alpha, power, effectSize, dropoutRate }, output: { sampleSize, formula, sensitivityTable }, implementation: "复用 SSA 的 RClientService 或内置公式" } ``` > **Phase 1 不实现**,预留接口。Phase 2 接入 R 统计引擎后启用。 ### 4.5 Tool 5: `sync_element`(用户确认触发) ```typescript { name: "sync_element", trigger: "user_explicit_action", description: "将确认的数据同步到方案(含硬依赖守卫)", input: { stageCode, data, source: "extracted | edited" }, output: { success, updatedBlackboard, nextSuggestion }, guards: { canSync: "硬依赖校验,不满足时返回友好提示 + 快捷操作按钮" }, implementation: "硬依赖校验 → 写入 protocol_contexts → 更新黑板 → SmartFocus 推荐" } ``` **硬依赖守卫伪代码**: ```typescript function canSync(stageCode: ProtocolStageCode, blackboard: ProtocolBlackboard): SyncGuardResult { const hardDeps = stageRegistry[stageCode].hardDependencies; const unmet = hardDeps.filter( dep => blackboard.stages[dep.stage].status !== 'completed' ); if (unmet.length > 0) { return { allowed: false, reason: `同步前需先确认: ${unmet.map(d => d.label).join('、')}`, quickActions: unmet.map(d => ({ label: `确认${d.label}`, action: `sync_stage:${d.stage}`, })), }; } return { allowed: true }; } ``` --- ## 5. 开发计划 ### 5.1 Phase 概览 ``` Phase 0: 基础设施搭建(3 天) → ProtocolBlackboard + WorkflowOrchestrator + StageRegistry(含双层依赖配置) Phase 1: 对话智能层核心(5 天) → OpeningAnalyzer + IntentRouter + PromptSelector + ConversationService 改造 → GlobalExtractTool + CheckProgressTool + SyncElementTool Phase 2: 前端重构(3 天) → ChatArea 改造 + StatePanel 改造 + 同步按钮重构 Phase 3: 联调测试 + 迁移(2 天) → 端到端测试 + V1.0 数据兼容 合计:~13 天 ``` ### 5.2 Phase 0:基础设施搭建(3 天) | # | 任务 | 工时 | 产出 | |---|------|------|------| | 0-1 | **ProtocolBlackboard 设计与实现** | 4h | `ProtocolBlackboardService`:CRUD + 增量 patch + 完整度计算。使用 `protocol_contexts` 表 JSONB 字段持久化 | | 0-2 | **StageRegistry 阶段注册表** | 4h | 6 个阶段的配置:promptCode、outputSchema(Zod)、completionRules、softDependencies、hardDependencies。JSON 配置 + Zod 校验 | | 0-3 | **WorkflowOrchestrator 实现** | 5h | 拼图板状态机:`SmartFocus.recommend()` / `handleRevision()` / `canSync()`。双层依赖校验 | | 0-4 | **阶段配置 JSON + Seed** | 3h | `protocol_stages.json`:6 阶段定义(含软硬依赖配置)。`seed-protocol-stages.ts`:写入数据库或加载到内存 | | 0-5 | **类型定义** | 2h | `ProtocolBlackboard`、`StageData`、`CompletionResult`、`StageConfig`、`SoftDependency`、`HardDependency` 等接口 | **验收标准**: - `ProtocolBlackboardService` 可以 get/patch/reset - `SmartFocus.recommend()` 可以根据黑板状态推荐聚焦阶段 - `canSync()` 正确拒绝硬依赖不满足的同步请求 - 每个阶段能加载对应的 Prompt Code ### 5.3 Phase 1:对话智能层核心(5 天) | # | 任务 | 工时 | 产出 | |---|------|------|------| | 1-1 | **IntentRouter 实现** | 4h | 规则引擎(关键词 + 上下文守卫)+ LLM 兜底。7 种意图(含 `multi_stage_input`)。`intent_rules.json` 配置 | | 1-2 | **OpeningAnalyzer 实现** | 3h | 首条消息分析,三模式判定(新手/有经验/跳阶段),初始化 focusStage | | 1-3 | **PromptSelector 实现** | 4h | 根据 focusStage + 软依赖状态选择 Prompt 策略(full_stage / dependency_aware)。依赖感知 Prompt 模板设计 | | 1-4 | **ConversationService 改造** | 5h | 核心改造:① 从 PromptService 加载验证提示词;② PromptSelector 策略组装;③ 注入全黑板摘要(自然语言);④ 阶段内对话历史隔离 | | 1-5 | **GlobalExtractTool 实现** | 6h | 独立 LLM 调用 + 全域扫描所有阶段 Schema + Zod 校验 + jsonrepair + 增量 patch 黑板。每个阶段有专属提取 Prompt | | 1-6 | **CheckProgressTool 实现** | 3h | 纯规则计算 + 硬依赖守卫。返回每个阶段的 completeness + missingFields + readyToSync | | 1-7 | **SyncElementTool 重构** | 3h | 替代现有 `handleProtocolSync`。canSync 硬依赖守卫 → 写入黑板(confirmed)→ SmartFocus 推荐 | | 1-8 | **ProtocolAgentController 重写** | 5h | `sendMessage` 走新架构:OpeningAnalyzer(首条) → IntentRouter → PromptSelector → ConversationService → 流式生成 → 后处理管线 | | 1-9 | **提取 Prompt 设计 + Seed** | 3h | 全域提取 Prompt 模板 + 6 个阶段的字段映射。写入 `prompt_templates` 表 | **验收标准**: - 新手开场:"你好" → 引导到科学问题 - 信息丰富开场:"做队列研究看出血事件" → 全域提取填充多个阶段,推荐最需要补充的阶段 - 跳阶段:"直接聊样本量" → 进入依赖感知模式,自然引导收集前提 - `check_progress` 在 PICO 四字段填满后返回 `readyToSync: true` - 同步样本量时,如果研究设计未确认 → canSync 返回拒绝 + 快捷操作 ### 5.4 Phase 2:前端重构(3 天) | # | 任务 | 工时 | 产出 | |---|------|------|------| | 2-1 | **ChatArea 改造** | 5h | ① 移除 `parseExtractedData` XML 解析逻辑;② 同步按钮改为由后端 `readyToSync` 控制显示;③ 同步前显示数据预览(可编辑);④ 硬依赖不满足时显示快捷操作按钮 | | 2-2 | **StatePanel 增强** | 3h | ① 显示 6 阶段拼图板(非线性展示);② 每个阶段显示完整度百分比;③ 已确认阶段支持查看和编辑;④ focusStage 高亮;⑤ 点击任意阶段可切换 focusStage | | 2-3 | **阶段过渡 UI** | 3h | ① SmartFocus 推荐提示(系统消息,用户可接受或忽略);② 进度条更新;③ 依赖关系可视化提示 | | 2-4 | **回溯编辑 UI** | 2h | ① StatePanel 已确认阶段的编辑按钮;② 编辑弹窗;③ 编辑后触发 `handleRevision` | | 2-5 | **Markdown 渲染修复** | 1h | 修复段落序号全为 "1." 的问题(Issue #0) | **验收标准**: - 同步按钮只在 `readyToSync`(含硬依赖满足)时出现 - 硬依赖不满足时显示友好提示和快捷操作 - 同步前可以预览和编辑提取的数据 - StatePanel 点击阶段可切换聚焦 - 已确认阶段可以查看详情和编辑 ### 5.5 Phase 3:联调测试 + 迁移(2 天) | # | 任务 | 工时 | 产出 | |---|------|------|------| | 3-1 | **端到端测试脚本** | 4h | 覆盖 11 个 V1.0 反馈问题的回归测试 + 3 种开场模式测试 | | 3-2 | **V1.0 数据兼容** | 2h | 已有的 protocol_contexts 数据迁移到新的 blackboard 格式 | | 3-3 | **Prompt 调优** | 3h | 根据测试结果微调阶段内指令、提取 Prompt、依赖感知指令 | | 3-4 | **文档更新** | 2h | 更新模块状态文档 + API 文档 | --- ## 6. 数据库变更 ### 6.1 无需新建表 V2.0 复用现有表: | 表 | Schema | 用途 | 变更 | |---|--------|------|------| | `protocol_contexts` | `protocol_schema` | ProtocolBlackboard 持久化 | 扩展 JSONB 字段结构 | | `conversations` | `aia_schema` | 对话管理 | 无变更 | | `messages` | `aia_schema` | 消息存储 | 新增 `metadata.stageCode` 字段(JSONB 内) | | `prompt_templates` | `capability_schema` | 提示词管理 | 新增 6 个提取 Prompt + 依赖感知 Prompt 模板 | | `agent_sessions` | `agent_schema` | Agent 会话 | 无变更 | ### 6.2 protocol_contexts 字段扩展 现有的 `protocol_contexts` 表已包含 `scientific_question`、`pico`、`study_design`、`sample_size`、`endpoints` 等 JSONB 字段。V2.0 在这些字段内增加 `status`、`completeness`、`confirmedAt` 等元数据,向后兼容。 --- ## 7. 配置文件清单 | 文件 | 位置 | 用途 | 维护者 | |------|------|------|--------| | `protocol_stages.json` | `backend/src/modules/agent/protocol/config/` | 6 阶段定义(promptCode、schema、completionRules、softDependencies、hardDependencies) | 方法学团队 | | `intent_rules.json` | `backend/src/modules/agent/protocol/config/` | 意图识别规则(7 种意图,关键词 + 上下文守卫) | IT 团队 | | `extraction_prompts/` | PromptService 数据库 | 6 个阶段的数据提取 Prompt + 全域提取模板 | 方法学团队 | --- ## 8. 保留什么(不动的部分) | 组件 | 理由 | |------|------| | `ProtocolContextService`(大部分) | CRUD 逻辑复用,增加 blackboard 适配层 | | `ProtocolExportService` | Word 导出,不变 | | `protocolGenerationPrompts.ts` | 全文生成 Prompt,不变 | | 前端 `DocumentPanel` | 方案预览和 A4 展示,不变 | | 前端 `useProtocolGeneration` | 一键生成逻辑,不变 | | 前端 `useProtocolConversations` | 对话管理,不变 | | 6 个验证过的 Prompt(数据库中) | 核心资产,阶段进入方式变了但阶段内仍加载验证提示词 | ## 9. 废弃什么 | 组件 | 替代 | |------|------| | `ProtocolAgentController.buildSystemPrompt()` | → PromptSelector + ConversationService(从 PromptService 加载) | | `ProtocolAgentController.buildMessagesWithContext()` | → ConversationService(黑板上下文 + 阶段内历史) | | `ProtocolAgentController.getStageOutputFormat()` | → StageRegistry(Zod Schema 定义) | | `ProtocolAgentController.getStageInstructions()` | → StageRegistry(阶段内指令) | | `ProtocolOrchestrator.buildSyncButton()`(关键词匹配) | → CheckProgressTool(规则计算 + 硬依赖守卫) | | `ProtocolOrchestrator.extractDataFromResponse()`(XML 解析) | → GlobalExtractTool(独立 LLM,全域扫描) | | 前端 `parseExtractedData()`(XML 解析) | → 后端推送 `readyToSync` 信号 | | 固定 `advanceStage()` 顺序推进 | → SmartFocus 智能推荐 | --- ## 10. V1.0 问题解决映射 | # | 问题 | V2.0 解决机制 | |---|------|-------------| | 0 | 段落序号全为 "1." | Phase 2 Markdown 渲染修复 | | 1 | 不结合上下文(说了队列还显示 RCT) | **ProtocolBlackboard** + 全黑板摘要注入 + **GlobalExtract** 全域提取 | | 2 | 未确认就可同步 AI 编造内容 | **CheckProgressTool** completionRules + **硬依赖守卫** canSync | | 3 | 重复讨论已确认信息 | **阶段内对话历史隔离** + 已确认数据以摘要形式注入 | | 4 | 观察指标阶段又讨论样本量 | **SmartFocus** 代码控制聚焦 + 每阶段专属验证提示词 | | 5 | 不联系对话过程中的上下文 | **ProtocolBlackboard** 统一存储 + **GlobalExtract** 跨阶段收集 | | 6 | 发送参数后不联系上下文 | **阶段内对话历史不截断**(窗口 ≤15 轮,非全局 20 条) | | 7 | 阶段未正确推进 | **SmartFocus.recommend()** 智能推荐 + 同步后自动切换 | | 8 | 纠正后又回退 | **ProtocolBlackboard** 为单一真相源,不受 LLM 遗忘影响 | | 9 | 反复回到已完成话题 | **SmartFocus** + 每阶段专属验证提示词 + 阶段内历史隔离 | | 10 | 同步内容与讨论不一致 | **GlobalExtractTool** 独立提取 + 同步前预览可编辑 | --- ## 11. 风险管理 | 风险 | 概率 | 影响 | 应对 | |------|------|------|------| | GlobalExtractTool 全域提取准确率不足 | 中 | 高 | Zod 校验 + 置信度阈值(<0.5 不更新黑板)+ 同步前人工确认 | | 全域提取误将信息归入错误阶段 | 中 | 中 | 阶段 Schema 设计有区分度 + 同步前预览可编辑 | | 验证提示词不适配对话场景 | 中 | 中 | 原提示词设计为一问一答,需增加阶段内指令适配多轮对话 | | 依赖感知模式 Prompt 收集效果不好 | 中 | 中 | 依赖感知指令模板迭代优化 + 前提收集完成后自然切换到完整模式 | | 后处理管线增加延迟 | 中 | 低 | GlobalExtract 异步执行,不阻塞 UI;先显示 AI 回复,提取结果后续更新 | | 拼图板自由度导致用户迷失 | 低 | 中 | SmartFocus 始终给出建议 + StatePanel 可视化进度 | | V1.0 数据迁移 | 低 | 低 | Blackboard 结构向后兼容,旧数据可平滑映射 | ### 回退策略 | 层级 | 正常路径 | 降级路径 | 触发条件 | |------|---------|---------|---------| | 验证提示词加载 | PromptService 从数据库加载 | 内置兜底 Prompt | 数据库不可用 | | OpeningAnalyzer | 三模式分析 | 默认新手模式(最安全) | 分析异常 | | IntentRouter | 规则引擎 + LLM 兜底 | 默认为 `provide_info`(最安全) | LLM 不可用 | | PromptSelector | full_stage / dependency_aware 切换 | 始终 full_stage(降级为只用当前阶段提示词) | 依赖分析异常 | | GlobalExtractTool | 全域扫描 + Zod 校验 | 仅提取 focusStage(降级为单阶段提取) | LLM 不可用或全域提取超时 | | CheckProgressTool | 规则计算 + 硬依赖守卫 | 不显示同步按钮,等待人工确认 | 规则异常 | --- ## 12. 工时与里程碑 | Phase | 名称 | 工时 | 日历天 | 里程碑 | |-------|------|------|--------|--------| | **0** | 基础设施搭建 | 18h | 3 天 | Blackboard + Orchestrator + StageRegistry(含双层依赖)可用 | | **1** | 对话智能层核心 | 36h | 5 天 | 三种开场模式、全域提取、依赖感知对话、硬依赖守卫全部可用 | | **2** | 前端重构 | 14h | 3 天 | 完整用户体验(拼图板 StatePanel + 同步守卫 UI) | | **3** | 联调测试 + 迁移 | 11h | 2 天 | 11 个问题 + 3 种开场模式全部验证通过 | | **合计** | | **79h** | **~13 天** | **Protocol Agent 2.0 上线** | ### 里程碑时间线 ``` Week 1 ────────────────────────────────── Day 1-3: Phase 0(基础设施 + 双层依赖配置) Day 4-5: Phase 1 前半(OpeningAnalyzer + IntentRouter + PromptSelector) Week 2 ────────────────────────────────── Day 6-8: Phase 1 后半(GlobalExtract + CheckProgress + SyncElement + Controller 重写) Day 9-11: Phase 2(前端重构) Week 3 ────────────────────────────────── Day 12-13: Phase 3(联调测试 + 迁移) ✅ Protocol Agent 2.0 上线 ``` --- ## 13. 未来扩展(Phase 2+) | 功能 | 说明 | 何时做 | |------|------|--------| | RAG 知识库接入 | `search_methodology` 工具接入方法学知识库 | V2.0 上线 + 知识库就绪后 | | 样本量计算器 | `compute_sample_size` 工具接入 R 统计引擎 | V2.0 上线 + R 引擎就绪后 | | 方法学评审 | 第 7 个阶段,方案生成后自动评审 | V2.1 | | 多会话支持 | 跨天/跨设备继续协作 | V2.1 | | 协作功能 | 多人协同编辑方案 | V3.0 | --- ## 14. 关键决策记录 | 决策 | 选择 | 理由 | |------|------|------| | 架构模型 | **智能拼图板**(非顺序流水线) | 真正融合 SSA 模式的核心思想:用户驱动对话流,系统智能填补空白 | | 依赖关系 | **双层模型**(软依赖 + 硬依赖) | 软依赖保证灵活性(可以聊),硬依赖保证严谨性(不能乱同步) | | 阶段聚焦 | **SmartFocus 建议,非强制锁定** | 用户可以从任意话题切入,系统推荐但不阻止 | | 开场方式 | **OpeningAnalyzer 三模式自适应** | 新手得到引导,有经验的用户不被束缚 | | 前提信息收集 | **依赖感知对话模式**(自然引导) | 像真正的方法学专家一样,在讨论目标话题时自然收集前提 | | 提示词来源 | 复用 6 个验证过的子 Agent 提示词 | 不重复造轮子,验证过的是核心资产。进入方式变了,阶段内提示词不变 | | 数据提取 | **GlobalExtract 全域提取**(非仅当前阶段) | 一次对话可能涉及多个阶段信息,全域扫描不遗漏 | | 同步判断 | 代码规则计算 + **硬依赖守卫** | 确定性逻辑 > 概率性判断,方法学约束代码化 | | 阶段内对话 | 自由对话 + 验证提示词引导 | 用户体验自然,专业深度有保证 | | 历史消息 | 阶段内隔离 + 全黑板摘要注入 | 避免跨阶段干扰,保留跨阶段上下文 | | Session 黑板 | protocol_contexts 表 JSONB | 复用现有表,无需新建 | | IntentRouter | 规则优先 + LLM 兜底(7 种意图) | 与 SSA 模式一致,已验证有效。新增 multi_stage_input 处理跨阶段输入 | --- > **一句话总结**:Protocol Agent 2.0 = 智能拼图板(6 块拼图任意顺序完成)+ 验证过的 AI 专家(每块拼图由专家坐诊)+ 双层依赖守卫(聊天自由,同步严谨),让用户像和方法学专家自由聊天一样完成研究方案制定。