AI优化病例报告表:从字段设计到逻辑校验,如何减少人工返工
CRF 设计返工通常不是因为表单页面做得慢,而是字段定义、取值范围、跳转逻辑和版本变更没有在早期被系统化检查。本文从技术架构角度复盘一个 AI 辅助 CRF 设计与校验服务的实现思路,示例仅用于工程流程说明,不提供诊断、治疗、分诊或用药建议;所有阈值、风险提示和升级规则都应由医疗专业人员及机构规范确认。
问题背景:CRF 返工通常发生在哪里
做过 CRF 或数据管理系统的人都知道,后期返工往往集中在三个点。
第一类是字段设计返工。比如同一个含义的字段在不同表单里出现了多个命名:visit_date、visit_time、followup_date,后续做数据导出、质控规则和统计口径时都要补映射。
第二类是逻辑冲突。字段 A 要求必填,但它只在字段 B 等于某个选项时才显示;或者某个日期字段允许为空,但下游规则又拿它计算间隔天数。
第三类是版本变更不可追踪。方案调整后,CRF 从 v1.2 改到 v1.3,字段删除、枚举值变更、必填状态修改没有结构化记录,测试环境和生产环境很容易出现口径不一致。
AI 在这里适合做“辅助发现”:根据字段描述生成候选字段、识别重复语义、提示规则冲突、总结版本差异。但是否发布,仍然必须人工确认。
技术目标与边界
本文的目标是构建一个轻量服务,覆盖 CRF 设计中的三个环节:
- 字段模板:用结构化 JSON 管理字段名称、类型、枚举、必填、显示条件。
- 逻辑校验:用 JSON Schema 做基础校验,用规则引擎做跨字段校验。
- 变更追踪:将每次 CRF 版本保存到 PostgreSQL,并生成字段级 diff。
系统不处理真实患者数据,示例字段也只用于说明工程流程。真实项目中应加入权限控制、审计日志、数据脱敏、环境隔离和机构合规流程。
架构设计:把 AI 放在“建议层”
一个比较稳妥的设计是把 AI 输出限制在建议层,而不是直接写入正式版本。
这样做的关键点是:AI 可以生成草稿,但不能绕过审核;规则可以提示风险,但不能替代医学或机构规范判断。
字段模板设计:先统一 Schema 再生成页面
CRF 字段建议不要直接生成前端表单,建议先落到统一 JSON 模型。下面是一个简化字段结构:
{
"form_code": "baseline_visit",
"version": "1.0.0",
"fields": [
{
"name": "visit_date",
"label": "访视日期",
"type": "date",
"required": true
},
{
"name": "has_prior_condition",
"label": "是否有既往相关情况",
"type": "enum",
"required": true,
"options": ["yes", "no", "unknown"]
},
{
"name": "prior_condition_note",
"label": "既往相关情况说明",
"type": "text",
"required": false,
"visible_when": {
"field": "has_prior_condition",
"equals": "yes"
}
}
]
}
这里的设计原则是字段语义稳定、展示逻辑显式、枚举值机器可读。AI 可以根据需求文本生成类似草稿,但字段命名、枚举含义、是否必填需要数据管理员或项目负责人确认。
用 Python 做字段重复和基础规则检查
下面代码演示一个最小可运行的检查器:检查字段重名、显示条件引用不存在字段、必填字段却依赖隐藏条件等常见问题。
from typing import Dict, List, Any
def validate_crf_template(crf: Dict[str, Any]) -> List[str]:
errors = []
fields = crf.get("fields", [])
names = [f.get("name") for f in fields]
name_set = set()
for name in names:
if not name:
errors.append("存在未命名字段")
elif name in name_set:
errors.append(f"字段重复: {name}")
else:
name_set.add(name)
for field in fields:
name = field.get("name")
visible_when = field.get("visible_when")
if visible_when:
ref = visible_when.get("field")
if ref not in name_set:
errors.append(f"{name} 的显示条件引用了不存在的字段: {ref}")
if field.get("required") is True:
errors.append(
f"{name} 设置为必填且存在显示条件,需确认隐藏时是否允许为空"
)
if field.get("type") == "enum":
options = field.get("options", [])
if not options:
errors.append(f"{name} 是枚举字段,但未配置 options")
return errors
if __name__ == "__main__":
crf_template = {
"form_code": "baseline_visit",
"version": "1.0.0",
"fields": [
{"name": "visit_date", "type": "date", "required": True},
{
"name": "prior_condition_note",
"type": "text",
"required": True,
"visible_when": {"field": "has_prior_condition", "equals": "yes"}
}
]
}
result = validate_crf_template(crf_template)
print("\n".join(result) if result else "CRF 模板检查通过")
运行结果会提示:
prior_condition_note 的显示条件引用了不存在的字段: has_prior_condition
prior_condition_note 设置为必填且存在显示条件,需确认隐藏时是否允许为空
这类检查不复杂,但可以把大量人工 review 中容易漏掉的问题提前暴露出来。
FastAPI 服务化:让设计、校验、版本进入同一流程
实际项目里,建议把 CRF 模板检查封装成接口,接入前端配置平台或内部数据管理系统。
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Any, Dict, List
app = FastAPI(title="CRF Template QA Service")
class CRFRequest(BaseModel):
crf: Dict[str, Any]
@app.post("/crf/validate")
def validate_crf(req: CRFRequest) -> Dict[str, List[str]]:
errors = validate_crf_template(req.crf)
return {"errors": errors}
进一步可以增加三个接口:
/crf/draft:接收需求文本,调用 AI 生成候选字段草稿。/crf/validate:执行基础校验和跨字段规则检查。/crf/version/diff:比较两个 CRF 版本,输出字段级变更。
AI 生成的草稿应标记为 draft,只有人工审核通过后才允许进入 approved 状态。
版本 Diff:返工成本要在变更时就量化
CRF 版本变更最怕“只改了一点点”这种描述。工程上建议保存完整 JSON,并在提交时生成结构化 diff。
示例 diff 输出可以长这样:
{
"from_version": "1.0.0",
"to_version": "1.1.0",
"changes": [
{
"field": "visit_date",
"change_type": "required_changed",
"before": true,
"after": false
},
{
"field": "has_prior_condition",
"change_type": "option_added",
"before": ["yes", "no"],
"after": ["yes", "no", "unknown"]
}
]
}
对于每条变更,可以附加影响范围:
- 是否影响历史数据导入。
- 是否影响已配置的质控规则。
- 是否影响导出字段映射。
- 是否需要重新确认前端展示逻辑。
这些不是医学判断,而是工程影响分析。它能帮助团队在发布前评估返工范围。
规则引擎:跨字段逻辑不要硬编码在页面里
基础字段类型适合 JSON Schema,跨字段规则建议用独立规则层。比如:
{
"rule_code": "R_VISIT_DATE_REQUIRED",
"description": "示例规则:访视日期在基线访视表中必填",
"when": {
"form_code": "baseline_visit"
},
"then": {
"field": "visit_date",
"operator": "not_empty"
},
"severity": "error"
}
注意这里写的是“示例规则”。真实项目里,哪些字段必填、哪些规则属于错误、哪些属于警告,都应由机构 SOP、项目方案和数据管理计划确认。
规则引擎的收益是可维护。前端负责展示,后端负责校验,规则仓库负责版本化,避免同一条逻辑散落在页面、导入脚本和质控 SQL 里。
性能与落地建议
在小型 CRF 中,几十到几百个字段的校验通常不是性能瓶颈。更值得关注的是版本治理和规则可解释性。
我在类似项目里更推荐以下做法:
- 字段模板、规则、版本 diff 都保存结构化 JSON。
- AI 输出必须带来源提示和置信说明,不能自动发布。
- 校验报告要给出字段名、规则编号、错误级别和修复建议。
- PostgreSQL 表中保留
created_by、approved_by、approved_at等审计字段。 - CI 流程中加入 CRF 模板校验,阻止明显冲突的配置进入测试环境。
如果后续字段规模扩大,可以把规则执行做成异步任务,并对常用版本的校验结果做缓存。
总结
AI 优化 CRF 的价值不在于“自动生成表单”,而在于把字段漏项、逻辑冲突和版本差异提前暴露出来。工程实现上,可以用 JSON 模板统一字段语义,用 JSON Schema 和规则引擎分层校验,用 PostgreSQL 保存版本并生成 diff。
最后再强调一次:本文是技术架构和工程流程示例,不提供任何诊断、治疗、分诊或用药建议。AI 只能辅助发现冲突和漏项,CRF 的最终发布口径必须由数据管理人员、医疗专业人员和机构规范共同确认。
本文文献检索、文献挖掘以及文献翻译采用的是【超能文献| AI文献检索|AI文档翻译】。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)