Files
AIclinicalresearch/backend/scripts/seed-ssa-reflection-prompt.ts
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

175 lines
6.3 KiB
TypeScript
Raw Permalink 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.
/**
* SSA Reflection Prompt Seed 脚本
*
* 将 SSA_REFLECTION prompt 写入 capability_schema.prompt_templates
* 运行: npx tsx scripts/seed-ssa-reflection-prompt.ts
*
* Phase R — 论文级结论生成 Prompt
* 特性:
* - 统计量槽位注入(反幻觉)
* - 敏感性分析冲突处理准则
* - 6 要素结构化 JSON 输出
* - 基于 decision_trace 的方法学说明
*/
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
const SSA_REFLECTION_PROMPT = `你是一位高级生物统计师,请基于以下分析结果生成论文级结论。
## 分析背景
分析目标:{{goal}}
分析标题:{{title}}
采用方法:{{methodology}}
样本信息:{{sampleInfo}}
## 方法选择的决策轨迹
请据此撰写方法学说明,不得臆造选择理由:
匹配规则:{{decision_trace.matched_rule}}
主要工具:{{decision_trace.primary_tool}}
{{#if decision_trace.fallback_tool}}备选工具:{{decision_trace.fallback_tool}}(触发条件:{{decision_trace.switch_condition}}{{/if}}
决策推理:{{decision_trace.reasoning}}
{{#if decision_trace.epv_warning}}⚠️ EPV 警告:{{decision_trace.epv_warning}}{{/if}}
## 各步骤统计结果
⚠️ 以下数值由系统自动注入,你必须原样引用,不得修改、四舍五入或重新表述任何数字。
{{#each findings}}
### 步骤 {{step_number}}{{tool_name}}{{tool_code}}
- 使用方法:{{method}}
{{#if statistic}}- 统计量({{statistic_name}}{{statistic}}{{/if}}
{{#if p_value}}- P 值:{{p_value}}{{/if}}
{{#if effect_size}}- 效应量({{effect_size_name}}{{effect_size}}{{/if}}
{{#if ci_lower}}- 95% 置信区间:{{ci_lower}} ~ {{ci_upper}}{{/if}}
- 显著性:{{#if is_significant}}显著P < 0.05{{else}}不显著P ≥ 0.05{{/if}}
{{#if group_stats}}
- 各组统计:
{{#each group_stats}} · {{group}} 组n={{n}}{{#if mean}}, 均值={{mean}}, SD={{sd}}{{/if}}{{#if median}}, 中位数={{median}}{{/if}}
{{/each}}
{{/if}}
{{/each}}
## 冲突处理准则(强制执行)
当主分析与敏感性分析的显著性结论不一致时:
1. 在 limitations 数组中必须包含:"敏感性分析未得到一致结论结果的稳健性Robustness较弱需谨慎解释临床意义"
2. 在 key_findings 中以主分析结果为基准报告,但需加注"(注:敏感性分析未验证此结论)"
3. 严禁选择性报告、强行拼凑显著性
4. 当所有分析方向一致时,在 key_findings 中可强调"敏感性分析进一步验证了结论的稳健性"
## 输出要求
请输出一个严格的 JSON 对象(不要输出任何其他内容,只输出 JSON包含以下字段
\`\`\`json
{
"executive_summary": "200-500字的综合摘要涵盖研究目的、主要发现和临床意义。使用论文'结果'章节的行文风格,可直接复制到论文中。引用统计量时必须与上方数值完全一致。",
"key_findings": [
"发现1具体描述含统计量和P值必须与上方数值一致",
"发现2..."
],
"statistical_summary": {
"total_tests": 3,
"significant_results": 2,
"methods_used": ["独立样本T检验", "Mann-Whitney U检验"]
},
"methodology": "方法学说明段落:基于上方决策轨迹撰写,解释为什么选择此方法、是否发生降级、数据满足了哪些假设。使用论文'方法'章节的行文风格。",
"limitations": [
"局限性1",
"局限性2"
],
"recommendations": [
"建议1基于分析结果的后续研究建议",
"建议2..."
]
}
\`\`\`
## 关键规则
1. **所有数值必须与上方统计结果完全一致**,不得修改、四舍五入、近似或重新表述
2. executive_summary 必须是完整的论文段落,不是要点列表
3. key_findings 每条必须包含具体的统计量和 P 值
4. methodology 必须基于决策轨迹撰写,说明方法选择的理由
5. limitations 至少包含 1 条,如果数据有局限则如实报告
6. 请只输出 JSON不要输出其他内容`;
async function main() {
console.log('🚀 开始写入 SSA Reflection Prompt...\n');
const existing = await prisma.prompt_templates.findUnique({
where: { code: 'SSA_REFLECTION' }
});
if (existing) {
console.log('⚠️ SSA_REFLECTION 已存在 (id=%d),创建新版本...', existing.id);
const latestVersion = await prisma.prompt_versions.findFirst({
where: { template_id: existing.id },
orderBy: { version: 'desc' }
});
const newVersion = (latestVersion?.version ?? 0) + 1;
await prisma.prompt_versions.updateMany({
where: { template_id: existing.id, status: 'ACTIVE' },
data: { status: 'ARCHIVED' }
});
await prisma.prompt_versions.create({
data: {
template_id: existing.id,
version: newVersion,
content: SSA_REFLECTION_PROMPT,
model_config: { model: 'deepseek-v3', temperature: 0.3, maxTokens: 4096 },
status: 'ACTIVE',
changelog: `Phase R v1.0: 6要素结构化JSON + 槽位注入 + 冲突处理准则`,
created_by: 'system-seed',
}
});
console.log(' ✅ 新版本 v%d 已创建并设为 ACTIVE', newVersion);
} else {
console.log('📝 创建 SSA_REFLECTION 模板...');
const template = await prisma.prompt_templates.create({
data: {
code: 'SSA_REFLECTION',
name: 'SSA 论文级结论生成 Prompt',
module: 'SSA',
description: 'Phase R — 将 StepResult[] 转化为论文级结论6要素结构化JSON含槽位注入反幻觉 + 敏感性冲突准则)',
variables: ['goal', 'title', 'methodology', 'sampleInfo', 'decision_trace', 'findings'],
}
});
await prisma.prompt_versions.create({
data: {
template_id: template.id,
version: 1,
content: SSA_REFLECTION_PROMPT,
model_config: { model: 'deepseek-v3', temperature: 0.3, maxTokens: 4096 },
status: 'ACTIVE',
changelog: 'Phase R v1.0: 初始版本6要素JSON + 槽位注入 + 冲突处理准则',
created_by: 'system-seed',
}
});
console.log(' ✅ 模板 id=%d + 版本 v1 已创建', template.id);
}
console.log('\n✅ SSA Reflection Prompt 写入完成!');
}
main()
.catch(e => {
console.error('❌ 写入失败:', e);
process.exit(1);
})
.finally(() => prisma.$disconnect());