4. AI模型在线推理服务封装

训练完成的AI模型要真正进入PACS阅片流程,必须被封装成一个可被RIS、后处理工作站或临床浏览器稳定调用的在线推理服务。这一节围绕模型格式转换、推理引擎选型、接口协议设计、请求响应协议、批处理与流式推理以及健康检查六个环节展开,目标是让读者理解从“一个权重文件”到“一个可运维服务”的完整工程链路。

一、模型格式转换:从训练产物到推理产物

训练框架产出的权重(如PyTorch的.pt、TensorFlow的SavedModel)通常带有训练期依赖,直接加载会引入大量冗余算子与动态图开销。工程上一般先做图固化,再转成推理引擎可识别的中间格式。以PyTorch为例,典型流程是:torch.jit.trace或torch.jit.script导出TorchScript,再用ONNX导出为.onnx,最后用TensorRT或OpenVINO编译为引擎文件。

# 示例:PyTorch 导出 ONNX(肺结节分类模型)
dummy = torch.randn(1, 1, 128, 128, 128).cuda()
torch.onnx.export(
    model, dummy, "nodule_cls.onnx",
    input_names=["ct_patch"], output_names=["logits"],
    dynamic_axes={"ct_patch": {0: "batch"}, "logits": {0: "batch"}},
    opset_version=17
)
# TensorRT 编译(FP16)
trtexec --onnx=nodule_cls.onnx --saveEngine=nodule_cls_fp16.plan \
        --fp16 --minShapes=ct_patch:1x1x128x128x128 \
        --optShapes=ct_patch:8x1x128x128x128 \
        --maxShapes=ct_patch:32x1x128x128x128

转换后必须做数值一致性校验:用同一批测试数据分别跑原始模型与推理引擎,比较输出最大绝对误差。分类模型一般要求max|Δlogits| < 1e-3,分割模型要求Dice下降不超过0.002。若误差超标,优先检查算子替换(如自定义算子回退到CPU)、精度模式(FP16溢出)和预处理是否一致。

二、推理引擎选型

选型要同时看硬件、模型类型和并发规模。GPU场景下TensorRT延迟最低,适合3D卷积类模型;CPU场景OpenVINO对Intel平台优化充分;跨平台部署可用ONNX Runtime,兼容性好但峰值性能略低。PACS场景常出现“白天高并发、夜间批量补算”的潮汐特征,因此建议保留ONNX Runtime作为兜底引擎,主引擎按硬件择优。

三、RESTful与gRPC接口设计

RESTful适合与前端、PACS Web服务集成,调试直观;gRPC基于HTTP/2与Protobuf,适合服务间高频调用和大体积张量传输。一个常见组合是:对外暴露RESTful供临床浏览器调用,内部推理节点之间用gRPC。接口设计要遵循“资源化”原则,例如:

  • POST /v1/inference/tasks:提交推理任务,返回task_id;
  • GET /v1/inference/tasks/{task_id}:查询状态与结果;
  • GET /v1/models:列出已加载模型及版本;
  • GET /healthz、GET /readyz:健康与就绪探针。

四、请求响应协议

医学影像请求体通常包含study_uid、series_uid、model_name、model_version、window(窗宽窗位)、roi(可选)和callback_url。响应体应包含task_id、status、result(如结节坐标、直径、恶性概率)、inference_ms和engine。所有字段建议用JSON Schema约束,并对DICOM UID做格式校验,避免脏数据进入推理队列。

五、批处理与流式推理

批处理通过动态批处理(dynamic batching)把短时间内到达的多个请求合并成一个batch,显著提升GPU利用率。例如设置max_batch_size=16、max_queue_delay=20ms,在延迟与吞吐之间取平衡。流式推理则适用于大体积序列或需要边推理边回传的场景,可用gRPC server streaming按切片返回中间结果,前端逐步渲染。

六、服务健康检查

健康检查分三层:进程存活(/healthz)、模型就绪(/readyz,确认引擎已加载且显存充足)、业务可用(用一条固定测试样本做端到端推理,校验输出在预期范围内)。Kubernetes中livenessProbe指向/healthz,readinessProbe指向/readyz,并设置合理的initialDelaySeconds,避免模型加载期间被误杀。

AI模型在线推理服务封装链路 训练产物 .pt / SavedModel 格式转换 TorchScript→ONNX →TensorRT/OpenVINO 推理引擎选型 TensorRT / OpenVINO ONNX Runtime 兜底 服务封装 RESTful + gRPC 动态批处理/流式 请求协议(JSON) study_uid / series_uid model_name / model_version window / roi / callback_url 校验:UID格式、字段必填 响应协议(JSON) task_id / status result:坐标/直径/概率 inference_ms / engine 错误码:400/422/503 健康检查三层 /healthz:进程存活 /readyz:模型就绪+显存 业务探针:固定样本端到端 K8s liveness / readiness 批处理与流式推理调度 动态批处理 max_batch=16 max_delay=20ms 流式推理 gRPC server streaming 按切片返回中间结果 结果回传 callback_url 异步通知 或轮询 task_id
工程建议:模型版本号必须与引擎文件、预处理参数、后处理阈值绑定为同一“推理包”,任何一项变更都要重新走数值一致性校验,避免线上出现“模型换了但阈值没换”的隐性错误。

把上述环节串起来,一个可上线的推理服务应具备:明确的模型版本与引擎文件、受Schema约束的请求响应、可配置的批处理参数、可观测的延迟与吞吐指标,以及分层的健康检查。只有这些要素同时到位,AI推理才能真正嵌入PACS的日常阅片流程,而不是停留在实验室脚本阶段。