Files
AIclinicalresearch/docs/03-业务模块/ASL-AI智能文献/02-技术设计/08-全文复筛质量保障策略.md
HaHafeng 66255368b7 feat(admin): Add user management and upgrade to module permission system
Features - User Management (Phase 4.1):
- Database: Add user_modules table for fine-grained module permissions
- Database: Add 4 user permissions (view/create/edit/delete) to role_permissions
- Backend: UserService (780 lines) - CRUD with tenant isolation
- Backend: UserController + UserRoutes (648 lines) - 13 API endpoints
- Backend: Batch import users from Excel
- Frontend: UserListPage (412 lines) - list/filter/search/pagination
- Frontend: UserFormPage (341 lines) - create/edit with module config
- Frontend: UserDetailPage (393 lines) - details/tenant/module management
- Frontend: 3 modal components (592 lines) - import/assign/configure
- API: GET/POST/PUT/DELETE /api/admin/users/* endpoints

Architecture Upgrade - Module Permission System:
- Backend: Add getUserModules() method in auth.service
- Backend: Login API returns modules array in user object
- Frontend: AuthContext adds hasModule() method
- Frontend: Navigation filters modules based on user.modules
- Frontend: RouteGuard checks requiredModule instead of requiredVersion
- Frontend: Remove deprecated version-based permission system
- UX: Only show accessible modules in navigation (clean UI)
- UX: Smart redirect after login (avoid 403 for regular users)

Fixes:
- Fix UTF-8 encoding corruption in ~100 docs files
- Fix pageSize type conversion in userService (String to Number)
- Fix authUser undefined error in TopNavigation
- Fix login redirect logic with role-based access check
- Update Git commit guidelines v1.2 with UTF-8 safety rules

Database Changes:
- CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled)
- ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code)
- INSERT 4 permissions + role assignments
- UPDATE PUBLIC tenant with 8 module subscriptions

Technical:
- Backend: 5 new files (~2400 lines)
- Frontend: 10 new files (~2500 lines)
- Docs: 1 development record + 2 status updates + 1 guideline update
- Total: ~4900 lines of code

Status: User management 100% complete, module permission system operational
2026-01-16 13:42:10 +08:00

43 KiB
Raw Blame History

全文复筛质量保障与可追溯策略

文档版本: V1.0
创建日期: 2025-11-22
适用模块: AI 智能文献 - 全文复筛
目标: 分阶段提升全文复筛的准确率、方法学质量判断和完整可追溯性


📋 文档概述

本文档定义了全文复筛模块MVP → V1.0 → V2.0 三个阶段的质量保障策略。

全文复筛 vs 标题摘要初筛:核心差异

维度 标题摘要初筛 全文复筛 策略差异
信息量 200-500字 5,000-20,000字 🔴 需分段处理
判断依据 PICOS匹配度 12字段方法学质量 🔴 需专业判断标准
决策复杂度 低(是/否) 高(12个字段×3级) 🔴 需结构化提取
容错策略 宁错勿漏 不能漏关键信息 🔴 需验证机制
Token成本 ¥0.005/篇 ¥0.05-0.20/篇 🔴 需成本优化
可追溯性 引用摘要 具体页码/段落/表格 🔴 需证据链

核心设计原则

原则 说明
循证医学标准 基于Cochrane RoB 2.0工具的方法学质量评估标准
结构化提取 Nougat + 分段提取 + 全文验证,避免"Lost in the Middle"
完整证据链 每个字段强制要求原文引用(页码、段落、表格)
分步实施 MVP先验证可行性V1.0提升质量V2.0达到医学级标准
成本与质量平衡 MVP用成本友好模型关键字段用高端模型验证

🎯 三阶段路线图

MVP (3周)              V1.0 (5周)            V2.0 (8周)
├─ Nougat结构化提取    ├─ Cochrane标准Prompt  ├─ 三模型仲裁
├─ 12字段分段提取      ├─ Few-shot医学案例库  ├─ 医学逻辑规则引擎
├─ 双模型验证          ├─ 完整证据链          ├─ 自动质量审计
├─ 字段级冲突检测      ├─ 全文交叉验证        ├─ HITL智能分流
└─ 基础可追溯          └─ 分级人工复核        └─ 审计级日志
   ↓                      ↓                    ↓
  准确率 ≥ 85%           准确率 ≥ 92%          准确率 ≥ 96%

🚀 MVP 阶段3 周)

目标定位

  • 准确率目标:≥ 85%
  • 信息完整率:≥ 90%12字段不遗漏
  • 成本预算:≤ ¥0.05/篇DeepSeek-V3 + Qwen3-Max
  • 交付标准:基础功能可用,支持结构化提取和双模型验证

一、核心技术策略

1.1 Nougat结构化提取关键优势

为什么选择Nougat

对比维度 PyMuPDF Nougat
输出格式 纯文本 Markdown结构化
章节识别 需LLM二次识别60%准确率) 天然保留结构95%准确率)
表格处理 文本乱码 Markdown表格
公式识别 乱码 LaTeX格式
适用场景 中文论文 英文学术论文

实施方案

// 混合策略Nougat优先PyMuPDF降级
async function extractFullText(pdfBuffer: Buffer, filename: string) {
  // Step 1: 检测语言
  const language = await detectLanguage(pdfBuffer);
  
  // Step 2: 英文论文优先用Nougat
  if (language === 'english') {
    try {
      const nougatResult = await extractionClient.extractPdf(
        pdfBuffer, filename, 'nougat'
      );
      
      if (nougatResult.quality > 0.8) {
        return {
          method: 'nougat',
          text: nougatResult.text,
          format: 'markdown',
          structured: true  // ⭐ 关键优势
        };
      }
    } catch (error) {
      console.warn('Nougat失败降级到PyMuPDF');
    }
  }
  
  // Step 3: 中文论文或Nougat失败用PyMuPDF
  const pymupdfResult = await extractionClient.extractPdf(
    pdfBuffer, filename, 'pymupdf'
  );
  
  return {
    method: 'pymupdf',
    text: pymupdfResult.text,
    format: 'plaintext',
    structured: false  // 需要LLM识别结构
  };
}

1.2 12字段分段提取避免Lost in the Middle

核心问题全文20K tokens一次性喂给LLM中间章节信息遗漏率高达33%

解决方案:按字段定向提取相关章节

// 12字段提取路由表
const FIELD_EXTRACTION_ROUTES = {
  '研究设计': {
    sections: ['abstract', 'methods'],
    maxTokens: 3000,
    priority: 'high'
  },
  '研究人群': {
    sections: ['methods', 'results'],
    maxTokens: 3500,
    priority: 'high',
    lookForTables: true  // Table 1: Baseline
  },
  '干预措施': {
    sections: ['methods', 'results'],
    maxTokens: 3000,
    priority: 'high'
  },
  '对照措施': {
    sections: ['methods', 'results'],
    maxTokens: 2500,
    priority: 'high'
  },
  '结局指标': {
    sections: ['methods', 'results'],
    maxTokens: 4000,
    priority: 'high',
    lookForTables: true  // Results tables
  },
  '随机化方法': {
    sections: ['methods', 'figures'],
    maxTokens: 2500,
    priority: 'critical',  // 关键字段
    keywords: ['randomization', 'allocation', 'sequence', 'CONSORT']
  },
  '盲法': {
    sections: ['methods'],
    maxTokens: 2000,
    priority: 'critical'
  },
  '样本量计算': {
    sections: ['methods'],
    maxTokens: 2000,
    priority: 'medium'
  },
  '基线可比性': {
    sections: ['results', 'tables'],
    maxTokens: 3000,
    priority: 'high',
    specificTable: 'Table 1'
  },
  '结果完整性': {
    sections: ['results', 'figures'],
    maxTokens: 4000,
    priority: 'critical',
    keywords: ['ITT', 'per-protocol', 'missing data', 'dropout']
  },
  '选择性报告': {
    sections: ['methods', 'results', 'supplementary'],
    maxTokens: 3000,
    priority: 'medium',
    checkTrialRegistry: true  // 对比注册方案
  },
  '其他偏倚': {
    sections: ['methods', 'discussion', 'supplementary'],
    maxTokens: 3000,
    priority: 'medium'
  }
};

// 分段并行提取
async function extractAllFields(sections: ParsedSections) {
  const extractionTasks = Object.entries(FIELD_EXTRACTION_ROUTES).map(
    ([fieldName, config]) => ({
      field: fieldName,
      task: extractFieldWithEvidence(fieldName, sections, config)
    })
  );
  
  // 并行执行(降低延迟)
  const results = await Promise.all(
    extractionTasks.map(t => t.task)
  );
  
  return results;
}

优势

  • 避免中间信息遗漏(准确率 70% → 90%
  • Token消耗降低40%20K → 12K
  • 并行提取延迟降低60%
  • 每个字段LLM注意力更集中

1.3 双模型交叉验证

模型组合DeepSeek-V3 + Qwen3-Max成本友好

// 双模型并行调用
async function dualModelExtraction(
  fieldName: string,
  relevantContent: string,
  prompt: string
) {
  const [resultA, resultB] = await Promise.all([
    llmService.chat('deepseek-v3', prompt, relevantContent),
    llmService.chat('qwen-max', prompt, relevantContent)
  ]);
  
  // 解析结果
  const assessmentA = parseFieldAssessment(resultA);
  const assessmentB = parseFieldAssessment(resultB);
  
  // 冲突检测
  const hasConflict = assessmentA.level !== assessmentB.level;
  
  return {
    field: fieldName,
    modelA: {
      model: 'deepseek-v3',
      assessment: assessmentA.level,  // '完整'/'不完整'/'无法判断'
      evidence: assessmentA.evidence,
      confidence: assessmentA.confidence
    },
    modelB: {
      model: 'qwen-max',
      assessment: assessmentB.level,
      evidence: assessmentB.evidence,
      confidence: assessmentB.confidence
    },
    hasConflict,
    needReview: hasConflict || 
                assessmentA.confidence < 0.7 || 
                assessmentB.confidence < 0.7
  };
}

1.4 字段级冲突检测与分级复核

不是简单的"全部冲突就人工复核",而是根据字段重要性分级

// 字段重要性分级
const FIELD_IMPORTANCE = {
  critical: ['随机化方法', '盲法', '结果完整性'],      // 核心偏倚风险
  high: ['研究设计', '研究人群', '干预措施', '结局指标', '基线可比性'],
  medium: ['样本量计算', '选择性报告', '其他偏倚']
};

// 智能分流
function prioritizeReview(conflicts: FieldConflict[]): ReviewQueue {
  const queue = {
    urgent: [],      // 关键字段冲突 → 立即人工复核
    important: [],   // 高优先级字段冲突 → 24小时内复核
    normal: []       // 中等优先级字段冲突 → 48小时内复核
  };
  
  for (const conflict of conflicts) {
    if (!conflict.hasConflict) continue;
    
    if (FIELD_IMPORTANCE.critical.includes(conflict.field)) {
      queue.urgent.push({
        ...conflict,
        reason: '关键方法学字段冲突,影响偏倚风险评估',
        deadline: new Date(Date.now() + 2 * 3600 * 1000) // 2小时
      });
    } else if (FIELD_IMPORTANCE.high.includes(conflict.field)) {
      queue.important.push({
        ...conflict,
        reason: '高优先级字段冲突',
        deadline: new Date(Date.now() + 24 * 3600 * 1000) // 24小时
      });
    } else {
      queue.normal.push({
        ...conflict,
        reason: '一般字段冲突',
        deadline: new Date(Date.now() + 48 * 3600 * 1000) // 48小时
      });
    }
  }
  
  return queue;
}

1.5 基础证据链(原文引用)

MVP阶段要求:每个字段必须有原文引用

interface FieldEvidence {
  field: string;
  assessment: '完整' | '不完整' | '无法判断';
  
  // ⭐ 强制要求
  evidence: {
    quote: string;           // 原文引用100-300字
    location: {
      section: string;       // "Methods"
      page?: number;         // 3如果PDF有页码
      paragraph?: number;    // 2
      table?: string;        // "Table 1"
      figure?: string;       // "Figure 1"
    };
    highlightedKeywords: string[];  // 关键信号词
  };
  
  reasoning: string;        // 判断理由50-200字
  confidence: number;       // 0.0-1.0
}

// 后处理验证:确保每个字段都有证据
function validateEvidence(result: ExtractionResult): ValidationReport {
  const errors = [];
  
  for (const [field, data] of Object.entries(result.fields)) {
    // 检查1必须有引用
    if (!data.evidence?.quote) {
      errors.push({
        field,
        type: 'missing_evidence',
        message: `字段"${field}"缺少原文引用`
      });
    }
    
    // 检查2引用不能太短避免敷衍
    if (data.evidence?.quote && data.evidence.quote.length < 50) {
      errors.push({
        field,
        type: 'insufficient_evidence',
        message: `字段"${field}"的引用过短(<50字可能不足以支持判断`
      });
    }
    
    // 检查3必须有位置信息
    if (!data.evidence?.location?.section) {
      errors.push({
        field,
        type: 'missing_location',
        message: `字段"${field}"未标注原文位置`
      });
    }
  }
  
  return {
    isValid: errors.length === 0,
    errors,
    completeness: 1 - (errors.length / (Object.keys(result.fields).length * 3))
  };
}

二、12字段专业Prompt模板MVP版

示例:随机化方法(关键字段)

# 字段提取任务:随机化方法

## 背景说明
你是一位循证医学专家正在评估一篇RCT研究的方法学质量。
请根据Cochrane偏倚风险评估工具RoB 2.0)的标准,判断该研究的随机化方法是否充分。

## 待分析内容
以下是论文的Methods章节和相关图表

${relevantContent}

## 判断标准

### 完整Low risk of bias
需**同时满足**以下条件:
1. ✅ 明确说明随机序列生成方法
   - 示例computer-generated random sequence, random number table, 
           central randomization, minimization
2. ✅ 说明分配隐藏方法
   - 示例sealed opaque envelopes, central allocation, 
           pharmacy-controlled, IWRS (Interactive Web Response System)
3. ✅ 无选择偏倚的证据
   - 基线特征平衡
   - 无异常的入组时间模式

### 不完整High/Unclear risk of bias
以下情况判定为不完整:
- ❌ 仅提到"随机分组"但无具体方法
- ❌ 使用不当的随机化方法(按日期、住院号、交替分配)
- ❌ 无分配隐藏或分配隐藏不当(开放分配表)
- ❌ 基线存在显著不平衡且无调整
- ⚠️ 方法描述模糊,无法判断充分性

### 无法判断Unclear risk
- 论文完全未提及随机化方法
- 仅在其他地方(如注册方案)提到,但本文未描述

## 关键信号词

**高质量信号(完整)**
- "computer-generated random sequence"
- "central randomization/allocation"
- "sealed opaque envelopes"
- "stratified randomization"
- "block randomization"
- "minimization"
- "allocation concealment"

**风险信号(不完整)**
- "alternating allocation"
- "by date of birth"
- "by hospital number"
- "open allocation"
- "assigned by investigator"

## 提取指南

1. **优先查找位置**
   - Methods章节的"Randomization"小节
   - Figure 1 (CONSORT流程图)
   - Trial Registration信息
   - 补充材料Supplementary Materials

2. **交叉验证**
   - Methods描述 vs. Results中的基线数据
   - 声称的方法 vs. 实际的基线平衡情况

3. **特殊情况**
   - 如果提到"see protocol"或"see trial registration",标记为需要查阅外部资料
   - 如果是多中心研究,应该有中心随机化系统

## 输出格式严格JSON

{
  "assessment": "完整" | "不完整" | "无法判断",
  "evidence": {
    "quote": "原文引用100-300字包含关键方法描述",
    "location": {
      "section": "Methods",
      "subsection": "Randomization",
      "page": 3,
      "paragraph": 2,
      "figure": "Figure 1 (CONSORT diagram)"
    },
    "highlightedKeywords": [
      "关键词1",
      "关键词2"
    ]
  },
  "reasoning": "判断理由:根据原文引用,该研究...",
  "confidence": 0.95,
  "robAssessment": "Low risk" | "High risk" | "Unclear risk",
  "needsExternalVerification": false,
  "notes": "其他说明(可选)"
}

## 注意事项

1. **严格遵守Cochrane标准**:宁可判断为"不完整",不要过于宽松
2. **引用必须具体**:不要笼统地说"Methods章节提到",必须给出具体引用
3. **置信度诚实**如果信息不清晰降低confidence并标记needsExternalVerification
4. **区分"未做"和"未报告"**
   - 如果论文明确说"no randomization"assessment="不完整"
   - 如果论文完全未提及assessment="无法判断"

其他11个字段的Prompt模板类似结构根据Cochrane标准调整判断标准


三、MVP成本预算

场景100篇全文复筛

环节 Token消耗 模型 成本
Nougat提取 - 本地模型 ¥0
12字段提取双模型 12K × 2 = 24K DeepSeek-V3 + Qwen3-Max ¥0.06/篇
冲突字段人工复核20% - 人工 2分钟/字段
100篇总成本 - - ¥6 + 人工成本

对比

  • 全文一次性提取¥10/100篇
  • 分段提取¥6/100篇
  • 节省40%成本 + 准确率提升

四、MVP验收标准

指标 目标 验证方法
字段提取完整率 ≥ 90% 12字段都有结果非"无法判断"
双模型一致率 ≥ 75% 12字段中至少9个一致
证据链完整性 100% 每个字段都有原文引用和位置
人工复核队列 ≤ 30% 需要人工介入的文献占比
Nougat成功率 ≥ 85% 英文论文成功提取比例
处理速度 ≤ 3分钟/篇 从PDF到结果的总时长

📈 V1.0 阶段5 周)

目标定位

  • 准确率目标:≥ 92%
  • 信息完整率:≥ 95%
  • 成本预算:≤ ¥0.08/篇(智能成本优化)
  • 交付标准:高质量输出,完整证据链,智能质量控制

一、质量提升策略

1.1 Cochrane标准Prompt增强

在MVP基础上增加

  1. Few-shot医学案例每个字段3-5个真实案例
## 参考案例

以下是3个真实RCT研究的随机化方法评估案例帮助你理解判断标准

### 案例1高质量RCTNEJM, 2023
**原文引用**
"Randomization was performed with the use of a computer-generated sequence 
with stratification according to center and baseline NIHSS score (≤10 or >10). 
Allocation was concealed through a central web-based system (IWRS)."

**评估结果**:完整
**理由**
1. ✅ 明确的序列生成方法computer-generated
2. ✅ 分层随机化(提高平衡性)
3. ✅ 中心分配隐藏IWRS
4. ✅ 基线Table 1显示两组平衡良好P>0.05
**RoB 2.0判断**Low risk of bias

---

### 案例2质量不足某期刊, 2020
**原文引用**
"Patients were randomly assigned to receive either drug A or placebo 
in a 1:1 ratio. Randomization was performed by the study coordinator."

**评估结果**:不完整
**理由**
1. ❌ 未说明序列生成方法(仅说"随机"
2. ❌ 由研究协调员执行随机化(无分配隐藏)
3. ⚠️ Table 1显示对照组年龄偏大66.2 vs 62.1, P=0.04
**RoB 2.0判断**High risk of bias
**问题**:可能存在选择偏倚

---

### 案例3边界情况Lancet, 2021
**原文引用**
"Randomization was done with sequentially numbered, opaque, sealed envelopes 
prepared by an independent statistician not otherwise involved in the trial."

**评估结果**:完整
**理由**
1. ✅ 虽非中心随机化,但使用密封信封
2. ✅ 独立第三方准备(统计师)
3. ✅ 不透光opaque且密封sealed
4. ✅ 基线平衡良好
**RoB 2.0判断**Low risk of bias
**说明**符合Cochrane标准密封信封 + 独立准备可接受)

---

现在请你参考以上案例的评估方式,分析当前论文...
  1. Chain of Thought推理
## 输出格式(增强版)

{
  "assessment": "完整",
  
  // ⭐ 新增:逐步推理过程
  "reasoning_steps": {
    "step1_sequenceGeneration": {
      "finding": "论文提到'computer-generated random sequence'",
      "evaluation": "满足序列生成方法要求 ✅"
    },
    "step2_allocationConcealment": {
      "finding": "使用'central web-based system (IWRS)'",
      "evaluation": "满足分配隐藏要求 ✅"
    },
    "step3_baselineBalance": {
      "finding": "Table 1显示主要特征P>0.05",
      "evaluation": "无明显选择偏倚证据 ✅"
    },
    "step4_finalJudgment": {
      "conclusion": "三项标准均满足,判断为'完整'",
      "confidence": 0.95
    }
  },
  
  "evidence": { ... },
  "robAssessment": "Low risk"
}

1.2 全文交叉验证(防遗漏)

在分段提取后,增加全文验证环节

// 阶段1分段提取已完成
const segmentedResults = await extractAllFieldsSegmented(sections);

// ⭐ 阶段2全文交叉验证新增
async function crossValidateWithFullText(
  segmentedResults: FieldResult[],
  fullTextMarkdown: string
): Promise<ValidationReport> {
  
  // 验证1检查是否有遗漏信息
  const missingInfoChecks = await Promise.all([
    checkForMissingInfo('随机化方法', fullTextMarkdown, segmentedResults),
    checkForMissingInfo('盲法', fullTextMarkdown, segmentedResults),
    // ... 其他关键字段
  ]);
  
  // 验证2检查是否有矛盾信息
  const contradictionChecks = await checkContradictions(
    segmentedResults,
    fullTextMarkdown
  );
  
  // 验证3检查是否提到补充材料
  const supplementaryCheck = checkSupplementaryMaterial(fullTextMarkdown);
  
  return {
    missingInfoAlerts: missingInfoChecks.filter(c => c.hasIssue),
    contradictions: contradictionChecks,
    needsSupplementary: supplementaryCheck.needsExternal,
    overallCompleteness: calculateCompleteness(...)
  };
}

// 示例:检查遗漏信息
async function checkForMissingInfo(
  field: string,
  fullText: string,
  extractedResult: FieldResult
): Promise<ValidationAlert> {
  
  // 如果已经判定为"完整",跳过
  if (extractedResult.assessment === '完整') {
    return { field, hasIssue: false };
  }
  
  // 在全文中搜索关键词
  const keywords = FIELD_KEYWORDS[field];  // 预定义关键词表
  const foundKeywords = keywords.filter(kw => 
    fullText.toLowerCase().includes(kw.toLowerCase())
  );
  
  // 如果全文中有关键词,但提取结果是"无法判断"
  if (foundKeywords.length > 0 && extractedResult.assessment === '无法判断') {
    return {
      field,
      hasIssue: true,
      severity: 'warning',
      message: `全文中发现关键词【${foundKeywords.join(', ')}】,
                但字段"${field}"判断为"无法判断",可能存在遗漏`,
      suggestedAction: 'targeted_re_extraction',
      keywords: foundKeywords
    };
  }
  
  return { field, hasIssue: false };
}

效果

  • 遗漏信息检出率0% → 80%
  • 准确率提升85% → 92%

1.3 医学逻辑规则引擎

自动检查常见的逻辑错误

const MEDICAL_LOGIC_RULES = [
  {
    id: 'rule_001',
    name: 'RCT必须有随机化',
    check: (data) => {
      const isRCT = data.研究设计.toLowerCase().includes('rct') ||
                    data.研究设计.includes('随机');
      const hasRandomization = data.随机化方法 !== '无法判断';
      return !isRCT || hasRandomization;
    },
    severity: 'error',
    message: '研究声称是RCT但未找到随机化方法描述',
    action: 'flag_for_urgent_review'
  },
  
  {
    id: 'rule_002',
    name: '双盲研究必须说明盲法',
    check: (data) => {
      const isDoubleBlind = data.研究设计.includes('双盲') ||
                            data.研究设计.includes('double-blind');
      const hasBlinding = data.盲法 !== '无法判断' && 
                          data.盲法 !== '不完整';
      return !isDoubleBlind || hasBlinding;
    },
    severity: 'error',
    message: '声称双盲但盲法描述不完整',
    action: 'flag_for_review'
  },
  
  {
    id: 'rule_003',
    name: '样本量与基线数据一致性',
    check: (data) => {
      const planned = extractNumber(data.样本量计算);
      const enrolled = extractNumber(data.研究人群);
      if (!planned || !enrolled) return true;  // 无法提取则跳过
      
      const deviation = Math.abs(planned - enrolled) / planned;
      return deviation < 0.3;  // 偏差<30%
    },
    severity: 'warning',
    message: '计划样本量与实际入组差异较大(>30%)',
    action: 'add_note'
  },
  
  {
    id: 'rule_004',
    name: '基线不平衡需要调整',
    check: (data) => {
      const hasImbalance = data.基线可比性.includes('不平衡') ||
                          data.基线可比性.includes('P<0.05');
      const hasAdjustment = data.结局指标.includes('调整') ||
                           data.结局指标.includes('adjusted');
      return !hasImbalance || hasAdjustment;
    },
    severity: 'warning',
    message: '基线存在不平衡但未见调整分析',
    action: 'add_note'
  },
  
  {
    id: 'rule_005',
    name: 'ITT分析完整性',
    check: (data) => {
      const hasDropout = extractNumber(data.结果完整性) > 0;
      const hasITT = data.结果完整性.toLowerCase().includes('itt') ||
                    data.结果完整性.includes('intention-to-treat');
      return !hasDropout || hasITT;
    },
    severity: 'warning',
    message: '存在失访但未明确ITT分析',
    action: 'flag_for_review'
  }
];

// 自动验证
function validateMedicalLogic(extractedData: ExtractionResult): LogicReport {
  const violations = [];
  
  for (const rule of MEDICAL_LOGIC_RULES) {
    try {
      const passed = rule.check(extractedData);
      if (!passed) {
        violations.push({
          ruleId: rule.id,
          ruleName: rule.name,
          severity: rule.severity,
          message: rule.message,
          action: rule.action
        });
      }
    } catch (error) {
      console.error(`规则${rule.id}执行失败:`, error);
    }
  }
  
  return {
    totalRules: MEDICAL_LOGIC_RULES.length,
    passedRules: MEDICAL_LOGIC_RULES.length - violations.length,
    violations,
    overallValidity: violations.filter(v => v.severity === 'error').length === 0
  };
}

1.4 完整证据链(增强版)

V1.0要求:不仅有引用,还要有具体定位和高亮

interface EnhancedEvidence {
  field: string;
  assessment: string;
  
  evidence: {
    // 主要证据
    primaryQuote: {
      text: string;              // 原文引用
      location: {
        section: string;         // "Methods"
        subsection?: string;     // "Randomization"
        page: number;            // 3
        paragraph: number;       // 2
        lineRange?: [number, number];  // [45, 52]
      };
      highlightedText: string;   // HTML高亮版本
      keywords: string[];        // 关键词列表
    };
    
    // 支持证据(可选)
    supportingQuotes?: Array<{
      text: string;
      location: any;
      relation: string;  // "confirms" | "contradicts" | "complements"
    }>;
    
    // 表格/图片证据
    tableEvidence?: {
      tableName: string;         // "Table 1"
      relevantCells: string[];   // 相关单元格内容
      interpretation: string;    // 对表格的解读
    };
    
    figureEvidence?: {
      figureName: string;        // "Figure 1"
      caption: string;
      relevantInfo: string;
    };
  };
  
  // ⭐ 新增:完整推理链
  reasoningChain: {
    cochraneCriteria: string[];  // 应用的Cochrane标准
    keyFindings: string[];       // 关键发现
    assessment: string;          // 最终判断
    confidence: number;
    uncertainties?: string[];    // 不确定因素
  };
  
  // ⭐ 新增:可追溯性元数据
  metadata: {
    extractionTimestamp: string;
    modelUsed: string;
    promptVersion: string;
    processingTime: number;
  };
}

二、V1.0成本预算

场景100篇全文复筛

环节 Token消耗 模型 成本
12字段分段提取双模型 12K DeepSeek-V3 + Qwen3-Max ¥0.06/篇
全文交叉验证 3K DeepSeek-V3 ¥0.003/篇
关键字段补充提取20% 2K Qwen3-Max ¥0.016/篇仅20%文献)
100篇总成本 - - ¥7.9

质量提升:准确率 85% → 92%
成本增加¥6 → ¥8+33%,但质量显著提升)


三、V1.0验收标准

指标 目标 验证方法
准确率(人工抽查) ≥ 92% 随机抽查50篇专家评估
信息完整率 ≥ 95% 12字段均有有效结果
证据链完整性 100% 每个字段有详细证据和推理链
遗漏信息检出率 ≥ 80% 交叉验证发现的遗漏比例
逻辑规则覆盖率 ≥ 80% 规则引擎检查通过率
人工复核队列 ≤ 25% 需要人工介入的文献占比

🏆 V2.0 阶段8 周)

目标定位

  • 准确率目标:≥ 96%(医学级标准)
  • 人机一致性Cohen's Kappa ≥ 0.90
  • 成本预算:按需配置(质量优先)
  • 交付标准自动化质量审计符合Cochrane发表标准

一、医学级质量保障

1.1 三模型仲裁机制

关键字段冲突时,启用第三方仲裁

async function threeModelArbitration(
  conflict: FieldConflict,
  relevantContent: string
) {
  
  // 第三方仲裁Claude-4.5(高质量模型)
  const arbitrationPrompt = `
你是Cochrane系统评价专家现有两个AI模型对同一字段的判断存在冲突
请你从循证医学的角度给出权威判断。

【冲突字段】:${conflict.field}

【模型A判断】${conflict.modelA.assessment}
证据:${conflict.modelA.evidence.quote}
理由:${conflict.modelA.reasoning}
置信度:${conflict.modelA.confidence}

【模型B判断】${conflict.modelB.assessment}
证据:${conflict.modelB.evidence.quote}
理由:${conflict.modelB.reasoning}
置信度:${conflict.modelB.confidence}

【原文】:
${relevantContent}

【仲裁任务】:
1. 根据Cochrane RoB 2.0标准,给出你的判断
2. 分析两个模型的判断,指出哪个更准确(或都不准确)
3. 引用Cochrane手册相关条款支持你的判断
4. 如果仍不确定,明确指出需要人工复核的原因

【输出格式】JSON
  `;
  
  const arbitrationResult = await llmService.chat(
    'claude-4.5',
    arbitrationPrompt
  );
  
  return {
    field: conflict.field,
    arbitrator: 'claude-4.5',
    finalJudgment: arbitrationResult.assessment,
    analysis: {
      modelAAccuracy: arbitrationResult.modelA_correct,
      modelBAccuracy: arbitrationResult.modelB_correct,
      correctModel: arbitrationResult.agree_with,
      cochraneCitation: arbitrationResult.cochrane_reference
    },
    confidence: arbitrationResult.confidence,
    stillNeedsHumanReview: arbitrationResult.confidence < 0.9
  };
}

成本控制

  • 仅在关键字段冲突时启用预计10-15%
  • 单次仲裁成本¥0.02Claude-4.5
  • 100篇总额外成本¥2-3

1.2 HITL智能分流

基于规则的智能优先级排序

function intelligentTriage(
  extractionResult: ExtractionResult,
  validationReport: ValidationReport,
  arbitrationResults?: ArbitrationResult[]
): TriageDecision {
  
  let priority = 0;
  let needReview = false;
  const reasons = [];
  
  // 规则1三模型仍不一致 → 最高优先级
  if (arbitrationResults?.some(a => a.stillNeedsHumanReview)) {
    priority = 100;
    needReview = true;
    reasons.push('三模型仲裁后仍存在不确定性');
  }
  
  // 规则2关键字段质量问题 → 高优先级
  const criticalIssues = validationReport.violations.filter(v =>
    v.severity === 'error' && 
    FIELD_IMPORTANCE.critical.includes(v.field)
  );
  if (criticalIssues.length > 0) {
    priority = Math.max(priority, 90);
    needReview = true;
    reasons.push(`关键字段存在质量问题: ${criticalIssues.map(i => i.field).join(', ')}`);
  }
  
  // 规则3RCT研究 → 中等优先级(质量要求高)
  if (extractionResult.研究设计.includes('RCT')) {
    priority = Math.max(priority, 70);
    // RCT如果置信度低才需要复核
    if (extractionResult.overallConfidence < 0.9) {
      needReview = true;
      reasons.push('RCT研究但整体置信度低于0.9');
    }
  }
  
  // 规则4关键结局指标死亡率→ 高优先级
  if (extractionResult.结局指标.includes('死亡') || 
      extractionResult.结局指标.includes('mortality')) {
    priority = Math.max(priority, 80);
    if (extractionResult.结果完整性 !== '完整') {
      needReview = true;
      reasons.push('关键结局指标(死亡率)但结果完整性有问题');
    }
  }
  
  // 规则5高置信度 + 无冲突 → 自动通过
  if (extractionResult.overallConfidence > 0.95 && 
      validationReport.violations.length === 0 &&
      !arbitrationResults) {
    priority = 10;
    needReview = false;
    reasons.push('高质量提取,无需人工复核');
  }
  
  // 规则6发表在顶级期刊 → 降低复核优先级
  const topJournals = ['NEJM', 'Lancet', 'JAMA', 'BMJ'];
  if (topJournals.some(j => extractionResult.metadata.journal?.includes(j))) {
    priority = Math.max(0, priority - 20);
    reasons.push('发表在顶级期刊,方法学质量通常较高');
  }
  
  return {
    priority,
    needReview,
    reasons,
    estimatedReviewTime: estimateReviewTime(extractionResult, needReview),
    reviewDeadline: calculateDeadline(priority)
  };
}

1.3 自动质量审计

定期批量抽查10%),自动生成质量报告

// 每周自动审计
async function weeklyQualityAudit(
  startDate: Date,
  endDate: Date
): Promise<QualityAuditReport> {
  
  // 1. 获取本周所有提取结果
  const weeklyExtractions = await db.fulltextScreeningResults.findMany({
    where: {
      createdAt: { gte: startDate, lte: endDate }
    }
  });
  
  // 2. 随机抽样10%
  const sampleSize = Math.ceil(weeklyExtractions.length * 0.1);
  const sample = randomSample(weeklyExtractions, sampleSize);
  
  // 3. 人工复核样本
  const humanReviews = await requestHumanReview(sample);
  
  // 4. 计算质量指标
  const metrics = {
    准确率: calculateAccuracy(sample, humanReviews),
    人机一致性: calculateCohenKappa(sample, humanReviews),
    假阳性率: calculateFalsePositiveRate(sample, humanReviews),
    假阴性率: calculateFalseNegativeRate(sample, humanReviews),
    
    // 分字段准确率
    字段准确率: FIELD_LIST.map(field => ({
      field,
      accuracy: calculateFieldAccuracy(field, sample, humanReviews)
    }))
  };
  
  // 5. 模型性能对比
  const modelPerformance = {
    'deepseek-v3': analyzeModelPerformance('deepseek-v3', sample, humanReviews),
    'qwen-max': analyzeModelPerformance('qwen-max', sample, humanReviews),
    'claude-4.5': analyzeModelPerformance('claude-4.5', sample, humanReviews)
  };
  
  // 6. 问题分析
  const issues = identifyCommonIssues(sample, humanReviews);
  
  // 7. 改进建议
  const recommendations = generateRecommendations(metrics, issues);
  
  return {
    period: { start: startDate, end: endDate },
    totalExtractions: weeklyExtractions.length,
    sampledExtractions: sampleSize,
    metrics,
    modelPerformance,
    issues,
    recommendations,
    generatedAt: new Date()
  };
}

// 自动识别常见问题
function identifyCommonIssues(
  sample: Extraction[],
  humanReviews: HumanReview[]
): Issue[] {
  
  const issues = [];
  
  // 问题1某个字段错误率高
  for (const field of FIELD_LIST) {
    const fieldErrors = countFieldErrors(field, sample, humanReviews);
    if (fieldErrors / sample.length > 0.15) {  // 错误率>15%
      issues.push({
        type: 'high_field_error_rate',
        field,
        errorRate: fieldErrors / sample.length,
        examples: getErrorExamples(field, sample, humanReviews, 3),
        recommendation: `优化字段"${field}"的Prompt模板或Few-shot案例`
      });
    }
  }
  
  // 问题2特定类型研究错误率高
  const studyTypeErrors = analyzeByStudyType(sample, humanReviews);
  for (const [studyType, errorRate] of Object.entries(studyTypeErrors)) {
    if (errorRate > 0.15) {
      issues.push({
        type: 'high_study_type_error_rate',
        studyType,
        errorRate,
        recommendation: `增加"${studyType}"类型研究的Few-shot案例`
      });
    }
  }
  
  // 问题3特定模型表现差
  const modelErrors = analyzeByModel(sample, humanReviews);
  for (const [model, errorRate] of Object.entries(modelErrors)) {
    if (errorRate > 0.15) {
      issues.push({
        type: 'model_underperformance',
        model,
        errorRate,
        recommendation: `考虑调整模型"${model}"的参数或更换模型`
      });
    }
  }
  
  return issues;
}

质量报表示例

# 全文复筛质量审计报告

**审计周期**2025-11-15 至 2025-11-22  
**总提取数**148篇  
**抽样数**15篇10.1%

## 整体质量指标

| 指标 | 本周 | 上周 | 趋势 |
|------|------|------|------|
| 准确率 | 94.7% | 93.2% | ↑ +1.5% |
| Cohen's Kappa | 0.89 | 0.87 | ↑ +0.02 |
| 假阳性率 | 3.1% | 4.2% | ↓ -1.1% |
| 假阴性率 | 2.2% | 2.6% | ↓ -0.4% |

## 分字段准确率

| 字段 | 准确率 | 状态 |
|------|--------|------|
| 研究设计 | 100% | ✅ 优秀 |
| 随机化方法 | 93.3% | ✅ 良好 |
| 盲法 | 86.7% | ⚠️ 需改进 |
| 基线可比性 | 100% | ✅ 优秀 |
| 结果完整性 | 93.3% | ✅ 良好 |
| ... | ... | ... |

## 模型性能对比

| 模型 | 准确率 | 平均置信度 | 处理时间 |
|------|--------|-----------|----------|
| DeepSeek-V3 | 92.1% | 0.87 | 45s |
| Qwen3-Max | 94.5% | 0.91 | 38s |
| Claude-4.5(仲裁) | 97.2% | 0.94 | 62s |

## 发现的问题

1. **字段"盲法"错误率偏高13.3%**
   - 常见错误:将"单盲"误判为"完整"
   - 原因分析Prompt未明确区分单盲/双盲的质量差异
   - 改进建议更新Prompt增加"单盲通常不足以防止检测偏倚"的说明

2. **队列研究提取准确率低于RCT89% vs 96%**
   - 原因分析:队列研究的方法学描述更灵活,标准化程度低
   - 改进建议增加3个队列研究的Few-shot案例

## 改进建议

1. ✅ 立即执行:更新"盲法"字段Prompt模板
2. ⚡ 本周内增加队列研究Few-shot案例库
3. 📅 下周:重新评估"盲法"字段准确率

## 下周目标

- 准确率:≥ 95%
- Cohen's Kappa≥ 0.90
- "盲法"字段准确率:≥ 93%

1.4 Prompt版本管理

Git管理提示词模板支持A/B测试

backend/prompts/asl/fulltext_screening/
├── changelog.md
├── fields/
│   ├── 随机化方法/
│   │   ├── v1.0.0-basic.md
│   │   ├── v1.1.0-with-examples.md
│   │   ├── v1.2.0-cot.md
│   │   └── v1.3.0-enhanced-cochrane.md  ← 当前版本
│   ├── 盲法/
│   │   ├── v1.0.0-basic.md
│   │   ├── v1.1.0-clarify-single-double.md  ← 改进版
│   │   └── ...
│   └── ...
└── tests/
    └── benchmark_results.json

数据库记录

model PromptVersion {
  id              String   @id @default(uuid())
  
  field           String   // "随机化方法"
  version         String   // "v1.3.0"
  content         String   @db.Text
  changelog       String   // "增强Cochrane标准描述添加5个Few-shot案例"
  
  // 性能指标A/B测试结果
  accuracy        Float?   // 0.947
  usageCount      Int      @default(0)
  avgConfidence   Float?
  
  // 状态
  isActive        Boolean  @default(false)
  isExperimental  Boolean  @default(false)
  
  createdAt       DateTime @default(now())
  deactivatedAt   DateTime?
  
  @@map("asl_prompt_versions")
}

A/B测试

// 20%流量使用新版Prompt
async function extractFieldWithABTest(
  field: string,
  content: string
) {
  const isExperimentGroup = Math.random() < 0.2;
  
  const promptVersion = isExperimentGroup
    ? await getPromptVersion(field, 'experimental')
    : await getPromptVersion(field, 'stable');
  
  const result = await llmService.chat(
    'deepseek-v3',
    promptVersion.content,
    content
  );
  
  // 记录使用
  await trackPromptUsage({
    field,
    version: promptVersion.version,
    isExperiment: isExperimentGroup,
    result
  });
  
  return result;
}

// 每周分析A/B测试结果
async function analyzeABTest(field: string): Promise<ABTestReport> {
  const stableResults = await getPromptUsageStats(field, 'stable');
  const experimentResults = await getPromptUsageStats(field, 'experimental');
  
  const improvement = {
    accuracy: experimentResults.accuracy - stableResults.accuracy,
    confidence: experimentResults.avgConfidence - stableResults.avgConfidence,
    processingTime: experimentResults.avgTime - stableResults.avgTime
  };
  
  // 统计显著性检验
  const isSignificant = performTTest(stableResults, experimentResults);
  
  return {
    field,
    stableVersion: stableResults.version,
    experimentVersion: experimentResults.version,
    sampleSize: {
      stable: stableResults.count,
      experiment: experimentResults.count
    },
    improvement,
    isSignificant,
    recommendation: isSignificant && improvement.accuracy > 0.02
      ? 'promote_to_stable'  // 提升为稳定版
      : 'continue_testing'   // 继续测试
  };
}

二、V2.0成本预算

场景100篇全文复筛高质量项目

环节 Token消耗 模型 成本
12字段分段提取双模型 12K DeepSeek-V3 + Qwen3-Max ¥0.06/篇
全文交叉验证 3K DeepSeek-V3 ¥0.003/篇
关键字段三模型仲裁15% 3K Claude-4.5 ¥0.03/篇仅15%
质量审计10%抽查) 2K 人工 10分钟/篇
100篇总成本 - - ¥10 + 人工成本

质量提升:准确率 92% → 96%
成本增加¥8 → ¥10+25%,但达到医学级标准)


三、V2.0验收标准

指标 目标 验证方法
准确率(专家评估) ≥ 96% 人工抽查100篇
人机一致性 Cohen's Kappa ≥ 0.90 统计分析
假阳性率 ≤ 3% 统计分析
假阴性率 ≤ 2% 统计分析
证据链完整性 100% 自动检查
自动化审计 每周1次 系统报表
Prompt版本管理 100% Git历史追踪
符合Cochrane标准 ≥ 95% 专家认证

📊 三阶段对比总结

维度 MVP V1.0 V2.0
准确率 85% 92% 96%
核心策略 Nougat+分段提取 +全文验证+逻辑规则 +三模型仲裁+审计
证据链 基本引用 完整定位 审计级日志
质量控制 双模型验证 医学逻辑引擎 HITL+自动审计
成本/100篇 ¥6 ¥8 ¥10
开发周期 3周 5周 8周
适用场景 快速验证 常规项目 Cochrane发表

🔄 实施路径

阶段1MVP开发Week 1-3

Week 1:基础架构

  • PDF存储服务已完成
  • Nougat提取+章节解析
  • 12字段路由表设计
  • 基础Prompt模板12个字段

Week 2:核心功能

  • 分段并行提取
  • 双模型调用
  • 字段级冲突检测
  • 基础证据链

Week 3:前端+测试

  • 前端工作台
  • 冲突对比视图
  • 人工复核界面
  • 功能测试+准确率评估

阶段2V1.0增强Week 4-8

Week 4-5:质量提升

  • Cochrane标准Prompt增强
  • Few-shot医学案例库每字段3-5个
  • CoT推理增强

Week 6-7:验证机制

  • 全文交叉验证
  • 医学逻辑规则引擎
  • 完整证据链

Week 8:优化+文档

  • 性能优化
  • A/B测试
  • 文档完善

阶段3V2.0完善Week 9-16

Week 9-11:高级功能

  • 三模型仲裁
  • HITL智能分流
  • Prompt版本管理+A/B测试

Week 12-14:质量审计

  • 自动审计系统
  • 质量报表
  • 异常检测

Week 15-16:医学专家验证

  • Cochrane专家评审
  • 全量测试
  • 发布文档

📚 相关文档


更新日志

  • 2025-11-22: 创建文档,定义全文复筛三阶段质量保障策略
  • 基于Nougat结构化+分段提取+全文验证的技术方案
  • 参考Cochrane RoB 2.0标准设计专业Prompt模板
  • 强调完整证据链和可追溯性