健康咨询 Agent 工作流设计

医疗健康场景下 AI 咨询 Agent 的工作流设计:为什么不能用纯 LLM 自由对话、意图分类方案选型、阶段推进条件设计、安全检测插入点。

#type / concept #status / growing #tech / ai

[!info] related notes

健康咨询 Agent 工作流设计

这篇解决什么问题

用 AI 做健康咨询,最简单的方案是”用户说什么,LLM 就回什么”。但在医疗健康场景,纯自由对话有几个致命问题:

  1. 信息收集不可控 — 用户说”我肩膀疼”,LLM 可能直接给诊断,跳过必要的信息收集
  2. 阶段不可控 — 用户还没确认诊断,LLM 就生成治疗方案
  3. 安全检测无处插入 — 没有明确的”检测点”来判断是否有危险症状
  4. 质量不可审计 — 完全依赖 LLM 的”判断”,无法验证是否收集了足够信息

所以需要一个显式的工作流来控制对话的推进。

核心设计:四阶段状态机

collecting → analysis_ready → diagnosis_confirmed → treatment_generated
  (收集)        (可分析)          (确认诊断)          (生成方案)

每个阶段有明确的进入条件允许的动作

阶段进入条件允许的动作
collecting新会话收集症状、追问细节
analysis_ready至少一个症状 + 一个细节生成诊断、继续追问
diagnosis_confirmed用户确认诊断生成治疗方案
treatment_generated方案已生成讨论方案、复评

关键决策:阶段推进必须有硬性条件,不能靠 LLM “觉得信息够了”。

意图分类:方案选型

用户消息进来后,第一步是分类意图(用户想干什么)。三种方案:

方案 A:正则关键词匹配

PATTERNS = [
    (r"(分析|诊断|判断|看看)", REQUEST_ANALYSIS, 0.8),
    (r"(确认|同意|是的|)", CONFIRM_DIAGNOSIS, 0.8),
    (r"(方案|改善|治疗|训练)", REQUEST_TREATMENT, 0.8),
]
  • 优点:极快(<1ms)、确定性、可审计
  • 缺点:覆盖面有限、无法理解复杂表述
  • 适用:意图类型少、表述相对固定的场景

方案 B:LLM 分类

把用户消息和意图列表发给 LLM,让它返回分类结果。

  • 优点:理解复杂表述、覆盖面广
  • 缺点:慢(1-3s)、有成本、结果不确定
  • 适用:意图类型多、表述灵活的场景

方案 C:混合方案(推荐)

先用正则快速匹配高置信度意图,匹配不到再用 LLM:

def classify_intent(message, context):
    # 快速路径:正则匹配
    for pattern, intent, confidence in PATTERNS:
        if re.search(pattern, message):
            if confidence >= 0.7:
                return intent

    # 慢速路径:LLM 分类
    return await llm_classify(message, context)

这样大多数常见意图走快速路径,只有模糊表述才调 LLM。

信息收集完整性判断

不要用”对话轮数”判断信息够不够,要用结构化数据判断:

def is_info_sufficient(extracted_info: list[Symptom]) -> bool:
    for symptom in extracted_info:
        if not symptom.body_part:
            continue
        # 至少有部位 + 一个维度的细节
        has_detail = any([
            symptom.symptom_type,   # 疼痛/酸胀/麻木
            symptom.duration,       # 持续时间
            symptom.trigger,        # 触发场景
            symptom.severity,       # 严重程度
        ])
        if has_detail:
            return True
    return False

设计要点

  • 用 Function Calling 提取结构化症状,而不是从文本里猜
  • 提取是增量的——每轮对话都可能补充新信息
  • 完整性检查基于结构化字段,不是”用户说了几句话”

Function Calling 提取症状

SYMPTOM_TOOL = {
    "name": "extract_symptom_info",
    "description": "从对话中提取结构化症状信息",
    "parameters": {
        "type": "object",
        "properties": {
            "body_part": {"type": "string", "description": "身体部位"},
            "symptom_type": {"type": "string", "description": "症状类型"},
            "duration": {"type": "string", "description": "持续时间"},
            "trigger": {"type": "string", "description": "触发场景"},
            "severity": {"type": "string", "description": "严重程度"},
        },
        "required": ["body_part"],
    },
}

LLM 在对话过程中自动调用这个工具,提取到的结构化数据用于:

  1. 驱动阶段推进(is_info_sufficient)
  2. 注入后续 prompt(让 LLM 知道已经收集了什么)
  3. 渲染到 UI(人体可视化面板)

安全检测插入点

Red Flag 检测必须在 LLM 生成回复之前 执行:

用户消息

Red Flag 检测 → (命中) → 立即推送安全警告 SSE 事件

意图分类 → 动作决策 → RAG 检索 → LLM 生成 → 推送回复

不能依赖 LLM 自己判断”用户描述的症状很严重”——LLM 可能漏判,而且用户需要在看到 LLM 回复之前就看到安全警告。

完整的单轮处理流程

1. 收到用户消息
2. Red Flag 检测(关键词匹配,<1ms)
3. 如果有 red flag → 推送 red_flag SSE 事件
4. 意图分类(正则 + LLM 混合)
5. 动作决策(意图 + 当前阶段 → 下一步动作)
6. RAG 检索(带意图感知重排)
7. Function Calling 提取症状
8. LLM 生成回复(流式)
9. 推送 text / extracted_info / phase_changed SSE 事件
10. 更新会话状态

与纯 LLM 方案的对比

维度纯 LLM显式工作流
信息收集依赖 LLM “判断”硬性条件检查
阶段推进LLM 自行决定状态机控制
安全检测LLM 自己判断独立模块,先于 LLM
可审计性黑盒每步有决策依据
灵活性极高受限于预定义流程
开发成本中等

推荐:医疗健康场景用显式工作流,一般聊天场景用纯 LLM 就够。

常见错误

用对话轮数判断信息够不够

# ❌
if len(messages) >= 6:
    generate_diagnosis()

# ✅
if is_info_sufficient(extracted_info):
    generate_diagnosis()

让 LLM 决定是否推进阶段

# ❌ prompt 里写"你觉得信息够了就生成诊断"
# LLM 可能在第 1 轮就"觉得够了"

# ✅ 代码里检查结构化数据
if not is_info_sufficient(extracted_info):
    return ask_follow_up()

Red Flag 检测放在 LLM 之后

# ❌ 先让 LLM 回复,再检查 red flag
response = await llm.chat(messages)
if has_red_flag(user_message):
    response = add_warning(response)

# ✅ 先检测,再生成
if has_red_flag(user_message):
    yield red_flag_event(...)
response = await llm.chat(messages)  # LLM 回复正常内容
创建于 2026/6/25 更新于 2026/6/25