
医疗行业对准确性、合规性、安全性有着极高的要求,大模型在医疗场景,如病历撰写、医嘱辅助、医学科普、诊断建议参考等,不能简单直接的“输入-输出”,否则可能出现医疗信息错误、违反医疗规范、泄露患者隐私等严重问题。
而在实际的应用过程中,从最初的摸索到最后的落地,整个环节也经历了多轮的反复优化改造,也逐步形成了”生成前校验 + 生成后审计”的全链路管控,通过这一流程的控制,也很好的解决过程中一系列的问题,让大模型安全落地医疗行业有了系统的解决方案;“生成前校验”就像医生看病时,先核对患者基本信息是否准确,“生成后审计”就像诊疗结束后还要整理病历并由上级医师审核,形成一套闭环的质量控制体系。

我们这里所说大的医疗大模型是经过大量医学数据预训练,数据包括教材、指南、病历、文献等,能够理解和生成医疗相关文本和内容的垂直大模型,一般是以个轻量模型为基座,整理行业知识对其进行多轮训练、微调,从而达到预期的输出效果;
在把用户需求通过输入传给大模型进行内容生成之前,对输入内容的合法性、合规性、完整性、安全性进行检查和处理的过程。
大模型完成内容生成并输出后,对输出内容的准确性、合规性、安全性、实用性进行检查、验证、修正和归档的过程。

3 个核心步骤,把好入口关,这是大模型生成内容的前置过滤器,核心是提前排除可能存在的隐患,减少后续无效工作。
第一步:输入完整性校验
第二步:输入合规性校验
这是校验环节的核心,主要防范隐私泄露和恶意输入。
第三步:输入标准化处理
4个核心步骤,把好出口关,这是大模型输出内容的最终质检站,核心是确保交付内容合格,分为机器初筛和人工复核两部分,其中前3个步骤以机器为主,第4步为人机协同。
第一步:输出格式合规性审计
第二步:输出内容准确性审计
第三步:输出隐私与合规性审计
第四步:输出归档与可追溯处理
我们提供 “生成前校验” 和 “生成后审计” 的基础说明示例,核心实现完整性校验、隐私信息脱敏、格式合规性审计、简单内容准确性校验,校验基于规则引擎和简易医疗知识库;
# 导入所需库
import re
from fuzzywuzzy import fuzz
# ====================== 第一步:构建基础医疗知识库和规则引擎 ======================
REQUIRED_INFO = {
"电子病历": ["姓名", "性别", "年龄", "主诉", "现病史"],
"用药建议": ["疾病名称", "年龄", "过敏史"]
}
# 隐私脱敏:仅对高确定性字段脱敏(手机号、身份证、住院号)
# 暂不自动脱敏“姓名”(因正则易误杀医学术语),依赖输入规范或后续泛化
PRIVACY_PATTERNS = {
"手机号": re.compile(r"1[3-9]\d{9}"),
"身份证号": re.compile(r"\d{17}[\dXx]"),
"住院号": re.compile(r"住院号[::]?\s*\d+|住院编号[::]?\s*\d+")
}
MEDICAL_KNOWLEDGE = {
"疾病名称": ["高血压", "2型糖尿病", "冠心病", "肺炎", "支气管炎"],
"药物名称": ["阿司匹林", "硝苯地平", "二甲双胍", "阿莫西林", "沙丁胺醇"],
"标准剂量": {
"硝苯地平": "每日2次,每次10-20mg,每日最大剂量不超过60mg",
"阿司匹林": "每日1次,每次100mg,饭后服用"
}
}
FORMAT_RULES = {
"电子病历": ["包含主诉", "包含现病史", "无乱码", "排版清晰"],
"用药建议": ["包含药物名称", "包含服用剂量", "包含过敏提醒", "结尾标注仅供参考"]
}
# ====================== 第二步:生成前校验(语义化检查) ======================
def pre_generate_validate(input_content: str, scene: str) -> tuple[bool, str, str]:
is_pass = True
tip_info = "校验通过"
processed_content = input_content
if scene not in REQUIRED_INFO:
return False, f"不支持的医疗场景,支持场景:{list(REQUIRED_INFO.keys())}", processed_content
missing_info = []
# === 语义化完整性校验 ===
if scene == "用药建议":
# 检查疾病(标准 + 口语 + 错别字)
disease_terms = set(MEDICAL_KNOWLEDGE["疾病名称"]) | {"血压高", "血糖高", "心口疼", "高雪压"}
if not any(term in processed_content for term in disease_terms):
missing_info.append("疾病名称")
# 检查年龄
if not re.search(r"\d+\s*岁", processed_content):
missing_info.append("年龄")
# 检查过敏史
if "过敏" not in processed_content:
missing_info.append("过敏史")
elif scene == "电子病历":
if not re.search(r"患者|某[男女]|[男女]性", processed_content):
missing_info.append("患者标识")
if not re.search(r"[男女]性", processed_content):
missing_info.append("性别")
if not re.search(r"\d+\s*岁", processed_content):
missing_info.append("年龄")
if not re.search(r"主诉|因.*?就诊", processed_content):
missing_info.append("主诉")
if not re.search(r"现病史|近.*?天", processed_content):
missing_info.append("现病史")
# === 隐私脱敏(仅安全字段)===
for privacy_type, pattern in PRIVACY_PATTERNS.items():
if pattern.search(processed_content):
processed_content = pattern.sub(f"[{privacy_type}]", processed_content)
tip_info += f" | 已脱敏{privacy_type}"
# === 标准化处理 ===
typo_correction = {"高雪压": "高血压", "阿斯匹林": "阿司匹林", "二甲双瓜": "二甲双胍"}
for typo, correct in typo_correction.items():
if typo in processed_content:
processed_content = processed_content.replace(typo, correct)
tip_info += f" | 已修正错别字:{typo}→{correct}"
oral_to_standard = {"血压高": "高血压", "血糖高": "2型糖尿病", "心口疼": "胸痛(冠心病待查)"}
for oral, standard in oral_to_standard.items():
if oral in processed_content:
processed_content = processed_content.replace(oral, standard)
tip_info += f" | 已标准化术语:{oral}→{standard}"
if missing_info:
is_pass = False
tip_info = f"输入内容缺少必要信息:{', '.join(missing_info)},请补充"
return is_pass, tip_info, processed_content
# ====================== 第三步:生成后审计 ======================
def post_generate_audit(output_content: str, scene: str) -> tuple[bool, str, str]:
is_pass = True
tip_info = "审计通过"
processed_output = output_content
if scene not in FORMAT_RULES:
return False, f"不支持的医疗场景:{scene}", processed_output
# === 格式合规检查 ===
format_rules_list = FORMAT_RULES[scene]
detected_rules = []
if "药物名称" in format_rules_list and any(drug in processed_output for drug in MEDICAL_KNOWLEDGE["药物名称"]):
detected_rules.append("包含药物名称")
if "服用剂量" in format_rules_list and re.search(r"\d+\s*mg|每次|每日", processed_output):
detected_rules.append("包含服用剂量")
if "过敏提醒" in format_rules_list and ("过敏" in processed_output or "避免" in processed_output):
detected_rules.append("包含过敏提醒")
if "结尾标注仅供参考" in format_rules_list and "仅供参考" in processed_output:
detected_rules.append("结尾标注仅供参考")
missing_format = [rule for rule in format_rules_list if rule not in detected_rules]
if missing_format:
is_pass = False
tip_info = f"输出格式不合规,缺少:{', '.join(missing_format)}"
if "结尾标注仅供参考" in missing_format:
processed_output += "\n\n注:本文内容仅供医疗参考,不构成最终诊疗建议,具体请遵医嘱。"
tip_info += " | 已自动补充“仅供参考”标注"
# === 内容准确性审计 ===
medical_errors = []
for drug, std_dose in MEDICAL_KNOWLEDGE["标准剂量"].items():
if drug in processed_output and std_dose not in processed_output:
medical_errors.append(f"药物'{drug}'剂量未按标准表述(标准:{std_dose})")
if medical_errors:
is_pass = False
tip_info += f" | 内容准确性存疑:{', '.join(medical_errors)},建议人工复核"
# === 隐私二次审计(仅高风险字段)===
for privacy_type, pattern in PRIVACY_PATTERNS.items():
if pattern.search(processed_output):
processed_output = pattern.sub(f"[{privacy_type}]", processed_output)
tip_info += f" | 已脱敏输出中的{privacy_type}信息"
is_pass = False
# === 强制匿名化:移除任何可能的真实姓名引用 ===
# 简单策略:将“患者XXX”替换为“患者”
processed_output = re.sub(r"患者\s*[\u4e00-\u9fa5]{2,4}", "患者", processed_output)
return is_pass, tip_info, processed_output
# ====================== 第四步:完整测试流程 ======================
if __name__ == "__main__":
# 模拟用户输入(含真实姓名、手机号、错别字)
user_input = """
患者张三,手机号13812345678,年龄55岁,过敏史:青霉素。
患有高雪压,需要生成用药建议,推荐阿斯匹林和硝苯地平。
"""
medical_scene = "用药建议"
print("=" * 60)
print("【系统提示】正在处理医疗请求,请稍候...")
print("(注意:手机号等高风险信息将被脱敏;姓名由系统泛化处理)")
# 步骤1:生成前校验
pre_pass, pre_tip, pre_processed_input = pre_generate_validate(user_input, medical_scene)
print("\n" + "=" * 60)
print("🔹 步骤1:生成前校验")
status = "√ 校验通过" if pre_pass else "× 校验未通过"
print(status)
# print(f"√ 通过:{pre_pass}")
print(f"!提示:{pre_tip}")
print(f"脱敏并标准化后的输入内容:\n{pre_processed_input.strip()}")
if pre_pass:
print("\n" + "=" * 60)
print("🔹 步骤2:大模型生成(模拟)")
# 模拟 LLM 基于脱敏输入生成内容(使用泛化表述)
llm_output = """
针对高血压患者,推荐用药:阿司匹林、硝苯地平。
阿司匹林:每日1次,每次200mg。
硝苯地平:每日3次,每次20mg。
过敏提醒:避免使用青霉素类药物。
"""
print("大模型原始输出:")
print(llm_output.strip())
# 步骤3:生成后审计
post_pass, post_tip, post_processed_output = post_generate_audit(llm_output, medical_scene)
print("\n" + "=" * 60)
print("🔹 步骤3:生成后审计")
# print(f"√ 通过:{post_pass}")
status = "√ 校验通过" if post_pass else "× 校验未通过"
print(status)
print(f"!提示:{post_tip}")
print(f"最终交付内容(安全、匿名、合规):\n{post_processed_output.strip()}")
print("\n" + "=" * 60)
print("√ 流程结束。输出已脱敏、匿名化,并符合医疗规范要求。")
else:
print("\n" + "=" * 60)
print("× 流程终止:生成前校验未通过,无法继续。")输出结果:
============================================================ 【系统提示】正在处理医疗请求,请稍候... (注意:手机号等高风险信息将被脱敏;姓名由系统泛化处理) ============================================================ 🔹 步骤1:生成前校验 √ 校验通过 !提示:校验通过 | 已脱敏手机号 | 已修正错别字:高雪压→高血压 | 已修正错别字:阿斯匹林→阿司匹林 脱敏并标准化后的输入内容: 患者张三,手机号[手机号],年龄55岁,过敏史:青霉素。 患有高血压,需要生成用药建议,推荐阿司匹林和硝苯地平。 ============================================================ 🔹 步骤2:大模型生成(模拟) 大模型原始输出: 针对高血压患者,推荐用药:阿司匹林、硝苯地平。 阿司匹林:每日1次,每次200mg。 硝苯地平:每日3次,每次20mg。 过敏提醒:避免使用青霉素类药物。 ============================================================ 🔹 步骤3:生成后审计 × 校验未通过 !提示:输出格式不合规,缺少:包含药物名称, 包含服用剂量, 包含过敏提醒, 结尾标注仅供参考 | 已自动补充“仅供参考”标注 | 内容准确性存疑:药物'硝苯地平'剂量未按标准表述(标准:每日2次,每次10-20mg,每日最大剂量不超过60mg), 药物' 阿司匹林'剂量未按标准表述(标准:每日1次,每次100mg,饭后服用),建议人工复核 最终交付内容(安全、匿名、合规): 针对高血压患者,推荐用药:阿司匹林、硝苯地平。 阿司匹林:每日1次,每次200mg。 硝苯地平:每日3次,每次20mg。 过敏提醒:避免使用青霉素类药物。 注:本文内容仅供医疗参考,不构成最终诊疗建议,具体请遵医嘱。 ============================================================ √ 流程结束。输出已脱敏、匿名化,并符合医疗规范要求。
这个图用来展示生成后审计中发现的各类问题占比,比如剂量错误、禁忌风险、格式不合规等,直观呈现核心问题痛点,方便后续优化管控策略。

图例说明:突出核心问题(药物剂量 / 频次错误占 38.0%、用药禁忌未规避占 25.0%),贴合医疗场景的核心管控重点。
这个图用来展示多批次(按日期)生成前校验通过率、生成后审计通过率的变化趋势,直观呈现管控效果的优化过程,贴合落地实践中的数据追踪需求。

图例说明:直观呈现“生成前校验通过率”始终高于“生成后审计通过率”,符合实际应用中前校验是基础过滤,后审计是深度质检。
这段时间跟着实操医疗大模型前校验后审计的落地内容,算是把核心逻辑摸透了,也踩了不少坑、避了不少雷。核心就是搞懂医疗场景的特殊性,不能像普通大模型那样只做输入输出,必须把隐私脱敏和内容准确性 焊死在流程里。生成前重点是把好入口关,用简单直接的关键词校验避免误判,同时对患者标识、就诊卡号这些医疗隐私做脱敏,既合规又安全,之前踩过模糊匹配的坑,现在知道极简字符串包含判断才最实用。
生成后审计是重中之重,得盯着药物剂量、用药频次、禁忌症这些关键项,比如肾不全患者不能用硝苯地平、阿司匹林剂量不能超 100mg,这些医疗安全点必须精准校验,还得自动补合规声明,避免风险。整体下来,医疗大模型落地不是堆复杂逻辑,而是把合规、安全、准确做到位,极简实用、能跑通闭环才是关键,后续可以把这些逻辑直接套用到实际医疗项目里。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。