feat(ssa): Complete SSA-Pro MVP development plan v1.3

Summary:

- Add PRD and architecture design V4 (Brain-Hand model)

- Complete 5 development guide documents

- Pass 3 rounds of team review (v1.0 -> v1.3)

- Add module status guide document

- Update system status document

Key Features:

- Brain-Hand architecture: Node.js + R Docker

- Statistical guardrails with auto degradation

- HITL workflow: PlanCard -> ExecutionTrace -> ResultCard

- Mixed data protocol: inline vs OSS

- Reproducible R code delivery

MVP Scope: 10 statistical tools

Status: Design 100%, ready for development
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-18 21:58:37 +08:00
parent f9ed0c2528
commit 8137e3cde2
19 changed files with 5756 additions and 98 deletions

View File

@@ -0,0 +1,351 @@
# **SSA-01: R工具封装标准与前后端数据协议技术规范**
**文档状态:** v1.0 (Draft)
**创建日期:** 2026-02-06
**适用对象:** R 工程师、后端工程师
**目标:** 定义 SSA 模块中 100+ R 工具的标准化封装规范,以及前后端交互的数据契约。
## **1\. 核心设计理念**
为了实现 **SSA-Pro V4.0** 的“同步调用”、“统计护栏”和“白盒交付”,我们需要对现有的 R 脚本进行 **"Wrapper 改造"**。
* **原则 1JSON In, JSON Out**。所有工具统一使用 JSON 格式进行输入输出,严禁直接读写本地文件路径(除非是临时的)。
* **原则 2护栏内嵌 (Guardrails Inside)**。统计假设检验(如正态性)必须在 R 代码内部完成,而不是依赖 LLM。
* **原则 3代码自生成 (Self-Generating)**。每个工具必须能“吐出”一份可独立运行的 R 代码片段,用于交付给用户。
## **2\. R 工具封装标准 (The Wrapper Spec)**
所有纳入 SSA 体系的 R 工具,必须遵循以下函数签名和文件结构。
### **2.1 标准函数签名**
\#' @title SSA Standard Wrapper Interface
\#' @param input\_json JSON字符串或列表包含 data, params, guardrails 等
\#' @return JSON字符串包含 status, results, plots, trace\_log, reproducible\_code
run\_ssa\_tool \<- function(input\_json) {
\# ...
}
### **2.2 输入结构定义 (Input Schema)**
后端调用 R API 时Request Body 将被解析为以下 R List 结构:
list(
\# 1\. 核心数据 (必需)
\# 前端/DC模块清洗后的干净数据通常为数据框的列列表格式
data \= list(
col\_group \= c("A", "A", "B", "B", ...),
col\_val \= c(1.2, 1.3, 2.1, 2.2, ...)
),
\# 2\. 统计参数 (必需)
\# 由 LLM 生成,用于控制统计行为
params \= list(
group\_col \= "col\_group",
val\_col \= "col\_val",
conf\_level \= 0.95,
paired \= FALSE,
alternative \= "two.sided"
),
\# 3\. 护栏配置 (可选)
\# 控制是否开启强制检查
guardrails \= list(
check\_normality \= TRUE,
check\_variance \= TRUE,
auto\_fix \= TRUE \# 若检查失败,是否允许自动降级(如T检验转Wilcoxon)
),
\# 4\. 元信息 (可选)
meta \= list(
tool\_code \= "ST\_T\_TEST\_IND",
user\_id \= "u123",
session\_id \= "s456"
)
)
### **2.3 输出结构定义 (Output Schema)**
R 函数必须返回以下结构的 List (最终被 Plumber 序列化为 JSON)
list(
\# 1\. 执行状态
status \= "success", \# "success" | "warning" | "error"
message \= "执行成功,数据满足正态分布。", \# 给用户看的简短提示
\# 2\. 统计结果 (结构化)
\# 用于前端渲染表格或 LLM 解读
results \= list(
method \= "Two Sample t-test",
statistic \= 2.34, \# t值
p\_value \= 0.023,
conf\_int \= c(0.5, 2.1),
estimate \= c(mean\_x \= 5.1, mean\_y \= 4.2),
df \= 18
),
\# 3\. 可视化 (Base64)
\# 推荐返回 1-2 张核心图表
plots \= list(
"data:image/png;base64,iVBORw0K...", \# 图1
"data:image/png;base64,..." \# 图2
),
\# 4\. 执行路径日志 (Trace Log)
\# 用于前端展示 "执行树"
trace\_log \= list(
list(step \= "check\_normality", status \= "pass", msg \= "Shapiro-Wilk P=0.23 \> 0.05"),
list(step \= "check\_variance", status \= "pass", msg \= "Levene P=0.45 \> 0.05"),
list(step \= "main\_test", status \= "done", msg \= "t.test executed")
),
\# 5\. 可复现代码 (Reproducible Code)
\# 用户下载的 R 脚本内容
reproducible\_code \= "library(ggplot2)\\ndata \<- read.csv('your\_data.csv')..."
)
## **3\. R 脚本开发模板 (Developer Guide)**
R 工程师请直接复制此模板开发新工具。以 **"独立样本 T 检验"** 为例。
### **文件名tools/st\_t\_test\_ind.R**
library(jsonlite)
library(ggplot2)
library(car) \# for leveneTest
\#' @title 独立样本T检验 (Independent Samples T-Test)
\#' @description 用于比较两组独立正态分布数据的均值是否存在显著差异。
\#' @usage\_context 适用于数值型因变量(Y)和二分类自变量(X)。需满足正态性和方差齐性。
\#' @param input\_json 标准输入对象
\#' @export
run\_tool \<- function(input\_json) {
\# \--- 0\. 初始化 \---
logs \<- list()
log\_step \<- function(step, status, msg) {
logs \<\<- c(logs, list(list(step=step, status=status, msg=msg)))
}
\# 解析数据
df \<- as.data.frame(input\_json$data)
p \<- input\_json$params
\# 构造复现代码 (Header)
code\_lines \<- c(
"\# \------------------------------------------------",
"\# SSA 生成代码: 独立样本 T 检验",
"\# \------------------------------------------------",
"library(ggplot2)",
"library(car)",
"",
"\# 1\. 加载数据 (请替换为您的本地文件路径)",
"df \<- read.csv('your\_data.csv')",
""
)
tryCatch({
\# \--- 1\. 数据预处理 (Statistical Prep) \---
\# 强制类型转换
df\[\[p$group\_col\]\] \<- as.factor(df\[\[p$group\_col\]\])
df\[\[p$val\_col\]\] \<- as.numeric(df\[\[p$val\_col\]\])
code\_lines \<- c(code\_lines,
"\# 2\. 数据预处理",
sprintf("df\[\['%s'\]\] \<- as.factor(df\[\['%s'\]\])", p$group\_col, p$group\_col),
sprintf("df\[\['%s'\]\] \<- as.numeric(df\[\['%s'\]\])", p$val\_col, p$val\_col)
)
\# \--- 2\. 护栏检查 (Guardrails) \---
run\_test \<- "t.test" \# 默认方法
if (isTRUE(input\_json$guardrails$check\_normality)) {
\# 简化的正态性检查 (对每组进行 Shapiro 检验)
groups \<- unique(df\[\[p$group\_col\]\])
is\_normal \<- TRUE
for (g in groups) {
sub\_data \<- df\[df\[\[p$group\_col\]\] \== g, p$val\_col\]
\# 样本量 \< 3 或 \> 5000 不做 shapiro
if (length(sub\_data) \>= 3 && length(sub\_data) \<= 5000\) {
pval \<- shapiro.test(sub\_data)$p.value
if (pval \< 0.05) is\_normal \<- FALSE
}
}
if (\!is\_normal) {
log\_step("check\_normality", "fail", "数据不满足正态分布 (P\<0.05)")
if (isTRUE(input\_json$guardrails$auto\_fix)) {
run\_test \<- "wilcox.test"
log\_step("auto\_fix", "switch", "自动降级为 Wilcoxon 秩和检验")
code\_lines \<- c(code\_lines, "\# 注意:由于数据不满足正态分布,已切换为非参数检验")
} else {
return(list(status="error", message="数据不满足正态分布,请尝试非参数检验。", trace\_log=logs))
}
} else {
log\_step("check\_normality", "pass", "正态性检验通过")
}
}
\# \--- 3\. 核心计算 \---
f \<- as.formula(paste(p$val\_col, "\~", p$group\_col))
if (run\_test \== "t.test") {
\# 方差齐性检查
var\_pval \<- leveneTest(f, data=df)$\`Pr(\>F)\`\[1\]
var\_equal \<- var\_pval \> 0.05
res \<- t.test(f, data=df, var.equal=var\_equal)
log\_step("main\_test", "done", sprintf("T-Test (var.equal=%s)", var\_equal))
\# 添加代码
code\_lines \<- c(code\_lines,
"", "\# 3\. 执行 T 检验",
sprintf("res \<- t.test(%s \~ %s, data=df, var.equal=%s)", p$val\_col, p$group\_col, var\_equal),
"print(res)"
)
} else {
res \<- wilcox.test(f, data=df)
log\_step("main\_test", "done", "Wilcoxon Test")
\# 添加代码
code\_lines \<- c(code\_lines,
"", "\# 3\. 执行 Wilcoxon 检验",
sprintf("res \<- wilcox.test(%s \~ %s, data=df)", p$val\_col, p$group\_col),
"print(res)"
)
}
\# \--- 4\. 绘图 \---
plot\_file \<- tempfile(fileext \= ".png")
png(plot\_file, width=800, height=600)
p\_plot \<- ggplot(df, aes\_string(x=p$group\_col, y=p$val\_col, fill=p$group\_col)) \+
geom\_boxplot() \+
theme\_minimal() \+
labs(title="Boxplot Comparison")
print(p\_plot)
dev.off()
\# 转 Base64
plot\_base64 \<- base64enc::base64encode(plot\_file)
plot\_base64 \<- paste0("data:image/png;base64,", plot\_base64)
\# 添加绘图代码
code\_lines \<- c(code\_lines,
"", "\# 4\. 绘图",
"library(ggplot2)",
sprintf("ggplot(df, aes(x=%s, y=%s, fill=%s)) \+ geom\_boxplot() \+ theme\_minimal()",
p$group\_col, p$val\_col, p$group\_col)
)
\# \--- 5\. 返回结果 \---
return(list(
status \= "success",
message \= "分析完成",
results \= list(
method \= res$method,
statistic \= as.numeric(res$statistic),
p\_value \= as.numeric(res$p.value),
conf\_int \= if(\!is.null(res$conf.int)) as.numeric(res$conf.int) else NULL
),
plots \= list(plot\_base64),
trace\_log \= logs,
reproducible\_code \= paste(code\_lines, collapse="\\n")
))
}, error \= function(e) {
return(list(status="error", message=e$message, trace\_log=logs))
})
}
## **4\. 前后端通信 API (API Contract)**
### **4.1 执行统计分析**
* **URL**: POST /api/v1/ssa/execute
* **Content-Type**: application/json
* **发起方**: Frontend (用户点击“确认并执行”后)
**Request Body:**
{
"tool\_code": "ST\_T\_TEST\_IND",
"data": {
"group": \["A", "A", "B", "B"\],
"bmi": \[21.5, 22.1, 25.4, 26.8\]
},
"params": {
"group\_col": "group",
"val\_col": "bmi",
"conf\_level": 0.95
},
"guardrails": {
"check\_normality": true,
"auto\_fix": true
}
}
**Response Body (200 OK):**
{
"code": 200,
"data": {
"status": "success",
"message": "分析完成",
"results": {
"method": "Welch Two Sample t-test",
"p\_value": 0.042,
"statistic": \-2.31
},
"plots": \["data:image/png;base64,..."\],
"trace\_log": \[
{"step": "check\_normality", "status": "pass", "msg": "正态性检验通过"},
{"step": "main\_test", "status": "done", "msg": "T-Test executed"}
\],
"reproducible\_code": "\# SSA 生成代码...\\nlibrary(ggplot2)..."
}
}
## **5\. 元数据注册规范 (Metadata Spec)**
为了让 SSA-Planner (DeepSeek) 能够检索到这个工具,我们需要提取以下 JSON 元数据,存入 pgvector。
**JSON 结构示例:**
{
"tool\_code": "ST\_T\_TEST\_IND",
"name": "独立样本 T 检验",
"description": "用于比较两组独立样本的均值差异。基于 t 分布理论。",
"usage\_context": "适用于1. 因变量为连续数值型2. 自变量为二分类如性别、分组3. 数据满足正态分布和方差齐性。",
"params\_schema": {
"group\_col": {
"type": "string",
"desc": "分组变量列名必须只有2个水平"
},
"val\_col": {
"type": "string",
"desc": "数值变量列名"
}
},
"guardrails\_supported": \["check\_normality", "check\_variance"\]
}
## **6\. 总结与行动指南**
1. **R 工程师**
* 请按照 **第 3 节 (R 脚本开发模板)**,先试着封装 1 个工具(如 T 检验)。
* 确保 reproducible\_code 生成的代码可以在干净的 RStudio 环境中跑通。
* 确保所有 library() 调用都在函数内部或头部声明。
2. **后端工程师**
* 在 Node.js 中实现 POST /api/v1/ssa/execute 接口。
* 该接口的核心逻辑是:将前端 JSON \-\> 转发给 R Plumber 服务 \-\> 接收 R 响应 \-\> 存入数据库日志 \-\> 返回前端。
* **不要在 Node.js 里写任何统计逻辑**,只做“二传手”。
3. **前端工程师**
* 根据 API 定义Mock 一份数据,开始开发“执行路径树”和“代码下载”组件。

View File

@@ -0,0 +1,167 @@
# **SSA-02: 数据库与向量库 Schema 设计规范**
**文档状态:** v1.0 (Draft)
**创建日期:** 2026-02-06
**关联模块:** SSA, Common RAG
**目标:** 定义存储 R 工具元数据、向量索引及执行审计日志的数据库结构。
## **1\. 设计原则**
### **1.1 复用平台能力**
* **向量引擎**:严格使用 pgvector (0.8.1),向量维度固定为 **1024** (对应 text-embedding-v4)。
* **全文检索**:使用 pg\_bigm (1.2) 实现中英文混合的高性能关键词检索。
* **Schema 隔离**:所有表必须位于 ssa\_schema 命名空间下。
### **1.2 "工具即文档" (Tool-as-Document)**
与 PKB 模块将长文切分为 Chunk 不同SSA 模块中**一个 R 工具就是一个原子检索单位**。我们不进行切分,而是进行**特征合成**。
## **2\. 核心表结构设计 (DDL)**
### **2.1 工具库表 (tools\_library) —— 核心资产**
这张表存储了 100+ 个 R 工具的定义、参数结构以及用于检索的向量数据。
\-- 确保扩展已启用 (通常在 platform\_schema 或 public)
\-- CREATE EXTENSION IF NOT EXISTS vector;
\-- CREATE EXTENSION IF NOT EXISTS pg\_bigm;
CREATE TABLE ssa\_schema.tools\_library (
id UUID PRIMARY KEY DEFAULT gen\_random\_uuid(),
\-- 1\. 业务标识
tool\_code VARCHAR(50) NOT NULL UNIQUE, \-- 例如: 'ST\_T\_TEST\_IND'
name VARCHAR(100) NOT NULL, \-- 例如: '独立样本 T 检验'
version VARCHAR(20) DEFAULT '1.0.0', \-- R 脚本版本
\-- 2\. 结构化元数据 (用于 LLM 生成参数)
description TEXT NOT NULL, \-- 简短描述
usage\_context TEXT, \-- 适用场景 (什么时候用?)
params\_schema JSONB NOT NULL, \-- 参数定义 (JSON Schema)
guardrails JSONB, \-- 护栏配置 (支持哪些检查?)
\-- 3\. 检索专用字段 (Search Optimization)
\-- 将 name \+ description \+ usage\_context \+ keywords 拼接
search\_text TEXT NOT NULL,
\-- 4\. 向量索引 (1024维)
embedding vector(1024),
\-- 5\. 审计字段
created\_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated\_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
is\_active BOOLEAN DEFAULT TRUE
);
\-- 索引策略 (Hybrid Search Ready)
\-- 1\. 向量索引 (IVFFlat 或 HNSW) \- 用于语义检索
CREATE INDEX idx\_ssa\_tools\_embedding ON ssa\_schema.tools\_library
USING hnsw (embedding vector\_cosine\_ops);
\-- 2\. 全文索引 (pg\_bigm) \- 用于关键词精确匹配 (如 "T检验", "ANOVA")
CREATE INDEX idx\_ssa\_tools\_search\_text\_bigm ON ssa\_schema.tools\_library
USING gin (search\_text gin\_bigm\_ops);
\-- 3\. 业务索引
CREATE INDEX idx\_ssa\_tools\_code ON ssa\_schema.tools\_library(tool\_code);
### **2.2 执行审计日志表 (execution\_logs) —— 优化之源**
这张表是 SSA-Pro **"白盒化"** 的证据。它完整记录了从用户提问到最终代码交付的全过程。
CREATE TABLE ssa\_schema.execution\_logs (
id UUID PRIMARY KEY DEFAULT gen\_random\_uuid(),
\-- 1\. 归属信息
user\_id VARCHAR(255) NOT NULL,
session\_id VARCHAR(255), \-- 关联的会话 ID
\-- 2\. 输入 (User Intent)
user\_query TEXT NOT NULL, \-- 用户原始提问
data\_summary JSONB, \-- 数据摘要 (Schema, 非原始数据)
\-- 3\. 规划 (AI Plan)
sap\_content TEXT, \-- AI 生成的统计分析计划 (Markdown)
selected\_tool VARCHAR(50), \-- 最终选择的 tool\_code
generated\_params JSONB, \-- AI 生成的参数
\-- 4\. 执行 (R Runtime)
execution\_status VARCHAR(20), \-- 'success', 'error', 'warning'
trace\_log JSONB, \-- R 返回的执行路径日志
error\_message TEXT, \-- 如果失败,记录报错
\-- 5\. 性能指标
duration\_ms INTEGER, \-- 总耗时
tokens\_used INTEGER, \-- LLM 消耗 Token
created\_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
\-- 索引
CREATE INDEX idx\_ssa\_logs\_user ON ssa\_schema.execution\_logs(user\_id);
CREATE INDEX idx\_ssa\_logs\_tool ON ssa\_schema.execution\_logs(selected\_tool);
CREATE INDEX idx\_ssa\_logs\_time ON ssa\_schema.execution\_logs(created\_at DESC);
## **3\. 向量检索策略 (Retrieval Strategy)**
### **3.1 检索字段合成策略 (The "Synthetic Document")**
为了保持高准确率,我们不能只 Embedding 描述字段。我们需要构造一个**富含语义的虚拟文档**。
**search\_text 字段的内容模板:**
工具名称: {name}
功能描述: {description}
适用场景: {usage\_context}
关键词: {keywords} (如: 差异, 比较, 连续变量, 正态分布)
模拟提问: {synthetic\_queries} (如: "怎么比较两组数据的均值?", "两组病人的血糖有区别吗?")
**策略说明:**
* **模拟提问 (Synthetic Queries)**:这是一个高级技巧。在录入工具时,利用 LLM 生成 3-5 个“用户可能会问的问题”,并入索引。这能极大缩短“用户口语”与“专业术语”之间的语义距离。
### **3.2 混合检索流程 (Hybrid Search Workflow)**
复用平台的 VectorSearchService采用 **Brain-Hand** 模式。
1. **查询理解 (Brain Layer)**
* 用户输入:"看看这两组病人的 BMI 也没有差异"
* Query Rewriter (DeepSeek):生成关键词 \["独立样本T检验", "两组差异", "连续变量"\]。
2. **双路召回 (Engine Layer)**
* **路 A (Semantic)**:使用 embedding 字段进行向量相似度搜索 (Top 10)。
* **路 B (Keyword)**:使用 search\_text 字段进行 pg\_bigm 模糊匹配 (Top 10)。
3. **融合与重排 (Rerank)**
* 使用 Reciprocal Rank Fusion (RRF) 合并两路结果。
* 使用 qwen3-rerank 模型,基于用户的 Data Schema (例如:数据是分类的还是数值的) 对候选工具进行重排。
* **截断**:取 Top 5 返回给 Planner。
## **4\. 数据流与写入流程**
### **4.1 工具注册流程 (DevOps Pipeline)**
1. **R 工程师**:在 R 脚本中编写 roxygen2 注释。
2. **CI/CD 脚本**
* 解析 R 脚本,提取元数据。
* 调用 LLM 生成 synthetic\_queries (模拟提问)。
* 拼接 search\_text。
* 调用 EmbeddingService 生成向量。
* Upsert 到 ssa\_schema.tools\_library 表。
### **4.2 运行时流程**
1. **Node.js** 接收用户请求。
2. 调用 ssa\_schema.tools\_library 进行混合检索。
3. 将命中的工具 params\_schema 注入到 Planner 的 Prompt 中。
4. 执行结束后,将全过程写入 ssa\_schema.execution\_logs。
## **5\. 总结**
这套设计方案充分利用了我们现有的 **Postgres-Only** 架构优势:
1. **不需要额外的向量数据库**:直接用 RDS PostgreSQL维护成本最低。
2. **高准确率保证**:通过 search\_text 的精心构造(特别是加入模拟提问)和 pg\_bigm 的关键词辅助,解决了“工具选错”的最大痛点。
3. **可追溯**:详尽的审计日志为未来的“自我进化”(根据用户反馈优化工具推荐)提供了数据基础。

View File

@@ -0,0 +1,200 @@
# **SSA-03: Agent Prompt 与编排流程设计规范**
**文档状态:** v1.0 (Draft)
**创建日期:** 2026-02-06
**关联模块:** SSA, AIA (LLM Gateway)
**目标:** 定义 SSA 模块的认知层逻辑,包括 Prompt 模板、上下文组装策略及错误自愈流程。
## **1\. 认知层架构总览**
SSA 的认知层不是一个简单的 Chatbot而是一个 **"Retrieve-Plan-Execute-Critic"** 的流水线。
### **核心智能节点 (AI Nodes)**
| 节点名称 | 对应模型 | 职责 | 输入 | 输出 |
| :---- | :---- | :---- | :---- | :---- |
| **Query Rewriter** | DeepSeek-V3 | **查询翻译与扩展**。将用户口语转化为统计学术语,用于向量检索。 | 用户提问 | 关键词列表 (JSON) |
| **SSA Planner** | DeepSeek-V3 | **分析规划**。阅读候选工具文档,生成执行参数。 | 提问 \+ 数据元数据 \+ Top-5工具 | SAP 计划书 (JSON) |
| **SSA Critic** | DeepSeek-V3 | **结果解释**。基于统计原则解读 R 输出,警示风险。 | R 执行结果 \+ 路径日志 | Markdown 报告 |
| **Synthetic Gen** | Qwen-Max | **离线数据增强**。为工具生成模拟提问,用于建库。 | 工具描述 | 模拟问答对 (List) |
## **2\. 编排流程逻辑 (Orchestration Logic)**
Node.js 后端将按照以下伪代码逻辑调度各个节点:
async function runAnalysisFlow(userQuery, dataSchema) {
// 1\. \[Rewriter\] 查询理解
const keywords \= await rewriter.extractKeywords(userQuery);
// 2\. \[RAG\] 检索候选工具 (混合检索)
const candidateTools \= await vectorDB.searchTools(keywords, { limit: 5 });
// 3\. \[Planner\] 生成计划
const sap \= await planner.generatePlan(userQuery, dataSchema, candidateTools);
// 4\. \[Frontend\] 用户确认 (HITL)
// ... 等待用户点击 "确认执行" ...
// 5\. \[Executor\] 调用 R 服务
// 此时带有用户确认过的 params
let rResult \= await rService.execute(sap.tool\_code, sap.params);
// 6\. \[Self-Healing\] 简单自愈 (可选)
if (rResult.status \=== 'error' && rResult.is\_fixable) {
const fixedParams \= await planner.fixParams(rResult.error, sap.params);
rResult \= await rService.execute(sap.tool\_code, fixedParams);
}
// 7\. \[Critic\] 生成报告
const finalReport \= await critic.interpret(userQuery, rResult);
return finalReport;
}
## **3\. 详细 Prompt 设计**
### **3.1 Query Rewriter (查询重写器)**
* **目标**解决“用户搜看差异库里存T检验”的语义鸿沟。
* **Model**DeepSeek-V3 (Temperature: 0.3)
**System Prompt:**
你是一个精通统计学的检索助手。你的任务是将用户的自然语言需求转化为精准的检索关键词。
输入规则:
1\. 提取核心统计意图(如:差异、相关、预测、降维)。
2\. 识别变量类型(如:连续变量、分类变量)。
3\. 生成 3-5 个同义专业术语(如:用户说"看两个组不一样",你生成 "独立样本T检验", "差异性分析", "Wilcoxon检验")。
输出格式JSON 字符串列表
示例输入:"我想看看吸烟和不吸烟的人,肺活量有没有区别"
示例输出:\["独立样本T检验", "两组均值比较", "差异分析", "连续变量", "二分类自变量"\]
### **3.2 SSA Planner (核心规划师) ⭐ 最关键**
* **目标**:精准选择工具并填对参数。
* **Model**DeepSeek-V3 (Temperature: 0.1)
* **Context 组装**:动态插入 candidate\_tools 的 JSON Schema。
**System Prompt Template:**
你是一名资深的生物统计学家。你面前有一份数据摘要Metadata和一组可用的统计工具箱。
请根据用户的需求选择最合适的一个工具并生成详细的执行计划SAP
\#\#\# 数据摘要
{{data\_schema\_json}}
\#\#\# 可用工具箱 (Candidates)
{{candidate\_tools\_json}}
\#\#\# 决策规则 (Guardrails)
1\. \*\*类型匹配\*\*:严格检查变量类型。不要把分类变量(如 "男/女"填入要求数值型Numeric的参数中。
2\. \*\*工具匹配\*\*:如果用户要做 "预测",优先选 "回归" 类工具;如果做 "差异",选 "检验" 类工具。
3\. \*\*护栏配置\*\*:对于 T 检验、ANOVA 等参数检验,必须开启 \`check\_normality\`(正态性检查)。
\#\#\# 输出要求
请先在 \<thinking\> 标签中进行推理,分析变量类型和工具适用性。
然后输出纯 JSON格式如下
{
"tool\_code": "选中工具的CODE",
"reasoning": "一句话解释为什么选这个工具(展示给用户看)",
"params": { ...根据工具定义的 params\_schema 填写... },
"guardrails": { "check\_normality": true, "auto\_fix": true }
}
**User Input Example:**
"比较性别Gender对血压SBP的影响。"
**Model Output Example:**
\<thinking\>
用户想要比较 "Gender" (分类变量通常2组) 对 "SBP" (数值变量) 的影响。
候选工具中有ST\_T\_TEST\_IND (独立样本T检验) 和 ST\_CORRELATION (相关性)。
T检验适用于 分类(2组) vs 数值。相关性适用于 数值 vs 数值。
因此选择 ST\_T\_TEST\_IND。
参数映射group\_col="Gender", val\_col="SBP"。
需要开启正态性检查。
\</thinking\>
{
"tool\_code": "ST\_T\_TEST\_IND",
"reasoning": "目标变量'SBP'为数值型,分组变量'Gender'为二分类,适合使用独立样本 T 检验比较均值差异。",
"params": { "group\_col": "Gender", "val\_col": "SBP" },
"guardrails": { "check\_normality": true, "auto\_fix": true }
}
### **3.3 SSA Critic (结果审查员)**
* **目标**:将 R 的输出翻译成人话,并遏制学术不端表述。
* **Model**DeepSeek-V3 (Temperature: 0.5)
**System Prompt:**
你是一名严谨的期刊审稿人。请根据 R 语言的统计结果,为用户撰写一段简短的分析结论。
\#\#\# 输入信息
1\. 用户问题:{{user\_query}}
2\. 统计方法:{{method\_name}}
3\. 执行结果:{{r\_result\_json}}
4\. 执行路径日志:{{trace\_log}}
\#\#\# 撰写原则 (Strict Rules)
1\. \*\*拒绝绝对化\*\*:严禁使用 "证明了" (proved)、"确信" 等词。请使用 "差异具有统计学意义" (statistically significant) 或 "未发现显著差异"。
2\. \*\*关注前提\*\*:如果 trace\_log 显示 "正态性检验失败,切换为非参数检验",必须在报告中指出这一点。
3\. \*\*完整性\*\*:不仅要报告 P 值,还要报告统计量(如 t值、F值和置信区间如果有
4\. \*\*业务关联\*\*:尝试结合用户问题中的变量名进行解释,而不是只说 "X 和 Y"。
\#\#\# 输出格式
Markdown 段落。
## **4\. 离线数据增强 (Offline Synthetic Generation)**
为了让 RAG 检索更准,我们需要在工具入库时,用 AI 生成“模拟用户提问”。这是 **"SSA-02 数据库设计"** 中 search\_text 字段的数据来源。
**Worker Prompt (Qwen-Max):**
我有一个 R 语言统计工具,定义如下:
名称:{{tool\_name}}
描述:{{tool\_desc}}
参数:{{params\_schema}}
请模拟 5 个临床医生可能会问的自然语言问题,这些问题应该触发这个工具的使用。
问题要包含:
1\. 极其口语化的表达(如 "看看这两组有没有区别")。
2\. 带有具体医学场景的表达(如 "比较吃药和不吃药的血糖差异")。
3\. 包含统计术语的表达(如 "做个T检验")。
输出格式:纯文本,每行一个问题。
## **5\. 错误自愈流程 (Self-Healing Flow)**
当 R 服务返回 status: "error" 时Node.js 不会直接把报错甩给用户,而是尝试一次自愈。
**Trigger Condition**: R 返回错误,且错误信息包含 ParameterError 或 ColumnNotFound。
**Fixer Prompt:**
你生成的参数导致 R 代码运行报错。请修正参数。
\#\#\# 原始计划
工具:{{tool\_code}}
参数:{{original\_params}}
\#\#\# 报错信息
{{error\_message}} (例如Error: Column 'age' not found in data)
\#\#\# 数据摘要
{{data\_schema}}
请输出修正后的 params JSON。
## **6\. 开发建议**
1. **Prompt 版本管理**:所有的 Prompt 必须存入 capability\_schema.prompt\_templates 表(复用 ADMIN 模块的能力),不要硬编码在代码里。这样运营人员可以在后台动态调整 Prompt。
2. **Context Window 优化**candidate\_tools 的 JSON Schema 可能会很长。如果超出 Token 限制,仅保留 tool\_code, name, desc 和 params\_schema去除无关字段。
3. **流式输出**Critic 生成报告时,建议使用 SSE 流式输出,减少用户等待的焦虑感。

View File

@@ -0,0 +1,130 @@
# **SSA-Pro: 智能统计分析项目开发管理与实施计划**
**文档版本:** v1.0
**创建日期:** 2026-02-07
**项目代号:** SSA (Smart Statistical Analysis)
**技术架构:** SSA-Pro V4.0 (Sync API \+ Guardrails \+ White-box)
**产品目标:** 打造医疗科研领域最严谨、透明、可交付代码的智能统计助手。
## **1\. 总体里程碑规划 (Milestones Map)**
我们将项目划分为三个阶段,采取 **"走通链路 \-\> 完善体验 \-\> 批量量产"** 的策略。
| 阶段 | 周期 | 核心目标 (OKR) | 交付物 |
| :---- | :---- | :---- | :---- |
| **Phase 1: 骨架与地基** | **Week 1-2** | **跑通 "Hello World"**。 打通 Node \-\> R 的调用链路,完成数据库与 Docker 环境搭建。 | ✅ R Docker 基础镜像 ✅ 核心数据库表 (tools\_library) ✅ 第 1 个工具 (T检验) 跑通 API |
| **Phase 2: 智能与交互 MVP** | **Week 3-5** | **实现 "V2 原型体验"**。 完成 RAG 检索、AI 规划、前端交互卡片,集成 Top 10 核心工具。 | ✅ 完整 Chat 交互界面 ✅ 智能规划 (Planner) 上线 ✅ 10 个高频统计工具可用 |
| **Phase 3: 量产与交付** | **Week 6-8** | **覆盖 80% 场景**。 批量迁移剩余工具,完善结果解释 (Critic) 与代码下载功能。 | ✅ 50+ 工具上线 ✅ 代码下载/Word导出功能 ✅ 生产环境部署与压测 |
## **2\. 详细任务清单 (To-Do List by Role)**
### **🏁 Phase 1: 骨架与地基 (Week 1-2)**
**目标:** 不追求 UI 美观,只追求 API 通畅。实现 POST /execute 能返回 T 检验的 JSON 结果。
#### **🐹 后端工程 (Node.js)**
* \[ \] **DB 设计**:根据 SSA-02 创建 ssa\_schema 及 tools\_library, execution\_logs 表。
* \[ \] **API 存根**:实现 POST /api/v1/ssa/execute 接口目前仅做转发Proxy到 R 服务。
* \[ \] **RAG 基础**:复用 common/rag创建 ToolSearchService支持对工具描述的向量检索。
#### **📐 R 工程 (Statistics)**
* \[ \] **环境构建**:编写 Dockerfile基于 rocker/r-ver安装 plumber, jsonlite, ggplot2 等基础包。
* \[ \] **Wrapper 规范**:根据 SSA-01编写标准 wrapper\_template.R含输入解析、错误捕获、Base64输出
* \[ \] **首个工具**:迁移并封装 ST\_T\_TEST\_IND (独立样本 T 检验),实现正态性检查逻辑。
* \[ \] **服务启动**:编写 plumber.R 入口文件,挂载 /run 端点。
#### **🎨 前端工程 (React)**
* \[ \] **Mock 数据**:根据原型图,构造 PlanCard 和 ResultCard 的 Mock JSON 数据。
* \[ \] **组件开发**:开发基础的 ChatContainer复用 AIA 模块)和侧边栏框架。
### **🚀 Phase 2: 智能与交互 MVP (Week 3-5)**
**目标:** 用户可以上传数据AI 能听懂并规划,前端能展示“执行树”和“三线表”。
#### **🧠 AI 策略 (Prompt Engineering)**
* \[ \] **Query Rewriter**:调试 Prompt将用户口语"看差异")转化为术语("T检验")。
* \[ \] **Planner Agent**:根据 SSA-03调试 DeepSeek-V3 的 Prompt确保稳定输出符合 Schema 的 JSON 计划。
* \[ \] **元数据注入**:实现动态 Context 组装逻辑(只注入 Top-5 工具定义)。
#### **📐 R 工程 (Statistics)**
* \[ \] **Top 10 工具迁移**完成卡方、ANOVA、相关性、Mann-Whitney、Wilcoxon 等高频工具的封装。
* \[ \] **Trace Log 实现**:在 R 代码中埋点,记录 check\_normality, check\_variance 等步骤的状态。
* \[ \] **代码生成器**:实现 generate\_code() 函数,拼接可独立运行的 R 脚本字符串。
#### **🎨 前端工程 (React)**
* \[ \] **卡片组件**:开发 ConfirmationCard (确认卡片) 和 ExecutionTree (执行路径树,支持动画)。
* \[ \] **结果渲染**:开发 ResultCard支持 Tab 切换 (解读/图表/表格)。
* \[ \] **数据上传**:实现侧边栏文件上传,调用 DC 模块解析 Schema不传数据给 LLM
#### **🐹 后端工程 (Node.js)**
* \[ \] **编排逻辑**:实现 Retrieve \-\> Plan \-\> Wait \-\> Execute 的完整业务流。
* \[ \] **数据隐私**:确保传给 LLM 的只有 Schema传给 R 的才有 Data。
### **📦 Phase 3: 量产与交付 (Week 6-8)**
**目标:** 工具库丰富,报告专业,具备生产环境稳定性。
#### **📐 R 工程 (Statistics)**
* \[ \] **批量工厂**:编写脚本扫描旧 R 代码注释,自动生成 tools\_library.json 元数据Metadata Engineering
* \[ \] **长尾工具迁移**:按优先级迁移剩余工具(回归、生存分析、降维等)。
* \[ \] **错误处理**:增强 tryCatch对常见统计错误返回友好的 Message。
#### **🧠 AI 策略 (Critic)**
* \[ \] **Critic Agent**:调试“结果解释” Prompt确保输出严谨的学术结论P值解读、置信区间
* \[ \] **模拟提问生成**:使用 Qwen-Max 离线生成 500+ 条模拟用户提问,更新向量库,提升检索准确率。
#### **🎨 前端工程 (React)**
* \[ \] **三线表组件**:优化表格样式,符合 APA 格式。
* \[ \] **资产交付**:实现 R 代码下载(.zip和 Word 报告导出(调用 Pandoc 服务)。
* \[ \] **图表预览**:集成 react-photo-view 实现图表点击放大。
#### **🛡️ 运维与测试**
* \[ \] **网络隔离**:配置 SAE 网络策略,禁止 R 容器访问外网。
* \[ \] **并发测试**:测试 10 个并发请求下的 R 服务内存占用。
* \[ \] **端到端测试**:验证 20 个典型统计场景的准确性。
## **3\. 关键依赖检查 (Dependencies)**
在项目启动前,请确认以下资源已就绪:
1. **基础设施**
* \[x\] SAE 环境 (Node.js \+ Python 已就绪,需新增 R 应用)
* \[x\] RDS PostgreSQL (pgvector 插件已安装)
* \[x\] OSS 存储 (用于存临时图表或大文件)
2. **技术资产**
* \[x\] DC 模块 (Tool C):用于前置数据清洗和 Excel 解析。
* \[x\] 通用 Chat 组件AIA 模块已沉淀,可直接复用。
* \[x\] LLM 网关DeepSeek-V3 接口已调通。
## **4\. 风险管理 (Risk Management)**
| 风险点 | 概率 | 影响 | 应对策略 |
| :---- | :---- | :---- | :---- |
| **R 工具封装进度慢** | 高 | 阻塞上线 | 优先封装 Top 10编写代码生成脚本辅助封装。 |
| **LLM 规划参数错误** | 中 | 运行报错 | 在 R 入口处做强类型校验;前端卡片允许用户人工修正参数。 |
| **大文件导致 R 崩溃** | 中 | 服务不可用 | 严格限制上传文件 \< 2MBSAE 配置内存监控和自动重启。 |
| **统计结果解释幻觉** | 低 | 学术误导 | Critic Prompt 强制要求基于 R 输出的 JSON 说话,禁止脑补。 |
## **5\. 每日工作流建议 (Daily Workflow)**
建议采用 **"R 优先,前后端跟进"** 的模式:
1. **R 工程师**:每天封装 2-3 个工具,提交到代码库,并更新 tools\_metadata.json。
2. **后端工程师**:更新向量库数据,确保 LLM 能检索到新工具。
3. **前端工程师**:针对新工具的特殊参数(如生存分析的时间列),微调卡片展示逻辑。
4. **每日站会**:演示昨天封装的工具是否能跑通闭环。