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>
This commit is contained in:
@@ -226,7 +226,98 @@ ggplot(df_long, aes(x = time, y = value, group = id)) +
|
||||
theme_minimal() +
|
||||
labs(title = "Paired Comparison")
|
||||
')
|
||||
|
||||
|
||||
# ===== 构建 report_blocks =====
|
||||
d <- output_results$descriptive
|
||||
blocks <- list()
|
||||
|
||||
# Block 1: 样本概况
|
||||
blocks[[length(blocks) + 1]] <- make_kv_block(
|
||||
title = "样本概况",
|
||||
items = list(
|
||||
list(key = paste0(before_var, " (n)"), value = as.character(d$before$n)),
|
||||
list(key = paste0(before_var, " Mean"), value = as.character(d$before$mean)),
|
||||
list(key = paste0(before_var, " SD"), value = as.character(d$before$sd)),
|
||||
list(key = paste0(before_var, " Median"), value = as.character(d$before$median)),
|
||||
list(key = paste0(after_var, " (n)"), value = as.character(d$after$n)),
|
||||
list(key = paste0(after_var, " Mean"), value = as.character(d$after$mean)),
|
||||
list(key = paste0(after_var, " SD"), value = as.character(d$after$sd)),
|
||||
list(key = paste0(after_var, " Median"), value = as.character(d$after$median)),
|
||||
list(key = "差值 Mean", value = as.character(d$difference$mean)),
|
||||
list(key = "差值 SD", value = as.character(d$difference$sd))
|
||||
)
|
||||
)
|
||||
|
||||
# Block 2: 检验结果表格(根据 use_wilcoxon 区分)
|
||||
if (use_wilcoxon) {
|
||||
blocks[[length(blocks) + 1]] <- make_table_block(
|
||||
title = "Wilcoxon 符号秩检验结果",
|
||||
headers = c("统计量 V", "P 值", "效应量 r", "效应量解释"),
|
||||
rows = list(list(
|
||||
round(as.numeric(output_results$statistic), 4),
|
||||
format_p_value(output_results$p_value),
|
||||
round(output_results$effect_size$r, 4),
|
||||
output_results$effect_size$interpretation
|
||||
)),
|
||||
footnote = method_used
|
||||
)
|
||||
} else {
|
||||
ci_str <- if (length(output_results$conf_int) >= 2) {
|
||||
sprintf("[%.4f, %.4f]", output_results$conf_int[1], output_results$conf_int[2])
|
||||
} else {
|
||||
"—"
|
||||
}
|
||||
blocks[[length(blocks) + 1]] <- make_table_block(
|
||||
title = "配对 T 检验结果",
|
||||
headers = c("t", "df", "P 值", "95% CI", "Cohen's d", "效应量解释"),
|
||||
rows = list(list(
|
||||
round(as.numeric(output_results$statistic), 4),
|
||||
round(as.numeric(output_results$df), 2),
|
||||
format_p_value(output_results$p_value),
|
||||
ci_str,
|
||||
round(output_results$effect_size$cohens_d, 4),
|
||||
output_results$effect_size$interpretation
|
||||
)),
|
||||
footnote = method_used
|
||||
)
|
||||
}
|
||||
|
||||
# Block 3: 配对比较图
|
||||
if (!is.null(plot_base64)) {
|
||||
blocks[[length(blocks) + 1]] <- make_image_block(
|
||||
base64_data = plot_base64,
|
||||
title = paste0("配对比较: ", before_var, " vs ", after_var),
|
||||
alt = paste("配对比较图:", before_var, "与", after_var)
|
||||
)
|
||||
}
|
||||
|
||||
# Block 4: 结论摘要
|
||||
sig <- if (output_results$p_value < 0.05) "存在统计学显著差异" else "差异无统计学意义"
|
||||
if (use_wilcoxon) {
|
||||
concl <- paste0(
|
||||
"配对样本 **", before_var, "** 与 **", after_var, "** 的比较(", method_used, "):",
|
||||
"V = ", round(as.numeric(output_results$statistic), 3),
|
||||
",P ", format_p_value(output_results$p_value),
|
||||
",效应量 r = ", round(output_results$effect_size$r, 3),
|
||||
"(", output_results$effect_size$interpretation, ")。",
|
||||
sig, "。"
|
||||
)
|
||||
} else {
|
||||
concl <- paste0(
|
||||
"配对样本 **", before_var, "** 与 **", after_var, "** 的比较(", method_used, "):",
|
||||
"t = ", round(as.numeric(output_results$statistic), 3),
|
||||
",df = ", round(as.numeric(output_results$df), 1),
|
||||
",P ", format_p_value(output_results$p_value),
|
||||
",Cohen's d = ", round(output_results$effect_size$cohens_d, 3),
|
||||
"(", output_results$effect_size$interpretation, ")。",
|
||||
sig, "。"
|
||||
)
|
||||
}
|
||||
blocks[[length(blocks) + 1]] <- make_markdown_block(
|
||||
title = "结果摘要",
|
||||
content = concl
|
||||
)
|
||||
|
||||
# ===== 返回结果 =====
|
||||
log_add("分析完成")
|
||||
|
||||
@@ -235,6 +326,7 @@ ggplot(df_long, aes(x = time, y = value, group = id)) +
|
||||
message = "分析完成",
|
||||
warnings = if (length(warnings_list) > 0) warnings_list else NULL,
|
||||
results = output_results,
|
||||
report_blocks = blocks,
|
||||
plots = if (!is.null(plot_base64)) list(plot_base64) else list(),
|
||||
trace_log = logs,
|
||||
reproducible_code = as.character(reproducible_code)
|
||||
|
||||
Reference in New Issue
Block a user