Files
AIclinicalresearch/backend/prisma/seeds/protocol-agent-seed.ts
HaHafeng 2481b786d8 deploy: Complete 0126-27 deployment - database upgrade, services update, code recovery
Major Changes:
- Database: Install pg_bigm/pgvector plugins, create test database
- Python service: v1.0 -> v1.1, add pymupdf4llm/openpyxl/pypandoc
- Node.js backend: v1.3 -> v1.7, fix pino-pretty and ES Module imports
- Frontend: v1.2 -> v1.3, skip TypeScript check for deployment
- Code recovery: Restore empty files from local backup

Technical Fixes:
- Fix pino-pretty error in production (conditional loading)
- Fix ES Module import paths (add .js extensions)
- Fix OSSAdapter TypeScript errors
- Update Prisma Schema (63 models, 16 schemas)
- Update environment variables (DATABASE_URL, EXTRACTION_SERVICE_URL, OSS)
- Remove deprecated variables (REDIS_URL, DIFY_API_URL, DIFY_API_KEY)

Documentation:
- Create 0126 deployment folder with 8 documents
- Update database development standards v2.0
- Update SAE deployment status records

Deployment Status:
- PostgreSQL: ai_clinical_research_test with plugins
- Python: v1.1 @ 172.17.173.84:8000
- Backend: v1.7 @ 172.17.173.89:3001
- Frontend: v1.3 @ 172.17.173.90:80

Tested: All services running successfully on SAE
2026-01-27 08:13:27 +08:00

564 lines
14 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.
/**
* Protocol Agent 初始配置数据种子
*
* 运行方式: npx tsx prisma/seeds/protocol-agent-seed.ts
*/
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
console.log('🌱 Seeding Protocol Agent configuration...');
// 1. 创建Agent定义
const agentDefinition = await prisma.agentDefinition.upsert({
where: { code: 'protocol_agent' },
update: {},
create: {
code: 'protocol_agent',
name: '研究方案制定助手',
description: '帮助研究者系统地制定临床研究方案覆盖科学问题、PICO、研究设计、样本量和观察指标5个核心阶段',
version: '1.0.0',
config: {
defaultModel: 'deepseek-v3',
maxTurns: 100,
timeout: 60000,
enableTrace: true,
enableReflexion: true,
},
isActive: true,
},
});
console.log('✅ Created Agent Definition:', agentDefinition.code);
// 2. 创建5个阶段
const stages = [
{
stageCode: 'scientific_question',
stageName: '科学问题梳理',
sortOrder: 1,
isInitial: true,
isFinal: false,
nextStages: ['pico'],
config: {
requiredFields: ['content'],
minContentLength: 10,
},
},
{
stageCode: 'pico',
stageName: 'PICO要素',
sortOrder: 2,
isInitial: false,
isFinal: false,
nextStages: ['study_design'],
config: {
requiredFields: ['P', 'I', 'C', 'O'],
},
},
{
stageCode: 'study_design',
stageName: '研究设计',
sortOrder: 3,
isInitial: false,
isFinal: false,
nextStages: ['sample_size'],
config: {
requiredFields: ['type'],
},
},
{
stageCode: 'sample_size',
stageName: '样本量计算',
sortOrder: 4,
isInitial: false,
isFinal: false,
nextStages: ['endpoints'],
config: {
requiredFields: ['total'],
},
},
{
stageCode: 'endpoints',
stageName: '观察指标',
sortOrder: 5,
isInitial: false,
isFinal: true,
nextStages: [],
config: {
requiredFields: ['primary'],
},
},
];
for (const stage of stages) {
await prisma.agentStage.upsert({
where: {
agentId_stageCode: {
agentId: agentDefinition.id,
stageCode: stage.stageCode,
},
},
update: stage,
create: {
agentId: agentDefinition.id,
...stage,
},
});
console.log(` ✅ Stage: ${stage.stageName}`);
}
// 3. 创建Prompt模板
const prompts = [
// 系统Prompt
{
promptType: 'system',
promptCode: 'protocol_system',
content: `你是一位经验丰富的临床研究方法学专家,正在帮助研究者制定研究方案。
你的职责:
1. 系统引导用户完成研究方案的5个核心要素科学问题、PICO、研究设计、样本量、观察指标
2. 提供专业、准确的方法学建议
3. 确保研究设计的科学性和可行性
4. 使用通俗易懂的语言,同时保持学术严谨性
当前阶段: {{context.currentStage}}
已完成阶段: {{context.completedStages}}
请根据用户的输入,提供专业指导。`,
variables: ['context'],
},
// 科学问题阶段Prompt
{
promptType: 'stage',
promptCode: 'stage_scientific_question',
stageCode: 'scientific_question',
content: `【科学问题梳理阶段】
你正在帮助用户梳理研究的科学问题。一个好的科学问题应该:
- 明确、具体、可操作
- 有实际的临床或学术意义
- 可通过研究方法验证
{{#if context.scientificQuestion}}
用户当前的科学问题草稿:
{{context.scientificQuestion.content}}
{{/if}}
请引导用户:
1. 描述研究背景和动机
2. 明确想要解决的核心问题
3. 阐述研究的潜在意义
当用户表达清晰后,帮助整理成规范的科学问题陈述,并提供"同步到方案"按钮。`,
variables: ['context'],
},
// PICO阶段Prompt
{
promptType: 'stage',
promptCode: 'stage_pico',
stageCode: 'pico',
content: `【PICO要素梳理阶段】
PICO是临床研究问题结构化的核心框架
- P (Population): 研究人群
- I (Intervention): 干预措施
- C (Comparison): 对照措施
- O (Outcome): 结局指标
{{#if context.pico}}
当前PICO
- P: {{context.pico.P.value}}
- I: {{context.pico.I.value}}
- C: {{context.pico.C.value}}
- O: {{context.pico.O.value}}
{{/if}}
请引导用户逐一明确四个要素,确保:
1. P: 纳入标准、排除标准清晰
2. I: 干预措施具体可操作
3. C: 对照组设置合理
4. O: 结局指标可测量、有临床意义
当四要素都明确后,提供"同步到方案"按钮。`,
variables: ['context'],
},
// 研究设计阶段Prompt
{
promptType: 'stage',
promptCode: 'stage_study_design',
stageCode: 'study_design',
content: `【研究设计阶段】
根据科学问题和PICO需要确定合适的研究设计
科学问题:{{context.scientificQuestion.content}}
PICO
- P: {{context.pico.P.value}}
- I: {{context.pico.I.value}}
常见研究类型:
- 随机对照试验(RCT):最高证据等级,适合验证干预效果
- 队列研究:适合观察性研究,探索风险因素
- 病例对照研究:适合罕见疾病研究
- 横断面研究:描述性研究
请引导用户确定:
1. 研究类型
2. 盲法设计(如适用)
3. 随机化方法(如适用)
4. 研究周期
5. 是否多中心
设计确定后,提供"同步到方案"按钮。`,
variables: ['context'],
},
// 样本量阶段Prompt
{
promptType: 'stage',
promptCode: 'stage_sample_size',
stageCode: 'sample_size',
content: `【样本量计算阶段】
样本量计算需要考虑:
- α (显著性水平): 通常0.05
- β (统计效力): 通常0.8-0.9
- 预期效应量
- 预计脱落率
研究设计:{{context.studyDesign.type}}
主要结局:{{context.pico.O.value}}
请引导用户:
1. 确定检验类型(优效、非劣效、等效)
2. 估计预期效应量(基于文献或预试验)
3. 设定显著性水平和统计效力
4. 考虑脱落率调整
可以使用样本量计算工具辅助计算。
样本量确定后,提供"同步到方案"按钮。`,
variables: ['context'],
},
// 观察指标阶段Prompt
{
promptType: 'stage',
promptCode: 'stage_endpoints',
stageCode: 'endpoints',
content: `【观察指标设计阶段】
观察指标是评价研究结果的关键:
研究类型:{{context.studyDesign.type}}
PICO-O{{context.pico.O.value}}
需要明确的指标类型:
1. **主要结局指标(Primary Endpoint)**
- 与科学问题直接相关
- 用于样本量计算
- 每个研究通常只有1-2个
2. **次要结局指标(Secondary Endpoints)**
- 支持主要结局的补充指标
- 可以有多个
3. **安全性指标(Safety Endpoints)**
- 不良事件、实验室检查等
4. **探索性指标(Exploratory)**
- 为未来研究提供线索
请引导用户定义每个指标的:
- 名称
- 操作定义
- 测量方法
- 评价时点
所有指标确定后,提供"同步到方案"按钮。
🎉 完成观察指标后,您可以点击"一键生成研究方案"生成完整方案文档!`,
variables: ['context'],
},
// 数据提取Prompt
{
promptType: 'extraction',
promptCode: 'extraction_scientific_question',
stageCode: 'scientific_question',
content: `请从以下对话中提取科学问题信息:
用户消息:{{userMessage}}
请以JSON格式输出
{
"content": "完整的科学问题陈述",
"background": "研究背景",
"significance": "研究意义",
"readyToSync": true/false
}
如果信息不完整readyToSync设为false。`,
variables: ['userMessage'],
},
{
promptType: 'extraction',
promptCode: 'extraction_pico',
stageCode: 'pico',
content: `请从以下对话中提取PICO要素
用户消息:{{userMessage}}
当前PICO{{currentPico}}
请以JSON格式输出
{
"P": { "value": "研究人群", "details": "详细描述" },
"I": { "value": "干预措施", "details": "详细描述" },
"C": { "value": "对照措施", "details": "详细描述" },
"O": { "value": "结局指标", "details": "详细描述" },
"readyToSync": true/false
}
只更新用户提到的字段,保留其他字段不变。
如果PICO四要素都已完整readyToSync设为true。`,
variables: ['userMessage', 'currentPico'],
},
// 研究方案生成Prompt
{
promptType: 'generation',
promptCode: 'generate_protocol',
content: `你是一位资深的临床研究方法学专家,请基于以下核心要素生成一份完整、规范的临床研究方案。
## 核心要素
### 科学问题
{{scientificQuestion.content}}
{{#if scientificQuestion.background}}背景:{{scientificQuestion.background}}{{/if}}
### PICO要素
- **研究人群(P)**: {{pico.P.value}}
{{pico.P.details}}
- **干预措施(I)**: {{pico.I.value}}
{{pico.I.details}}
- **对照措施(C)**: {{pico.C.value}}
{{pico.C.details}}
- **结局指标(O)**: {{pico.O.value}}
{{pico.O.details}}
### 研究设计
- 研究类型: {{studyDesign.type}}
- 盲法设计: {{studyDesign.blinding}}
- 随机化方法: {{studyDesign.randomization}}
- 研究周期: {{studyDesign.duration}}
{{#if studyDesign.multiCenter}}- 多中心: 是,{{studyDesign.centerCount}}个中心{{/if}}
### 样本量
- 总样本量: {{sampleSize.total}}
- 每组样本量: {{sampleSize.perGroup}}
- 计算依据: {{sampleSize.justification}}
### 观察指标
**主要结局指标:**
{{#each endpoints.primary}}
- {{name}}: {{definition}} ({{method}}, {{timePoint}})
{{/each}}
**次要结局指标:**
{{#each endpoints.secondary}}
- {{name}}: {{definition}}
{{/each}}
**安全性指标:**
{{#each endpoints.safety}}
- {{name}}: {{definition}}
{{/each}}
---
## 生成要求
请生成包含以下章节的完整研究方案:
1. **研究背景与立题依据**
- 疾病/问题背景
- 国内外研究现状
- 研究的必要性和意义
2. **研究目的**
- 主要目的
- 次要目的
3. **研究方法**
- 研究类型与设计
- 研究对象
- 干预措施
- 对照设置
- 随机化与盲法
4. **受试者选择**
- 入选标准
- 排除标准
- 退出/剔除标准
5. **观察指标与评价标准**
- 主要疗效指标
- 次要疗效指标
- 安全性指标
- 评价时点
6. **统计分析计划**
- 样本量估算
- 分析数据集定义
- 统计方法
7. **质量控制**
- 数据管理
- 质量保证措施
8. **伦理考虑**
- 伦理审查
- 知情同意
- 受试者保护
9. **研究进度安排**
- 时间节点
- 里程碑
请使用专业、规范的学术语言,确保内容完整、逻辑清晰、符合临床研究规范。`,
variables: ['scientificQuestion', 'pico', 'studyDesign', 'sampleSize', 'endpoints'],
},
];
// 获取阶段ID映射
const stageIdMap = new Map<string, string>();
const savedStages = await prisma.agentStage.findMany({
where: { agentId: agentDefinition.id },
});
for (const stage of savedStages) {
stageIdMap.set(stage.stageCode, stage.id);
}
// 创建Prompts
for (const prompt of prompts) {
const stageId = prompt.stageCode ? stageIdMap.get(prompt.stageCode) : null;
await prisma.agentPrompt.upsert({
where: {
agentId_promptCode_version: {
agentId: agentDefinition.id,
promptCode: prompt.promptCode,
version: 1,
},
},
update: {
content: prompt.content,
variables: prompt.variables,
},
create: {
agentId: agentDefinition.id,
stageId: stageId,
promptType: prompt.promptType,
promptCode: prompt.promptCode,
content: prompt.content,
variables: prompt.variables,
version: 1,
isActive: true,
},
});
console.log(` ✅ Prompt: ${prompt.promptCode}`);
}
// 4. 创建Reflexion规则
const reflexionRules = [
{
ruleCode: 'scientific_question_completeness',
ruleName: '科学问题完整性检查',
triggerStage: 'scientific_question',
triggerTiming: 'on_sync',
ruleType: 'rule_based',
conditions: {
content: { required: true, minLength: 10 },
},
severity: 'warning',
failureAction: 'warn',
sortOrder: 1,
},
{
ruleCode: 'pico_completeness',
ruleName: 'PICO要素完整性检查',
triggerStage: 'pico',
triggerTiming: 'on_sync',
ruleType: 'rule_based',
conditions: {
P: 'required',
I: 'required',
C: 'required',
O: 'required',
},
severity: 'error',
failureAction: 'warn',
sortOrder: 2,
},
{
ruleCode: 'sample_size_validity',
ruleName: '样本量有效性检查',
triggerStage: 'sample_size',
triggerTiming: 'on_sync',
ruleType: 'rule_based',
conditions: {
total: { required: true, min: 1 },
},
severity: 'error',
failureAction: 'warn',
sortOrder: 3,
},
{
ruleCode: 'endpoints_primary_required',
ruleName: '主要终点指标必填',
triggerStage: 'endpoints',
triggerTiming: 'on_sync',
ruleType: 'rule_based',
conditions: {
primary: { notEmpty: true },
},
severity: 'error',
failureAction: 'warn',
sortOrder: 4,
},
];
for (const rule of reflexionRules) {
await prisma.reflexionRule.upsert({
where: {
agentId_ruleCode: {
agentId: agentDefinition.id,
ruleCode: rule.ruleCode,
},
},
update: rule,
create: {
agentId: agentDefinition.id,
...rule,
isActive: true,
},
});
console.log(` ✅ Rule: ${rule.ruleName}`);
}
console.log('\n🎉 Protocol Agent configuration seeded successfully!');
}
main()
.catch((e) => {
console.error('❌ Seed failed:', e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});