Files
AIclinicalresearch/backend/scripts/seed-ssa-phase3-prompts.ts
HaHafeng 3446909ff7 feat(ssa): Complete Phase I-IV intelligent dialogue and tool system development
Phase I - Session Blackboard + READ Layer:
- SessionBlackboardService with Postgres-Only cache
- DataProfileService for data overview generation
- PicoInferenceService for LLM-driven PICO extraction
- Frontend DataContextCard and VariableDictionaryPanel
- E2E tests: 31/31 passed

Phase II - Conversation Layer LLM + Intent Router:
- ConversationService with SSE streaming
- IntentRouterService (rule-first + LLM fallback, 6 intents)
- SystemPromptService with 6-segment dynamic assembly
- TokenTruncationService for context management
- ChatHandlerService as unified chat entry
- Frontend SSAChatPane and useSSAChat hook
- E2E tests: 38/38 passed

Phase III - Method Consultation + AskUser Standardization:
- ToolRegistryService with Repository Pattern
- MethodConsultService with DecisionTable + LLM enhancement
- AskUserService with global interrupt handling
- Frontend AskUserCard component
- E2E tests: 13/13 passed

Phase IV - Dialogue-Driven Analysis + QPER Integration:
- ToolOrchestratorService (plan/execute/report)
- analysis_plan SSE event for WorkflowPlan transmission
- Dual-channel confirmation (ask_user card + workspace button)
- PICO as optional hint for LLM parsing
- E2E tests: 25/25 passed

R Statistics Service:
- 5 new R tools: anova_one, baseline_table, fisher, linear_reg, wilcoxon
- Enhanced guardrails and block helpers
- Comprehensive test suite (run_all_tools_test.js)

Documentation:
- Updated system status document (v5.9)
- Updated SSA module status and development plan (v1.8)

Total E2E: 107/107 passed (Phase I: 31, Phase II: 38, Phase III: 13, Phase IV: 25)

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

136 lines
4.1 KiB
TypeScript
Raw 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.
/**
* Phase III — method_consult Prompt 种子脚本
*
* 写入 Prompt 模板:
* 1. SSA_METHOD_CONSULT — 方法推荐指令P1: 结论先行 + 结构化列表)
*
* 运行方式: npx tsx scripts/seed-ssa-phase3-prompts.ts
* 前置: 数据库已启动
*/
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
interface PromptDef {
code: string;
name: string;
description: string;
variables: string[];
content: string;
modelConfig: Record<string, any>;
}
const PROMPTS: PromptDef[] = [
{
code: 'SSA_METHOD_CONSULT',
name: 'SSA 方法推荐指令',
description: 'Phase III — method_consult 工具调用后,指导 LLM 生成结构化方法推荐P1 格式约束)',
variables: [],
content: `## 当前任务:统计方法推荐
你正在为用户推荐统计分析方法。系统已通过决策表匹配到候选方法,匹配结果在"工具执行结果"中给出。
### 输出要求(严格遵守)
1. **首先用一句话给出明确的推荐**(如:"建议采用独立样本 T 检验"
2. 然后使用 Markdown 列表分别列出:
- **选择理由** (Rationale):为什么这个方法适合当前数据和研究目的
- **必须满足的前提条件** (Prerequisites):该方法对数据的要求(如正态性、样本量等)
- **备选降级方案** (Alternatives):如果前提条件不满足,应该切换到什么方法
3. 如果匹配结果包含降级方案,必须说明切换条件
4. 如果匹配不完整或信息不足,诚实告知用户需要补充什么信息
### 禁止事项
- 严禁生成大段的不分段的长篇大论
- 严禁直接执行分析,只推荐方法
- 严禁编造数据特征或假设用户未提供的信息`,
modelConfig: { model: 'deepseek-v3', temperature: 0.5, maxTokens: 1500 },
},
];
async function upsertPrompt(def: PromptDef): Promise<void> {
const existing = await prisma.prompt_templates.findUnique({
where: { code: def.code },
});
if (existing) {
const latestVersion = await prisma.prompt_versions.findFirst({
where: { template_id: existing.id },
orderBy: { version: 'desc' },
});
const activeVersion = await prisma.prompt_versions.findFirst({
where: { template_id: existing.id, status: 'ACTIVE' },
});
if (activeVersion && activeVersion.content === def.content) {
console.log(` ⏭️ ${def.code} 内容未变化,跳过`);
return;
}
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: def.content,
model_config: def.modelConfig,
status: 'ACTIVE',
changelog: `Phase III v${newVersion}: ${def.description}`,
created_by: 'system-seed',
},
});
console.log(`${def.code} 更新到 v${newVersion}`);
} else {
const template = await prisma.prompt_templates.create({
data: {
code: def.code,
name: def.name,
module: 'SSA',
description: def.description,
variables: def.variables,
},
});
await prisma.prompt_versions.create({
data: {
template_id: template.id,
version: 1,
content: def.content,
model_config: def.modelConfig,
status: 'ACTIVE',
changelog: `Phase III v1.0: ${def.description}`,
created_by: 'system-seed',
},
});
console.log(`${def.code} 创建成功 (id=${template.id})`);
}
}
async function main() {
console.log('🚀 开始写入 SSA Phase III Prompt 模板...\n');
for (const def of PROMPTS) {
console.log(`📝 处理 ${def.code} (${def.name})...`);
await upsertPrompt(def);
}
console.log(`\n✅ 全部 ${PROMPTS.length} 个 Prompt 模板写入完成!`);
}
main()
.catch(e => {
console.error('❌ Seed 失败:', e);
process.exit(1);
})
.finally(() => prisma.$disconnect());