用 Amazon Bedrock 和 AWS HealthLake 搭建智能理赔流水线

2026-06-30 34 预计阅读时间: 1 分钟
来源: aws.amazon.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:10 分钟

医疗理赔处理最怕两件事:表单信息散落在 PDF、扫描件和附件里,人工录入又慢又容易出错。这个方案的核心变化是把“读单据、抽字段、校验、转成标准医疗数据”串成一条自动化流水线:Amazon Bedrock Data Automation 负责从理赔表单中提取结构化信息,Amazon Bedrock AgentCore 托管 AI Agent 来做校验和转换,最后把结果写入 AWS HealthLake 中的 FHIR 资源。

这不是简单的 OCR。理赔表单通常包含患者信息、服务日期、诊断代码、费用项目、服务提供方、保险计划等字段,很多字段之间还存在业务约束。Agentic pipeline 的价值在于:抽取之后还有一个可以执行规则、调用工具、补齐上下文并输出标准格式的智能处理层。

流水线里每个组件做什么

一个典型流程可以拆成四段:

  1. 文档进入对象存储:理赔表单、附件、扫描件上传到 Amazon S3。
  2. Bedrock Data Automation 抽取信息:从 claim form 中识别患者、服务、诊断、账单等结构化字段。
  3. AgentCore 托管的 Agent 做验证和转换:检查必填字段、日期范围、代码格式、金额一致性,并把结果映射为 FHIR 资源。
  4. 写入 AWS HealthLake:把验证通过的数据以 FHIR JSON 的形式导入或写入 HealthLake,便于后续检索、分析和互操作。

这里的关键是职责边界:Data Automation 专注“从文档里读出内容”,Agent 专注“理解这些内容是否合理,以及如何变成系统可用的数据”。这能避免把复杂业务规则塞进单纯的 OCR 或解析逻辑里。

为什么要转成 FHIR,而不是自定义 JSON

理赔数据如果只停留在自定义 JSON,短期看很灵活,长期会变成每个系统都要写一次适配器。FHIR 的意义在于把医疗数据放进一套行业通用的资源模型中。

在理赔场景里,常见映射可能包括:

  • 患者基本信息可以映射到 Patient
  • 医疗服务提供方可以映射到 PractitionerOrganization
  • 理赔请求可以映射到 Claim
  • 诊断、服务项目、金额、保险信息可以进入 Claim 的相关字段。

实际项目里不建议让模型“自由发挥”生成 FHIR。更稳妥的做法是让 Agent 只负责受控转换:输入结构、输出 schema、校验规则、失败原因都要明确。这样才能让自动化既快又可审计。

可以这样实践:用 Agent 校验并生成 FHIR Claim

下面是一个可改造的最小 Python 示例。它不依赖真实 AWS 调用,适合先在本地验证“抽取结果 → 校验 → FHIR Claim JSON”的处理逻辑。接入 Bedrock Data Automation 和 AgentCore 时,可以把 extracted_claim 替换成文档抽取结果,把 build_fhir_claim() 包装成 Agent 可调用工具。

运行前准备:

python -m venv .venv
source .venv/bin/activate
python claims_to_fhir.py

创建 claims_to_fhir.py

import json
from datetime import date

REQUIRED_FIELDS = [
    "claim_id",
    "patient_id",
    "patient_name",
    "provider_id",
    "service_date",
    "diagnosis_code",
    "procedure_code",
    "amount_usd",
]


def validate_claim(claim: dict) -> list[str]:
    errors = []

    for field in REQUIRED_FIELDS:
        if not claim.get(field):
            errors.append(f"Missing required field: {field}")

    if claim.get("amount_usd", 0) <= 0:
        errors.append("amount_usd must be greater than 0")

    if claim.get("service_date") > date.today().isoformat():
        errors.append("service_date cannot be in the future")

    if not str(claim.get("diagnosis_code", "")).startswith("ICD10:"):
        errors.append("diagnosis_code must use ICD10:<code> format")

    return errors


def build_fhir_claim(claim: dict) -> dict:
    errors = validate_claim(claim)
    if errors:
        return {
            "status": "validation_failed",
            "claim_id": claim.get("claim_id"),
            "errors": errors,
        }

    return {
        "resourceType": "Claim",
        "id": claim["claim_id"],
        "status": "active",
        "use": "claim",
        "patient": {
            "reference": f"Patient/{claim['patient_id']}",
            "display": claim["patient_name"],
        },
        "provider": {
            "reference": f"Organization/{claim['provider_id']}"
        },
        "created": date.today().isoformat(),
        "diagnosis": [
            {
                "sequence": 1,
                "diagnosisCodeableConcept": {
                    "coding": [
                        {
                            "system": "http://hl7.org/fhir/sid/icd-10-cm",
                            "code": claim["diagnosis_code"].replace("ICD10:", ""),
                        }
                    ]
                },
            }
        ],
        "item": [
            {
                "sequence": 1,
                "productOrService": {
                    "coding": [
                        {
                            "system": "http://www.ama-assn.org/go/cpt",
                            "code": claim["procedure_code"],
                        }
                    ]
                },
                "servicedDate": claim["service_date"],
                "net": {
                    "value": claim["amount_usd"],
                    "currency": "USD",
                },
            }
        ],
    }


extracted_claim = {
    "claim_id": "claim-10001",
    "patient_id": "patient-42",
    "patient_name": "Jane Doe",
    "provider_id": "provider-88",
    "service_date": "2024-05-17",
    "diagnosis_code": "ICD10:E11.9",
    "procedure_code": "99213",
    "amount_usd": 185.75,
}

print(json.dumps(build_fhir_claim(extracted_claim), indent=2))

这个示例刻意把校验和转换放在同一个小模块里,方便理解。在生产环境中,更推荐拆成三层:

  • 抽取层:只输出结构化字段和置信度。
  • 校验层:执行确定性规则,例如必填、格式、金额、日期、代码集。
  • 转换层:生成符合 HealthLake 接收要求的 FHIR JSON。

接入 AWS 时的工作流骨架

下面这个 Step Functions 风格的 YAML 是一个可改造的编排骨架,用来表达端到端流程。具体 API 名称、权限策略和资源 ARN 需要按你的 AWS 账户、Region、Bedrock Data Automation 项目和 HealthLake 数据存储配置调整。

Comment: Claims processing pipeline with Bedrock and HealthLake
StartAt: ExtractClaimDocument
States:
  ExtractClaimDocument:
    Type: Task
    Resource: arn:aws:states:::aws-sdk:bedrockdataautomation:startJob
    Parameters:
      InputS3Uri.$: $.document_s3_uri
      OutputS3Uri.$: $.extraction_output_s3_uri
      ProjectArn: arn:aws:bedrock:us-east-1:123456789012:data-automation-project/claims
    Next: RunClaimsAgent

  RunClaimsAgent:
    Type: Task
    Resource: arn:aws:states:::lambda:invoke
    Parameters:
      FunctionName: claims-agentcore-adapter
      Payload:
        extraction_output_s3_uri.$: $.extraction_output_s3_uri
    Next: CheckValidation

  CheckValidation:
    Type: Choice
    Choices:
      - Variable: $.Payload.status
        StringEquals: validation_failed
        Next: SendToManualReview
    Default: WriteToHealthLake

  WriteToHealthLake:
    Type: Task
    Resource: arn:aws:states:::lambda:invoke
    Parameters:
      FunctionName: write-fhir-to-healthlake
      Payload:
        fhir_resource.$: $.Payload.fhir_resource
    End: true

  SendToManualReview:
    Type: Task
    Resource: arn:aws:states:::sns:publish
    Parameters:
      TopicArn: arn:aws:sns:us-east-1:123456789012:claims-review
      Message.$: $.Payload.errors
    End: true

这段 YAML 的重点不是让你直接部署,而是给出分层方式:抽取任务、Agent 校验转换、失败分流、成功写入。医疗和保险系统里,“不能自动处理”的路径和“自动成功”的路径一样重要,因为异常样本通常需要审计、追踪和人工复核。

生产落地时别跳过这些边界

医疗理赔涉及敏感数据,自动化越强,治理要求越高。建议上线前至少检查这些点:

  • 最小权限:S3、Bedrock、Lambda、HealthLake、SNS 或 Step Functions 权限都应按资源和动作收窄。
  • 字段级审计:保留原始文档位置、抽取字段、置信度、校验错误和最终 FHIR 资源版本。
  • 人工复核通道:低置信度、金额异常、代码不匹配、缺失患者标识等情况必须可回退。
  • 确定性校验优先:日期、金额、代码集、必填字段不要只交给模型判断。
  • PHI 保护:日志、监控、调试样本和失败消息中避免泄露受保护健康信息。

这类架构的最佳切入点不是一上来追求“全自动理赔”,而是先选择格式稳定、规则明确、人工成本高的单据类型。让 Bedrock Data Automation 负责读文档,让 AgentCore 中的 Agent 负责受控推理和转换,再由 HealthLake 承接标准化数据。这样既能减少手工录入,又能保留医疗系统需要的准确性、可解释性和审计链路。


相关推荐