Files
AIclinicalresearch/docs/03-业务模块/AIA-AI智能问答/04-开发计划/07-Protocol-Agent-2.0-开发计划.md
HaHafeng 2030ebe28f feat(iit): Complete V3.1 QC engine + GCP business reports + AI timeline + bug fixes
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
2026-03-01 22:49:49 +08:00

924 lines
53 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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` 用"禁止事项"约束 LLMLLM 经常违反
3. **`<extracted_data>` 机制脆弱**:依赖 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
│ 使用通用 StreamingServiceOpenAI 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<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`(自动触发)
```typescript
{
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.1Zod 校验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`(自动触发 + 按需)
```typescript
{
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 调用"
}
```
**完成标准规则示例**
```typescript
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 判定(含硬依赖守卫)**
```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、outputSchemaZod、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()` | → StageRegistryZod 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 专家(每块拼图由专家坐诊)+ 双层依赖守卫(聊天自由,同步严谨),让用户像和方法学专家自由聊天一样完成研究方案制定。