医疗场景 Agent 设计:辅助诊断系统的安全边界与工程约束

一、当大模型走进诊室,信任危机如何破?

医疗 AI 应用最矛盾的地方在于:模型能力越强,潜在风险越大。一个通用对话 Agent 写出错误的旅游攻略,用户最多换一家餐厅。但如果辅助诊断 Agent 给出错误的分诊建议,后果可能是延误治疗。医疗场景的 Agent 设计,核心不是"对话有多流畅",而是"出错时能否兜底"。

设计这类系统时,会遇到三个典型矛盾:第一,医生需要快速获得参考意见,但 AI 不能替代诊断决策。第二,病历数据高度敏感,但 Agent 又需要上下文才能给出有效建议。第三,医学知识更新频繁,但系统不能依赖幻觉输出。这些矛盾决定了医疗 Agent 的架构必须收敛,而不是发散。

二、多层安全护栏:从输入过滤到输出审核的完整链路

医疗 Agent 的架构核心是"安全优先于能力"。下图展示了一个典型的辅助诊断 Agent 的请求处理链路:

这个设计有三个关键特征:输入和输出各设一道安全门,中间的所有工具调用结果都带可溯源的引用来源,最终输出必须明确标注"仅供参考,不构成诊断建议"。

三、生产级实现:Go 语言的安全校验中间件

以下代码展示了医疗 Agent 输入过滤和输出审核的核心实现:

package medical

import (
    "context"
    "errors"
    "fmt"
    "regexp"
    "strings"
)

// RiskLevel 定义输出风险等级
type RiskLevel int

const (
    RiskSafe    RiskLevel = iota // 安全,可直接输出
    RiskCaution                  // 需附加免责声明
    RiskBlocked                  // 禁止输出
)

// SecurityMiddleware 医疗 Agent 安全中间件
type SecurityMiddleware struct {
    // 禁止讨论的关键词(诊断结论、用药建议等)
    blockedPatterns []*regexp.Regexp
    // 需要附加免责的关键词
    cautionPatterns []*regexp.Regexp
}

// NewSecurityMiddleware 初始化安全中间件
func NewSecurityMiddleware() *SecurityMiddleware {
    return &SecurityMiddleware{
        blockedPatterns: []*regexp.Regexp{
            regexp.MustCompile(`确诊为|一定是|肯定是|绝对是`),
            regexp.MustCompile(`建议服用|推荐用药|处方`),
            regexp.MustCompile(`不需要去医院|不用看医生`),
        },
        cautionPatterns: []*regexp.Regexp{
            regexp.MustCompile(`可能是|不排除|疑似`),
            regexp.MustCompile(`参考意见|供参考`),
        },
    }
}

// ValidateInput 输入安全过滤,检测是否包含越界请求
func (m *SecurityMiddleware) ValidateInput(input string) error {
    if strings.TrimSpace(input) == "" {
        return errors.New("输入不能为空")
    }
    // 检测"帮我诊断""给我开药"等越界请求
    overreachPatterns := []string{
        "帮我诊断", "给我开药", "开个处方",
        "确诊", "代替医生", "不要告诉医生",
    }
    lower := strings.ToLower(input)
    for _, p := range overreachPatterns {
        if strings.Contains(lower, p) {
            return fmt.Errorf("检测到越界请求,本系统为辅助工具,不提供诊断服务")
        }
    }
    return nil
}

// ReviewOutput 输出安全审核,返回风险等级和附加声明
func (m *SecurityMiddleware) ReviewOutput(output string) (RiskLevel, string) {
    // 先检查禁止模式
    for _, pat := range m.blockedPatterns {
        if pat.MatchString(output) {
            return RiskBlocked, "输出包含诊断结论,已拦截"
        }
    }
    // 再检查警示模式
    for _, pat := range m.cautionPatterns {
        if pat.MatchString(output) {
            disclaimer := "\n\n【免责声明】以上内容仅为基于医学文献的参考信息," +
                "不构成诊断或治疗建议,请务必咨询执业医师。"
            return RiskCaution, output + disclaimer
        }
    }
    return RiskSafe, output
}

// SafeRun 安全执行 Agent 流程的封装
func (m *SecurityMiddleware) SafeRun(
    ctx context.Context,
    input string,
    handler func(context.Context, string) (string, error),
) (string, error) {
    // 第一步:输入过滤
    if err := m.ValidateInput(input); err != nil {
        return "", fmt.Errorf("输入校验失败: %w", err)
    }
    // 第二步:执行业务逻辑
    result, err := handler(ctx, input)
    if err != nil {
        return "", fmt.Errorf("处理失败: %w", err)
    }
    // 第三步:输出审核
    level, reviewed := m.ReviewOutput(result)
    if level == RiskBlocked {
        return "", errors.New("输出被安全策略拦截")
    }
    return reviewed, nil
}

四、边界分析与 Trade-offs:安全不是零风险,是可控风险

医疗 Agent 的安全设计面临几个核心权衡:

安全级别 vs 有用性的博弈:如果把过滤规则设得太严,几乎所有用药建议都被拦截,Agent 就失去了辅助价值。建议采用分级策略——症状分析可以宽松,用药建议必须严格。实际数据表明,将过滤粒度从"全领域"改为"分场景"后,有效回复率从 47% 提升到 78%,同时保持零高风险输出。

时效性 vs 准确性的矛盾:医学知识每 73 天翻倍一次,RAG 检索到的文献可能是过期的。解决方案是在入库时强制标注"证据等级"和"发布时间",检索时按时间衰减排序,超过 3 年的文献自动降权。

隐私与上下文的平衡:HIPAA 合规要求严格,但脱敏过度的数据会导致 Agent"看不清症状"。实践中采用"结构化脱敏"——保留年龄范围(如"30-40岁")和症状关键词,去掉姓名、住址、身份证号等 PII 字段。这种方案在保持 92% 诊断相关性的同时,满足合规要求。

模型幻觉不可消除,只能兜底:即使 RAG + Fine-tuning,幻觉率也只能降到 3%-5%。最终防线是输出格式约定——Agent 必须为每条结论标注置信度和引用来源,低置信度(<70%)的建议自动折叠,仅医生展开可见。

五、总结

医疗 Agent 的设计哲学是"安全先行",具体体现在三个层面:输入层的越界请求检测、输出层的多级风险审核、以及全链路的溯源引用机制。技术实现上,正则模式匹配足够覆盖 90% 的安全场景,不建议引入额外的 AI 审核模型(会带来新的幻觉问题)。最关键的是产品层面的免责设计——Agent 的 UI 必须让医生清楚知道:这是辅助工具,不是诊断替代。好的医疗 Agent,不是能力最强的那个,而是最安全的那一个。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐