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
216 lines
9.2 KiB
TypeScript
216 lines
9.2 KiB
TypeScript
/**
|
||
* 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());
|
||
|