Go 语言构建Ambient AI 病历自动生成系统研讨(上)

Go 语言构建Ambient AI 病历自动生成系统研讨(上)

一、整体架构:用 Go 做“中心大脑”

您提出的四层架构非常经典且精准。我们的核心就是要把 Go 语言的优势发挥在「业务服务层」和「集成层」,让它成为整个 AI 流程中那个最可靠、最高效的“交通枢纽”和“中央处理器”。

1.1 架构全景图(文字版)

为了便于理解,我们先在脑海里构建一张架构图:


+----------------+      +----------------+      +----------------+      +------------------+
|   采集层      |      |   AI 处理层    |      |  业务服务层    |      |    集成层       |
| (IoT / App)   |----->| (ASR / LLM)    |<----->|  (Go Core)     |----->| (HIS / EMR / FHIR)|
|                |      |                |      |                |      |                  |
| - 诊室麦克风   |      | - 科大讯飞/阿里 |      | - gateway      |      | - HL7 v2/v3      |
| - 医生 App     |      | - OpenAI GPT-4 |      | - session      |      | - FHIR R4        |
| - 患者小程序   |      | - 自研医疗模型 |      | - nlp-service  |      | - 厂商私有 API   |
| - 床旁交互屏   |      |                |      | - emr-service  |      |                  |
| - 护士工作站   |      |                |      | - audit        |      |                  |
+----------------+      +----------------+      +----------------+      +------------------+
       ^                         ^                       ^                         ^
       | 音频流                  | 文本/结构化数据         | RPC/HTTP 请求           | API 调用
       |                         |                       |                         |
(医院内网 / 专线)         (GPU 集群 / 公有云)         (K8s 集群 / 裸金属)        (医院数据中心)

1.2 Go 的定位与核心价值

为什么 Go 是这个“中心大脑”的最佳人选?

高并发与高性能:一个中型医院可能有上百个诊室、上千个床位同时进行语音采集。Go 的 Goroutine 和 Channel 模型能以极低的资源开销处理成千上万的并发连接(WebSocket 长连接、gRPC 流),这是 Python 等传统解释型语言难以比拟的。微服务生态的天然契合:Go 的编译速度快、部署简单(单一二进制文件)、内置强大网络库。结合
gRPC

protobuf

Gin
等框架,可以轻松构建出清晰、高效、松耦合的微服务集群。稳定性与可维护性:Go 的静态类型和强约束语法,能在编译期发现大量潜在错误。这对于需要 7×24 小时稳定运行、且不容有失的医疗系统至关重要。一个由 Go 构建的后端,在长期维护上具有显著优势。“胶水语言”的卓越能力:AI 模型(ASR, NLP)多半是 Python 实现,集成层(HIS/EMR)接口五花八门。Go 极其擅长作为“胶水”,通过标准化的 HTTP/gRPC 客户端与这些异构系统进行高效、可靠的通信,并进行协议转换、数据聚合与分发。

1.3 数据流与控制流

让我们以一个数据包的生命周期,来理解 Go 在其中的作用:

数据上行

音频数据
->
采集层
-> (WebSocket) ->
gateway-service
(Go, 负载均衡、鉴权) -> (gRPC Streaming) ->
asr-adapter-service
(Go, 音频缓冲、转发) -> (HTTP/WebSocket) ->
AI 处理层
(ASR 引擎)。
AI 处理与下行

ASR 引擎
->
转写文本结果
-> (HTTP Callback/gRPC Stream) ->
asr-adapter-service
(Go, 组装结果、时间戳对齐) -> (消息队列) ->
session-service
(Go, 持久化存储) &
nlp-medical-service
(Go, 拉取对话,触发 NLP)。
业务处理与集成

nlp-medical-service
->
调用 LLM API
->
LLM 返回结构化病历
->
nlp-medical-service
(Go, 校验、模板渲染) ->
gateway-service
->
前端展示
(医生编辑) ->
医生提交
->
gateway-service
->
emr-integration-service
(Go, 调用 HIS/EMR API) ->
HIS/EMR 系统

在这个流程中,Go 服务负责了几乎所有的状态管理、流程编排、数据校验、协议转换和外部系统集成工作,是整个系统的“骨架”和“神经中枢”。


二、核心模块设计(Go 为主的服务拆分)

将庞大的系统拆分为职责单一的小服务,是“真落地”的第一步。这便于团队并行开发、独立部署和故障隔离。

2.1 服务拆分粒度原则

按业务能力拆分:每个服务对应一个明确的业务领域(如“会话管理”、“EMR集成”)。数据所有权分离:每个服务拥有自己独立的数据库表,避免跨服务的数据库直接耦合。高内聚、低耦合:服务内部逻辑紧密关联,服务间通过明确的 API(gRPC/REST)通信。可独立运维:单个服务可以独立进行扩缩容、升级和监控。

2.2 详细服务设计

1.
gateway-service
(API 网关)

职责
系统的统一入口,所有来自外部的请求都必须经过它。身份认证与鉴权(验证医生/护士的 Token)。权限控制(基于 Casbin,判断该医生是否有权限访问该患者的数据)。请求路由(将
/api/v1/sessions
的请求转发给
session-service
)。流量控制与熔断(防止恶意请求或后端服务雪崩)。请求/响应日志记录。
Go 技术选型
Web 框架
Gin

Echo
。性能极高,中间件生态丰富。
Gin
社区更大,文档更全,可作为首选。鉴权
golang-jwt/jwt
库处理 JWT Token 的生成和解析。权限控制
Casbin
。强大的访问控制框架,支持 ACL、RBAC 等多种模型。我们可以将权限策略(如
doctor, 123, patient, 456, read
)存储在数据库或配置文件中。服务发现:如果使用 Kubernetes,可以利用其 Service 机制。如果是裸机部署,可以引入
Consul

Etcd
限流熔断
go-kratos/aegis

sentinel-golang

核心接口示例


// POST /api/v1/sessions
// Body: {"patientId": "P12345", "deptId": "D01", "type": "outpatient"}
// Response: {"sessionId": "sess_xxx", "wsUrl": "wss://.../asr/sess_xxx"}
func (h *SessionHandler) CreateSession(c *gin.Context) { ... }

// WebSocket /ws/asr/{sessionId}
// 用于前端建立音频流长连接
func (h *ASRHandler) HandleAudioStream(c *gin.Context) { ... }
2.
session-service
(会话 & 录音管理)

职责
核心业务实体管理:
Session
(问诊/查房会话)、
Turn
(对话轮次)、
Recording
(录音文件)。创建、查询、更新、结束会话。绑定会话与参与者(医生、患者、科室)。管理录音文件元数据(存储地址、时长、格式、MD5)。与
asr-adapter-service
协同,将转写结果与
Turn
关联。
Go 技术选型
框架
gRPC
。作为内部核心服务,gRPC 的高性能和强类型接口是首选。数据库
PostgreSQL
。强一致性,支持 JSONB 字段,非常适合存储半结构化的转写文本和病历草稿。ORM
GORM
。功能强大,社区活跃,能极大提高数据库操作效率。消息队列
NATS

RabbitMQ
。用于接收来自
asr-adapter-service
的转写结果,实现异步处理,避免阻塞。
Proto 定义示例


service SessionService {
    rpc CreateSession(CreateSessionRequest) returns (CreateSessionResponse);
    rpc GetSession(GetSessionRequest) returns (GetSessionResponse);
    rpc EndSession(EndSessionRequest) returns (EndSessionResponse);
    rpc AddTranscription(AddTranscriptionRequest) returns (google.protobuf.Empty);
}

message Session {
    string session_id = 1;
    string doctor_id = 2;
    string patient_id = 3;
    string department_id = 4;
    SessionType type = 5; // OUTPATIENT, INPATIENT_WARD
    google.protobuf.Timestamp start_time = 6;
    google.protobuf.Timestamp end_time = 7;
    SessionStatus status = 8; // ACTIVE, ENDED, PROCESSING, COMPLETED
}
3.
asr-adapter-service
(语音识别适配层)

职责
纯粹的适配器,不执行任何 ASR 算法。通过 WebSocket 接收来自前端的音频流。处理音频格式转换(如前端 WebM 转 PCM)、分帧。建立与 ASR 引擎(云服务或自建)的连接。流量整形与容错
将前端音频流可靠地转发给 ASR 引擎。处理 ASR 引擎的部分转写结果和最终结果。实现断线重连、心跳检测机制。当 ASR 引擎响应超时或失败时,发送错误通知。
将带有时间戳的最终转写文本,通过消息队列发送给
session-service

Go 技术选型
WebSocket
gorilla/websocket
,事实上的标准库。并发模型:每个 WebSocket 连接一个 Goroutine,完美适配 Go 模型。HTTP 客户端:标准库
net/http

fasthttp
(如果对性能有极致要求)。配置管理
Viper
,用于动态加载不同 ASR 厂商的 API Key、URL 等配置。
核心逻辑伪代码


func (s *ASRServer) HandleWS(w http.ResponseWriter, r *http.Request) {
    conn, _ := upgrader.Upgrade(w, r, nil)
    defer conn.Close()

    // 1. 从路径中获取 sessionId
    sessionId := ...

    // 2. 建立 ASR 引擎连接
    asrClient := s.createASRClient(sessionId)

    // 3. 启动两个 goroutine 进行双向数据转发
    // a) 读取前端音频,发给 ASR
    go func() {
        for {
            messageType, audioData, err := conn.ReadMessage()
            if err != nil { break }
            asrClient.SendAudio(audioData)
        }
    }()

    // b) 读取 ASR 结果,发给前端并持久化
    for {
        result, err := asrClient.ReceiveResult()
        if err != nil { break }
        
        // 发送实时字幕给前端
        conn.WriteJSON(result) 

        // 如果是最终结果,发给 session-service
        if result.IsFinal {
            s.producer.Publish("transcription.queue", result)
        }
    }
}
4.
nlp-medical-service
(医疗文本理解 & 病历草稿生成)

职责
LLM/医疗 NLP 模型的“指挥官”。订阅
session-service
发出的“会话结束”消息。拉取完整的对话文本(带说话人标签 D/P)。Prompt Engineering:构建高质量的 Prompt,指导 LLM 生成符合医学规范的病历。Prompt 中应包含:
角色定义:“你是一名资深内科医生…”任务描述:“根据以下医患对话,生成一份结构化的门诊病历初稿…”输出格式要求:严格的 JSON Schema,定义
chief_complaint
,
history_of_present_illness
等字段。对话原文。(可选)患者历史信息摘要。
调用 LLM API(OpenAI, Azure, 或自建模型)。结果后处理与校验
解析 LLM 返回的 JSON。如果解析失败,进行重试或降级处理。根据内置规则进行校验(例如,主诉不能为空,诊断编码格式正确)。进行术语标准化(如“感冒” -> “上呼吸道感染”)。将结构化结果存入数据库,并更新
session
状态为
COMPLETED

Go 技术选型
LLM 客户端
go-openai
库(如果使用 OpenAI 系列),或自行封装 HTTP Client 调用其他 API。JSON Schema 校验
jsonschema
库,可以验证 LLM 返回的 JSON 是否符合预期结构。规则引擎:可以自己实现一个简单的
map[string]func(string)string
来做术语标准化,复杂场景可引入
go-ruleengine
消息队列消费者
stan.go
(NATS Streaming) 或
amqp
(RabbitMQ)。
接口抽象(关键!)
为了方便切换不同的 LLM 供应商,定义接口是必须的:


type LLMClient interface {
    GenerateEMR(ctx context.Context, req *GenerateEMRRequest) (*GenerateEMRResponse, error)
}

type GenerateEMRRequest struct {
    Dialog     []Turn  `json:"dialog"`
    TemplateID string  `json:"template_id"` // "outpatient_respiratory"
    PatientInfo *PatientInfo `json:"patient_info,omitempty"`
}

type GenerateEMRResponse struct {
    Draft *EMRDraft `json:"draft"`
    Raw   string    `json:"raw"` // LLM 原始返回,用于调试
}

// --- 实现一个 OpenAI 客户端 ---
type OpenAIClient struct {
    client *openai.Client
}

func (c *OpenAIClient) GenerateEMR(ctx context.Context, req *GenerateEMRRequest) (*GenerateEMRResponse, error) {
    // 1. 构建 Prompt
    prompt := buildPrompt(req)
    // 2. 调用 OpenAI API
    resp, err := c.client.CreateChatCompletion(...)
    // 3. 解析响应,填充 GenerateEMRResponse
    // ...
}

// --- 在 service 中使用 ---
type NLPService struct {
    llmClient LLMClient
}

// 通过依赖注入,可以轻松切换 LLMClient 的具体实现
5.
emr-integration-service
(EMR 集成服务)

职责
“翻译官”和“信使”,负责将我们的数据“翻译”成目标系统能懂的语言,并可靠地送达。维护与多家医院、多种 EMR 系统的适配器。字段映射:将我们的
EMRDraft
JSON 结构,映射到目标 EMR 的字段。这通常需要复杂的配置。协议转换:处理 REST API、SOAP、HL7 v2 MLLP、FHIR 等不同协议。调用 EMR 接口并处理响应。提供“补偿机制”:如果写入失败(如 EMR 系统维护),自动重试,或转为人工介入任务。记录每一次调用的详细日志和回执。
Go 技术选型
HTTP/REST 客户端
net/http

resty
SOAP 客户端
github.com/hooklift/gowsoapservice
HL7 v2
github.com/ghetzel/go-stockutil/stringutil
或更专业的库(可能需要寻找或自建)来解析和构建 HL7 消息。FHIR
github.com/samply/golang-fhir-models
提供了数据结构定义,配合 HTTP 客户端使用。任务调度与重试
Asynq

go-queue
。将 EMR 写入操作作为异步任务,支持延时重试、死信队列。
核心设计 – 适配器模式


type EMRWriter interface {
    Write(ctx context.Context, session *Session, draft *EMRDraft) (*WriteResult, error)
    GetCapabilities() *Capabilities // 返回该EMR支持的功能
}

// 为某家医院的某款EMR实现适配器
type VendorAEMRWriter struct {
    baseURL string
    apiKey   string
    mapping  map[string]string // 字段映射配置
}

func (w *VendorAEMRWriter) Write(ctx context.Context, session *Session, draft *EMRDraft) (*WriteResult, error) {
    // 1. 根据 mapping 将 draft 转换为 VendorA API 需要的格式
    payload := w.mapToVendorAFormat(session, draft)
    
    // 2. 调用 VendorA 的 REST API
    resp, err := resty.R().SetBody(payload).Post(w.baseURL + "/api/emr")
    
    // 3. 解析响应,返回统一的 WriteResult
    return &WriteResult{Success: err == nil, Message: resp.String()}, nil
}

// --- 在 service 中使用 ---
type IntegrationService struct {
    // 假设我们对接多家医院
    writers map[string]EMRWriter // key: hospital_id
}
6.
audit-log & monitoring-service
(审计 / 日志 / 监控)

职责
数据不可篡改的记录者。所有关键操作(创建会话、生成病历、写入EMR)都必须有日志。接收来自其他服务的审计事件(通过消息队列)。将审计日志写入独立的、高可靠性的存储(如 Elasticsearch 或专门的日志数据库)。监控大脑
自身暴露
/metrics
接口(Prometheus 格式)。聚合其他服务的指标。配置告警规则(如病历生成失败率超过5%)。

Go 技术选型
日志库
zap

zerolog
。高性能、结构化日志,是 Go 服务首选。Metrics 库
prometheus/client_golang
。业界标准。存储
Elasticsearch
。强大的日志检索和分析能力,配合
Kibana
做可视化。Tracing
OpenTelemetry-Go
。实现分布式链路追踪,定位性能瓶颈和错误根源。


三、Go 技术选型(总览与深化)

这一节,我们汇总并深化之前提到的技术选型,形成一个完整的技术栈。

分类 技术 选择理由 Go 相关库/工具
Web/API REST API 对外提供标准接口,前端调用方便
Gin
/
Echo
gRPC 内部服务间通信,高性能、强类型
grpc-go
,
protoc-gen-go
WebSocket 实时音频流、实时字幕推送
gorilla/websocket
数据存储 SQL (PostgreSQL) 存储核心业务数据,支持事务和JSONB
GORM
,
pgx
Cache (Redis) 存储会话状态、Token、热点数据
go-redis
Object Storage (MinIO/S3) 存放海量录音文件,成本低,易扩展
aws-sdk-go
(兼容MinIO)
Message Queue (NATS) 服务解耦,异步处理,削峰填谷
stan.go
,
nats.go
Search/Log (Elasticsearch) 存储和检索审计日志、对话文本
olivere/elastic
AI 对接 LLM Client 调用大模型生成病历
go-openai
,
resty
ASR Client 适配多种语音识别服务
net/http
,
websocket
可观测性 Metrics (Prometheus) 收集系统性能指标,监控告警
prometheus/client_golang
Logging (Loki/ELK) 集中式日志管理
zap
,
zerolog
Tracing (Jaeger) 分布式链路追踪
OpenTelemetry-Go
安全/配置 Auth (JWT) 无状态认证
golang-jwt/jwt
Permission (RBAC) 细粒度权限控制
Casbin
Config (Viper) 管理不同环境下的配置
Viper
部署 Container (Docker) 环境一致性,方便打包分发
Dockerfile
,
Docker Compose
Orchestration (K8s) 自动化部署、扩缩容、故障自愈 Kubernetes
CI/CD 自动化测试、构建、部署
GitHub Actions
,
GitLab CI

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...