OpenClaw 在医疗行业:健康咨询机器人实战(合规+症状分析+用药提醒+RAG)
文章目录
摘要:医疗行业是 AI 落地最谨慎、试错成本最高的战场。本文以 OpenClaw 框架为骨架,从 HIPAA 与《个人信息保护法》的合规基线出发,搭建生产可用的健康咨询机器人:症状初步分析 Skill 用"规则引擎 + LLM 推理"双层架构识别危险信号;用药提醒 Agent 内置药物相互作用检查与定时调度;健康数据追踪通过 7/30 天趋势分析做指标预警;医疗 RAG 用权威性重排序 + 安全过滤阻断诊断性表述;三级分诊把"危急/紧急/常规"映射到立即转人工、尽快就医和自我护理。文章重点拆解"辅助而非替代"的设计哲学——医疗 AI 的边界不在能力上限,而在合规下限。
1. 引言:医疗 AI 为什么这么难做?
你有没有过这种体验——半夜三点突然不舒服,第一反应是打开手机搜症状,结果越搜越害怕?又或者在医院排队两小时,医生五分钟就看完,出来一堆想问的没问?这些痛点,恰恰是健康咨询机器人可以发力的地方。
但医疗 AI 真的太难做了。技术不是难点——大模型理解症状、给出建议早就不是问题。真正的难点浓缩为三个字:合规性。医疗关乎生命,任何一句"你得了 XX"都可能引发严重后果。所以你在设计医疗 AI Agent 时,首先要思考的不是"能做什么",而是"不能做什么"。
这就是本文的出发点。我们用 OpenClaw 框架来搭建一个健康咨询机器人,它能在合规边界内提供真正有价值的辅助服务:症状初步分析帮你判断紧急程度,用药提醒确保你不漏服,健康数据追踪让你对自身状态心中有数。同时它严格遵守"辅助不替代"原则——遇到紧急情况立刻转人工,绝不给诊断性结论,所有隐私数据全部脱敏。
这篇文章会比较长,因为医疗场景的每个环节都不能马虎。但跟着走完,你会对"如何在合规框架下落地医疗 AI"有一个完整的认知闭环:合规先行 → 规则兜底 → RAG 增强 → 多轮问诊 → 分诊转人工 → 持续审计。下面我们从概念拆解开始。
1.1 三个核心概念前置拆解
| 概念 | 通俗解释 | 医疗场景含义 |
|---|---|---|
| 辅助不替代(Augment, not Replace) | AI 是"分诊台",不是"医生" | 不出诊断结论,只描述症状相关性 |
| 合规先行(Compliance First) | 合规是设计约束,不是事后补丁 | 免责声明、隐私脱敏、审计日志必须在第一行业务代码前就位 |
| 规则兜底(Rule Fallback) | 危险信号由规则引擎硬保障,LLM 只做软辅助 | 即使模型漏判,规则也不会漏报 |
1.2 医疗 AI 的"五个不能"
⚠️ 在写任何业务代码之前,请先记住这五条合规红线,缺一不可:
- 不能给诊断性结论:可以说"症状可能与呼吸道感染相关",不能说"你得了肺炎"。
- 不能让用户跳过紧急转人工:胸痛、呼吸困难等危急信号必须立即建议拨打 120。
- 不能明文存储敏感数据:姓名、身份证、详细症状、用药记录都属于敏感个人信息。
- 不能跳过免责声明:每次会话开始前,用户必须看到并确认免责条款。
- 不能没有审计日志:所有关键决策必须留痕,以备合规审查。
2. 健康咨询:从信息检索到智能辅助
2.1 什么是健康咨询?
健康咨询,简单说就是帮助人们获取健康相关信息和建议的过程。传统模式下,这个角色由医生、药师、健康顾问等人承担——你挂号排队、面对面交流、获取专业意见。但现实是医疗资源永远不够用:中国每千人执业医师数约 3.0,远低于发达国家的 4-5。这意味着大量轻量级咨询需求(“这个药能不能和那个药一起吃?”“孩子发烧 38.5 度要不要去医院?”)其实并不需要占用宝贵的医生时间。
健康咨询机器人的定位就在这里——在患者和医生之间建立一道智能分诊层。它处理那些基于公开医学知识就能回答的问题,把真正需要专业判断的情况转给医生。这不是替代医生,而是释放医生的时间,让他们专注于真正需要专业判断的病例。
2.2 发展历程:从搜索到结构化问诊
早期的健康咨询基本上就是搜索引擎——输入关键词返回一堆网页链接,你搜"头痛怎么办"出来一堆营销号文章,越看越焦虑。后来有了结构化的健康问答平台(好大夫在线、春雨医生等),但本质上还是"人回答人"的模式,效率瓶颈没变。
大模型时代改变了一切。GPT-4 在美国执业医师考试(USMLE)中得分超过 85%,证明 AI 已具备相当程度的医学知识理解能力。但通用大模型不是医疗设备,它不应该也不可以给出诊断。所以真正的挑战变成了:如何在大模型能力之上,构建一个合规、可控、有用的健康咨询系统?
OpenClaw 在这里发挥作用。它不是一个通用聊天机器人框架,而是一个可编程的 Agent 编排系统——你可以精确控制它的行为边界、接入专业的医学知识库、设计严格的多轮问诊流程,并且在不同渠道(微信、飞书、App)上统一交付。
2.3 核心能力模型
一个合格的健康咨询机器人需要具备六大能力:
| 能力层级 | 描述 | 实现方式 |
|---|---|---|
| 信息检索 | 基于症状/疾病查询公开医学知识 | 医学知识库 RAG |
| 风险评估 | 判断症状紧急程度,识别危险信号 | 规则引擎 + LLM 推理 |
| 用药指导 | 药物信息查询、用法用量提醒 | 结构化药物数据库 + 定时任务 |
| 健康追踪 | 记录和趋势分析健康指标 | 数据采集 + 可视化 |
| 分诊转介 | 识别超出能力范围的咨询并转人工 | 降级策略 + 人工接管 |
| 隐私保护 | 敏感信息脱敏,合规存储 | 数据脱敏管线 |

3. 医疗行业:AI 落地的特殊战场
3.1 数字化现状
医疗行业是数字化转型最慢的行业之一,原因不难理解——试错成本太高。一个电商推荐系统推荐错了,用户顶多买件不喜欢的衣服;一个医疗 AI 给错了建议,可能危及生命。
但变化正在加速。2023 年中国互联网医疗市场规模突破 3600 亿元,在线问诊、电子处方、远程医疗等场景已经相当成熟。AI 在医疗影像、药物研发、临床决策支持等领域都有深入应用。不过面向 C 端用户的健康咨询 AI,始终是一个相对空白但又需求巨大的领域——大量轻量级咨询(“哺乳期能不能吃这个药?”“孩子发烧 38.5 度怎么办?”)占据了三甲医院大量门诊时间。
3.2 监管框架对比
医疗 AI 的合规是这篇文章的核心线索,你必须深刻理解它。以下是中外主要监管框架的对比:
| 维度 | 美国(HIPAA/FDA) | 中国(个人信息保护法/药监局) |
|---|---|---|
| 数据保护法 | HIPAA(健康保险可携性和责任法案) | 《个人信息保护法》《数据安全法》 |
| 敏感信息定义 | PHI(受保护健康信息)18 类 | 个人敏感信息(健康生理、生物识别) |
| AI 医疗器械 | FDA 将部分 AI 诊断工具归类为 SaMD | 国家药监局对 AI 医疗软件按二类/三类管理 |
| 合规要点 | 数据加密、访问控制、审计日志、BAA 协议 | 最小必要原则、告知同意、数据本地化 |
| 违规后果 | 每次违规最高 150 万美元罚款 | 最高 5000 万元或上一年度营业额 5% 罚款 |
HIPAA 官方资料见 HHS HIPAA Security Rule,国内法律见 《个人信息保护法》全文。
3.3 合规红线与分诊流程
在开始写代码之前,必须牢记下面这套"分诊漏斗"。它把"用户进线 → 免责确认 → 症状分析 → 紧急判定 → 分级响应"全流程都纳入设计:
这个流程图体现的是"安全优先"的设计哲学——宁可误报,不能漏报。如果规则引擎把一个"岔气"误判为"心脏急症",最坏的结果是用户多打了一个电话;如果把真正的心脏急症漏掉,后果不堪设想。这种"防御性设计"贯穿整个医疗 AI 系统。
4. 系统架构设计
4.1 整体架构:四层解耦
一个完整的健康咨询机器人不只是"一个聊天窗口 + 大模型"。它需要多个组件协同工作:医学知识库提供专业知识,规则引擎做紧急情况判断,定时任务系统做用药提醒,数据管线做隐私保护。

这个架构的核心思想是分层解耦。用户接入层只管交互,Agent 层只管业务逻辑,知识层只管专业数据,安全层只管合规。每一层都可以独立演进和替换——比如把微信换成钉钉,只需要改接入层;把 Milvus 向量库换成 Elasticsearch,只影响知识层。这种"关注点分离"在医疗场景下尤其重要,因为合规要求系统能清楚地证明"每条数据流经哪里、被如何处理"。
4.2 技术选型对比
在医疗 AI 的技术选型上,框架选择至关重要。以下是 OpenClaw 与其他主流方案的对比:
| 维度 | OpenClaw | LangChain + Rasa | 微软 Health Bot | 自研方案 |
|---|---|---|---|---|
| 部署方式 | 本地自托管 ✅ | 本地/云端 | 云端 SaaS ❌ | 本地 |
| 数据主权 | 完全本地 ✅ | 依赖配置 | 微软云端 ❌ | 完全本地 ✅ |
| 多渠道接入 | 20+ 平台 ✅ | 需自建 | 有限渠道 ❌ | 需自建 |
| Skill/插件体系 | 原生支持 ✅ | 自定义 Chain | 预设场景 ❌ | 需自建 |
| 合规定制 | 完全可控 ✅ | 需二次开发 | 有限定制 ⚠️ | 完全可控 ✅ |
| 开发成本 | 低 ✅ | 中 ⚠️ | 低(但受限)⚠️ | 高 ❌ |
| 维护成本 | 低 ✅ | 高 ❌ | 低 ⚠️ | 极高 ❌ |
| 医疗场景适配 | 需定制 Skill | 需定制 | 部分预设 ⚠️ | 完全定制 ✅ |
OpenClaw 的优势在于:它提供了足够的开箱即用能力(多渠道、Agent 编排、定时任务),同时又保留完全的定制自由度。在医疗场景下,你不需要"从零造轮子",但也不能"受制于平台"。OpenClaw 恰好在这个甜蜜点上——Skill 配置见 OpenClaw 官方文档。
5. 医疗合规实现:从免责声明到审计日志
5.1 免责声明与用户确认
📌 版本说明:本文示例基于 OpenClaw v2.1(2026-06),引用法规为《个人信息保护法》2021 版与 HIPAA Security Rule 现行版。如未来法规更新或框架升级到 v3.x,请以最新官方文档为准。框架的"规则兜底 + LLM 辅助"原理长期适用,是医疗 AI 的经典模式。
合规的第一步是确保用户知情同意。我们设计一个必须在会话开始时触发的免责声明 Skill:
# skills/health-disclaimer/disclaimer.py - 免责声明强制流程
import asyncio
from datetime import datetime, timedelta
from typing import Optional
DISCLAIMER_TEXT = """
⚠️ 健康咨询免责声明
1. 本服务提供的健康信息仅供参考,不构成任何医疗诊断或治疗建议。
2. 本服务不能替代专业医疗人员的诊断和治疗。
3. 如您正在经历紧急医疗状况,请立即拨打 120 急救电话。
4. 您的健康数据将按《个人信息保护法》进行脱敏处理和加密存储。
5. 继续使用本服务即表示您已阅读并同意以上声明。
"""
DISCLAIMER_VERSION = "2.1"
ACCEPT_KEYWORDS = {"同意", "确认", "1", "ok", "yes"}
RECORD_VALID_DAYS = 30 # 免责声明记录 30 天有效
class DisclaimerEnforcer:
"""免责声明强制执行器:检查 -> 发送 -> 等待 -> 留痕"""
def __init__(self, db, audit_logger):
self.db = db
self.audit = audit_logger
async def enforce(self, user_id: str, session) -> bool:
"""返回 True 表示已通过免责声明"""
record = await self.db.get_disclaimer_record(user_id)
if record and record["accepted"]:
age = datetime.utcnow() - record["accepted_at"]
if age < timedelta(days=RECORD_VALID_DAYS):
return True # 已接受且未过期,放行
await session.send(DISCLAIMER_TEXT)
response = await session.wait_for_response(timeout=300)
if not response or response.strip().lower() not in ACCEPT_KEYWORDS:
await session.send("请先同意免责声明才能继续咨询。")
return False
# 记录接受(时间戳 + IP + 版本号,合规审计硬性要求)
await self.db.save_disclaimer_acceptance(
user_id=user_id, accepted_at=datetime.utcnow(),
ip_address=session.client_ip, version=DISCLAIMER_VERSION,
)
await self.audit.log(
"disclaimer_accepted", session.session_id,
user_hash=self._hash_user(user_id),
details={"version": DISCLAIMER_VERSION},
)
return True
@staticmethod
def _hash_user(uid: str) -> str:
import hashlib
return hashlib.sha256(uid.encode()).hexdigest()[:16]
这段代码实现了免责声明的完整流程。声明文本明确列出五条关键告知事项,涵盖"不能替代医生""紧急情况拨打 120""数据脱敏处理"等合规必备项。强制执行逻辑每次会话开始时先查库看用户是否已接受过(30 天有效),如果没有就发送声明并等待确认。确认记录包含时间戳、IP、版本号——这是合规审计的硬性要求。注意 user_hash 用 SHA-256 截断而非真实 ID,日志本身也必须脱敏。
5.2 隐私数据脱敏
医疗数据脱敏不是"把名字替换成 "就完事。根据《个人信息保护法》,健康生理信息、生物识别信息都属于敏感个人信息,需要更系统化的脱敏策略。脱敏的核心思想是按字段分级*——不同敏感度使用不同脱敏方法:
| 字段 | 脱敏方法 | 示意 | 适用理由 |
|---|---|---|---|
patient_name |
部分遮掩 | 张** | 保留姓氏便于检索;隐去名字 |
id_number |
SHA-256 哈希 | a3f2...b8c1 |
完全不可逆,防身份关联 |
phone |
中段掩码 | 138****1234 |
保留号段便于客服核对 |
symptom_detail |
症状泛化 | “胸痛放射至左臂” → “胸部不适” | 去除特异性,保护诊断隐私 |
medication_dose |
保留(keep) | 阿司匹林 100mg | 剂量影响临床判断,不能脱敏 |
health_metrics |
范围替代 | 收缩压 135 → “正常范围偏高” | 范围足趋势分析,去精度防识别 |
脱敏处理的核心流程是:读取字段 → 查规则表 → 选择方法 → 输出。伪代码逻辑极简:定义 FIELD_RULES 字典(field → MASK/SHA256_TRUNC/GENERALIZE/KEEP/RANGE),对数据字典逐字段调用对应规则的 apply(value) 方法;未配置的字段原样保留(白名单兜底)。整个 desensitize 函数在 PII 处理链路中只占几行,关键的工程量在"规则表"配置和"症状泛化映射表"的医学领域知识上——这些都需要医学专家和合规团队联合评审。
这个脱敏策略的核心是分级脱敏 + 字段独立——不同类型的敏感信息使用不同强度的脱敏方法,且每个字段可独立配置。姓名用部分遮掩(保留姓氏),身份证号用 SHA-256 哈希(完全不可逆),症状描述用泛化(“胸痛放射至左臂"变成"胸部不适”),健康指标用范围替代(血压 135/85 变成"正常范围")。值得注意的是药物剂量被标记为 keep——因为脱敏的目的是保护患者身份,不是破坏临床参考价值,过度脱敏反而会让系统失去实用性。
5.3 审计日志系统
在医疗场景中,审计日志不是"锦上添花",而是"法律要求"。每一个关键决策点都必须被完整记录。一条合规的审计事件至少包含以下字段:
| 字段 | 类型 | 用途 | 合规要点 |
|---|---|---|---|
event_id |
UUID | 事件唯一标识 | 用于跨表关联 |
event_type |
枚举 | 事件类型 | 强类型,避免自由文本分类不一致 |
session_id |
str | 会话标识 | 关联一次问诊全过程 |
user_hash |
str | 脱敏用户标识 | 禁止真实用户ID,日志本身也必须脱敏 |
timestamp |
ISO8601 | 事件时间 | 精确到毫秒 |
risk_level |
枚举 | 风险等级 | normal / high / critical |
details |
dict | 事件明细 | 决策依据(症状列表/规则命中/转人工原因) |
system_version |
str | 系统版本号 | 合规审查可追溯"当时系统逻辑" |
关键事件类型枚举共 7 类:SESSION_START、DISCLAIMER_ACCEPTED、SYMPTOM_ANALYSIS、EMERGENCY_DETECTED、HUMAN_HANDOFF、MEDICATION_QUERY、DATA_ACCESS。当 risk_level ∈ {high, critical} 时,会同时触发告警通道(短信/邮件给值班医生),确保相关人员即时知晓。所有审计记录写入 encrypted_postgresql 存储,保留期 5 年(符合《医疗机构病历管理规定》要求)。审计日志的设计有几个关键点:第一,事件类型用枚举而非自由文本,确保分类一致性;第二,用户标识用 user_hash 而不是真实 ID,日志本身也必须脱敏;第三,高风险事件(紧急情况检测、转人工)会同时触发告警;第四,每条记录包含 system_version,合规审查时可追溯"当时的系统逻辑是什么"。
6. 症状初步分析 Skill
6.1 设计思路:描述相关性,不判断因果性
症状初步分析是健康咨询机器人最核心的功能,也是最容易"踩线"的功能。我们的设计原则是:描述相关性,不判断因果性。
什么意思呢?如果用户说"我头痛、发热、脖子僵硬",机器人可以说"这些症状的组合可能与脑膜炎相关,属于需要尽快就医的情况",但不能说"你得了脑膜炎"。前者是信息关联,后者是诊断结论——这个边界必须严格守住。
实现上,我们采用规则引擎 + LLM 推理的双层架构。规则引擎负责识别已知的危险信号组合(如"胸痛 + 呼吸困难"→紧急),LLM 负责理解用户自然语言描述并匹配医学知识。规则引擎是"硬约束",LLM 是"软辅助",两者结果取并集——任何一个通道标记为紧急,就按紧急处理。
6.2 危险信号规则引擎
# skills/symptom-analyzer/danger_rules.py
from dataclasses import dataclass
from typing import List, Dict
@dataclass
class DangerRule:
"""危险信号规则:关键词组合触发"""
id: str; keywords: List[str]; min_match: int
urgency: str # critical / urgent / normal
message: str; action: str # call_120 / see_doctor / self_care
# 预定义危险信号规则库(核心条目)
DANGER_RULES = [
DangerRule("cardiac_emergency",
keywords=["胸痛", "胸闷", "呼吸困难", "出冷汗", "左臂麻木"],
min_match=2, urgency="critical",
message="⚠️ 您描述的症状组合可能提示心脏急症,请立即拨打 120!",
action="call_120"),
DangerRule("stroke_warning",
keywords=["突然剧烈头痛", "一侧肢体无力", "说话不清",
"嘴角歪斜", "视力模糊"],
min_match=2, urgency="critical",
message="⚠️ 您描述的症状可能提示脑血管意外,请立即拨打 120!",
action="call_120"),
DangerRule("respiratory_distress",
keywords=["呼吸困难", "喘息", "不能平卧", "嘴唇发紫"],
min_match=2, urgency="critical",
message="⚠️ 呼吸困难是紧急情况,请立即拨打 120!",
action="call_120"),
DangerRule("severe_infection",
keywords=["高热", "持续发热", "寒战", "意识模糊", "皮疹"],
min_match=2, urgency="urgent",
message="您的症状可能提示严重感染,建议尽快就医检查。",
action="see_doctor"),
]
def evaluate_danger_rules(symptom_text: str) -> List[Dict]:
"""评估症状文本:返回触发的规则(按 critical→urgent→normal 排序)"""
urgency_order = {"critical": 0, "urgent": 1, "normal": 2}
results = []
for rule in DANGER_RULES:
matched = [kw for kw in rule.keywords if kw in symptom_text]
if len(matched) >= rule.min_match:
results.append({"rule_id": rule.id, "urgency": rule.urgency,
"matched": matched, "message": rule.message,
"action": rule.action})
return sorted(results, key=lambda x: urgency_order[x["urgency"]])
这个规则引擎的核心是关键词组合触发。单靠"胸痛"一个词不能判断为心脏急症,但如果"胸痛"和"呼吸困难"同时出现,匹配数达到 min_match=2,就触发 cardiac_emergency 规则。规则按紧急程度排序返回,最紧急的排在前面。这种设计的优势是:规则可解释、可审计、可快速调整——你不需要重新训练模型就能新增一条危险信号规则。
6.3 多轮对话问诊流程
真正的问诊不是一问一答,而是医生通过多轮追问逐步缩小范围。我们用 OpenClaw 的对话状态机来实现这个流程:
这个状态机的关键在于危险信号筛查的位置——它在主诉采集之后、追问细节之前。这意味着用户一说出症状,系统立即检查是否有危急信号。如果有,直接转人工或建议拨打 120,不再继续问诊。这是一个"安全优先"的设计决策:宁可误报,不能漏报。
多轮问诊的对话管理逻辑分阶段实现。阶段一是主诉采集:用户描述最不舒服的地方(“肚子疼两天了”),系统立即进行危险信号筛查;阶段二是症状细节追问:用 0-10 分视觉模拟量表评估严重程度、起病方式(突然/渐进)、伴随症状;阶段三是病史补充:询问慢性病、当前用药、过敏史;阶段四是初步分析:根据采集到的结构化信息给出"就医/自护"建议,每条建议都附信息来源和免责声明。
7. 用药提醒 Agent
7.1 为什么需要独立 Agent?
用药依从性(Medication Adherence)是慢性病管理的核心挑战。研究显示,慢性病患者的用药依从率仅有 50% 左右——也就是说,一半的药没按时吃。这不仅影响治疗效果,还可能导致病情恶化后急诊入院,给医疗系统带来巨大负担。
用药提醒看似简单——“早上 8 点吃药”——但实际远比这复杂。药物之间有相互作用,有些药需要空腹服用,有些需要随餐,有些不能和葡萄柚汁一起吃。一个合格的用药提醒 Agent 需要理解这些规则,并在适当的时间给出适当的提醒。
7.2 用药提醒 Skill 实现
# skills/medication-reminder/handler.py
from datetime import time
from typing import List, Optional, Tuple
class MedicationReminder:
"""用药提醒:药物交互检查 + 时间规则 + 定时调度"""
# 药物相互作用规则(按字母序归一化 key,节选 2 条核心禁忌)
INTERACTIONS = {
("华法林", "阿司匹林"): {"level": "contraindicated",
"msg": "⚠️ 华法林与阿司匹林联用显著增加出血风险,请医生指导下使用!"},
("甲硝唑", "酒精"): {"level": "contraindicated",
"msg": "⚠️ 服用甲硝唑期间严禁饮酒,可能导致双硫仑样反应!"},
}
TIMING_RULES = {"空腹": {"before_meal_min": 60, "after_meal_min": 120},
"随餐": {"with_meal": True}, "餐后": {"after_meal_min": 30},
"睡前": {"before_sleep_min": 30}}
def __init__(self, db, scheduler):
self.db, self.scheduler = db, scheduler
async def add_medication(self, user_id: str, med_name: str,
dosage: str, frequency: str,
timing: str) -> dict:
"""添加用药:查交互 -> 算提醒时间 -> 注册调度任务"""
current = await self.db.get_user_medications(user_id)
interactions = self._check_interactions(med_name, current)
if any(i["level"] == "contraindicated" for i in interactions):
return {"success": False, "reason": interactions[0]["msg"],
"requires_doctor_confirm": True}
times = self._calc_times(frequency)
for rt in times:
await self.scheduler.create_recurring_task(
user_id=user_id, task_type="medication_reminder",
trigger_time=rt,
message=f"💊 该吃药啦!{med_name} {dosage}({timing})",
payload={"med_name": med_name, "dosage": dosage,
"timing": timing})
return {"success": True, "interactions": interactions,
"reminder_count": len(times)}
def _check_interactions(self, new_med: str,
current: List[dict]) -> List[dict]:
"""检查新药与现有药物的相互作用(按字母序归一化避免重复)"""
return [self.INTERACTIONS[tuple(sorted([new_med, m["name"]]))]
for m in current
if tuple(sorted([new_med, m["name"]])) in self.INTERACTIONS]
@staticmethod
def _calc_times(frequency: str) -> List[time]:
"""根据频次计算每日提醒时间点(qd/bid/tid 三档)"""
base = {"qd": [time(8, 0)], "bid": [time(8, 0), time(20, 0)],
"tid": [time(8, 0), time(14, 0), time(20, 0)]}
return base.get(frequency, [time(8, 0)])
这段代码实现了用药提醒的三个核心功能。第一是药物相互作用检查——添加新药时自动检测与现有药物的冲突,禁忌联用的药物会直接阻止添加并提醒用户咨询医生。第二是服药时间规则——不同药物的服用时间有讲究(空腹、随餐、餐后、睡前),系统根据这些规则计算最佳提醒时间。第三是定时任务注册——利用 OpenClaw 的调度系统,在正确的时间点推送提醒。禁忌规则用 (药A, 药B) 元组存储并通过 sorted 归一化顺序,避免"华法林-阿司匹林"和"阿司匹林-华法林"重复存储。
8. 健康数据追踪
8.1 为什么需要健康数据追踪?
单次咨询解决的是"我现在怎么了"的问题,但健康管理是持续性的。血压是不是比上个月高了?血糖控制得怎么样?体重趋势如何?这些纵向数据才是健康管理的核心价值。
OpenClaw 的健康数据追踪 Agent 可以通过对话式交互采集数据,也可以对接智能穿戴设备(通过 API 对接),然后进行趋势分析和异常预警。系统支持的核心指标包括:
| 指标 | 名称 | 单位 | 正常范围 | 预警阈值 |
|---|---|---|---|---|
| blood_pressure_systolic | 收缩压 | mmHg | 90-140 | ≥ 140 |
| blood_pressure_diastolic | 舒张压 | mmHg | 60-90 | ≥ 90 |
| heart_rate | 心率 | bpm | 60-100 | ≥ 100 |
| blood_glucose_fasting | 空腹血糖 | mmol/L | 3.9-6.1 | ≥ 7.0 |
| weight | 体重 | kg | 因人而异 | — |
| sleep_hours | 睡眠时长 | 小时 | 7-9 | < 6 |
8.2 趋势分析三步法
健康追踪的核心逻辑是"记录 → 检测 → 分析"三步走:
- 记录:用户通过对话或设备上传指标数据,系统先做实时异常检测——如果某个指标超过预警阈值立即发出提醒。
- 检测:单点数据超阈值则触发即时告警;多点数据则进入趋势分析。
- 分析:比较最近 7 天和更早 7 天的均值,如果变化超过 10% 就标记为"显著变化"并建议就医。
# skills/health-tracker/tracker.py - 健康追踪核心逻辑
import hashlib
from datetime import datetime, timedelta
class HealthTracker:
"""健康指标追踪:记录 + 实时检测 + 趋势分析三步走"""
TRACKABLE_METRICS = {
"blood_pressure_systolic": {"name": "收缩压", "warning": 140},
"blood_pressure_diastolic": {"name": "舒张压", "warning": 90},
"blood_glucose_fasting": {"name": "空腹血糖", "warning": 7.0},
"sleep_hours": {"name": "睡眠时长", "warning_low": 6.0}}
def __init__(self, db, notifier):
self.db, self.notifier = db, notifier
async def record_metric(self, user_id: str, metric: str,
value: float) -> dict:
"""记录单条指标:脱敏 -> 实时检测 -> 趋势分析"""
if metric not in self.TRACKABLE_METRICS:
return {"success": False, "reason": f"不支持: {metric}"}
user_hash = hashlib.sha256(user_id.encode()).hexdigest()[:16]
await self.db.insert_metric(user_id=user_hash, metric=metric,
value=value, recorded_at=datetime.utcnow())
cfg = self.TRACKABLE_METRICS[metric]
if cfg.get("warning") and value >= cfg["warning"]:
await self.notifier.send(user_id, metric, value, cfg)
elif cfg.get("warning_low") and value <= cfg["warning_low"]:
await self.notifier.send(user_id, metric, value, cfg)
return {"success": True,
"trend": await self._analyze_trend(user_hash, metric)}
async def _analyze_trend(self, user_hash: str,
metric: str, days: int = 30) -> dict:
"""双窗口对比:最近 7 天均值 vs 早期 7 天均值(变化>10% 视为显著)"""
since = datetime.utcnow() - timedelta(days=days)
records = await self.db.get_recent_metrics(
user_hash, metric, since=since)
if len(records) < 3:
return {"status": "insufficient_data",
"message": "数据不足,继续记录后可查看趋势"}
values = [r["value"] for r in records]
n = min(7, len(values))
recent, early = sum(values[-n:])/n, sum(values[:n])/n
if early == 0:
return {"status": "stable", "message": "指标趋势稳定"}
change = (recent - early) / early * 100
if abs(change) > 10:
name = self.TRACKABLE_METRICS[metric]["name"]
direction = "上升" if change > 0 else "下降"
return {"status": "significant_change",
"message": f"近 30 天{name}{direction}{abs(change):.1f}%,建议就医。",
"change_pct": round(change, 2)}
return {"status": "stable", "message": "指标趋势稳定,继续保持!"}
这段代码实现了"记录 → 检测 → 分析"三步走。注意这里存储用户 ID 时做了 SHA-256 哈希脱敏——即使数据库泄露,也无法关联到具体个人。趋势分析采用"最近 7 天 vs 早期 7 天"的双窗口对比,避免单点波动造成的误报;同时设置 10% 的最小变化阈值,过滤日常波动。
9. 紧急情况识别与转人工机制
9.1 三级分诊模型
紧急情况的识别和响应是整个系统最关键的环节。我们设计了三级分诊模型:
| 等级 | 标识 | 判定条件 | 响应动作 |
|---|---|---|---|
| 🔴 一级(危急) | CRITICAL | 触发危险规则且 urgency=critical,或用户明确表示意识模糊、呼吸困难等 |
立即建议拨打 120,强制转人工客服 |
| 🟡 二级(紧急) | URGENT | 触发危险规则且 urgency=urgent,或症状持续加重 |
建议尽快就医,提供就近医院信息 |
| 🟢 三级(常规) | NORMAL | 未触发任何危险规则,症状轻微且稳定 | 提供自我护理建议,告知观察要点 |
9.2 转人工流程

转人工流程有几个设计要点。第一,双通道通知——机器人不仅建议用户拨打 120,还同时通知人工客服介入,形成双重保障。第二,会话摘要脱敏传递——转人工时,客服看到的是脱敏后的会话摘要,而不是原始对话记录。第三,机器人静默——一旦转人工成功,机器人自动静默,避免和人工客服的信息冲突。第四,全程审计——从危险信号检测到转人工完成,每一步都有审计记录。
10. 医疗知识库 RAG 检索
10.1 为什么需要 RAG?
通用大模型的医学知识有两个问题:一是不够专业,二是可能过时。RAG(Retrieval-Augmented Generation)通过检索专业医学知识库来补充大模型的知识盲区,让回答更准确、更可靠。
在医疗场景下,RAG 的知识库来源必须严格控制。我们使用的知识库来源包括:
| 知识库 | 内容 | 更新频率 | 权威性 |
|---|---|---|---|
| 默沙东诊疗手册 | 疾病症状、诊断标准、治疗方案 | 年度更新 | ⭐⭐⭐⭐⭐ |
| 国家药监局药品说明书 | 药物适应症、用法用量、禁忌事项 | 实时更新 | ⭐⭐⭐⭐⭐ |
| 中国居民膳食指南 | 营养建议、饮食禁忌 | 每 5 年更新 | ⭐⭐⭐⭐ |
| WHO 国际疾病分类 ICD-11 | 疾病分类与编码 | 年度更新 | ⭐⭐⭐⭐⭐ |
参考链接:默沙东诊疗手册专业版、国家药监局药品说明书查询、WHO ICD-11。
10.2 RAG 检索实现
医疗 RAG 的实现有三个独特之处。第一是权威性重排序——检索结果不是按相似度简单排序,而是优先展示权威来源的内容。一个来自默沙东诊疗手册的结果,即使相似度略低,也应该排在营销号文章前面。第二是安全过滤——自动将"诊断为 XX"替换为"可能与 XX 相关",阻断诊断性表述。第三是强制标注来源和免责语——每条检索结果都标注信息出处并附带免责声明,确保用户知道这是参考资料而非医嘱。
实现上分三步:第一步是向量化检索——用 bge-large-zh-v1.5 等中文医学 Embedding 模型把症状和文档都映射到向量空间,做相似度检索。第二步是权威性重排序——按 authority_level 倒序 + last_updated 倒序,让最新最权威的来源排在前面。第三步是安全过滤——遍历每条结果,用 _neutralize_diagnosis 把"诊断为"换成"可能与…相关"、用 _neutralize_prescription 把"建议服用 XX 药"换成"应在医生指导下使用 XX",最后强制追加 📚 信息来源:XX(更新于 YYYY-MM-DD) 和 ⚠️ 以上信息仅供参考 的免责附加语。
11. 多轮对话问诊流程详解
11.1 为什么多轮对话这么重要?
单轮问答在医疗场景下几乎是不可用的。你问"我头痛怎么办",一个负责任的回答不可能是泛泛的"多喝水多休息"——头痛的病因从紧张性头痛到脑肿瘤,严重程度天差地别。必须通过多轮追问来缩小范围:头痛多久了?什么部位?搏动性还是压迫性?伴不伴发热?有没有恶心呕吐?
这些追问不是随意的,而是遵循临床问诊的 SOP(标准操作流程)。我们把这种结构化问诊逻辑编码到 OpenClaw 的对话状态机中,确保每次问诊都覆盖关键信息点。
11.2 问诊流程对比
| 维度 | 传统搜索式 | 单轮 LLM | OpenClaw 多轮问诊 |
|---|---|---|---|
| 信息采集 | 用户自己描述,无引导 | 用户自己描述,无引导 | 结构化追问,逐步完善 |
| 紧急识别 | 无 | 依赖模型判断,不可控 | 规则引擎硬保障 + LLM 辅助 |
| 追问深度 | 无 | 一轮结束,无追问 | 多轮追问直到信息充分 |
| 合规保障 | 无 | 无 | 免责声明 + 审计日志 + 脱敏 |
| 转人工 | 无 | 无 | 三级分诊自动转人工 |
| 可解释性 | 低 | 低 | 规则引擎部分完全可解释 |
11.3 问诊对话示例
以下是真实的多轮问诊流程示例(已脱敏):
🤖 健康咨询机器人:您好!我是健康咨询助手。在开始之前,请确认以下免责声明:本服务仅供参考,不能替代专业医疗建议。回复"同意"继续。
👤 用户:同意
🤖 请描述一下您目前最不舒服的地方是什么?
👤 用户:这两天肚子一直隐隐作痛
🤖 了解。请问:1) 疼痛具体在哪个位置?(上腹/脐周/下腹/全腹)2) 持续了多长时间?3) 如果 0-10 分评分,大约几分?
👤 用户:上腹位置,大概两天了,5分左右,不是特别疼
🤖 收到。上腹痛两天、中度疼痛。请问:1) 和吃饭有关系吗?(空腹加重/饭后加重/无关)2) 有没有伴随恶心、呕吐、反酸?3) 大便正常吗?有没有发黑?
👤 用户:饭后好像更不舒服,有点反酸,大便正常
🤖 根据您描述的症状(上腹痛、饭后加重、反酸),可能与胃部不适相关。以下建议供参考:避免辛辣、油腻、过酸食物;少食多餐,避免暴饮暴食;避免饭后立即平躺。如症状持续超过 1 周或加重,建议消化内科就诊。
📚 信息来源:默沙东诊疗手册-消化系统
⚠️ 以上信息仅供参考,具体诊疗请咨询专业医生。需要我帮您了解更多信息,或者设置用药提醒吗?
注意这个对话中的几个关键设计:每轮追问都是结构化的(给出选项而不是开放问题),降低用户回答的认知负担;症状描述使用"可能与 XX 相关"而非"你得了 XX";建议分自我护理和就医两部分;每条建议都标注来源和免责声明。这些"细节"决定了用户体验和合规风险。
12. OpenClaw Skill 配置与部署
12.1 完整 Skill 配置
把前面所有的功能模块整合成 OpenClaw 的 Skill 配置:
# openclaw-skills/health-advisor/config.yaml
# 医疗健康咨询 Skill 部署配置(合规参数 + Skill 清单)
skills:
# ── 症状初步分析 ──
symptom-analyzer:
name: "症状初步分析"
description: "基于用户描述的症状进行初步分析和分诊建议"
trigger: "当用户描述身体不适或健康问题时触发"
config:
danger_rules_file: "danger_rules.json"
rag_retriever: "medical-rag"
max_dialog_turns: 8
emergency_action: "notify_human_agent"
# ── 用药提醒 ──
medication-reminder:
name: "用药提醒"
description: "药物提醒、用法指导和相互作用检查"
trigger: "当用户提到药物或需要用药提醒时触发"
config:
interaction_db: "drug_interactions.json"
scheduler_type: "recurring"
# ── 健康数据追踪 ──
health-tracker:
name: "健康数据追踪"
description: "记录和分析健康指标趋势"
trigger: "当用户报告健康数据或查询趋势时触发"
config:
trackable_metrics: ["blood_pressure", "heart_rate",
"blood_glucose", "weight", "sleep_hours"]
trend_analysis_days: 30
# ── 医疗知识库 RAG ──
medical-rag:
name: "医学知识检索"
description: "基于权威医学知识库的 RAG 检索"
config:
vector_store: "milvus_medical"
embedding_model: "bge-large-zh-v1.5"
safety_filters: {block_diagnosis: true, block_prescription: true}
# ── 全局合规配置 ──
compliance:
disclaimer: {required: true, version: "2.1", confirm_before_session: true}
audit: {enabled: true, storage: "encrypted_postgresql",
retention_days: 1825} # 5 年保留
desensitization:{enabled: true, method: "field_level", hash_algorithm: "sha256"}
这个配置文件把四个核心 Skill 和合规设置整合到一起。每个 Skill 的 trigger 字段告诉 OpenClaw 什么时候激活,config 字段包含运行所需参数。合规部分是全局配置——免责声明版本、审计日志存储和保留期、脱敏算法——影响所有 Skill 的行为。retention_days: 1825(5 年)符合《医疗机构病历管理规定》的最低要求。
12.2 部署 Checklist
部署上线前必须逐项确认:
- ✅ 免责声明 Skill 已配置且版本号正确
- ✅ 审计日志写入加密存储(encrypted_postgresql)
- ✅ 危险信号规则已通过医学专家审核
- ✅ RAG 知识库内容已由专业人士复核
- ✅ 数据脱敏管线在采集、传输、存储、展示全链路启用
- ✅ 转人工通道已联通客服系统并测试双通道通知
- ✅ 紧急情况压测:故意输入"胸痛+呼吸困难"验证规则触发
- ✅ 合规审查:律师审核免责声明、数据处理协议
13. 性能优化与注意事项
13.1 延迟优化
医疗咨询场景对延迟非常敏感。用户描述了症状,如果 30 秒还没收到回复,焦虑感会急剧上升。我们的优化策略包括:
| 优化点 | 方法 | 效果 |
|---|---|---|
| 危险信号检测 | 规则引擎本地执行,不走 LLM | < 50ms 响应 |
| RAG 检索 | 预热热点查询缓存 | 缓存命中 < 100ms |
| LLM 推理 | 流式输出 + 中间状态提示 | 首字延迟 < 1s |
| 转人工通知 | 异步非阻塞发送 | 不影响主流程 |
13.2 关键注意事项
💡 不要把合规当负担,把它当设计约束。 合规不是事后补的文档,而是系统设计的一部分。你在画架构图的时候,就应该把数据脱敏管线、审计日志模块画进去,而不是开发完再"加个脱敏"。
💡 紧急情况宁可误报,不能漏报。 如果规则引擎把一个"岔气"误判为"心脏急症",最坏的结果是用户多打了一个电话。但如果把一个真正的心脏急症漏掉了,后果不堪设想。调整危险规则的阈值时,始终偏向灵敏度。
💡 RAG 知识库必须人工审核。 自动爬取的医学信息可能包含错误或过时内容,必须由医学专业人士审核后才能入库。这是"信息质量"的底线。
💡 定期回测和更新。 医学知识在持续更新,药物指南每年都有修订。你的知识库和规则引擎也需要定期更新,否则系统给出的建议可能会滞后于最新的临床指南。
14. 总结
这篇文章从一个核心问题出发:如何在医疗行业的严格合规约束下,构建一个真正有用的健康咨询机器人?我们用 OpenClaw 框架给出了完整的答案。
核心要点归纳如下:
-
合规先行:医疗 AI 的第一原则是"不伤害"。免责声明、隐私脱敏、审计日志不是可选功能,而是系统的基石。在写第一行业务代码之前,先确保合规基础设施就位。
-
辅助不替代:健康咨询机器人的定位是"智能分诊层",不是"AI 医生"。症状分析描述相关性而非因果性,用药提醒提供信息而非处方,紧急情况立即转人工而非继续问诊。
-
规则引擎 + LLM 双保险:紧急情况的识别不能仅依赖 LLM 的判断——模型可能漏掉危险信号,但规则引擎不会。两者结合,规则引擎作为硬约束兜底,LLM 提供灵活的自然语言理解。
-
RAG 确保专业性和时效性:通用大模型的医学知识不够专业,通过检索权威医学知识库来补充,同时用安全过滤器阻断诊断性表述。
-
多轮对话是问诊的核心:单轮问答在医疗场景下不可用,结构化多轮追问才能收集足够的信息做出有价值的建议。
-
数据脱敏是持续过程:不是"存储时脱敏一次"就完了,而是从采集、传输、存储到展示的全链路脱敏,每个环节都不能遗漏。
思考题
- 如果用户坚持要求机器人给出诊断结论,系统应该如何回应?你会设计怎样的"柔性拒绝"策略,既不破坏用户体验又守住合规底线?
- 在不同国家和地区的医疗法规差异下,如何设计一个可配置的合规引擎,让同一套系统能适配 HIPAA、GDPR、《个人信息保护法》等不同法律要求?哪些规则应该做成"强约束"哪些应该做成"软提示"?
- 除了本文提到的场景,健康咨询机器人还可以在哪些医疗细分领域(如心理健康、老年照护、术后随访、慢病管理)发挥作用?需要哪些额外的合规考量和数据脱敏策略?
参考资料
更多推荐
所有评论(0)