V3.1 QC Engine: - QcExecutor unified entry + D1-D7 dimension engines + three-level aggregation - HealthScoreEngine + CompletenessEngine + ProtocolDeviationEngine + QcAggregator - B4 flexible cron scheduling (project-level cronExpression + pg-boss dispatcher) - Prisma migrations for qc_field_status, event_status, project_stats GCP Business Reports (Phase A - 4 reports): - D1 Eligibility: record_summary full list + qc_field_status D1 overlay - D2 Completeness: data entry rate and missing rate aggregation - D3/D4 Query Tracking: severity distribution from qc_field_status - D6 Protocol Deviation: D6 dimension filtering - 4 frontend table components + ReportsPage 5-tab restructure AI Timeline Enhancement: - SkillRunner outputs totalRules (33 actual rules vs 1 skill) - iitQcCockpitController severity mapping fix (critical->red, warning->yellow) - AiStreamPage expandable issue detail table with Chinese labels - Event label localization (eventLabel from backend) Business-side One-click Batch QC: - DashboardPage batch QC button with SyncOutlined icon - Auto-refresh QcReport cache after batch execution Bug Fixes: - dimension_code -> rule_category in 4 SQL queries - D1 eligibility data source: record_summary full + qc_field_status overlay - Timezone UTC -> Asia/Shanghai (QcReportService toBeijingTime helper) - Pass rate calculation: passed/totalEvents instead of passed/totalRecords Docs: - Update IIT module status with GCP reports and bug fix milestones - Update system status doc v6.6 with IIT progress Tested: Backend compiles, frontend linter clean, batch QC verified Made-with: Cursor
53 KiB
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开发完成.md06-开发记录/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 个根本缺陷
- 编排器被绕过:
ProtocolAgentController.sendMessage直接调用 LLM,未经过BaseAgentOrchestrator,Agent 框架形同虚设 - 阶段管理 100% 靠 Prompt:
buildSystemPrompt用"禁止事项"约束 LLM,LLM 经常违反 <extracted_data>机制脆弱:依赖 LLM 在对话中输出 XML 标签,前端解析后触发同步- 历史消息注入低效:
take: 20原始消息不分阶段全部注入,浪费 Token 且丢失关键上下文 - 未复用已验证的子 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 选择策略伪代码
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 数据结构
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<string, { startMessageId: string; endMessageId?: string }>;
}
interface StageData<T> {
status: 'pending' | 'in_progress' | 'completed' | 'needs_review';
data: Partial<T>; // 已收集的数据(可能不完整)
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 在对话中输出 <extracted_data> 标签 |
GlobalExtractTool(独立 LLM,全域扫描多阶段,Zod 校验) |
| 同步按钮 | 关键词匹配 / 前端解析 XML 标签 | CheckProgressTool 规则计算 + 硬依赖守卫(双重校验) |
| 编排器 | BaseAgentOrchestrator 被绕过 |
WorkflowOrchestrator 统一入口 |
| 意图识别 | 无 | IntentRouter(7 种意图,规则 + LLM 兜底) |
| 开场方式 | 强制从科学问题开始 | OpeningAnalyzer 三模式自适应(新手/有经验/跳阶段) |
| 跨阶段修改 | 不支持 | 回溯机制(小修改直接更新,大修改提示用户) |
4. 工具定义(5 个)
4.1 Tool 1: global_extract(自动触发)
{
name: "global_extract",
trigger: "auto_after_response",
description: "从最近对话中全域提取结构化数据,可同时更新多个阶段黑板",
input: {
recentMessages: "最近 3 轮对话",
allStageSchemas: "所有 6 个阶段的 Zod Schema",
currentBlackboard: "黑板当前状态"
},
output: {
updates: "Record<StageCode, { updatedFields, confidence }>",
rationale: "提取依据"
},
implementation: "独立 LLM 调用(非对话层),temperature=0.1,Zod 校验,jsonrepair 容错"
}
与 V1.0 的区别:
- V1.0 要求对话 LLM 在回复中输出
<extracted_data>标签(不可靠) - 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(自动触发 + 按需)
{
name: "check_progress",
trigger: "auto_after_extract | on_demand",
description: "评估各阶段完整度 + 硬依赖校验",
input: {},
output: {
stageProgress: "Record<StageCode, { completeness, missingFields, readyToSync }>",
globalCompleteness: "number 0-100",
suggestion: "string(下一步建议)"
},
implementation: "纯规则计算,无 LLM 调用"
}
完成标准规则示例:
const COMPLETION_RULES: Record<ProtocolStageCode, (data: any) => 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 判定(含硬依赖守卫):
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(按需)
{
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(按需)
{
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(用户确认触发)
{
name: "sync_element",
trigger: "user_explicit_action",
description: "将确认的数据同步到方案(含硬依赖守卫)",
input: { stageCode, data, source: "extracted | edited" },
output: { success, updatedBlackboard, nextSuggestion },
guards: {
canSync: "硬依赖校验,不满足时返回友好提示 + 快捷操作按钮"
},
implementation: "硬依赖校验 → 写入 protocol_contexts → 更新黑板 → SmartFocus 推荐"
}
硬依赖守卫伪代码:
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/resetSmartFocus.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 专家(每块拼图由专家坐诊)+ 双层依赖守卫(聊天自由,同步严谨),让用户像和方法学专家自由聊天一样完成研究方案制定。