Files
AIclinicalresearch/backend/scripts/migrate-rvw-prompts.ts
HaHafeng 87655ea7e6 feat(rvw,asl): RVW V3.0 smart review + ASL deep research history + stability
RVW module (V3.0 Smart Review Enhancement):
- Add LLM data validation via PromptService (RVW_DATA_VALIDATION)
- Add ClinicalAssessmentSkill with FINER-based evaluation (RVW_CLINICAL)
- Remove all numeric scores from UI (editorial, methodology, overall)
- Implement partial_completed status with Promise.allSettled
- Add error_details JSON field to ReviewTask for granular failure info
- Fix overallStatus logic: warning status now counts as success
- Restructure ForensicsReport: per-table LLM results, remove top-level block
- Refactor ClinicalReport: structured collapsible sections
- Increase all skill timeouts to 300s for long manuscripts (20+ pages)
- Increase DataForensics LLM timeout to 180s, pg-boss to 15min
- Executor default fallback timeout 30s -> 60s

ASL module:
- Add deep research history with sidebar accordion UI
- Implement waterfall flow for historical task display
- Upgrade Unifuncs DeepSearch API from S2 to S3 with fallback
- Add ASL_SR module seed for admin configurability
- Fix new search button inconsistency

Docs:
- Update RVW module status to V3.0
- Update deployment changelist
- Add 0305 deployment summary

DB Migration:
- Add error_details JSONB column to rvw_schema.review_tasks

Tested: All 4 review modules verified, partial completion working
Made-with: Cursor
2026-03-07 19:24:21 +08:00

216 lines
9.2 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.
/**
* RVW模块 Prompt 迁移脚本
*
* 将现有文件Prompt迁移到数据库
*
* 迁移内容:
* 1. RVW_EDITORIAL - 稿约规范性评估 (review_editorial_system.txt)
* 2. RVW_METHODOLOGY - 方法学质量评估 (review_methodology_system.txt)
* 3. RVW_TOPIC_SYSTEM - 选题评估系统提示 (topic_evaluation_system.txt)
* 4. RVW_TOPIC_USER - 选题评估用户模板 (topic_evaluation_user.txt)
*/
import { PrismaClient, PromptStatus } from '@prisma/client';
import * as fs from 'fs';
import * as path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const prisma = new PrismaClient();
// 变量提取函数
function extractVariables(content: string): string[] {
const regex = /\{\{(\w+)\}\}/g;
const variables = new Set<string>();
let match;
while ((match = regex.exec(content)) !== null) {
// 排除 Handlebars 控制语句如 #if, /if
if (!match[1].startsWith('#') && !match[1].startsWith('/')) {
variables.add(match[1]);
}
}
return Array.from(variables);
}
// RVW Prompt 配置
// 注意topic_evaluation_* 是"选题评估"功能,不属于 RVW 审稿模块
const rvwPrompts = [
{
code: 'RVW_EDITORIAL',
name: '稿约规范性评估',
module: 'RVW',
description: '评估医学稿件是否符合期刊稿约规范包括文题、摘要、参考文献等11项标准。输出JSON格式的评分和建议。',
file: 'review_editorial_system.txt',
modelConfig: { model: 'deepseek-v3', temperature: 0.3 },
},
{
code: 'RVW_METHODOLOGY',
name: '方法学质量评估',
module: 'RVW',
description: '评估医学稿件的科研设计、统计学方法和统计分析质量共20个检查点。输出JSON格式的评分和建议。',
file: 'review_methodology_system.txt',
modelConfig: { model: 'deepseek-v3', temperature: 0.3 },
},
{
code: 'RVW_DATA_VALIDATION',
name: '数据验证 LLM 核查',
module: 'RVW',
description: '使用大语言模型对医学科研稿件中的表格进行核查,包括百分比计算、统计检验方法、统计分析结果准确性等。',
inlineContent: `你正在处理的是医学科研稿件请对附件中的表格进行核查包括百分比计算是准确统计检验方法使用是否正确统计分析检验结果是否准确卡方检验中如果适用fisher精确检验的条件不给卡方值不是问题请忽略。最终形成一个核查报告重点列出核查出的问题。
请按表格逐个输出核查结果,使用以下格式:
## 表N: <表格标题>
<该表格的核查结论和发现的问题>`,
modelConfig: { model: 'deepseek-v3', temperature: 0.3 },
},
{
code: 'RVW_CLINICAL',
name: '临床专业评估',
module: 'RVW',
description: '基于 FINER 标准(可行性、创新性、伦理性、相关性)对研究选题进行系统评估,涵盖创新性、临床价值、科学性、可行性四个维度。',
inlineContent: `你作为临床研究设计智能顾问CRD-IA将依据 FINER 标准(可行性 Feasibility、创新性 Interesting、伦理性 Ethical、相关性 Relevant对研究选题进行系统评估并用中文回答。
第一步:研究问题的明确性评估
1. 判断研究问题是否清晰
研究问题是否包含完整的 PICO 要素Population/Intervention/Comparator/Outcome
若 PICO 不完整,提示研究者补充必要信息。
2. 研究问题的完善与优化
研究者已有明确的临床问题:通过对话识别其陈述中的关键信息,优化 PICO 框架。
研究者尚未形成清晰的研究问题:询问其关注的疾病领域,并协助提出可供研究的具体问题。
判断是否需进一步咨询专家:若研究问题仍不够明确,建议研究者寻求该领域专家的意见。
第二步:研究问题的要素完整性验证
CRD-IA 将按以下维度评估研究问题的完整性,确保其符合 FINER 标准,并依据 循证医学原则 和 ICH-GCP 规范 进行多维度价值评估。评估逻辑包括 假设解构 → 知识验证 → 缺陷识别 → 优化建议,所有结论需明确 证据等级A/B/C类
1. 创新性评估
检索国际指南、PubMed 已发表论文,以及 ICTRP、ClinicalTrials.gov 近三年注册研究,分析研究选题的 相似度(相似度<30%为高创新)。
识别研究假设中的 知识突破点,判断是否填补现有研究空白。
2. 临床价值评估
通过 PubMed 检索该疾病的 疾病负担指数(参考最新 GBD 数据),判断该研究的 临床紧迫性。
检索该疾病相关的 国际指南,明确指南是否指出该问题 需要进一步证据。
评估研究者定义的 结局指标 是否与临床关注的核心获益一致;如偏离临床重点,应予以提示。
3. 科学性评估
研究假设是否 符合基本科学原理,若存在与已知科学常识矛盾的部分,应提示研究者重新审视理论基础。
该研究问题能否通过 合理的研究设计 进行科学验证。
4. 可行性评估
进行 风险-受益比分析(基于 DECISION 模型),评估该研究是否存在 重大伦理风险,影响可行性。
估算目标患者群体的 潜在样本量,若可能难以收集足够样本,应明确指出并建议调整研究方案。
第三步:最终评估结论与优化建议
在综合分析 创新性、临床价值、科学性、可行性 之后CRD-IA 将:
总结研究选题的整体评估结果,标明各项评估的 证据等级A/B/C类
提出优化建议,帮助研究者改进研究设计,使其更具科学价值、临床意义和可操作性。
回答需要考虑聊天历史。
如果过程中有不明确的问题,通过聊天让用户补充相关信息。除特殊要求外,用中文回复。`,
modelConfig: { model: 'deepseek-v3', temperature: 0.3 },
},
];
async function main() {
console.log('🚀 开始迁移 RVW Prompt 到数据库...\n');
const promptsDir = path.join(__dirname, '..', 'prompts');
for (const prompt of rvwPrompts) {
console.log(`📄 处理: ${prompt.code} (${prompt.name})`);
// 读取内容:优先使用 inlineContent否则从文件读取
let content: string;
if ((prompt as any).inlineContent) {
content = (prompt as any).inlineContent;
console.log(` 📝 使用内联内容,长度: ${content.length} 字符`);
} else {
const filePath = path.join(promptsDir, (prompt as any).file);
if (!fs.existsSync(filePath)) {
console.log(` ⚠️ 文件不存在: ${filePath}`);
continue;
}
content = fs.readFileSync(filePath, 'utf-8').trim();
}
const variables = extractVariables(content);
console.log(` 📝 内容长度: ${content.length} 字符`);
console.log(` 🔤 提取变量: [${variables.join(', ')}]`);
// 创建或更新模板
const template = await prisma.prompt_templates.upsert({
where: { code: prompt.code },
update: {
name: prompt.name,
description: prompt.description,
variables: variables.length > 0 ? variables : null,
updated_at: new Date(),
},
create: {
code: prompt.code,
name: prompt.name,
module: prompt.module,
description: prompt.description,
variables: variables.length > 0 ? variables : null,
},
});
// 检查是否已有 ACTIVE 版本
const existingActive = await prisma.prompt_versions.findFirst({
where: {
template_id: template.id,
status: PromptStatus.ACTIVE,
},
});
if (existingActive) {
console.log(` ✅ 已存在 ACTIVE 版本 (v${existingActive.version})`);
} else {
// 创建第一个 ACTIVE 版本
await prisma.prompt_versions.create({
data: {
template_id: template.id,
version: 1,
content: content,
model_config: prompt.modelConfig,
status: PromptStatus.ACTIVE,
changelog: '从文件迁移的初始版本',
created_by: 'system-migration',
},
});
console.log(` ✅ 创建 ACTIVE 版本 (v1)`);
}
console.log('');
}
// 验证结果
console.log('═══════════════════════════════════════════════════════');
console.log('📊 迁移结果验证\n');
const templates = await prisma.prompt_templates.findMany({
where: { module: 'RVW' },
include: {
versions: {
orderBy: { version: 'desc' },
take: 1,
},
},
});
console.log(`✅ 共迁移 ${templates.length} 个 RVW Prompt:\n`);
for (const t of templates) {
const latestVersion = t.versions[0];
console.log(` 📋 ${t.code}`);
console.log(` 名称: ${t.name}`);
console.log(` 变量: ${t.variables ? JSON.stringify(t.variables) : '无'}`);
console.log(` 最新版本: v${latestVersion?.version} (${latestVersion?.status})`);
console.log('');
}
console.log('✅ RVW Prompt 迁移完成!');
}
main()
.catch((error) => {
console.error('❌ 迁移失败:', error);
process.exit(1);
})
.finally(() => prisma.$disconnect());