电子病历系统里大量信息仍然来自自由文本主诉、现病史、既往史、过敏史、体格检查记录等医生录入耗时后续质控和检索也困难。本文从工程实现角度拆解一个 Agent 辅助病史整理、结构化录入和摘要生成的最小可落地方案。本文仅讨论技术架构和工程流程示例不提供诊断、治疗、分诊或用药建议所有规则都应由医疗专业人员和机构规范确认。问题背景自由文本为什么难以直接入库在电子病历场景中开发者经常遇到三个问题。第一自由文本格式不稳定。同一个字段可能写成“否认药物过敏史”“青霉素过敏”“过敏史不详”简单正则很难覆盖全部表达。第二结构化字段有强约束。例如chief_complaint、present_illness、past_history、allergy_history等字段需要类型明确、来源可追溯、可被人工修改。第三模型输出不能直接覆盖病历。Agent 可以提升整理效率但必须保留审核边界哪些字段来自原文、哪些是模型归纳、哪些需要人工确认都要在数据结构里体现。因此合理目标不是“自动写病历”而是构建一个“候选结构化结果生成器 审核工作台”。技术目标与边界本文示例技术栈如下Python FastAPI提供病历解析和审核接口PostgreSQL保存原始文本、抽取结果、审核状态vector store存储历史模板、科室常用表达、字段示例LLM API完成字段抽取、摘要生成和一致性检查系统目标可以拆成四步接收原始病历文本做脱敏和分段。Agent 根据字段 Schema 抽取结构化候选值。生成病史摘要并标注来源片段。审核工作台展示差异由人工确认后回填。需要特别注意示例中的风险提示、字段完整性检查、升级规则都只是可配置工程规则真实项目必须由医疗专业人员和机构制度确认。方案总览把 Agent 拆成可控流程Agent 不建议设计成一个黑盒接口。更稳妥的方式是拆成多个节点每个节点只做一件事。原始病历文本脱敏与分段字段抽取 AgentSchema 校验摘要生成 Agent一致性检查审核工作台人工确认后回填 EMR核心设计点是“候选结果”和“最终病历”分离。模型只写入draft_record人工审核后才写入confirmed_record。这样可以避免模型生成内容直接污染正式病历数据。一个简化的数据结构如下emr_raw_note - id - patient_visit_id - raw_text - deidentified_text - created_at emr_draft_extract - id - raw_note_id - field_name - field_value - evidence_text - confidence - status: pending / accepted / rejected / edited emr_confirmed_record - id - patient_visit_id - structured_json - reviewer_id - reviewed_at实现步骤一定义字段 Schema不要让模型自由发挥字段名。先定义固定 Schema抽取任务围绕 Schema 进行。frompydanticimportBaseModel,FieldfromtypingimportOptional,ListclassEvidenceField(BaseModel):value:Optional[str]Field(defaultNone,description抽取出的字段值)evidence:Optional[str]Field(defaultNone,description原文依据片段)confidence:floatField(default0.0,ge0.0,le1.0)classEmrExtractResult(BaseModel):chief_complaint:EvidenceField present_illness:EvidenceField past_history:EvidenceField allergy_history:EvidenceField family_history:EvidenceField medication_history:EvidenceField missing_fields:List[str][]need_human_review:List[str][]这里的evidence很关键。审核人员看到的不应只是模型结论还要能回到原始文本。confidence也不要理解为医学准确率它只是工程上的模型自评或规则综合评分不能替代人工判断。实现步骤二FastAPI 接口与 Agent 调用下面是一个最小示例演示如何把原始文本传入 LLM并要求返回符合 Schema 的 JSON。实际项目中还应加入鉴权、审计日志、敏感信息处理和异常重试。importjsonfromfastapiimportFastAPIfrompydanticimportBaseModelfromopenaiimportOpenAI appFastAPI()clientOpenAI(api_keyYOUR_LLM_API_KEY)classExtractRequest(BaseModel):patient_visit_id:strraw_text:strSYSTEM_PROMPT 你是电子病历结构化助手只能根据输入文本抽取字段。 不得生成诊断、治疗、分诊或用药建议。 如果原文没有明确依据字段 value 填 null并加入 missing_fields。 每个字段必须返回 evidence表示原文依据片段。 输出严格 JSON不要输出解释。 defbuild_user_prompt(text:str)-str:returnf 请从以下电子病历自由文本中抽取结构化字段 字段包括 chief_complaint, present_illness, past_history, allergy_history, family_history, medication_history。 原文{text}返回 JSON 格式 {{ chief_complaint: {{value: , evidence: , confidence: 0.0}}, present_illness: {{value: , evidence: , confidence: 0.0}}, past_history: {{value: , evidence: , confidence: 0.0}}, allergy_history: {{value: , evidence: , confidence: 0.0}}, family_history: {{value: , evidence: , confidence: 0.0}}, medication_history: {{value: , evidence: , confidence: 0.0}}, missing_fields: [], need_human_review: [] }} app.post(/emr/extract)defextract_emr(req:ExtractRequest):responseclient.chat.completions.create(modelgpt-4o-mini,temperature0.1,messages[{role:system,content:SYSTEM_PROMPT},{role:user,content:build_user_prompt(req.raw_text)}])contentresponse.choices[0].message.content resultjson.loads(content)validatedEmrExtractResult(**result)return{patient_visit_id:req.patient_visit_id,draft_extract:validated.model_dump(),status:pending_review}这个接口只返回待审核草稿不直接写入正式病历。工程上建议把 LLM 原始响应、Prompt 版本、模型版本、调用时间都记录下来方便追溯和回放。实现步骤三摘要生成不要脱离证据摘要生成常见问题是“写得像病历但找不到出处”。建议摘要 Agent 只基于已抽取字段和证据片段生成不直接基于完整原文自由发挥。摘要 Prompt 可以限制为根据已审核或待审核的结构化字段生成病史摘要。 不得新增输入中不存在的信息。 如果字段状态为 pending需要在摘要元数据中标记 pending_sourcetrue。 不得输出诊断、治疗、分诊或用药建议。摘要结果建议保存为{summary:患者主诉及病史摘要文本,source_fields:[chief_complaint,present_illness,past_history],pending_source:true,generated_at:2026-05-30T09:00:00}这样审核工作台可以明确提示摘要中包含未确认字段不能直接作为最终内容使用。审核工作台人工校对边界怎么设计审核界面至少需要展示四列信息原文片段模型抽取字段置信度或规则提示人工操作接受、修改、驳回建议增加字段级状态而不是整份病历一个状态。因为一段文本中主诉可能很明确过敏史可能缺失既往史可能需要人工确认。常见操作流程如下医生或质控人员打开待审核记录。系统高亮每个字段对应的 evidence。审核人员逐字段确认。修改记录写入审计日志。全部必要字段确认后才允许回填正式 EMR。对于“缺失字段提示”“冲突字段提示”等规则应写成可配置策略。例如如果过敏史字段为空系统只提示“该字段缺失需人工确认”不能推断患者不存在过敏史。向量库在这里解决什么问题vector store 不建议直接存患者隐私文本除非完成脱敏、权限控制和合规评估。更常见的用途是存储以下内容字段填写样例科室常用病史模板机构认可的术语规范Prompt few-shot 示例抽取时先检索相似模板再拼入 Prompt可以提升字段格式稳定性。例如同一机构希望“过敏史”统一写成“否认 / 明确药物或食物 / 不详”就可以通过模板约束输出。踩坑与调试建议第一JSON 解析失败要单独处理。LLM 偶尔会输出多余文本生产环境建议使用 JSON schema response 或函数调用能力。第二不要只看字段是否非空还要看 evidence 是否能支持 value。可以写一个一致性检查 Agent专门判断“字段值是否能从证据片段推出”。第三Prompt 要版本化。字段定义、规则说明、示例文本变化后历史结果必须能追溯到当时的 Prompt 版本。第四脱敏要前置。日志、向量库、调试平台中都不应裸存敏感身份信息。真实项目还需结合机构安全规范、访问控制和审计要求。性能与扩展取舍如果每份病历都串行调用多个 Agent延迟会比较高。工程上可以把流程拆成同步和异步两部分字段抽取同步返回摘要生成和一致性检查放入队列异步执行。对于短文本门诊记录可以一次性抽取全部字段。对于较长住院记录建议先分段再按字段路由到不同抽取任务最后合并结果。合并时要保留来源段落避免摘要阶段丢失依据。成本方面可以将模板检索、规则校验、字段完整性检查放在本地完成只把需要语义理解的部分交给 LLM。这样既能减少 token也便于做稳定性测试。总结与下一步Agent 辅助电子病历落地的关键不是让模型替代人工录入而是把自由文本整理成可审核、可追溯、可回填的候选结构化数据。推荐的工程路径是固定 Schema、证据片段绑定、草稿与正式数据隔离、字段级审核、Prompt 与模型版本可追溯。下一步可以继续完善三块能力脱敏与权限控制、审核工作台交互、字段一致性评估。只要把医疗专业判断留在人工和机构规范内Agent 就能作为提升录入效率和文本整理质量的工程组件。本文文献检索、文献挖掘以及文献翻译采用的是【超能文献| AI文献检索|AI文档翻译】。