Files
AIclinicalresearch/docs/03-业务模块/SSA-智能统计分析/04-开发计划/10-QPER架构开发计划-智能化主线.md
HaHafeng 371e1c069c feat(ssa): Complete QPER architecture - Query, Planner, Execute, Reflection layers
Implement the full QPER intelligent analysis pipeline:

- Phase E+: Block-based standardization for all 7 R tools, DynamicReport renderer, Word export enhancement

- Phase Q: LLM intent parsing with dynamic Zod validation against real column names, ClarificationCard component, DataProfile is_id_like tagging

- Phase P: ConfigLoader with Zod schema validation and hot-reload API, DecisionTableService (4-dimension matching), FlowTemplateService with EPV protection, PlannedTrace audit output

- Phase R: ReflectionService with statistical slot injection, sensitivity analysis conflict rules, ConclusionReport with section reveal animation, conclusion caching API, graceful R error classification

End-to-end test: 40/40 passed across two complete analysis scenarios.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-21 18:15:53 +08:00

82 KiB
Raw Blame History

SSA-Pro Q-P-E-R 架构开发计划 — 智能化主线

文档版本: v7.1
创建日期: 2026-02-20
最后更新: 2026-02-21v7.1 — 新增核心原则"领域知识可配置化" + Phase P 配置化基础设施Zod 校验 / 热更新 API / 领域文件拆分)
架构模式: Query → Planner → Execute → Reflection
目标: 让不懂统计的医生完成专业级的统计分析
本文档定位: 替代旧 MVP 开发计划总览,成为 SSA 开发的主线指南


1. 架构总览

1.1 Q-P-E-R 四层架构

用户:"我有 200 个患者数据,想看看新药有没有效"
    │
    ▼
┌─────────────────────────────────────────────────────────┐
│  Q · Query Layer (理解层)                                │
│  "用户到底想要什么?数据长什么样?"                      │
│                                                          │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐   │
│  │ IntentParser │→ │ DataProfiler │→ │  Clarifier   │   │
│  │  LLM 意图    │  │ 数据诊断     │  │ 追问澄清     │   │
│  └──────────────┘  └──────────────┘  └──────────────┘   │
│                                                          │
│  输出ParsedQuery { goal, y, x, design, dataProfile }  │
└──────────────────────┬──────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────┐
│  P · Planner Layer (规划层)                              │
│  "该用什么方法?按什么顺序?"                            │
│                                                          │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐   │
│  │DecisionTable │→ │FlowTemplate  │→ │ SAP Builder  │   │
│  │ 四维匹配     │  │ 流程模板     │  │ 计划生成     │   │
│  └──────────────┘  └──────────────┘  └──────────────┘   │
│                                                          │
│  输出AnalysisPlan { steps[], methodology, rationale } │
└──────────────────────┬──────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────┐
│  E · Execute Layer (执行层) ✅ 已完成                    │
│  "调用 R 引擎,跑出数字"                                │
│                                                          │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐   │
│  │  Orchestrator│→ │  R Client    │→ │  SSE Stream  │   │
│  │  步骤编排    │  │  调用 R 引擎 │  │  实时进度    │   │
│  └──────────────┘  └──────────────┘  └──────────────┘   │
│                                                          │
│  输出StepResult[] { stats, tables, plots, code }      │
└──────────────────────┬──────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────┐
│  R · Reflection Layer (审视层)                           │
│  "结果说明了什么?可以发论文吗?"                        │
│                                                          │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐   │
│  │  Integrator  │→ │  LLM Critic  │→ │ReportBuilder │   │
│  │  结果整合    │  │  论文级结论  │  │  报告生成    │   │
│  └──────────────┘  └──────────────┘  └──────────────┘   │
│                                                          │
│  输出Report { conclusion, methodology, limitations }  │
└─────────────────────────────────────────────────────────┘

1.2 与现有代码的映射

Q-P-E-R 层 现有代码 现状 目标
Q · Query WorkflowPlannerService.parseUserIntent() 正则匹配,无 LLM LLM 四维提取 + 追问
Q · Query DataProfileService + DataParserService 基础统计 增加诊断项 + 传递给 P 层
P · Planner WorkflowPlannerService.generateSteps() 硬编码 if/else 决策表 + 流程模板
E · Execute WorkflowExecutorService + RClientService 完成 保持不变
E · Execute 7 个 R 工具 + SSE + 前端展示 完成 Block-based 标准化输出
R · Reflection ConclusionGeneratorService 规则拼接,无 LLM LLM 论文级结论

1.3 核心原则

  1. Execute 层不动 — 这是花了最多时间搭建的基础,完整保留

  2. 前后加层 — 在 Execute 前面加更好的 Q+P后面加 R

  3. LLM 只在 Q 和 R 层使用 — P 层用确定性的决策表E 层用确定性的 R 引擎

  4. 渐进式替换 — 每层完成后立即可用,不需要全部完成才能看到效果

  5. 复用平台通用能力层,禁止重复造轮

    • LLM 调用 必须 通过 common/llm/LLMFactory + common/streaming/StreamingService
    • Prompt 管理 必须 使用 common/prompt/PromptService(数据库版本化 capability_schema.prompt_templates),禁止在代码中硬编码 Prompt 字符串
    • 缓存使用 common/cache/CacheServicePostgres-Only日志使用 common/logging/
    • 参考 docs/04-开发规范/08-云原生开发规范.mddocs/02-通用能力层/00-通用能力层清单.md
  6. 领域知识可配置化 — QPER 四层的所有"领域知识"由统计学方法学团队配置,不写死在代码中

    IT 团队负责搭建引擎和管道,统计学方法学团队负责往管道里填充内容。"可配置"是贯穿所有 Phase 的架构约束。

    约束:一切业务逻辑靠读 JSON/数据库驱动,绝不写死在 TypeScript 的 if-else 和常量对象中。

    QPER 层 方法学团队可配置的内容 配置载体
    Q 层 Intent PromptFew-Shot 示例、Confidence Rubric、Goal 类型枚举) PromptService 数据库( 已实现)
    P 层 决策表规则、流程模板、Switch Condition、EPV 阈值 JSON 文件 → Repository 接口Phase P
    E 层 R 工具注册表100 个工具的参数定义、前置条件、护栏规则) JSON 文件 tools_registry.jsonPhase P 创建)
    R 层 结论模板、方法学说明模板、统计量阈值定义 JSON 文件 narrative_templates.jsonPhase R 创建)

    配置化三道防线Phase P 落地):

    1. Zod Schema 严格校验 — 方法学团队编辑 JSON 时的拼写错误、结构错误在加载时立即拦截,不传播到运行时
    2. 热更新 API — 方法学团队修改 JSON 后无需 IT 团队重启服务,调用 POST /reload-config 即可生效(校验失败则保留旧配置)
    3. 领域文件物理拆分 — 按职责拆为独立 JSON 文件,避免版本冲突,每个文件有明确的所有者
    backend/src/modules/ssa/config/
    ├── tools_registry.json        # E 层100 个工具的注册定义(方法学团队维护)
    ├── decision_tables.json       # P 层:四维匹配规则 + 降级触发条件(方法学团队维护)
    ├── flow_templates.json        # P 层:标准步骤流组合(方法学团队维护)
    └── narrative_templates.json   # R 层结论生成和理由说明的文案模板Phase R 创建)
    

1.4 架构红线(不可为清单)

来源: 四份外部调研报告 + 架构审查共识。以下三条为强制约束,任何 Phase 均不可违反。

# 红线 理由
🚫 1 禁止引入 LangGraph / AutoGen 等编排框架 QPER 是线性流水线 + 重试Node.js 原生 while + try-catch 足够编排,框架只增加复杂度和调试成本
🚫 2 禁止 LLM 生成并执行 R 代码 只允许 LLM 修改参数 JSON 重新请求固定 R 脚本(r-statistics-service/tools/杜绝远程代码执行风险。R 工具是参数化封装的固定脚本,不是 LLM 的画布
🚫 3 禁止多智能体辩论Multi-Agent Debate 统计学有硬性定理(正态性 P<0.05 就是不满足),用决策表规则判定即可,不需要两个 LLM 互相消耗 Token

2. 当前系统资产盘点

2.1 可直接复用(不改动)

资产 文件 状态
R 统计引擎 r-statistics-service/ (7 个工具)
R 调用客户端 RClientService.ts
工作流执行器 WorkflowExecutorService.ts
SSE 实时通信 workflow.routes.ts
数据上传 + OSS 会话管理 + 文件上传路由
前端 V11 UI SSAWorkspace 全套组件
前端执行日志 terminal-box + TraceLogItem
前端结果展示 统计量/表格/图表渲染
R 代码导出 SSACodeModal (多步骤聚合)
Word 报告导出 useAnalysis.exportWorkflowReport
Python 数据质量 DataProfileService + extraction_service

2.2 需要拆分重构

现有代码 拆分为 层级
WorkflowPlannerService.parseUserIntent() QueryService.parseIntent() Q
WorkflowPlannerService.generateSteps() PlannerService.plan() P
AVAILABLE_TOOLS 硬编码对象 DecisionTable 配置文件 P
ConclusionGeneratorService(已有,规则拼接) ReflectionServiceLLM 升级) R

迁移策略: WorkflowPlannerService 不立即删除,而是在内部委托给新的 QueryService / PlannerService保留旧入口作为兼容层待 Q+P 层稳定后再移除。

2.3 需要新建

新建服务 层级 核心能力
QueryService Q LLM 意图解析 + 追问(通过平台 LLMFactory + PromptService
DataDiagnosticService Q 异常值/正态性/平衡性检测(扩展现有 DataProfileService
DecisionTableService P 四维匹配
FlowTemplateService P 流程模板管理
DynamicReport.tsx E(前端) Block-based 动态渲染

注意: ReflectionService 不是新建,而是对已有 ConclusionGeneratorService 的 LLM 升级重构(见 2.2)。

2.4 已有数据库资产Prisma schema ssa_schema

模型 状态 说明
SsaSession / SsaMessage / SsaFileUpload 使用中 会话管理 + 消息 + 文件上传
SsaDecisionTable 已建模 决策表记录,DecisionTableService 应优先使用此表
SsaRCodeLibrary 已建模 R 代码库记录
SsaAnalysisResult 已建模 分析结果记录(含 report_blocks 字段)

Phase P 的决策表配置应评估是否直接使用 SsaDecisionTable 数据库表,而非仅用静态 JSON 文件。


3. 开发计划5 个 Phase

Phase E+ : Execute 层标准化 — Block-based2.5 天)

为什么先做这个: 后续每新增一个 R 工具前端都需要写自定义渲染代码。Block-based 协议让这个成本归零,是所有后续开发的前提。

目标R 输出 report_blocks[] → Node.js 透传 → 前端 DynamicReport 渲染
# 任务 层级 工时 产出
1 R 端辅助函数库 block_helpers.R R 1h make_table_block(), make_kv_block(), make_image_block()
2 改造 t_test_ind.R 输出 report_blocks R 1h 第一个 Block-based 工具
3 改造其余 6 个 R 工具 R 6h 全部输出 report_blocks
4 后端透传 report_blocks 全链路 后端 1.5h WorkflowExecutorService → SSE 事件 → 前端 store需验证 SsaAnalysisResultreport_blocks 字段持久化
5 前端 DynamicReport.tsx 组件 前端 2h 4 个 Block 渲染子组件
6 前端 exportBlocksToWord.ts 前端 2h Block 数组 → Word 文档
7 SSAWorkspacePane 集成 + fallback 前端 1h 优先读 report_blocks,旧逻辑兜底
8 旧渲染代码保留为 fallback 前端 1h DescriptiveResultView 等组件2026-02-20 新建)暂保留,当 report_blocks 为空时自动降级使用;待 Block-based 全面验证后再清理

验收标准: 所有 7 个 R 工具的结果通过 DynamicReport 统一渲染Word 导出正常。


Phase Q : Query 层建设 — LLM 意图理解4 天)

为什么第二做: 这是用户体验提升最大的单一改进。从"用户必须知道 T 检验"变为"用户说'有没有效'就够了"。

目标:用户自然语言 → LLM 提取四维信息 → 不确定时追问

3.1 后端任务

# 任务 工时 说明
1 通过 PromptService 注册 Intent Prompt 5h 编写 Prompt + seed 脚本写入 capability_schema.prompt_templates;输出:{ goal, outcome_var, predictor_vars, design, confidence }必须包含 3-5 组 Few-Shot 示例(覆盖"哪个组更好"→差异比较、"血压和体重有关吗"→关联分析等典型口语表达),显著提升首次解析准确率。Confidence Rubric 客观化Prompt 中必须内嵌打分准则0.9+ = 用户原话明确了 Y 和至少一个 X0.7-0.8 = 指出了 Y 但 X 需推断;< 0.7 = 只说了"帮我分析"需追问),防止 LLM 自评虚高
2 新建 QueryService.ts 8h 通过 LLMFactory.create() 调用 LLM + json-repair + Zod 校验 + 低置信度追问逻辑 + 正则兜底(保留现有 parseUserIntent 逻辑作为 fallbackZod 动态防幻觉:用 createIntentSchema(validColumns) 动态生成 Schema通过 .refine() 校验 LLM 输出的 outcome_var/predictor_vars 是否存在于真实列名中,捏造列名立即触发重试或 fallback。Confidence 二次验证:若 LLM 打分 ≥0.9 但 outcome_var 或 predictor_vars 为空,强制降级到 0.5
3 增强 DataProfileService 4h 增加异常值检测IQR、分组平衡性、样本量评估注意DataParserService 的 0/1 分类规则已在 2026-02-19 优化完成,不重复。非分析变量自动标记Python 端对高基数字符串列uniqueValues/totalRows > 0.95)、日期列、列名匹配 _id/_no/编号/序号 模式的列打 is_id_like: true 标签Q→P 上下文裁剪时物理剔除这些列,让 LLM 看不到 patient_id 等非分析列
4 定义 ParsedQuery 接口 1h Q 层输出 → P 层输入的标准契约,放 types/query.types.ts
5 新建追问 API 2h POST /api/v1/ssa/sessions/:id/clarify,在现有 analysis.routes.ts 中扩展
6 安装 json-repair + zod 依赖 0.5h Phase 1 遗留任务,此处一并完成
7 Q→P 上下文裁剪Context Pruning 1h Q 层识别出 Y/X 变量后,只提取这几列的 DataProfile 子集传给 P 层Hot Context其余列的详情留在数据库按需拉取Cold Context。防止 100 列 CSV 的 50KB DataProfile JSON 导致 Planner 的 Token 爆炸和"注意力涣散"
8 DataProfile 会话级缓存 0.5h 用户上传文件后 DataProfiler 只执行一次,结果通过 CacheService 缓存key: ssa:profile:{sessionId}:{fileHash})。同一会话+同一文件的后续 Q 层循环(如追问后重新解析)直接读缓存,实现毫秒级响应,避免重复调用 Python 解析 20MB CSV

QueryService 核心逻辑:

// 伪代码 — 使用平台通用能力层
class QueryService {
  constructor(
    private promptService: PromptService,   // 平台通用能力Prompt 管理
    private llmFactory: LLMFactory,         // 平台通用能力LLM 网关
  ) {}

  async parseQuery(userText: string, dataProfile: DataProfile): Promise<ParsedQuery> {
    // 1. 从数据库加载 Prompt 模板(支持版本化 + A/B 测试)
    const promptTemplate = await this.promptService.getPrompt('ssa_intent_parse', 'latest');
    const prompt = this.promptService.render(promptTemplate, { userText, variables: dataProfile.variables });
    
    // 2. 通过 LLMFactory 调用 LLM自动选模型 + 统一错误处理)
    const llm = this.llmFactory.create({ model: 'deepseek-v3', temperature: 0.1 });
    const llmResult = await llm.chat(prompt);
    
    // 3. Zod 校验结构json-repair 容错)
    const parsed = IntentSchema.parse(jsonRepair(llmResult));
    
    // 4. 低置信度 → 生成追问
    if (parsed.confidence < 0.7) {
      return { needsClarification: true, questions: this.generateQuestions(parsed) };
    }
    
    // 5. 融合数据诊断结果
    const diagnosis = await this.diagnoseData(dataProfile, parsed);
    
    // 6. 上下文裁剪Context Pruning— 只保留 Y/X 变量的 DataProfile 子集
    //    Planner 不需要看 100 列的完整统计特征,只需相关变量的 Hot Context
    const prunedProfile = this.pruneForPlanner(dataProfile, parsed);
    
    return { ...parsed, dataDiagnosis: diagnosis, prunedProfile, needsClarification: false };
  }

  // 上下文裁剪:从全量 DataProfile 中提取 Planner 需要的最小子集
  private pruneForPlanner(fullProfile: DataProfile, parsed: ParsedQuery): PrunedProfile {
    const relevantVars = [parsed.outcome_var, ...parsed.predictor_vars];
    return {
      schema: fullProfile.variables.map(v => ({ name: v.name, type: v.type })), // 全部列的类型(轻量)
      details: fullProfile.variables.filter(v => relevantVars.includes(v.name)), // 只有 Y/X 的详细统计
      sampleSize: fullProfile.sampleSize,
      missingRateSummary: fullProfile.overallMissingRate,
    };
  }

  // FallbackLLM 调用失败时降级到现有正则匹配WorkflowPlannerService.parseUserIntent
  private async fallbackToRegex(userText: string, variables: Variable[]): Promise<ParsedQuery> { ... }
}

3.2 前端任务

# 任务 工时 说明
6 追问卡片组件 ClarificationCard.tsx 3h 必须是封闭式数据驱动选择题,禁止开放式提问。后端基于 DataProfile 变量列表预生成 2-3 个具有统计学意义的分析假设,前端渲染为可点击的快捷 Tag"检测到 [Drug] 和 [BP],您是想:👉[比较差异] 👉[相关分析]")。错误示范:"请问您想分析哪两列?"
7 SSAChatPane 集成追问流程 2h 收到 needsClarification 时展示卡片;用户点击选项后自动填充 ParsedQuery 缺失字段,重新提交
8 数据诊断增强展示 2h DataProfileCard 增加异常值/平衡性信息

3.3 Prompt 设计要点

存储方式: 以下 Prompt 通过 seed 脚本写入 capability_schema.prompt_templates 表,template_key = 'ssa_intent_parse'。运行时通过 PromptService.getPrompt() 加载,禁止硬编码在 TypeScript 中

你是一位临床研究统计顾问。请从用户的描述中提取以下信息:

1. goal: 分析目的
   - "difference": 比较差异("有没有效"、"是否不同"、"比较"
   - "association": 关联分析("相关"、"影响因素"、"关系"
   - "prediction": 预测建模("预测"、"风险"、"预后"
   - "description": 描述统计("描述"、"特征"、"分布"
   - "cohort_study": 队列研究全套分析("出一套完整报告"、"基线+单因素+多因素"、"Table 1-3"、"队列研究"

2. outcome_var: 结局变量Y从变量列表中识别
3. predictor_vars: 自变量/分组变量X从变量列表中识别
4. design: 实验设计
   - "independent": 独立样本(不同的人比较)
   - "paired": 配对设计(同一患者前后比较)

5. confidence: 0.0-1.0,你对以上解析的确信程度

**重要规则:**
- 请自动忽略明显的非分析变量(如 patient_id、姓名、病历号、病床号、录入日期等标识/管理类字段),不要将它们选为 outcome_var 或 predictor_vars。
- 如果变量列表中附有用户标注的中文含义variable_description优先参考含义而非列名进行角色判断。

可用变量列表:{{variables}}
用户查询:{{query}}

验收标准:

  • "分析 sex 与 Yqol 的相关性" → { goal: "association", outcome: "Yqol", predictors: ["sex"], confidence: 0.9 }
  • "有没有效" → { goal: "difference", confidence: 0.3, needsClarification: true, questions: [...] }
    • 追问必须是选择题"检测到数据包含 [Drug](分类) 和 [BP](连续)您是想A. 比较用药组 vs 对照组的 BP 差异 B. 分析 Drug 与 BP 的相关性"
    • 禁止开放式提问如 "请问您想比较哪个指标?"
  • prunedProfile 只包含 Y/X 变量的详细统计(非 100 列全量schema 字段包含全部列名+类型
  • 探路测试Tracer Bullet 后端需提供 test_query_pipeline.ts 脚本,用 mock DataProfile 验证 Q 层输出结构正确,无需前端和 R 服务

Phase P : Planner 层重构 — 决策表 + 流程模板4 天)

为什么第三做: 让系统从"单方法执行"跃迁到"完整分析流程"。用户会看到一个包含 4-6 个步骤的专业分析计划。

目标ParsedQuery → 决策表匹配 → 流程模板填充 → 完整 SAP

3.4 决策表设计

核心思想:一张表解决"该用什么方法"的问题。

v7.0 增强: ① 新增 Switch Condition 列 — 描述 Primary/Fallback 互换的触发条件,让方法切换从硬编码变为配置化;② 参数检验优先原则 — Primary 始终设为参数检验(统计效力更高),非参数方法作为 Fallback安全网最终裁决权交给 R 引擎的数据分布检验。

Goal Y_Type X_Type Design Primary Tool Fallback Tool Switch Condition
difference continuous categorical_2 independent ST_T_TEST_IND ST_MANN_WHITNEY normality_fail: Shapiro-Wilk P<0.05
difference continuous categorical_2 paired ST_T_TEST_PAIRED
difference continuous categorical_multi independent ST_ANOVA_ONE ST_KRUSKAL normality_fail: Shapiro-Wilk P<0.05
difference categorical categorical independent ST_CHI_SQUARE ST_FISHER expected_freq_low: 期望频数<5
association continuous continuous ST_CORRELATION
association categorical any ST_CHI_SQUARE ST_FISHER expected_freq_low: 期望频数<5
prediction categorical_binary any ST_LOGISTIC
prediction continuous any ST_LINEAR_REG
description any any ST_DESCRIPTIVE
cohort_study categorical_binary categorical independent ST_BASELINE_TABLE

cohort_study 场景说明: 当 Q 层识别到用户意图为"队列研究全套分析"(触发词:"出一套完整报告"、"基线比较+单因素+多因素"、"Table 1-3"等)时,不走单工具匹配,而是直接选用 cohort_study_standard 流程模板。Q 层 ParsedQuery.goal 需扩展支持 'cohort_study' 值。

3.4.1 决策表存储策略 — Repository 模式

v7.0 新增架构决策: 决策表初期使用 JSON 文件(内容稳定、不需 A/B 测试),但通过 Repository 接口解耦,后期可无缝切换到数据库。

// Repository 接口 — 核心业务逻辑只依赖此接口
interface IDecisionTableRepo {
  getRules(): Promise<DecisionRule[]>;
}

// Phase P 实现JSON 文件
class JsonDecisionTableRepo implements IDecisionTableRepo {
  async getRules() { return decisionTableJson as DecisionRule[]; }
}

// 预留 Phase Deploy 实现数据库SsaDecisionTable 模型已建好)
class PgDecisionTableRepo implements IDecisionTableRepo {
  async getRules() { return await prisma.ssaDecisionTable.findMany(); }
}

3.4.2 Expected vs Actual 双层审计日志

v7.0 新增架构决策: P 层规划时不做正态性预检(正态性检验只在 R 引擎中执行),而是生成"策略日志 (Planned Trace)"。E 层执行后生成"事实日志 (Actual Trace)"。R 层合并两者生成方法学说明。

P 层(策略)──→  PlannedTrace: { primary: "T-Test", fallback: "Wilcoxon", switchCondition: "Shapiro P<0.05" }
                  ↓
    前端 SAP 卡片: "将执行 T 检验。🛡️护栏:若正态性不满足,将自动降级为 Wilcoxon。"
                  ↓
E 层(事实)──→  R trace_log: { check: "normality", result: "fail", action: "switched to Wilcoxon" }
                  ↓
R 层(合并)──→  结合 PlannedTrace + trace_log 生成论文级方法学说明

PlannedTrace 类型定义:

interface PlannedTrace {
  matchedRule: string;          // "Goal=difference, Y=continuous, X=categorical_2, Design=independent"
  primaryTool: string;          // "ST_T_TEST_IND"
  fallbackTool: string | null;  // "ST_MANN_WHITNEY"
  switchCondition: string | null; // "normality_fail: Shapiro-Wilk P<0.05"
  templateUsed: string;         // "standard_analysis"
  reasoning: string;            // 人类可读的方法选择理由
}

原则: P 层只描述"如果…则…"的策略,绝不在 Node.js 中做正态性预检。R 引擎已有完整的分布检验 + 自动降级逻辑,它的 trace_log 天然就是 Actual Trace。

3.5 流程模板设计

核心思想:每种分析目的对应一个标准流程。

v7.0 优化:two_group_comparisonassociation_analysis 合并为 standard_analysis(结构相同,区别仅在决策表填充的工具不同)。最终为 4 个通用模板 + 1 个队列研究专用模板

const FLOW_TEMPLATES = {
  // 通用三步模板 — 适用于 comparison / correlation / association
  "standard_analysis": {
    name: "标准分析流程",
    steps: [
      { order: 1, role: "descriptive",  tool: "ST_DESCRIPTIVE" },
      { order: 2, role: "primary_test", tool: "{{matched_tool}}" },
      { order: 3, role: "sensitivity",  tool: "{{fallback_tool}}", condition: "fallback_exists" },
    ]
  },
  // 配对设计专用
  "paired_analysis": {
    name: "配对设计分析",
    steps: [
      { order: 1, role: "descriptive",  tool: "ST_DESCRIPTIVE" },
      { order: 2, role: "primary_test", tool: "{{matched_tool}}" },
    ]
  },
  // 回归建模
  "regression_analysis": {
    name: "回归建模",
    steps: [
      { order: 1, role: "descriptive",  tool: "ST_DESCRIPTIVE" },
      { order: 2, role: "primary_test", tool: "{{matched_tool}}" },
    ]
  },
  // 纯描述统计
  "descriptive_only": {
    name: "描述性统计",
    steps: [
      { order: 1, role: "descriptive",  tool: "ST_DESCRIPTIVE" },
    ]
  },
  // v6.0 新增:队列研究全套分析(覆盖经典 Table 1 → Table 2 → Table 3
  "cohort_study_standard": {
    name: "经典队列研究全套分析",
    steps: [
      { order: 1, role: "baseline_table",    tool: "ST_BASELINE_TABLE",
        name: "表1: 组间基线特征比较",
        params_mapping: { group_var: "{{exposure_var}}", analyze_vars: "{{all_covariates}}" }
      },
      { order: 2, role: "univariate_screen", tool: "ST_BASELINE_TABLE",
        name: "表2: 结局指标单因素分析",
        params_mapping: { group_var: "{{outcome_var}}", analyze_vars: "{{all_covariates}}" }
      },
      { order: 3, role: "multivariate_reg",  tool: "ST_LOGISTIC_BINARY",
        name: "表3: 多因素 Logistic 回归",
        params_mapping: { outcome_var: "{{outcome_var}}", predictors: "{{epv_capped_predictors}}" }
      },
    ]
  }
};

3.5.1 队列研究 Table 3 — "全量推入 + EPV 防护 + 免责声明"策略

v7.0 新增架构决策: Phase Q+ 的变量选择面板尚未上线前Table 3 的自变量列表采用全量推入策略,辅以 EPV 上限防护。

EPVEvents Per Variable防护逻辑

可纳入变量数 = floor( min(outcome=0的数量, outcome=1的数量) / 10 )
  • 如果 Q 层给出 20 个 predictor但 EPV 只允许 5 个 → P 层自动截断到前 5 个
  • 截断优先级:按 DataProfile 中与 outcome 的关联强度排序(分类变量用卡方统计量,连续变量用 T/Mann-Whitney 统计量)
  • 前端 SAP 卡片标注红色 Tag: [AI 自动探索模式]
  • 免责文案:"当前多因素回归模型纳入了 AI 自动选择的变量(受样本量限制已自动筛选),在后续版本中您将可以手动调整变量。"

Phase Q+ 上线后: {{epv_capped_predictors}} 替换为 {{user_confirmed_predictors}}EPV 防护仍保留作为兜底。

3.6 后端任务

v7.1 调整: 新增任务 0配置化基础设施和任务 1工具注册表原有任务顺延。所有领域知识从代码常量迁移到 JSON 文件,通过 Repository + Zod 校验加载。

# 任务 工时 说明
0 配置化基础设施ConfigLoader + Zod Schema + 热更新 API 2h ① 通用 ConfigLoader 基类(读 JSON + Zod 校验 + 内存缓存);② POST /api/v1/system/reload-config(管理员权限,校验失败保留旧配置,返回 400 + 错误详情);③ 四个领域 JSON 文件的 Zod Schema 定义
1 创建工具注册表 tools_registry.json 2h AVAILABLE_TOOLS 硬编码常量迁移为 JSON 文件。每个工具定义包含:code, name, category, description, inputParams(含 Zod 类型), outputType, prerequisite, fallback。通过 ToolRegistryService + Repository 加载
2 创建决策表配置 decision_tables.json 2h 四维匹配规则的 JSON 版本,含 switchCondition 字段
3 新建 DecisionTableService.ts 4h 通过 IDecisionTableRepo 接口加载Phase P: JSON 实现),四维匹配逻辑
4 创建流程模板配置 flow_templates.json 2h 4+1 个标准模板
5 新建 FlowTemplateService.ts 4h 模板选择 + 参数填充(含 EPV 截断逻辑)
6 重构 PlannerService.ts 4h 接收 ParsedQuery → 调用决策表 → 选模板 → 生成 SAP + PlannedTrace
7 前端 SAP 确认卡片增强 3h 显示每步方法、选择理由、护栏说明、[AI 自动探索模式] 标签
8 联调测试 3h Q → P → E 全链路 + Tracer Bullet 脚本

配置化校验流程:

方法学团队修改 JSON → 调用 POST /reload-config → Zod 校验
  ├── 通过 → 刷新内存缓存 → 返回 200 ✅ 新规则生效
  └── 失败 → 保留旧配置 → 返回 400 + 详细错误信息 ❌ 服务不受影响

PlannerService 核心逻辑v7.0 更新):

// 伪代码 — 体现 Repository 模式 + Expected/Actual 双层日志
class PlannerService {
  constructor(
    private decisionTableRepo: IDecisionTableRepo,  // Repository 模式JSON 或 DB
    private flowTemplateService: FlowTemplateService
  ) {}

  async plan(query: ParsedQuery, profile?: DataProfile): Promise<AnalysisPlan> {
    // 1. 决策表匹配 → 主方法 + 备选方法(通过 Repository 加载规则)
    const rules = await this.decisionTableRepo.getRules();
    const match = this.matchRule(rules, query.goal, query.outcome_type, query.predictor_types, query.design);
    
    // 2. 选择流程模板
    const template = this.flowTemplateService.select(query.goal, query.design, match);
    
    // 3. 填充参数(含 EPV 防护)
    const steps = this.flowTemplateService.fill(template, {
      matched_tool: match.primaryTool,
      fallback_tool: match.fallbackTool,
      outcome_var: query.outcome_var,
      predictor_vars: query.predictor_vars,
      grouping_var: query.grouping_var,
      profile,
    });
    
    // 4. 生成 PlannedTrace策略日志 — P 层只描述"如果…则…"
    const plannedTrace: PlannedTrace = {
      matchedRule: `Goal=${query.goal}, Y=${query.outcome_type}, X=${query.predictor_types[0]}, Design=${query.design}`,
      primaryTool: match.primaryTool,
      fallbackTool: match.fallbackTool,
      switchCondition: match.switchCondition,   // "normality_fail: Shapiro-Wilk P<0.05"
      templateUsed: template.id,
      reasoning: this.explainMethodChoice(match, query),
    };
    // 注意Actual Trace 由 E 层的 R trace_log 提供P 层不做正态性预检
    
    // 5. 生成 SAP
    return { steps, plannedTrace, methodology: plannedTrace.reasoning };
  }
}

验收标准v7.0 更新):

  • 输入 { goal: "comparison", outcome_type: "continuous", predictor_types: ["binary"], design: "independent" }
  • 输出 3 步流程:描述统计 → T 检验Primary → Mann-WhitneySensitivity条件展示
  • plannedTrace 包含 switchCondition: "normality_fail" + reasoning 人类可读理由
  • 前端 SAP 卡片每步显示选择理由;有 fallback 的步骤显示护栏说明("若正态性不满足,将自动降级为…"
  • P 层不做正态性预检,方法切换由 R 引擎在执行时根据数据分布自行决定
  • 队列研究场景:输入 { goal: "cohort_study" } → 输出 Table 1/2/3 三步流程Table 3 自变量经 EPV 截断 + [AI 自动探索模式] 标签
  • 探路测试Tracer Bullet 后端需提供 test_planner_pipeline.ts 脚本,用 mock ParsedQuery 验证 P 层输出结构正确(不依赖前端和 R 服务。Q→P 串联测试也必须通过

Phase R : Reflection 层建设 — LLM 论文级结论3 天)

为什么第四做: 这是让输出从"P=0.015"变成"可以直接用于论文"的关键。

目标StepResult[] → LLM 综合解读 → 论文级结论 + 方法学说明

3.7 后端任务

# 任务 工时 说明
1 通过 PromptService 注册 Reflection Prompt 3h seed 脚本写入 capability_schema.prompt_templatestemplate_key = 'ssa_reflection'输出6 要素结论。统计量通过槽位注入,禁止 LLM 生成数值含敏感性分析冲突处理准则3.10 节)
2 重构 ConclusionGeneratorServiceReflectionService 6h 通过 LLMFactory 调用 LLM + Zod 强校验 LLM 输出结构3.11 节) + 结果整合。接收 decision_trace 生成方法学说明。LLM 输出完整收集后校验不做字符级流式推送3.12 节)
3 E 层运行时崩溃优雅处理(重试机制推迟至 Phase Deploy 1h 错误分类映射表NA 值/列名缺失/R Fatal Error → 友好用户提示),不做跨层 Self-healing。完整重试机制MAX_RETRIES=2 + 参数级修复 + 方法级降级)推迟至 Phase Deploy(见 3.8 节详述)
4 结论缓存(CacheService+ API 2h GET /sessions/:id/conclusion,使用平台 CacheService 缓存结论避免重复 LLM 调用
5 前端论文结论展示 4h Markdown 渲染 + 一键复制 + 折叠/展开;采用"完整 JSON + 逐 section 渐入动画"方案3.12 节),不做字符级流式推送
6 Word 报告增强 3h 纳入 LLM 结论(替代当前的简单 summary
7 联调测试 3h Q → P → E → R 完整链路

重要: ReflectionService 是对现有 ConclusionGeneratorService 的升级重构,不是从零新建。保留 ConclusionGeneratorService 作为 fallback 入口LLM 调用失败或 Zod 校验失败时降级到规则拼接。

3.8 E 层运行时错误处理策略

来源: 《QPER架构审查与工程避坑指南》暗礁 2 + 架构委员会裁决。

关键区分: "统计降级"(如正态性不满足自动切非参数)由 R 脚本内部 if-else 处理,不是运行时错误。"运行时崩溃"(如 NA 值导致 R Fatal Error、列名隐形空格、数据结构异常才需要 Node.js 层处理。

Phase R 当前实施(优雅错误分类):

现有 WorkflowExecutorService 已具备步骤级 try-catch + step_error SSE 推送能力。Phase R 在此基础上增加错误分类映射表,将 R 引擎的原始错误转化为用户友好提示:

错误模式R 报错关键词) 用户友好提示 错误码
NAmissing valuesincomplete cases "数据中存在缺失值,请检查数据清洗后重试" E_MISSING_DATA
column not foundundefined columnsnot found "运算引擎未找到指定变量列,请检查数据源列名是否正确" E_COLUMN_NOT_FOUND
system is computationally singularcollinear "数据存在严重共线性,建议排除冗余变量后重试" E_COLLINEARITY
not enough observationssample size "样本量不足以执行该统计方法,建议增加样本或选用非参数方法" E_INSUFFICIENT_SAMPLE
contrasts can be applied only to factors with 2 or more levels "分组变量的水平数不足,请检查数据分组" E_FACTOR_LEVELS
其他未匹配的 R 错误 "运算引擎遇到异常,请检查数据结构后重试" E_UNKNOWN

Phase Deploy 推迟实施(完整重试短路机制):

以下机制推迟到 Phase Deploy 阶段实施Phase R 不做跨层 Self-healing。

强制规则: MAX_RETRIES = 2,超过后直接中断。

错误类型 典型报错关键词 处理策略
不可重试Hard Abort system is computationally singularnot enough observationscontrasts can be applied only to factors with 2 or more levels 直接中断,跳过重试,生成诊断报告给用户
可重试 — 参数级修复 column not foundinvalid factor levelmissing values LLM 分析错误日志 → 修改参数 JSON → 重新请求同一 R 脚本(禁止生成新 R 代码
可重试 — 方法级降级 sample size too small for parametric test 回调 Planner 切换 Fallback Tool如 T 检验 → Mann-Whitney

3.9 统计量"槽位注入"反幻觉机制

来源: 《医疗AI统计助手架构研究》议题 3 — LLM 被剥夺生成数值 Token 的权限。

核心规则: 结论中的所有统计量P 值、效应量、置信区间等)必须来自 R 引擎的实际输出,通过模板槽位渲染,禁止 LLM 在自由文本中"编写"任何数值

// Reflection Prompt 中的槽位引用示例
各步骤结果(以下数值为系统自动注入,你不得修改或重新表述这些数字):

步骤 1独立样本 T 检验
- 统计量t = {{steps[1].statistic}}
- P 值:{{steps[1].p_value}}
- 效应量 Cohen's d{{steps[1].effect_size}}
- 95% 置信区间:{{steps[1].ci_lower}} ~ {{steps[1].ci_upper}}

请基于上述精确数值生成论文结论,结论中引用数值时必须与上方完全一致。

实现方式: ReflectionService.extractKeyFindings() 将 R 返回的 JSON 中的数值提取为 {{slot}} 变量,在 Prompt 渲染时注入。LLM 只负责生成叙述性文字框架。

ReflectionService 核心逻辑:

// 伪代码 — 使用平台通用能力层v8.0 更新Zod 校验 + 完整 JSON 推送)
import { z } from 'zod';
import { jsonrepair } from 'jsonrepair';

// Zod Schema — 强校验 LLM 输出结构(见 3.11 节)
const ConclusionReportSchema = z.object({
  executive_summary: z.string().min(10),
  key_findings: z.array(z.string()).min(1),
  statistical_summary: z.object({
    total_tests: z.number(),
    significant_results: z.number(),
    methods_used: z.array(z.string()),
  }),
  methodology: z.string().min(10),
  limitations: z.array(z.string()).min(1),
  recommendations: z.array(z.string()).optional(),
});

class ReflectionService {
  constructor(
    private promptService: PromptService,       // 平台通用能力Prompt 管理
    private llmFactory: LLMFactory,             // 平台通用能力LLM 网关
    private cacheService: CacheService,         // 平台通用能力:缓存
    private conclusionGenerator: ConclusionGeneratorService, // Fallback旧规则拼接
  ) {}

  async reflect(plan: AnalysisPlan, results: StepResult[], sseEmitter?: SSEEmitter): Promise<ConclusionReport> {
    // 0. 缓存命中检查
    const cacheKey = `ssa:conclusion:${plan.workflow_id}`;
    const cached = await this.cacheService.get(cacheKey);
    if (cached) return cached;

    // 1. 发送 QPER 状态:正在生成结论
    sseEmitter?.emit({ type: 'qper_status', status: 'reflecting', message: '正在生成论文级结论...' });

    // 2. 整合所有步骤的关键指标(提取为槽位变量,用于反幻觉注入)
    const keyFindings = this.extractKeyFindings(results);
    
    // 3. 从数据库加载 Prompt 模板
    const promptTemplate = await this.promptService.getPrompt('ssa_reflection', 'latest');
    const prompt = this.promptService.render(promptTemplate, {
      goal: plan.goal, 
      methodology: plan.methodology,
      decision_trace: plan.decision_trace,
      findings: keyFindings,
      sampleSize: plan.sampleInfo
    });

    // 4. 调用 LLM完整收集不做字符级流式推送
    const llm = this.llmFactory.create({ model: 'deepseek-v3', temperature: 0.3 });
    try {
      const rawOutput = await llm.chat(prompt);
      
      // 5. jsonrepair + Zod 强校验(见 3.11 节)
      const repaired = jsonrepair(rawOutput);
      const parsed = JSON.parse(repaired);
      const conclusion = ConclusionReportSchema.parse(parsed);
      
      // 6. 缓存 + 通过 SSE 推送完整结构化结论(见 3.12 节)
      const report: ConclusionReport = {
        workflow_id: plan.workflow_id,
        ...conclusion,
        step_summaries: this.buildStepSummaries(results),
        generated_at: new Date().toISOString(),
      };
      await this.cacheService.set(cacheKey, report, { ttl: 3600 });
      sseEmitter?.emit({ type: 'reflection_complete', conclusion: report });
      return report;
      
    } catch (error) {
      // LLM 失败或 Zod 校验失败 → 降级到规则拼接
      logger.warn('[SSA:Reflection] LLM/Zod failed, falling back to rule-based', { error });
      const fallback = this.conclusionGenerator.generateConclusion(results, plan.goal);
      const report = this.adaptLegacyToNew(plan.workflow_id, fallback);
      sseEmitter?.emit({ type: 'reflection_complete', conclusion: report });
      return report;
    }
  }
}

Reflection Prompt 设计要点:

存储方式: 以下 Prompt 通过 seed 脚本写入 capability_schema.prompt_templates 表,template_key = 'ssa_reflection'。运行时通过 PromptService.getPrompt() 加载。

你是一位高级生物统计师,请基于以下分析结果生成论文级结论。

分析目标:{{goal}}
采用方法:{{methodology}}

方法选择的决策轨迹(请据此撰写方法学说明,不得臆造选择理由):
{{decision_trace.matched_rule}}
{{#each decision_trace.diagnosis_adjustments}}
- 调整:{{this}}
{{/each}}

各步骤结果(⚠️ 以下数值由系统自动注入,你必须原样引用,不得修改、四舍五入或重新表述任何数字):
{{#each findings}}
步骤 {{step_number}}{{tool_name}}
- 统计量:{{statistic}}
- P 值:{{p_value}}
- 效应量:{{effect_size}}
- 置信区间:{{ci_lower}} ~ {{ci_upper}}
{{/each}}

请生成包含以下要素的结论:
1. 样本描述(纳入/排除)
2. 主要结果(含统计量和 P 值 — 必须与上方数值完全一致)
3. 效应量解读(临床意义)
4. 敏感性分析结论(如有)
5. 方法学说明(基于上方决策轨迹撰写,解释为什么选择此方法)
6. 局限性声明

要求:使用论文"结果"章节的行文风格,可直接复制到论文中。

验收标准:

  • 输入 T 检验结果 { t=2.45, p=0.015, d=0.52 }
  • 输出包含 6 个要素的论文级结论
  • Word 导出包含 LLM 结论(非简单数字罗列)

3.10 敏感性分析结论冲突 Prompt 策略

来源: 架构委员会建议 1 — 当主分析与敏感性分析显著性不一致时LLM 容易陷入逻辑混乱或强行拼凑显著性。

业务痛点: 在"描述→主分析→敏感性分析"的标准流程中,如果 T 检验P=0.04(显著)但 Wilcoxon 检验P=0.06不显著LLM 可能选择性忽略不一致的结果。在临床研究中,这属于必须报告的结果稳健性问题。

实施方式:ssa_reflection Prompt 模板中硬编码冲突处理准则:

## 冲突处理准则(强制执行)
当主分析与敏感性分析的显著性结论不一致时:
1. 在【局限性声明】中必须指出:"敏感性分析未得到一致结论结果的稳健性Robustness较弱需谨慎解释临床意义"
2. 在【主要发现】中以主分析结果为基准报告,但需加注"敏感性分析未验证此结论"
3. 严禁选择性报告、强行拼凑显著性
4. 当所有分析方向一致时,在【主要发现】中强调"敏感性分析进一步验证了结论的稳健性"

效果: LLM 遇到矛盾数据时有明确的处理规程,既保证了学术诚信,又为临床研究者提供了稳健性判断依据。实现成本极低(仅在 Prompt 中增加 4 行准则)。

3.11 Zod Schema 强校验 LLM 输出

来源: 架构委员会建议 2 — LLM 偶尔漏掉 JSON Key 或将数组写成字符串,导致前端渲染崩溃。

与 Phase Q 的模式一致性: Phase Q 中已成功实践 jsonrepair + Zod 动态校验(createDynamicIntentSchema。Phase R 延续同一防御范式。

实施方式: ReflectionService 中对 LLM 输出进行三层防御:

Layer 1: jsonrepair  — 修复 LLM 输出的 JSON 格式错误(漏逗号、多余尾逗号等)
Layer 2: JSON.parse  — 解析为 JS 对象
Layer 3: Zod Schema  — 强校验结构完整性(字段是否齐全、类型是否正确、数组最小长度等)

Zod Schema 定义(与前端 ConclusionReport 接口对齐):

const ConclusionReportSchema = z.object({
  executive_summary: z.string().min(10),           // 不允许空摘要
  key_findings: z.array(z.string()).min(1),         // 至少 1 条发现
  statistical_summary: z.object({
    total_tests: z.number(),
    significant_results: z.number(),
    methods_used: z.array(z.string()),
  }),
  methodology: z.string().min(10),                  // 不允许空方法学说明
  limitations: z.array(z.string()).min(1),          // 至少 1 条局限性
  recommendations: z.array(z.string()).optional(),  // 建议为可选
});

降级触发: Zod 校验失败时,立即切回旧的 ConclusionGeneratorService(规则拼接),确保前端始终收到有效的结论结构。日志记录 Zod 错误详情,用于后续 Prompt 迭代优化。

3.12 Reflection 输出交付策略(完整 JSON + 逐 Section 渐入)

来源: 架构委员会建议 3 — 逐字推送 JSON 字符串会导致前端频繁抛出 SyntaxError

核心决策: Phase R 的 Reflection 输出不做字符级流式推送,采用"后端完整收集 + Zod 校验 + 一次性推送 + 前端逐 section 渐入动画"方案。

不采用字符级流式推送的理由:

  1. Zod 校验需要完整 JSON — 无法对不完整的 JSON 片段执行结构校验
  2. 结构化数据需求 — Word 导出、数据库存储、API 返回都需要完整的 ConclusionReport JSON
  3. 等待时间可接受 — LLM 生成结论通常 3-8 秒,期间通过 qper_status SSE 事件展示"正在生成论文级结论..."用户已看到所有数字结果E 层 report_blocks),不会焦虑
  4. 避免 Markdown↔JSON 双向转换的脆弱性 — 如果 LLM 输出纯 Markdown 再解析为 JSON逆向解析极易出错

完整的交付流程:

后端流程:
  1. 发送 SSE: { type: 'qper_status', status: 'reflecting', message: '正在生成论文级结论...' }
  2. LLM 完整生成结构化 JSON非流式
  3. jsonrepair → JSON.parse → Zod 校验
  4. 校验通过 → SSE: { type: 'reflection_complete', conclusion: ConclusionReport }
  5. 校验失败 → ConclusionGeneratorService fallback → SSE: { type: 'reflection_complete', ... }

前端渲染(逐 section 渐入动画):
  1. 收到 qper_status(reflecting) → 显示加载动画 "📝 正在生成论文级结论..."
  2. 收到 reflection_complete → 开始渐入动画:
     - 0ms:   executive_summary 淡入
     - 300ms: key_findings 逐条滑入
     - 600ms: methodology 淡入
     - 900ms: limitations 淡入
     - 1200ms: recommendations 淡入(如有)
  3. 动画完成 → 显示"一键复制"和"导出 Word"按钮

SSE 事件类型调整(见 5.5 节):reflection_streamchunk-based改为 reflection_complete(一次性完整推送)。


Phase Deploy : 工具补齐 + 部署上线4 天)

为什么最后做: 智能化架构搭好后,补齐剩余工具和部署上线。

# 任务 工时 说明
1 R 工具补齐ANOVA 3h ST_ANOVA_ONE + Block-based 输出
2 R 工具补齐Fisher 2h ST_FISHER + Block-based 输出
3 R 工具补齐Wilcoxon 2h ST_WILCOXON + Block-based 输出
4 R 工具补齐:线性回归 3h ST_LINEAR_REG + Block-based 输出
5 复合工具 ST_BASELINE_TABLER 端) 4h 基于 gtsummary::tbl_summary(by=group_var) %>% add_p() 封装;输入:group_var + analyze_vars[];自动判断连续/分类、正态/非正态、选择 T 检验/Mann-Whitney/卡方/FisherR Docker 镜像需新增 gtsummary+gt+broom 依赖
6 gtsummaryreport_blocks 转换层 4h gtsummary::as_tibble() 提取结构化表格 → 转换为 table block需处理合并行分类变量名+各水平值;列头:分组名称);输出需同时包含渲染用 blocks 和结构化 significant_vars[]P<0.05 的变量列表,供后续步骤消费)
7 前端三线表渲染增强 4h DynamicReport.tsxtable block 增强:支持 rowspan分类变量合并行、分组列头group1 vs group2 vs P 值、P<0.05 加粗/标星、横向滚动20+ 变量场景)
8 决策表补齐所有工具映射 2h 11 工具全部纳入(含 ST_BASELINE_TABLE
9 流程模板补齐 2h 覆盖所有 Goal 类型 + cohort_study_standard 模板(见下方)
10 R Docker 镜像推送 ACR 1h 新工具 + gtsummary 依赖包含在内
11 SAE 部署 + 联调 4h R 服务 + 后端 + 前端
12 端到端测试12 场景) 8h 原 10 场景 + 队列研究全套流程表1→表2→表3×2 数据集

Phase Q+ : 人机协同增强 — 变量字典 + 变量选择面板2.5 天)

为什么独立分期: Phase Q 核心目标是证明 LLM 能从自然语言中提取 [Goal, Y, X, Design]。将重度前端交互(表格编辑、穿梭框、状态回传)与核心 AI 逻辑耦合会导致单点阻塞。Phase Q+ 在 Q-P-E-R 主线闭环跑通后再启动,此时:① 已有 AI 基线准确率数据,可量化人机协同的提升价值;② 后端接口已稳定,前端可安全叠加。

核心哲学AI 负责统计专业知识,医生负责临床领域知识。

定位Phase Q 的增强层,非阻塞主线交付
前置依赖Phase Q 验收通过LLM 意图解析基线可用)
触发时机Q-P-E-R 主线闭环跑通后

3.10 增强点一变量数据字典Data Dictionary

解决什么问题: 临床数据列名极不规范(grpTxSBPDataProfile 只有统计特征没有语义信息。LLM 靠猜列名含义,猜错即全链路错误。

交互模式:"AI 先猜,用户微调"

  • 文件上传 + DataProfiler 完成后,后端静默调用 LLM基于列名 + 前 5 行数据 + 数据类型)猜测每个变量的中文含义
  • 前端推送变量字典编辑面板,用户确认或修改
  • 经用户确认的字典成为黄金上下文Golden Context,后续 Q/P/R 全链路可消费
# 任务 层级 工时 说明
1 VariableDictService.ts — LLM 变量含义猜测 后端 3h 通过 PromptService + LLMFactory 调用 LLM输入列名+前5行+类型,输出 { name, guessed_meaning, guessed_role }[]Zod 校验
2 Prisma schema 扩展 后端 1h SsaFileUpload 新增 variable_dictionary: Json? 字段(或新建 SsaVariableDictionary 表),存储用户确认后的字典
3 变量字典 API 后端 1h GET /api/v1/ssa/sessions/:id/variable-dict(获取 AI 猜测结果)+ PUT(保存用户修改)
4 VariableDictEditor.tsx 前端组件 前端 3h 表格形式:`变量名
5 QueryService 集成字典 后端 1h parseQuery 方法接受可选 variableDict 参数,有字典时将 variable_description 注入 Prompt 的 {{variables}}

验收标准:

  • 上传含 grp(1,2) 列的 CSV → AI 猜测"分组变量" → 用户标注"1=新药, 2=安慰剂" → 后续 Q 层正确识别 grp 为分组变量
  • 用户跳过字典编辑(直接点"确认")→ 系统正常运行AI 猜测结果作为默认值)

3.11 增强点二变量选择确认面板Variable Selection

解决什么问题: LLM 从 100 列中猜 Y/X 变量,可能选错或遗漏关键协变量。医生最清楚哪些是核心指标、哪些必须作为调整变量纳入。

交互模式AI 推荐 + 医生确认/调整

  • Q 层 LLM 解析完意图后,在进入 P 层之前推送变量选择确认面板
  • AI 预选的 Y/X 变量已标记医生可增删、可添加协变量Confounders
  • 医生确认后的变量集合替代 AI 原始选择,传入 P 层
# 任务 层级 工时 说明
6 QueryService 输出扩展 后端 1h ParsedQuery 增加 suggested_confounders: string[]AI 建议的协变量)+ all_candidate_vars 列表供前端渲染
7 VariableSelectionPanel.tsx 前端组件 前端 4h 穿梭框/卡片交互:左侧"可用变量"(全部),右侧"已选变量"分三区Y/X/协变量AI 预选项高亮标记;支持拖拽或点击增删
8 确认 API + Context Pruning 衔接 后端 1h POST /api/v1/ssa/sessions/:id/confirm-variables;用户确认的变量集合覆盖 AI 原始选择,pruneForPlanner 以医生确认集合为基准裁剪
9 SSE 事件 + 状态回传 后端 1h DICT_EDITING / VARIABLE_CONFIRMING 状态推送 + 前端状态管理集成
10 SSAChatPane 集成两个面板 前端 2h 接收 SSE 事件渲染字典编辑器/变量选择面板,用户操作后回传并恢复流程

验收标准:

  • AI 推荐 Y=BP, X=Drug → 医生增加协变量 Age, Sex → P 层收到完整的 [Y=BP, X=Drug, Confounders=[Age, Sex]]
  • 医生不修改直接确认 → 使用 AI 原始选择(零额外成本)

3.12 Phase Q+ 默认放行策略

重要: Phase Q+ 未上线前,系统自动跳过 DICT_EDITINGVARIABLE_CONFIRMING 状态,直接使用 AI 自动解析结果。后端接口契约保持不变。

// Phase Q+ 开关feature flag
const PHASE_Q_PLUS_ENABLED = false; // Phase Q+ 上线后改为 true 或从配置读取

// 状态机跳过逻辑
if (currentStatus === 'profiling_done') {
  nextStatus = PHASE_Q_PLUS_ENABLED ? 'dict_editing' : 'pending_intent';
}
if (currentStatus === 'intent_parsed') {
  nextStatus = PHASE_Q_PLUS_ENABLED ? 'variable_confirming' : 'planning';
}

Phase Q+ 工时汇总:

类型 任务 工时
后端 VariableDictService + Schema + API + QueryService集成 + 确认API + SSE 8h
前端 VariableDictEditor + VariableSelectionPanel + SSAChatPane集成 9h
测试 两个面板的端到端验证 3h
合计 20h2.5天)

4. 代码目录结构(渐进式,不做大规模重组)

策略: 所有新文件放入现有的 services/config/ 目录,而非创建 query/ planner/ reflection/ 子目录。原因:现有 SSA 模块已有大量文件互相引用,子目录化会导致全量 import 路径变更、风险过高、产出为零。用 文件命名前缀 区分 QPER 层级即可。

backend/src/modules/ssa/
├── services/                       ← 所有服务统一放此目录
│   ├── QueryService.ts             # Q 层LLM 意图解析 + 追问逻辑(新建)
│   ├── VariableDictService.ts     # Q+ 层LLM 变量含义猜测 + 字典管理Phase Q+ 新建)
│   ├── DataDiagnosticService.ts    # Q 层:数据深度诊断(新建,扩展 DataProfileService
│   ├── PlannerService.ts           # P 层:核心规划逻辑(新建,接收 ParsedQuery
│   ├── DecisionTableService.ts     # P 层:决策表加载 + 四维匹配(新建)
│   ├── FlowTemplateService.ts      # P 层:流程模板管理(新建)
│   ├── ReflectionService.ts        # R 层LLM 结论生成(重构自 ConclusionGeneratorService
│   ├── WorkflowExecutorService.ts  # E 层:步骤编排 + SSE✅ 保持不变)
│   ├── RClientService.ts           # E 层R 引擎调用(✅ 保持不变)
│   ├── WorkflowPlannerService.ts   # 兼容层:旧入口,内部委托 QueryService + PlannerService
│   ├── ConclusionGeneratorService.ts # 兼容层:旧入口,内部委托 ReflectionService
│   ├── DataProfileService.ts       # 共享Python 数据质量(✅ 保留)
│   └── DataParserService.ts        # 共享:文件解析(✅ 保留)
│
├── config/                         ← 决策表 + 流程模板配置
│   ├── decision_table.json         # P 层配置
│   └── flow_templates.json         # P 层配置
│
├── types/                          ← 新增 QPER 接口定义
│   ├── query.types.ts              # ParsedQuery 接口
│   ├── planner.types.ts            # AnalysisPlan / AnalysisStep 接口
│   └── reflection.types.ts         # Conclusion 接口
│
├── routes/                         # API 路由(扩展,不重建)
│   ├── analysis.routes.ts          # ✅ 保留
│   ├── workflow.routes.ts          # ✅ 保留
│   └── config.routes.ts            # ✅ 保留(已有决策表/代码库 CRUD
└── ...

Prompt 不放在本地文件中,而是通过平台 PromptService 存入 capability_schema.prompt_templates 数据库表,支持版本管理和 A/B 测试。开发阶段使用 seed 脚本初始化。


5. 数据流协议

5.1 Q → P 接口契约

interface ParsedQuery {
  // 用户意图
  goal: 'difference' | 'association' | 'prediction' | 'description';
  confidence: number;               // 0.0 - 1.0
  
  // 变量角色
  outcome_var: string;              // 结局变量 (Y)
  outcome_type: 'continuous' | 'categorical' | 'binary';
  predictor_vars: string[];         // 自变量 (X)
  predictor_types: string[];        // 各自变量类型
  
  // 实验设计
  design: 'independent' | 'paired';
  
  // 数据诊断Q 层产出)
  dataDiagnosis: {
    sampleSize: number;
    missingRate: Record<string, number>;
    outlierCount: Record<string, number>;
    normalityTests?: Record<string, { pValue: number; isNormal: boolean }>;
    groupBalance?: { groups: string[]; counts: number[] };
  };
  
  // 追问状态
  needsClarification: boolean;
  clarificationQuestions?: string[];
}

5.2 P → E 接口契约

兼容策略:AnalysisPlan 接口必须兼容现有 WorkflowPlanWorkflowExecutorService 已在使用),避免 Execute 层改动。AnalysisStep 扩展自现有 WorkflowStep,新增字段为可选。

// 现有接口WorkflowExecutorService 已使用,不可破坏)
interface WorkflowStep {
  step_number: number;
  tool_code: string;
  tool_name: string;
  description: string;
  params: Record<string, unknown>;
}

// 新增接口(扩展,向后兼容)
interface AnalysisStep extends WorkflowStep {
  role?: 'descriptive' | 'primary_test' | 'sensitivity' | 'effect_size';  // 可选,新增
}

interface AnalysisPlan {
  workflow_id: string;
  title: string;
  methodology: string;             // "因 Y 为连续变量且两组独立,采用独立样本 T 检验"
  rationale: string;               // "数据满足正态分布假设(Shapiro P=0.15)"
  
  steps: AnalysisStep[];           // 兼容 WorkflowStep[]
  
  // 元信息新增P 层产出)
  primary_tool: string;
  fallback_tool?: string;
  flow_template_used: string;
  
  // 决策审计日志P 层产出 → R 层消费,用于生成方法学说明)
  decision_trace: {
    matched_rule: string;          // "Y=continuous, X=categorical_2, Design=independent → ST_T_TEST_IND"
    diagnosis_adjustments: string[];  // ["Shapiro-Wilk P=0.03 < 0.05 → 切换非参数 Mann-Whitney"]
    triggered_at: string;          // ISO timestamp
  };
}

// 兼容转换函数PlannerService 内部使用)
function toWorkflowPlan(plan: AnalysisPlan): WorkflowPlan {
  return {
    workflow_id: plan.workflow_id,
    steps: plan.steps,  // AnalysisStep extends WorkflowStep直接兼容
    // ...
  };
}

5.3 E → R 接口契约

interface ExecutionResult {
  steps: StepResult[];              // 各步骤结果(已有)
  report_blocks: ReportBlock[];     // Block-based 输出Phase E+ 新增)
  total_duration_ms: number;
}

5.4 会话状态机(防面条代码)

来源: 《QPER V3.0 架构审查与工程护航报告》隐患 2 — QPER 流程存在 Clarifier等用户回复和 Reflection错误重试两处中断/恢复逻辑,用嵌套 if-else + while 会迅速劣化为面条代码。

enum ExecutionStatus {
  PENDING_UPLOAD       = 'pending_upload',       // 等待数据上传
  PROFILING            = 'profiling',            // 数据诊断中Python Tool C
  DICT_EDITING         = 'dict_editing',         // 🆕 Phase Q+:变量字典编辑中 — ⏸️ 中断,等待用户确认
  PENDING_INTENT       = 'pending_intent',       // 等待意图解析
  CLARIFYING           = 'clarifying',           // 追问中 — ⏸️ 中断,等待用户回复
  VARIABLE_CONFIRMING  = 'variable_confirming',  // 🆕 Phase Q+:变量选择确认中 — ⏸️ 中断,等待用户确认
  PLANNING             = 'planning',             // 规划中
  PLAN_CONFIRMING      = 'plan_confirming',      // 等待用户确认 SAP — ⏸️ 中断
  EXECUTING            = 'executing',            // R 引擎执行中
  REFLECTING           = 'reflecting',           // 结论生成中
  RETRYING             = 'retrying',             // 错误修复后重试中MAX_RETRIES=2
  COMPLETED            = 'completed',            // 完成
  FAILED               = 'failed',               // 失败(不可恢复)
}

状态持久化: ExecutionStatus 存入 SsaSession 表。当状态为 DICT_EDITINGCLARIFYINGVARIABLE_CONFIRMINGPLAN_CONFIRMING 时,后端立即中断执行并向前端发送交互面板,等待下一次 HTTP 请求(用户操作/确认)后从该状态恢复继续。

状态流转图:

PENDING_UPLOAD → PROFILING → [DICT_EDITING]* → PENDING_INTENT → CLARIFYING (可选,循环)
                                                      ↓
                                            [VARIABLE_CONFIRMING]*
                                                      ↓
                                                 PLANNING → PLAN_CONFIRMING (可选)
                                                      ↓
                                                 EXECUTING → REFLECTING → COMPLETED
                                                      ↑         ↓
                                                      └── RETRYING (MAX 2次)
                                                                ↓ (超限)
                                                             FAILED

* [方括号] 表示 Phase Q+ 新增状态Phase Q+ 未上线时自动跳过feature flag 控制)

5.5 QPER 级 SSE 事件类型(全链路状态推送)

来源: 《QPER V3.0 架构审查与工程护航报告》隐患 3 — R 层重试过程可能耗时 15-20 秒,用户只看到转圈会认为系统死了。"展示 AI 工作过程"是信任建立的关键。

当前 SSE 只覆盖 E 层步骤进度。扩展为 QPER 全链路状态推送:

// SSE 事件类型扩展v8.0 更新reflection_stream → reflection_complete
type SSAEvent =
  | { type: 'qper_status'; status: ExecutionStatus; message: string }  // 状态跃迁
  | { type: 'step_progress'; step: number; total: number; ... }       // E 层步骤进度(已有)
  | { type: 'clarification'; questions: ClarificationOption[] }       // 追问卡片
  | { type: 'plan_ready'; plan: AnalysisPlan }                        // SAP 确认
  | { type: 'reflection_complete'; conclusion: ConclusionReport }     // R 层完整结论(一次性推送,非字符流)
  | { type: 'error'; code: string; message: string }                  // 错误

// 前端渲染效果示例:
// [Query]      🧠 正在理解您的分析意图...
// [Query]      ✅ 识别到:差异比较 | Y=血压 | X=用药组
// [Planner]    📋 正在规划分析方案...
// [Planner]    ✅ 已生成 3 步分析计划(描述统计 → T检验 → Mann-Whitney
// [Executor]   🔄 步骤 1/3描述统计...
// [Executor]   ✅ 步骤 1/3 完成 [0.8s]
// [Executor]   ❌ 步骤 2/3 失败:变量存在完全共线性
// [Executor]   ⚠️ 运算引擎遇到异常数据存在严重共线性E_COLLINEARITY
// [Executor]   🔄 步骤 3/3Mann-Whitney...
// [Executor]   ✅ 步骤 3/3 完成 [0.6s]
// [Reflection] 📝 正在生成论文级结论...qper_status: reflecting
// [Reflection] ✅ 结论生成完成reflection_complete → 前端逐 section 渐入动画)

6. 工时与里程碑

Phase 名称 工时 日历天 里程碑 变更说明
E+ Block-based 标准化 15.5h 2.5天 R 输出标准化,前端动态渲染 后端透传需含 report_blocks 全链路验证
Q Query 层LLM 意图) 33h 5天 用户说"有没有效"即可分析 v4.0 +1.5hDataProfile 会话级缓存(0.5h) + Intent Prompt Few-Shot(1h)v3.0 +1hContext Pruning
P Planner 层(决策表+模板) 23h 4天 完整分析流程(非单方法) v3.0 +1hdecision_trace 决策审计日志输出
R Reflection 层LLM 结论) 22h 3天 论文级结论,可直接用于论文 v3.0 +2h统计量槽位注入反幻觉v8.0 -1h完整重试推迟至 DeployPhase R 仅做错误分类映射(1h)+0h敏感性冲突 Prompt + Zod 校验 + 完整 JSON 交付(融入现有任务工时)
Deploy 工具补齐 + 部署 37h 5.5天 11 工具上线(含复合工具),生产环境可用 v6.0 +12hST_BASELINE_TABLE(4h) + gtsummary→blocks 转换(4h) + 前端三线表增强(4h);端到端测试 +2h
主线合计 130.5h ~20天 Q-P-E-R 主线闭环 v6.0 Deploy +12hv4.0 +1.5hv3.0 +4hv8.0 -1h
--- --- --- --- --- ---
Q+ 人机协同增强 20h 2.5天 变量字典 + 变量选择面板 v5.0 新增医生注入临床领域知识AI→人机协同
总计 150.5h ~22.5天 Q-P-E-R + 人机协同 + 队列研究全套 主线闭环后启动 Phase Q+

里程碑时间线

Week 1 ──────────────────────────────────
  Day 1-2:   Phase E+ (Block-based)
  Day 3-5:   Phase Q  (Query 层前半Prompt 注册 + QueryService)

Week 2 ──────────────────────────────────
  Day 6-7:   Phase Q  (Query 层后半DataDiagnostic + 前端追问 + 联调)
  Day 8-11:  Phase P  (Planner 层)

Week 3 ──────────────────────────────────
  Day 12-14: Phase R  (Reflection 层)
  Day 15-19: Phase Deploy (原子工具补齐 + ST_BASELINE_TABLE 复合工具 + 部署)
  Day 20:    队列研究端到端验证Table 1→2→3 全流程)

Week 4 ──────────────────────────────────
  ✅ Q-P-E-R 主线闭环上线(里程碑 1含队列研究全套分析能力
  Day 20:    收集 AI 基线准确率数据(无人机协同下的意图识别准确率)

Week 4-5 ────────────────────────────────
  Day 19-21: Phase Q+ (变量字典 + 变量选择面板)
  ✅ 人机协同增强上线(里程碑 2
  对比量化:人机协同 vs 纯 AI 的准确率提升

7. 风险管理

风险 概率 影响 应对
LLM 意图提取准确率不足 低置信度时追问,不猜测;保留正则兜底(WorkflowPlannerService.parseUserIntent 作为 fallback
决策表覆盖率不足 先覆盖 10 工具,后续 Excel 可热加载扩展;评估使用已有 SsaDecisionTable 数据库表
LLM 结论"幻觉"虚构统计量 统计量槽位注入机制3.9 节):所有数值通过 {{slot}} 从 R 输出渲染LLM 被剥夺生成数值 Token 的权限Prompt 中明确标注"不得修改、四舍五入或重新表述任何数字"
Reflection 延迟过高LLM 调用) 通过平台 StreamingService 流式输出,用户先看到数字结果,结论异步加载
Q→P→E 串联复杂度 每层独立可测试,接口契约明确
新增LLM 服务不可用 Q 层降级到正则匹配R 层降级到规则拼接(ConclusionGeneratorService),系统功能不中断
新增Prisma 迁移遗漏 新增字段(如 report_blocks 存储)需通过 npx prisma migrate dev 正式迁移,禁止 db push --force-reset;每个 Phase 完成时检查 schema 变更
新增AnalysisPlan 接口破坏 Execute 层 AnalysisStep extends WorkflowStep保持向后兼容E 层不做任何接口改动
新增:旧组件过早删除 DescriptiveResultView 等现有组件2026-02-20 新建)在 Block-based 未完全验证前保留作为 fallback不提前删除
新增R 引擎运行时崩溃Runtime Crash 区分"统计降级"R 内部 if-else 处理)与"运行时崩溃"NA 值/列名错误/Fatal Error后者通过错误分类映射表转化为友好提示Phase R 不做跨层 Self-healing完整重试推迟至 Phase Deploy
新增:敏感性分析结论冲突 主分析与敏感性分析显著性不一致时Reflection Prompt 硬编码冲突处理准则必须在局限性中报告严禁强行拼凑显著性3.10 节)
新增LLM Reflection 输出结构残缺 jsonrepair + Zod Schema 三层防御3.11 节);校验失败自动降级到 ConclusionGeneratorService 规则拼接

7.1 回退策略Fallback Plan

层级 正常路径 降级路径 触发条件
Q 层 QueryServiceLLM 意图解析) WorkflowPlannerService.parseUserIntent()(正则匹配) LLM 超时/不可用/解析失败
P 层 PlannerService(决策表+模板) WorkflowPlannerService.generateSteps()(硬编码 if/else 决策表无匹配
E 层 WorkflowExecutorService(不变) 错误分类映射 → 友好用户提示 R 引擎运行时崩溃NA/列名/Fatal Error
R 层 ReflectionServiceLLM 论文结论) ConclusionGeneratorService(规则拼接) LLM 超时/不可用/Zod 校验失败
前端 DynamicReportBlock-based 渲染) 现有自定义渲染组件 report_blocks 为空时

原则: 每个 QPER 层都有明确的降级路径,确保 LLM 不可用时系统仍然可用(退化为 Phase 2A 水平。R 层新增 Zod 校验失败作为降级触发条件——LLM 输出结构不完整时,自动切回规则拼接,前端始终收到有效的 ConclusionReport 结构。


8. 验收场景

8.1 核心验收5 个场景)

# 用户输入 期望 Q 输出 期望 P 输出 期望 R 输出
1 "比较两组血压" goal=difference, design=independent 描述统计 → T检验 → Mann-Whitney "两组差异显著(P<0.001),中等效应(d=0.52)"
2 "分析 sex 与 Yqol 的关系" goal=association, Y=Yqol(categorical), X=sex 描述统计 → 卡方检验 "性别与 Yqol 存在显著关联(χ²=8.3, P=0.004)"
3 "age、smoke 对 Yqol 的影响" goal=prediction, Y=Yqol(binary) 描述统计 → Logistic 回归 "Logistic 回归显示 smoke 是显著预测因子(OR=2.1, P=0.03)"
4 "描述一下数据" goal=description 描述统计 各变量的集中趋势和离散程度汇总
5 "有没有效" confidence<0.7 → 追问 等待用户澄清后规划

8.2 智能化对比(改造前 vs 改造后)

场景 改造前 改造后
用户说"有没有效" 无法理解 追问后正确规划
数据不正态 🟡 R 内部降级,用户不知 规划阶段就选非参数方法,告知理由
分析结果 P=0.015 + 数字表格 论文级结论:"两组差异具有统计学意义..."
分析流程 1 个方法 描述统计 → 主分析 → 敏感性分析
Word 报告 表格 + 数字 完整论文段落 + 方法学说明

9. 与旧计划的关系

旧计划内容 处理方式 理由
配置中台Excel 导入体系) 延后 10 个工具用 JSON 配置足够100+ 工具时再做
咨询模式(无数据 SAP 延后 独立功能,不影响核心智能分析
决策表概念 保留并简化 从 Excel 配置中台简化为内置 JSON
Brain-Hand 命名 升级为 Q-P-E-R 更精确地描述四层职责
10 工具目标 扩展为 11 工具 原 10 个原子工具 + 1 个复合工具 ST_BASELINE_TABLEv6.0
SAE 部署 保留 Phase Deploy 中完成

文档维护者: SSA 架构团队
创建日期: 2026-02-20
最后更新: 2026-02-21v8.0 — Phase R 架构增强)
下一步行动: Phase E+/Q/P 已完成,按 R1→R7 顺序启动 Phase R 开发

变更日志

版本 日期 变更内容
v1.0 2026-02-20 初版QPER 架构设计 + 5 Phase 开发计划
v2.0 2026-02-21 代码审查后修订:① 核心原则新增"复用平台通用能力层";② ReflectionService 修正为重构;③ 目录结构改为渐进式平铺;④ 伪代码使用 LLMFactory + PromptService⑤ AnalysisStep extends WorkflowStep⑥ 新增已有数据库资产盘点;⑦ 新增全链路回退策略表;⑧ 工时 108.5h→114h
v3.0 2026-02-21 外部调研审查后修订综合4份报告① 架构红线(禁止 LangGraph/AutoGen/LLM 生成 R 代码/多智能体辩论);② Context Pruning 上下文裁剪;③ 封闭式追问;④ decision_trace 决策审计日志;⑤ 重试短路机制;⑥ 统计量槽位注入反幻觉;⑦ Tracer Bullet 探路测试;⑧ 工时 114h→118h
v4.0 2026-02-21 工程护航修订依据《QPER V3.0 架构审查与工程护航报告》):① DataProfile 会话级缓存;② 显式状态机ExecutionStatus 14 态);③ QPER 级 SSE 全链路状态推送;④ Intent Prompt Few-Shot 示例;⑤ 工时 118h→119.5h
v5.0 2026-02-21 人机协同增强修订(依据《架构与产品委员会综合评估报告》):① 新增 Phase Q+(变量字典 + 变量选择面板20h/2.5天);② 状态机扩展 DICT_EDITING + VARIABLE_CONFIRMING含 feature flag 自动跳过);③ Intent Prompt 增加忽略非分析变量指令;④ 总工时 119.5h→139.5h
v6.0 2026-02-21 复合工具扩展修订(依据队列研究 Table 1-3 终态验证 +《SSA-Pro 架构诊断与复合工具扩展方案》审查):① Phase Deploy 新增复合 R 工具 ST_BASELINE_TABLE(基于 gtsummary 封装,一次遍历所有变量 + 自动选方法 + 合并出表同时覆盖表1基线比较和表2单因素筛选② 新增 gtsummaryreport_blocks 转换层4h含合并行/分组列头的结构化提取);③ 前端三线表渲染增强4hDynamicReport.tsx 支持 rowspan/colspan/P值标星/横向滚动);④ 新增 cohort_study_standard 流程模板表1→表2→表3 三步流程表3自变量由用户确认而非自动 P<0.05 筛选);⑤ 决策表新增 cohort_study 场景行;⑥ Q 层 Intent Prompt goal 扩展支持 cohort_study 值(识别"出一套完整报告"等触发词);⑦ 工具总数从 10 扩展为 1110 原子 + 1 复合);⑧ Phase Deploy 工时 25h→37h+12h总工时 139.5h→151.5h
v7.0 2026-02-21 Phase P 架构增强(进入开发前的设计审查):① Expected/Actual 双层审计日志 — P 层生成 PlannedTrace策略E 层 R trace_log 提供 Actual Trace事实R 层合并两者生成方法学说明P 层绝不做正态性预检;② Repository 模式 — DecisionTableService 通过 IDecisionTableRepo 接口解耦,初期 JSON 实现,后期可切 DB核心业务逻辑零改动参数检验优先原则 — 决策表 Primary 始终为参数检验效力更高Fallback 为非参数(安全网),新增 switch_condition 列描述触发条件;④ EPV 变量上限防护 — 队列研究 Table 3 采用"全量推入 + EPV 截断 + 免责声明"策略,防止过拟合和 R 引擎崩溃;⑤ 流程模板合并two_group_comparison + association_analysis 合并为 standard_analysis,最终 4+1 模板
v7.1 2026-02-21 新增核心原则"领域知识可配置化" + Phase P 配置化基础设施:① 核心原则第 6 条 — "QPER 四层的所有领域知识由统计学方法学团队配置,不写死在代码中""可配置"作为贯穿所有 Phase 的架构约束IT 团队搭引擎、方法学团队填内容;② Zod Schema 严格校验 — 方法学团队编辑 JSON 时的拼写/结构错误在加载时立即拦截;③ 热更新 APIPOST /reload-config 无需重启服务即可生效,校验失败保留旧配置不影响线上;④ 领域文件物理拆分tools_registry.jsonE 层)、decision_tables.jsonP 层)、flow_templates.jsonP 层)、narrative_templates.jsonR 层),每文件有明确的方法学团队所有者;⑤ Phase P 后端任务新增任务 0ConfigLoader 基础设施2h+ 任务 1工具注册表2h总任务数 7→9
v8.0 2026-02-21 Phase R 架构增强(进入开发前的设计审查,依据架构委员会建议):① 敏感性分析结论冲突 Prompt 策略3.10 节) — 主分析与敏感性分析显著性不一致时Reflection Prompt 硬编码冲突处理准则,严禁强行拼凑显著性,必须在局限性中报告稳健性问题;② Zod Schema 强校验 LLM 输出3.11 节) — 延续 Phase Q 的 jsonrepair + Zod 三层防御范式,校验失败自动降级到 ConclusionGeneratorService 规则拼接;③ Reflection 输出交付策略调整3.12 节) — 不做字符级流式推送,采用"后端完整收集 + Zod 校验 + 一次性 SSE 推送 reflection_complete + 前端逐 section 渐入动画"方案,原 reflection_stream 事件改为 reflection_complete;④ 运行时崩溃优雅处理3.8 节重构) — 区分"统计降级"与"运行时崩溃"Phase R 仅做错误分类映射R 报错关键词→友好用户提示完整重试短路机制MAX_RETRIES + 参数级修复 + 方法级降级)推迟至 Phase DeployReflectionService 伪代码更新 — 加入 Zod Schema 定义、qper_status 状态推送、reflection_complete SSE 事件、Zod 校验失败降级逻辑;⑥ 风险管理表新增 3 行 — R 运行时崩溃、敏感性分析冲突、LLM 输出结构残缺;⑦ 回退策略表更新 — R 层触发条件新增"Zod 校验失败"E 层新增运行时崩溃处理路径;⑧ Phase R 工时 23h→22h-1h重试机制简化