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:
@@ -180,6 +180,66 @@ ggplot(df, aes(x = .data[[group_var]], y = .data[[value_var]])) +
|
||||
labs(title = paste("Distribution of", value_var, "by", group_var))
|
||||
')
|
||||
|
||||
# ===== 构建 report_blocks =====
|
||||
log_add("构建 report_blocks")
|
||||
|
||||
blocks <- list()
|
||||
|
||||
# Block 1: 描述统计键值对
|
||||
g1_label <- as.character(groups[1])
|
||||
g2_label <- as.character(groups[2])
|
||||
|
||||
blocks[[length(blocks) + 1]] <- make_kv_block(
|
||||
title = "样本概况",
|
||||
items = list(
|
||||
list(key = paste0(group_var, " = ", g1_label, " (n)"), value = as.character(length(g1_vals))),
|
||||
list(key = paste0(group_var, " = ", g2_label, " (n)"), value = as.character(length(g2_vals))),
|
||||
list(key = paste0(g1_label, " Mean ± SD"),
|
||||
value = paste0(round(mean(g1_vals), 3), " \u00b1 ", round(sd(g1_vals), 3))),
|
||||
list(key = paste0(g2_label, " Mean ± SD"),
|
||||
value = paste0(round(mean(g2_vals), 3), " \u00b1 ", round(sd(g2_vals), 3)))
|
||||
)
|
||||
)
|
||||
|
||||
# Block 2: 检验结果表格
|
||||
blocks[[length(blocks) + 1]] <- make_table_block(
|
||||
title = "独立样本 T 检验结果",
|
||||
headers = c("统计量", "自由度", "P 值", "95% CI 下限", "95% CI 上限", "均值差"),
|
||||
rows = list(
|
||||
list(
|
||||
round(as.numeric(result$statistic), 4),
|
||||
round(as.numeric(result$parameter), 2),
|
||||
format_p_value(result$p.value),
|
||||
round(result$conf.int[1], 4),
|
||||
round(result$conf.int[2], 4),
|
||||
round(diff(result$estimate), 4)
|
||||
)
|
||||
),
|
||||
footnote = result$method
|
||||
)
|
||||
|
||||
# Block 3: 箱线图
|
||||
if (!is.null(plot_base64)) {
|
||||
blocks[[length(blocks) + 1]] <- make_image_block(
|
||||
base64_data = plot_base64,
|
||||
title = paste0(value_var, " by ", group_var),
|
||||
alt = paste("箱线图:", value_var, "按", group_var, "分组")
|
||||
)
|
||||
}
|
||||
|
||||
# Block 4: 结论摘要
|
||||
sig <- if (result$p.value < 0.05) "存在统计学显著差异" else "差异无统计学意义"
|
||||
blocks[[length(blocks) + 1]] <- make_markdown_block(
|
||||
title = "结果摘要",
|
||||
content = paste0(
|
||||
"两组 **", value_var, "** 的比较(", result$method, "):",
|
||||
"t = ", round(as.numeric(result$statistic), 3),
|
||||
",df = ", round(as.numeric(result$parameter), 1),
|
||||
",P ", format_p_value(result$p.value),
|
||||
"。两组间", sig, "。"
|
||||
)
|
||||
)
|
||||
|
||||
# ===== 返回结果 =====
|
||||
log_add("分析完成")
|
||||
|
||||
@@ -196,10 +256,11 @@ ggplot(df, aes(x = .data[[group_var]], y = .data[[value_var]])) +
|
||||
conf_int = as.numeric(result$conf.int),
|
||||
estimate = as.numeric(result$estimate),
|
||||
group_stats = list(
|
||||
list(group = as.character(groups[1]), n = length(g1_vals), mean = mean(g1_vals), sd = sd(g1_vals)),
|
||||
list(group = as.character(groups[2]), n = length(g2_vals), mean = mean(g2_vals), sd = sd(g2_vals))
|
||||
list(group = g1_label, n = length(g1_vals), mean = mean(g1_vals), sd = sd(g1_vals)),
|
||||
list(group = g2_label, n = length(g2_vals), mean = mean(g2_vals), sd = sd(g2_vals))
|
||||
)
|
||||
),
|
||||
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