Summary: - Implement L2 Statistical Validator (CI-P consistency, T-test reverse) - Implement L2.5 Consistency Forensics (SE Triangle, SD>Mean check) - Add error/warning severity classification with tolerance thresholds - Support 5+ CI formats parsing (parentheses, brackets, 95% CI prefix) - Complete Python forensics service (types, config, validator, extractor) V2.0 Development Progress (Week 2 Day 6): - Day 1-5: Python service setup, Word table extraction, L1 arithmetic validator - Day 6: L2 StatValidator + L2.5 consistency forensics (promoted from V2.1) Test Results: - Unit tests: 4/4 passed (CI-P, SE Triangle, SD>Mean, T-test) - Real document tests: 5/5 successful, 2 reasonable WARNINGs Status: Day 6 completed, ready for Day 7 (Skills Framework) Co-authored-by: Cursor <cursoragent@cursor.com>
43 KiB
RVW V2.0 产品升级开发计划
文档版本: v1.2
创建日期: 2026-02-17
最后更新: 2026-02-17
维护者: 开发团队
项目代号: "数据侦探" + "柔性架构"
目标周期: 4周(含缓冲)
优先级: P0
审查状态: ✅ 已通过终审,纳入专家建议 (v1.2)
📋 目录
1. 项目概述
1.1 背景
当前 RVW 模块(V1.0/V3.2)是一个基于 LLM 的"文档阅读器",能较好地完成稿约规范性(11项标准)和方法学评估(20个检查点)。然而,在面对中文核心期刊(对政治安全和数据造假零容忍)和高水平英文期刊(对学术深度的要求)时,系统存在以下痛点:
| 痛点 | 影响 | 紧迫度 |
|---|---|---|
| 数据验证能力缺失 | 无法识别表格中的数据造假(P值捏造、合计错误) | 🔴 高 |
| 架构僵化 | 无法针对不同期刊配置不同的审稿流程 | 🟡 中 |
| PDF解析瓶颈 | 复杂表格在PDF中识别率低,导致计算不可行 | 🔴 高 |
1.2 升级策略
采用 "垂直切片 (Vertical Slice)" 策略,不追求大而全,集中兵力攻克核心技术壁垒:
- 以"数据侦探"功能为矛 —— 刺穿技术壁垒,实现Word表格的审计级验证
- 以"Skills架构"为盾 —— 构建系统底座,支持能力原子化和配置驱动
1.3 核心指标
| 指标 | 当前 | 目标 |
|---|---|---|
| 表格数据提取准确率 | ~70%(PDF) | ≥98%(Word) |
| 算术错误检出率 | 0% | ≥95% |
| P值逻辑错误检出率 | 0% | ≥80% |
| 上传到出报告时间 | ~2分钟 | ≤3分钟(含数据验证) |
2. 升级目标与范围
2.1 MVP 范围定义(V2.0)
| 维度 | ✅ MVP 包含 | ❌ MVP 不包含 |
|---|---|---|
| 文件格式 | Word (.docx) 仅支持 | .doc、PDF、图片扫描件 |
| 文件限制 | ≤ 20MB,单表 ≤ 500 行 | 超大文件、超长表格 |
| 表格类型 | 三线表 (Standard Tables) | 跨页断裂表、极复杂嵌套表 |
| 验证深度 | L1 (算术) + L2 (基础统计) + 🆕 L2.5 (一致性取证) | L3 (复杂回归逻辑)、L4 (跨表一致性) |
| 统计方法 | T检验、卡方检验、🆕 回归一致性(SE 三角验证)、SD>Mean 检查 | ANOVA、配对检验、生存分析、非参数检验 |
| Skill 数量 | DataForensicsSkill + EditorialSkill | 政治审查、竞品对标 |
| 配置方式 | 硬编码默认Profile | 动态Profile管理UI |
| 前端交互 | 静态报告(新增数据验证Tab) | 交互式Chat、在线修改表格 |
⚠️ 格式限制说明:MVP 阶段仅支持 .docx 格式。若用户上传 .doc 文件,前端提示"请使用 Word 另存为 .docx 格式后重新上传"。此决策基于 LibreOffice 容器化复杂度高、收益低的评估,V2.1 将评估 Pandoc 等替代方案。
2.2 与 V1.0 的关系
| 能力 | V1.0 | V2.0 |
|---|---|---|
| 稿约规范性评估(11项) | ✅ 保留 | ✅ 封装为 EditorialSkill |
| 方法学评估(20个检查点) | ✅ 保留 | ✅ 封装为 MethodologySkill |
| 数据表格验证 | ❌ 无 | ✅ 新增 DataForensicsSkill |
| Skills 架构 | ❌ 无 | ✅ 新增 |
| Word 导出 | ✅ 保留 | ✅ 保留 |
3. 技术架构设计
3.1 总体架构
┌─────────────────────────────────────────────────────────────────┐
│ 输入层 (Input Layer) │
│ 稿件 (Word/PDF) + 期刊配置 (Journal Profile) │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ Layer 1: 护栏中间件 (Middleware Guardrails) │
│ 🛡️ Pre-Hook: 格式校验、敏感词扫描(V2.1 政治审查) │
│ 🛡️ Post-Hook: 幻觉检测(V2.1) │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ Layer 2: 审稿编排引擎 (The Core) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Skills │ │ Skill │ │ Shared │ │
│ │ Registry │ │ Router │ │ Context │ │
│ │ 技能注册表 │ │ 动态路由 │ │ 共享上下文 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ Layer 3: 原子能力库 (Skills Library) │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ 🐍 DataForensics │ │ 📋 Editorial │ │
│ │ Skill │ │ Skill │ │
│ │ (Python计算) │ │ (稿约规范性) │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ 🔬 Methodology │ │ 🧠 MedicalLogic │ ← V2.1 │
│ │ Skill │ │ Skill │ │
│ │ (方法学评估) │ │ (常识校验) │ │
│ └──────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 输出层 (Output Layer) │
│ 📊 SOP 引擎(静态审稿报告) ← V2.0 MVP │
│ 💬 ReAct 引擎(交互式对话) ← V2.2 规划 │
└─────────────────────────────────────────────────────────────────┘
3.2 数据流图
┌─────────────────────────────────────────────────────────────────────────┐
│ 用户上传 .docx │
└─────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Node.js Backend (reviewService) │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ 1. 调用 Python 提取文本 (ExtractionClient, HTTP 120s) │ │
│ │ 2. 推送到 pg-boss 队列 (rvw_review_task) │ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
│
pg-boss 异步调度
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ reviewWorker (异步执行) │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ 3. DataForensicsSkill → 调用 Python API (HTTP 60s) │ │
│ │ 4. EditorialSkill → 调用 LLM │ │
│ │ 5. MethodologySkill → 调用 LLM │ │
│ │ 6. 汇总结果 → 存储到 ReviewTask.contextData │ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Python Service (extraction_service) │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ 现有: /api/extract/docx (文本提取, mammoth/python-docx) │ │
│ │ 🆕 新增: /api/v1/forensics/analyze_docx │ │
│ │ - python-docx 表格提取 │ │
│ │ - pandas 数据处理 │ │
│ │ - scipy 统计验证 (🆕 需新增依赖) │ │
│ │ - 返回 HTML 片段 + R1C1 坐标 │ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
通信机制说明:
| 通信路径 | 方式 | 超时 | 说明 |
|---|---|---|---|
| reviewService → pg-boss | 异步队列 | - | ✅ 已有,任务调度 |
| ExtractionClient → Python | HTTP 同步 | 60-120s | ✅ 已有,文本提取 |
| DataForensicsSkill → Python | HTTP 同步 | 60s | 🆕 新增,表格验证 |
📋 架构复用:V2.0 复用现有 pg-boss 异步架构,DataForensicsSkill 作为 reviewWorker 中的一个步骤执行,与 EditorialSkill/MethodologySkill 平级。
3.3 Skill 接口标准
// backend/src/modules/rvw/skills/core/types.ts
interface SkillContext {
taskId: string;
documentContent: string; // Markdown 格式的文档内容
documentPath?: string; // 原始文件路径(用于Python处理)
tables?: TableData[]; // 提取的表格数据
methods?: string[]; // 检测到的统计方法
previousResults?: SkillResult[]; // 前置Skill的结果
}
interface SkillResult {
skillId: string;
status: 'success' | 'warning' | 'error' | 'timeout'; // 新增 timeout 状态
score?: number; // 0-100 评分
issues: Issue[]; // 发现的问题列表
data?: any; // 结构化数据
executionTime: number; // 执行耗时(ms)
timedOut?: boolean; // 是否超时
}
interface Issue {
severity: 'ERROR' | 'WARNING' | 'INFO';
type: string; // 问题类型代码
message: string; // 人类可读描述
location?: { // 问题位置
tableId?: string;
cellRef?: string; // R1C1 坐标格式,如 "R3C4"
paragraph?: number;
};
evidence?: any; // 证据数据
}
interface Skill {
id: string;
name: string;
description: string;
timeout: number; // 🆕 超时时间(ms),默认 30000
run(context: SkillContext, config?: any): Promise<SkillResult>;
}
// 🆕 Skill 执行配置
interface SkillExecutionConfig {
defaultTimeout: number; // 默认 30000ms (30s)
maxRetries: number; // 默认 0(不重试)
continueOnError: boolean; // 单个 Skill 失败是否继续,默认 true
}
📋 R1C1 坐标系统:所有单元格位置使用 R1C1 格式(如
R3C4表示第3行第4列),确保前后端定位一致。前端根据此坐标直接高亮对应<td>元素。
3.4 Profile 配置结构
// MVP 阶段:硬编码默认配置
// V2.1 阶段:迁移到数据库
interface JournalProfile {
id: string;
name: string; // 如 "中华医学超声杂志"
skills: string[]; // 要执行的Skill列表
strictness: 'STRICT' | 'STANDARD' | 'LENIENT';
config?: {
dataForensics?: {
checkLevel: 'L1' | 'L1_L2' | 'L1_L2_L3';
tolerancePercent: number; // 容错百分比,默认 0.1
};
editorial?: {
// 稿约规范性配置
};
};
}
// MVP 默认 Profile
const DEFAULT_PROFILE: JournalProfile = {
id: 'default',
name: '通用期刊',
skills: ['DataForensicsSkill', 'EditorialSkill'],
strictness: 'STANDARD',
config: {
dataForensics: {
checkLevel: 'L1_L2',
tolerancePercent: 0.1
}
}
};
4. 功能需求详述
4.1 数据侦探 (DataForensicsSkill)
4.1.1 Word 表格精准提取
| 需求ID | 需求描述 | 优先级 |
|---|---|---|
| FR-1.1 | 识别 Word 文档中的所有表格对象 | P0 |
| FR-1.2 | 处理合并单元格(Forward Fill 策略) | P0 |
| FR-1.3 | 关联表格 Caption(向前回溯提取 "Table X. xxx") | P0 |
| FR-1.4 | 文件格式校验(仅接受 .docx,≤20MB) | P0 |
| FR-1.5 | 单表行数限制(≤500行,超出跳过并警告) | P1 |
⚠️ FR-1.4 变更说明:原计划通过 LibreOffice 支持 .doc 格式,经评估 Docker 容器化复杂度过高(需 headless 模式、字体配置、进程池管理),决定 MVP 阶段仅支持 .docx。.doc 支持推迟到 V2.1 评估 Pandoc 等替代方案。
合并单元格处理示例:
原始表格:
| Group A | Group B |
|-------|--------|---------|
| Male | Female | |
| 50 | 45 | 60 |
Forward Fill 后:
| Group A | Group A | Group B |
|---------|---------|---------|
| Male | Female | |
| 50 | 45 | 60 |
4.1.2 L1 算术自洽性验证
| 需求ID | 需求描述 | 优先级 |
|---|---|---|
| FR-2.1 | 识别 n (%) 格式,验证 n/N 是否等于 % | P0 |
| FR-2.2 | 识别 Total 列,验证是否等于其他列之和 | P0 |
| FR-2.3 | 容错范围:±0.1%(可配置) | P0 |
验证逻辑示例:
# 输入: "45 (50.0%)",Total N = 90
# 计算: 45 / 90 = 0.5 = 50.0% ✅ 通过
# 输入: "45 (60.0%)",Total N = 90
# 计算: 45 / 90 = 0.5 = 50.0% ≠ 60.0% ❌ 错误
4.1.3 L2 统计学复核
| 需求ID | 需求描述 | 支持状态 |
|---|---|---|
| FR-3.1 | 独立样本 T 检验 P 值逆向验证 | ✅ MVP |
| FR-3.2 | 卡方检验 P 值逆向验证 | ✅ MVP |
| FR-3.3 | CI 与 P 值逻辑一致性检查 | ✅ MVP |
| FR-3.4 | ANOVA 多组比较 | ❌ V2.1 |
| FR-3.5 | 配对 T 检验 / McNemar | ❌ V2.1 |
| FR-3.6 | 生存分析 (Log-rank, Cox) | ❌ V2.2 |
| FR-3.7 | 非参数检验 (Mann-Whitney, Wilcoxon) | ❌ V2.1 |
| FR-3.8 | 回归分析 (Logistic, Cox, Linear) | ❌ V2.2 |
CI 与 P 值逻辑检查(黄金法则):
对于 OR/HR/RR 数据:
- 若 95% CI 跨越 1.0(如 0.8-1.2)→ P 值必须 ≥ 0.05
- 若 95% CI 不跨越 1.0(如 1.1-1.5)→ P 值必须 < 0.05
违反此规则 = 数据逻辑矛盾,高度疑似造假
4.1.4 方法学定位(确定性规则优先)
采用正则匹配优先,LLM兜底的策略,减少幻觉风险:
# 确定性规则
METHOD_PATTERNS = {
"t-test": r"(t[\s-]?test|student.*test|independent.*sample|独立样本)",
"chi-square": r"(chi[\s-]?square|χ2|卡方|pearson.*chi)",
"anova": r"(anova|analysis\s+of\s+variance|方差分析)",
"logistic": r"(logistic\s+regression|逻辑回归|二元回归)",
"cox": r"(cox\s+regression|cox\s+proportional|生存分析|比例风险)",
"mann-whitney": r"(mann[\s-]?whitney|wilcoxon|秩和检验)",
}
def extract_methods(text: str) -> list:
"""优先使用正则匹配,仅在无结果时调用LLM"""
found = []
for method, pattern in METHOD_PATTERNS.items():
if re.search(pattern, text, re.IGNORECASE):
found.append(method)
# 如果正则无结果,可选调用LLM(V2.1增强)
if not found:
found = llm_extract_methods(text) # 兜底
return found
4.2 Skills 架构
4.2.1 Skill 注册与发现
| 需求ID | 需求描述 | 优先级 |
|---|---|---|
| FR-4.1 | 实现 SkillRegistry 注册表 | P0 |
| FR-4.2 | 支持 Skill 按 ID 获取 | P0 |
| FR-4.3 | 支持 Skill 列表查询 | P1 |
4.2.2 Skill 编排执行
| 需求ID | 需求描述 | 优先级 |
|---|---|---|
| FR-5.1 | 根据 Profile 依次执行 Skills | P0 |
| FR-5.2 | 前置 Skill 结果传递给后续 Skill | P0 |
| FR-5.3 | 单个 Skill 失败不影响其他 Skill | P0 |
| FR-5.4 | 执行结果汇总存储到 contextData | P0 |
| FR-5.5 | 🆕 Skill 执行超时熔断(30s) | P0 |
| FR-5.6 | 🆕 DataForensics 失败时降级执行 | P0 |
4.2.3 🆕 超时熔断机制
// backend/src/modules/rvw/skills/core/executor.ts
async function executeWithTimeout(skill: Skill, context: SkillContext): Promise<SkillResult> {
const timeout = skill.timeout || 30000; // 默认 30s
try {
const result = await Promise.race([
skill.run(context),
new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error('Skill execution timeout')), timeout)
)
]);
return result;
} catch (error) {
if (error.message === 'Skill execution timeout') {
logger.warn({ skillId: skill.id, timeout }, 'Skill execution timed out');
return {
skillId: skill.id,
status: 'timeout',
issues: [{
severity: 'WARNING',
type: 'SKILL_TIMEOUT',
message: `${skill.name} 执行超时,已跳过`
}],
executionTime: timeout,
timedOut: true
};
}
throw error;
}
}
4.2.4 🆕 Fallback 降级机制
当 DataForensicsSkill(Word 表格提取)失败时,系统不应完全中断,而是降级运行:
正常流程:
DataForensicsSkill ✅ → EditorialSkill → MethodologySkill → 完整报告
Fallback 流程(提取失败时):
DataForensicsSkill ❌ → EditorialSkill → MethodologySkill → 部分报告
↑
记录失败原因,报告中显示:
"数据验证功能暂不可用:[具体原因]
建议:请检查 Word 文件格式或联系管理员"
前端展示:
- 数据验证 Tab 显示警告状态(黄色)
- 清晰说明失败原因
- 不影响其他审稿结果的展示
4.3 前端展示
4.3.1 数据验证报告
| 需求ID | 需求描述 | 优先级 |
|---|---|---|
| FR-6.1 | TaskDetail 新增"数据验证"Tab | P0 |
| FR-6.2 | 🆕 直接渲染后端返回的 HTML 片段 | P0 |
| FR-6.3 | 错误列表展示(按严重程度排序) | P0 |
| FR-6.4 | 🆕 根据 R1C1 坐标高亮单元格 | P1 |
| FR-6.5 | 错误类型图标和颜色区分 | P1 |
| FR-6.6 | 🆕 提取失败时的降级展示 | P0 |
4.3.2 🆕 后端渲染一致性保障
为确保前端表格显示与后端数据提取 100% 一致,采用"后端渲染"策略:
// 后端返回的表格数据结构
interface TableRenderData {
id: string; // 表格ID
caption: string; // 表格标题
html: string; // 🆕 预渲染的 HTML 片段
data: string[][]; // 原始二维数组(备用)
issues: Issue[]; // 问题列表,含 R1C1 坐标
}
// 前端高亮实现
function highlightCell(tableId: string, cellRef: string) {
// cellRef 格式: "R3C4" -> 第3行第4列
const [, row, col] = cellRef.match(/R(\d+)C(\d+)/);
const cell = document.querySelector(
`#${tableId} td[data-coord="R${row}C${col}"]`
);
cell?.classList.add('highlight-error');
}
HTML 片段示例:
<table id="tbl_0" class="forensics-table">
<caption>Table 1. Baseline Characteristics</caption>
<tr>
<td data-coord="R1C1">Variable</td>
<td data-coord="R1C2">Group A</td>
<td data-coord="R1C3">Group B</td>
</tr>
<tr>
<td data-coord="R2C1">Age</td>
<td data-coord="R2C2">45.2 ± 12.3</td>
<td data-coord="R2C3" class="has-issue">48 (60.0%)</td> <!-- 错误单元格 -->
</tr>
</table>
4.3.3 🆕 问题严重程度分级(终审建议)
为避免"狼来了"效应,系统对发现的问题进行严格分级:
| 级别 | 图标 | 标准 | 示例 |
|---|---|---|---|
| 🔴 Error | ❌ | 数据确定性错误,几乎不可能是舍入/格式问题 | 算术加和不等、P 值严重矛盾(算出 <0.001,报告 >0.05)、SD > Mean(正值指标) |
| 🟡 Warning | ⚠️ | 疑似问题,可能是舍入误差或格式差异 | P 值轻微偏差(±0.01)、Table 1 P 值分布过于完美、无法验证仅提示 |
| 🔵 Info | ℹ️ | 提示信息,非错误 | 未检测到统计方法、跳过大表格 |
前端展示规则:
- Error: 红色高亮 + 置顶展示 + 必须关注
- Warning: 黄色高亮 + 建议审阅
- Info: 灰色 + 可折叠
容错阈值配置(终审建议):
# 舍入误差容错
P_VALUE_TOLERANCE = 0.01 # P值允许 ±0.01 差异
P_VALUE_RELATIVE_TOL = 0.05 # 或相对误差 ±5%
CI_TOLERANCE_PERCENT = 0.02 # CI 端点允许 ±2% 相对误差
# 只有超出容错阈值才报 Error,否则报 Warning
5. 分阶段实施计划
5.1 总体时间线
Week 1 Week 2 Week 3 Week 4
├─────────────┼─────────────┼─────────────┼─────────────┤
│ Python 核心 │ Node.js架构 │ 前端 + 联调 │ 测试 + 上线 │
│ L1 算术验证 │ Skills封装 │ 报告UI开发 │ Bug修复 │
│ 表格提取 │ L2统计补充 │ 全链路测试 │ 文档更新 │
└─────────────┴─────────────┴─────────────┴─────────────┘
5.2 Week 1: Python 核心能力(Day 1-5)
目标:输入 .docx 文件,Python API 能返回"第几张表第几行算错了" + HTML 预渲染片段
| Day | 任务 | 产出物 | 负责人 |
|---|---|---|---|
| Day 1 | 环境准备 | 依赖配置完成 | Python |
| - 更新 python-extraction 镜像 | requirements.txt 更新 | ||
| - 引入 python-docx, pandas, scipy | |||
| - 文件大小/格式校验逻辑 | |||
| Day 2 | 表格提取器开发 | DocxTableExtractor 类 | Python |
| - 解析 Word DOM 结构 | |||
| - 处理合并单元格(Forward Fill) | |||
| - 关联表格 Caption | |||
| - 🆕 生成 HTML 片段(含 data-coord 属性) | |||
| Day 3 | L1 算术验证器 + 🆕 L2.5 一致性取证 | ArithmeticValidator + ConsistencyValidator 类 | Python |
| - n (%) 格式解析 | |||
| - Sum/Total 校验 | |||
| - 容错逻辑(±0.1%) | |||
| - 🆕 返回 R1C1 坐标定位 | |||
| - 🆕 SE 三角验证(回归系数/OR/HR 一致性) | |||
| - 🆕 SD > Mean 检查(正值指标启发式规则) | |||
| - 🆕 CI 字符串清洗器(处理多种分隔符格式) | |||
| Day 4 | API 封装 | /api/v1/forensics/analyze_docx | Python |
| - 请求/响应格式定义 | |||
| - 🆕 返回 HTML + JSON 双格式 | |||
| - 错误处理(含降级提示) | |||
| - 日志记录 | |||
| Day 5 | 单元测试 + 联调 | 测试用例通过 | Python |
| - 准备 5 个测试稿件(.docx) | |||
| - 验证提取准确率 | |||
| - 🆕 验证 HTML 渲染一致性 | |||
| - 修复发现的问题 |
关键交付物:
extraction_service/forensics/extractor.py- 表格提取器(含 HTML 生成)extraction_service/forensics/validator.py- 算术验证器extraction_service/forensics/consistency.py- 🆕 一致性取证验证器(SE 三角、SD>Mean)extraction_service/forensics/api.py- API 路由POST /api/v1/forensics/analyze_docx接口可用
依赖变更(requirements.txt / requirements-prod.txt):
# 现有依赖(已满足)
python-docx==1.1.0 # ✅ Docx 读取
pandas>=2.0.0 # ✅ 表格处理
# 新增依赖
+ scipy>=1.11.0 # 🆕 T检验、卡方检验逆向计算
📋 v1.1 变更:移除 LibreOffice 配置,Day 1 更加轻量化。新增 HTML 片段生成,确保前后端渲染一致性。
5.3 Week 2: Node.js 架构 + L2 统计(Day 6-10)
目标:后端通过 Skills 模式执行审稿,不再硬编码逻辑
| Day | 任务 | 产出物 | 负责人 |
|---|---|---|---|
| Day 6 | L2 统计验证器 | StatValidator 类 | Python |
| - T 检验逆向计算 | |||
| - 卡方检验逆向计算 | |||
| - CI vs P 值逻辑检查 | |||
| Day 7 | Skill 接口定义 | types.ts, registry.ts | Node.js |
| - 定义 Skill 接口 | |||
| - 实现 SkillRegistry | |||
| - 实现 SkillExecutor | |||
| Day 8 | DataForensicsSkill | DataForensicsSkill.ts | Node.js |
| - 调用 Python API | |||
| - 结果转换为 SkillResult | |||
| - 错误处理 | |||
| Day 9 | EditorialSkill 封装 | EditorialSkill.ts | Node.js |
| - 封装现有 editorialService | |||
| - 适配 Skill 接口 | |||
| Day 10 | ReviewService 改造 | reviewService.ts 更新 | Node.js |
| - 引入 Profile 配置 | |||
| - 使用 SkillExecutor 执行 | |||
| - 存储 contextData |
关键交付物:
backend/src/modules/rvw/skills/core/- 核心框架backend/src/modules/rvw/skills/library/- Skill 实现- ReviewService 支持 Skills 模式
5.4 Week 3: 前端开发 + 联调(Day 11-15)
目标:用户能看到专业的"数据体检报告"
| Day | 任务 | 产出物 | 负责人 |
|---|---|---|---|
| Day 11 | 数据验证 Tab | DataForensicsTab.tsx | Frontend |
| - Tab 切换逻辑 | |||
| - 数据获取 Hook | |||
| Day 12 | 表格渲染组件 | ForensicsTable.tsx | Frontend |
| - 表格 HTML 渲染 | |||
| - 单元格高亮支持 | |||
| Day 13 | 错误列表组件 | IssueList.tsx | Frontend |
| - 按严重程度排序 | |||
| - 点击定位功能 | |||
| - 错误类型图标 | |||
| Day 14 | 全链路联调 | E2E 测试通过 | 全员 |
| - 上传 → Python → Node → 前端 | |||
| - 修复集成问题 | |||
| Day 15 | UI 优化 | 样式完善 | Frontend |
| - 响应式适配 | |||
| - 加载状态 | |||
| - 空状态处理 |
关键交付物:
frontend-v2/src/modules/rvw/components/DataForensicsTab.tsxfrontend-v2/src/modules/rvw/components/ForensicsTable.tsxfrontend-v2/src/modules/rvw/components/IssueList.tsx
5.5 Week 4: 测试与上线(Day 16-20)
目标:稳定发布,文档完善
| Day | 任务 | 产出物 | 负责人 |
|---|---|---|---|
| Day 16 | 功能测试 | 测试报告 | QA |
| - 正常流程测试 | |||
| - 边界情况测试 | |||
| - 错误处理测试 | |||
| Day 17 | 性能测试 | 性能报告 | QA |
| - 100 页 Word 文档测试 | |||
| - 并发上传测试 | |||
| Day 18 | Bug 修复 | Bug 清零 | 开发 |
| - 修复测试发现的问题 | |||
| Day 19 | 文档更新 | 更新完成 | 全员 |
| - 更新模块状态文档 | |||
| - API 文档补充 | |||
| - 用户使用指南 | |||
| Day 20 | 上线部署 | 生产环境可用 | DevOps |
| - 更新 Docker 镜像 | |||
| - SAE 部署 | |||
| - 监控配置 |
6. 验收标准
6.1 功能验收
| 验收项 | 标准 | 验证方法 |
|---|---|---|
| 表格提取准确率 | ≥98%(三线表) | 10份标准稿件测试 |
| L1 算术检测 | 能检出 Sum 错误(如 50+50=90) | 构造错误稿件测试 |
| L2 P值检测 | 能检出 P 值逻辑错误 | 构造矛盾稿件测试 |
| CI vs P 逻辑 | 能检出 CI 与 P 值矛盾 | 构造矛盾稿件测试 |
| Skills 架构 | 代码中无硬编码审稿逻辑 | 代码审查 |
| 前端展示 | 错误高亮清晰可见 | UI 走查 |
6.2 性能验收
| 验收项 | 标准 | 验证方法 |
|---|---|---|
| 处理时间 | 单文档 ≤ 60秒(100页内) | 计时测试 |
| 并发处理 | 支持 5 个文档同时处理 | 压力测试 |
| 稳定性 | 连续 20 个文档无崩溃 | 稳定性测试 |
6.3 代码验收
| 验收项 | 标准 |
|---|---|
| TypeScript 类型 | 无 any 类型滥用 |
| 错误处理 | 所有 async 函数有 try-catch |
| 日志规范 | 使用 logger 服务 |
| 云原生规范 | 符合项目开发规范 |
6.4 🆕 非功能性需求 (NFRs)
| 需求 | 指标 | 验证方法 |
|---|---|---|
| 文件大小限制 | 上传文件 ≤ 20MB | 前端校验 + 后端拦截 |
| 表格行数限制 | 单表 ≤ 500 行 | 后端校验,超出跳过并警告 |
| Python 服务并发 | 支持 10 个并发请求 | 压力测试 |
| Skill 执行超时 | 单个 Skill ≤ 30s | 熔断机制 |
| HTTP 调用超时 | Node.js → Python ≤ 60s | 配置校验 |
| 格式兼容性 | 仅 .docx,.doc 前端提示转换 | 功能测试 |
📋 并发说明:移除 LibreOffice 后,Python 服务为纯 CPU 计算,无进程池管理开销,并发能力提升。建议初始配置 10 并发,根据生产环境压测调整。
7. 风险管理
7.1 技术风险
| 风险 | 可能性 | 影响 | 缓解措施 |
|---|---|---|---|
| 合并单元格处理复杂度超预期 | 🟡 中 | 🔴 高 | Day 2 重点攻关,预留 Day 5 缓冲 |
| P 值逆向计算精度不够 | 🟡 中 | 🟡 中 | 设置合理阈值(差异 > 0.05 才报错) |
| 🆕 用户上传 .doc 文件被拒 | 🟡 中 | 🟡 中 | 前端清晰提示,提供转换指导 |
| 🆕 HTML 渲染在不同浏览器表现不一致 | 🟢 低 | 🟡 中 | 使用标准 HTML table 标签,避免复杂 CSS |
| Python 镜像体积过大 | 🟡 中 | 🟢 低 | 优化依赖,使用多阶段构建 |
📋 v1.1 变更:移除 LibreOffice 相关风险(容器化、性能),新增 .doc 拒绝和浏览器兼容性风险。整体风险等级降低。
7.2 进度风险
| 风险 | 可能性 | 影响 | 缓解措施 |
|---|---|---|---|
| Week 1 延期 | 🟡 中 | 🔴 高 | Week 4 有缓冲天数 |
| 联调发现重大问题 | 🟡 中 | 🟡 中 | Day 14 提前联调 |
| 测试人力不足 | 🟢 低 | 🟡 中 | 开发自测覆盖基础用例 |
7.3 应急预案
- 如果 Week 1 严重延期:砍掉 L2 统计验证,仅保留 L1 算术验证
- 如果前端来不及:直接使用后端 HTML 片段,简化高亮交互
- 如果 Skills 架构复杂度过高:MVP 阶段暂不封装,直接调用
- 🆕 如果 DataForensics 频繁失败:启用降级模式,优先保证 EditorialSkill 正常运行
8. 后续迭代规划
8.1 V2.1 迭代(预计 4 周)
主题:扩展统计验证能力 + 护栏中间件 + 格式兼容
| 功能 | 描述 | 优先级 |
|---|---|---|
| ANOVA 验证 | 多组比较 P 值验证 | P0 |
| 配对检验 | Paired T-test, McNemar | P0 |
| 非参数检验 | Mann-Whitney, Wilcoxon | P0 |
| 🆕 .doc 格式支持 | 评估 Pandoc 替代方案 | P1 |
| 方法学章节定位 | 自动提取"统计分析"段落 | P1 |
| 政治护栏 | 敏感词扫描(Pre-Hook) | P1 |
| Profile 管理 UI | 期刊配置界面 | P2 |
8.2 V2.2 迭代(预计 6 周)
主题:复杂统计 + 交互式对话
| 功能 | 描述 | 优先级 |
|---|---|---|
| 生存分析验证 | Log-rank, Cox 回归 | P0 |
| 回归分析验证 | Logistic, Linear, Cox | P0 |
| 跨表一致性检查 | 多表数据交叉验证 | P1 |
| ReAct 对话引擎 | 交互式审稿问答 | P1 |
| MedicalLogicSkill | 医学常识校验(pgvector) | P2 |
| BenchmarkSkill | 竞品对标(联动 ASL) | P2 |
8.3 V2.3 迭代(预计 4 周)
主题:高级功能 + 独立产品
| 功能 | 描述 | 优先级 |
|---|---|---|
| PDF 支持 | 基于视觉模型的表格识别 | P1 |
| 图片查重 | 图片相似度检测 | P2 |
| 独立产品打包 | 独立部署版本 | P2 |
| 审稿人管理 | 多审稿人协作 | P3 |
9. 附录
9.1 Python API 接口规范
Endpoint: POST /api/v1/forensics/analyze_docx
Request:
{
"file_url": "oss://.../manuscript.docx",
"config": {
"check_level": "L1_L2",
"tolerance_percent": 0.1,
"max_table_rows": 500
}
}
Response(成功):
{
"success": true,
"methods_found": ["t-test", "chi-square"],
"tables": [
{
"id": "tbl_0",
"caption": "Table 1. Baseline Characteristics",
"type": "BASELINE",
"row_count": 10,
"col_count": 5,
"html": "<table id=\"tbl_0\" class=\"forensics-table\"><caption>Table 1...</caption><tr><td data-coord=\"R1C1\">Variable</td>...</tr></table>",
"issues": [
{
"severity": "ERROR",
"type": "ARITHMETIC_ERROR",
"cell_ref": "R3C4",
"message": "计算百分比 (48.0%) 与报告值 (50.0%) 不符",
"evidence": {
"calculated": 48.0,
"reported": 50.0,
"n": 24,
"N": 50
}
}
],
"data": [
["Variable", "Group A", "Group B", "P-value"],
["Age", "45.2 ± 12.3", "44.8 ± 11.9", "0.82"]
]
}
],
"execution_time_ms": 1234
}
Response(失败/降级):
{
"success": false,
"error": {
"code": "EXTRACTION_FAILED",
"message": "Word 文档结构异常,无法提取表格",
"details": "表格嵌套过深,超出解析能力"
},
"fallback_available": true,
"execution_time_ms": 234
}
📋 v1.1 新增:
- 响应中增加
html字段,包含预渲染的 HTML 片段- 单元格包含
data-coord属性用于前端高亮定位- 新增失败响应格式,支持前端降级展示
9.2 数据库变更
// prisma/schema.prisma 变更
model ReviewTask {
// ... 现有字段 ...
// V2.0 新增
contextData Json? // Skills 执行结果汇总
profileId String? // 使用的 Profile ID
skillsExecuted String[] // 已执行的 Skill 列表
}
9.3 目录结构
backend/src/modules/rvw/
├── routes/index.ts
├── controllers/reviewController.ts
├── services/
│ ├── reviewService.ts # 主服务(改造)
│ ├── editorialService.ts # 保留
│ └── methodologyService.ts # 保留
├── skills/ # 🆕 新增
│ ├── core/
│ │ ├── types.ts # 接口定义
│ │ ├── registry.ts # 注册表
│ │ └── executor.ts # 执行器
│ ├── library/
│ │ ├── DataForensicsSkill.ts # 数据侦探
│ │ ├── EditorialSkill.ts # 稿约规范性
│ │ └── MethodologySkill.ts # 方法学评估
│ └── profiles/
│ └── default.ts # 默认配置
├── workers/reviewWorker.ts
└── types/index.ts
extraction_service/ # Python 微服务(现有)
├── main.py # FastAPI 入口
├── extractors/ # 现有提取器
│ ├── pdf_extractor.py
│ ├── docx_extractor.py
│ └── ...
├── forensics/ # 🆕 新增模块
│ ├── __init__.py
│ ├── extractor.py # Word 表格提取
│ ├── html_renderer.py # HTML 片段生成(含 data-coord)
│ ├── validator.py # 算术/统计验证
│ └── api.py # FastAPI 路由
├── requirements.txt # 开发依赖(+ scipy)
└── requirements-prod.txt # 生产依赖(+ scipy)
frontend-v2/src/modules/rvw/
├── pages/Dashboard.tsx
├── components/
│ ├── TaskDetail.tsx # 修改(新增 Tab)
│ ├── DataForensicsTab.tsx # 🆕 新增
│ ├── ForensicsTable.tsx # 🆕 新增
│ ├── IssueList.tsx # 🆕 新增
│ └── ...
└── types/index.ts # 更新类型
9.4 测试数据准备清单
MVP 开发前需准备以下测试稿件(全部为 .docx 格式):
| # | 稿件类型 | 用途 | 状态 |
|---|---|---|---|
| 1 | 标准三线表稿件(正确) | 基准测试 | ⬜ 待准备 |
| 2 | 含算术错误的稿件 | L1 验证测试 | ⬜ 待准备 |
| 3 | 含 P 值错误的稿件 | L2 验证测试 | ⬜ 待准备 |
| 4 | 含 CI vs P 矛盾的稿件 | 逻辑检查测试 | ⬜ 待准备 |
| 5 | 复杂合并单元格稿件 | 边界测试 | ⬜ 待准备 |
| 6 | 100 页长稿件 | 性能测试 | ⬜ 待准备 |
| 7 | 🆕 超大表格稿件(>500行) | 限制测试 | ⬜ 待准备 |
| 8 | 🆕 损坏/异常 Word 文件 | 降级测试 | ⬜ 待准备 |
📋 v1.1 变更:移除 .doc 格式测试,新增超大表格和异常文件测试用例。
9.5 Python 依赖变更清单
现有依赖(已满足,无需修改):
| 依赖 | 版本 | 用途 | 状态 |
|---|---|---|---|
python-docx |
1.1.0 | Word 文档解析、表格提取 | ✅ 已有 |
pandas |
≥2.0.0 | DataFrame 处理、数据清洗 | ✅ 已有 |
pdfplumber |
0.10.3 | 备用 PDF 处理 | ✅ 已有 |
fastapi |
0.104.1 | API 框架 | ✅ 已有 |
loguru |
0.7.2 | 日志 | ✅ 已有 |
需新增依赖:
| 依赖 | 版本 | 用途 | 大小 |
|---|---|---|---|
scipy |
≥1.11.0 | T检验、卡方检验统计计算 | ~30MB |
requirements.txt 变更:
# 在 pandas 行后添加
pandas>=2.0.0 # 表格处理
+ scipy>=1.11.0 # 统计验证(T检验、卡方检验)
📋 依赖说明:scipy 是 numpy 生态的标准统计库,与现有 pandas 兼容良好,不会引入冲突。
9.6 相关文档索引
| 文档 | 路径 | 说明 |
|---|---|---|
| PRD | 00-系统设计/RVW V2.0 MVP 产品需求文档 (PRD).md |
产品需求 |
| 架构方案 | 00-系统设计/RVW V2.0 架构升级方案:基于 Skills 的柔性审稿引擎.md |
技术架构 |
| 技术设计 | 00-系统设计/RVW V2.0 数据侦探:Word 优先架构技术设计文档.md |
详细设计 |
| 实施计划 | 00-系统设计/RVW V2.0 融合实施作战计划:架构与功能的统一.md |
原始计划 |
| V1.0 状态 | 00-模块当前状态与开发指南.md |
当前状态 |
文档版本: v1.1.1
创建日期: 2026-02-17
下次更新: Week 1 结束后更新进度
状态: 📋 待启动(团队审查通过,代码一致性已校验)
📝 变更记录
| 日期 | 版本 | 变更内容 | 作者 |
|---|---|---|---|
| 2026-02-17 | v1.0 | 初始版本,整合 PRD + 架构 + 技术设计 + 审查建议 | 开发团队 |
| 2026-02-17 | v1.1 | 根据团队深度审查报告更新 | 开发团队 |
| ✅ 移除 LibreOffice,仅支持 .docx 格式 | |||
| ✅ 新增 Python 返回 HTML 片段 + R1C1 坐标 | |||
| ✅ 新增 Skill 执行 30s 超时熔断机制 | |||
| ✅ 新增 DataForensics 失败降级机制 | |||
| ✅ 新增 NFRs(文件≤20MB,单表≤500行,并发10) | |||
| ✅ 明确 Node.js ↔ Python HTTP 60s 超时 | |||
| ✅ 更新测试用例清单 | |||
| 2026-02-17 | v1.1.1 | 根据实际代码校验更新 | 开发团队 |
| ✅ 修正数据流图:复用现有 pg-boss 异步架构 | |||
| ✅ 明确 ExtractionClient 已有 HTTP 通信机制 | |||
| ✅ 新增 scipy 依赖说明(统计验证必需) | |||
| ✅ 补充 Python 依赖变更清单(附录 9.5) |