财报里的 AI 医生「大为」,让我想到一个问题:很多技术人看这类新闻时只看到估值变化,却很少拆解背后的技术底座。健康领域的 AI 助手从演示走向业务,真正要解决的是知识库怎么建、大模型怎么约束、幻觉怎么控制、上线后怎么运维。这篇文章不讨论具体财务数据,也不对任何公司作投资判断,而是从工程视角完整拆解一类“AI 医生式”健康助手的落地过程。核心目标读者是后端工程师、AI 应用开发者和技术负责人。读完后,你可以获得一条可复制的实践路径:从业务边界界定、模型选型、医学知识库构建,到检索增强生成、工具调用、效果评测、部署上线,以及最终如何用技术指标支撑业务价值评估。
1. 先理解“AI 医生”在业务与技术之间承担的角色
1.1 业务侧为什么关注“财报里的 AI 医生”
一份财报会把某个业务单独拎出来写,通常意味着它在企业战略中的权重正在上升。放在“AI 医生”这个语境里,业务侧真正关心的不是模型能聊几句,而是健康服务流程能否被数字化重构:用户进平台后能不能更快找到科室,能不能理解药品说明书,能不能在就医前完成基础的信息筛查和分诊。
这些环节过去依赖人工客服和静态网页,成本高、响应慢。大模型出现后,自然语言交互能力让“一个入口承接健康咨询”成为可能。技术侧要回答的问题就从“能不能做 Demo”变成了“能不能稳定支撑高并发咨询、能不能保证答案不出错、能不能通过合规审计”。这才是价值重估背后真正的技术支点。
1.2 能力边界:问诊、导诊、健康管理不是一回事
很多团队把“AI 医生”想成一个模型,这是第一步误解。拆开看,健康场景至少包含四类能力,每类对技术的要求完全不同:
- 智能导诊:用户描述症状,系统推荐科室。本质是分类和意图识别,依赖结构化医院科室库。
- 健康问答:解释检验指标、科普疾病常识。本质是知识检索,必须给出可溯源的信息。
- 用药说明:解释用法、用量、禁忌。本质是高合规知识库查询,必须绑定药品说明书原文。
- 健康管理:基于用户档案给出生活方式建议。本质是个性化推荐,需要用户画像和规则引擎。
用一个大模型回答所有问题是最危险的做法。正确做法是按能力边界拆分模块,让模型只负责“理解问题、编排流程、生成表达”,知识来源全部交给检索系统和结构化数据。
1.3 从技术主线拆解:数据、模型、检索、服务、评测
把“AI 医生”当作一个软件系统来设计,可以分为五层:
- 数据层:医学教材、指南、药品说明书、院内科室库、医学术语表。
- 模型层:对话模型、Embedding 模型,可能包括识别模型的 OCR 和多模态能力。
- 检索层:向量数据库、关键词索引、过滤规则,负责从知识库召回候选片段。
- 服务层:Agent 编排、工具调用、权限控制、限流、日志。
- 评测层:自动化评测集、人工评审、安全合规检查。
这五层缺一不可。如果只做模型层,就是聊天机器人;只有前面的四层加上评测层,才有可能成为一个业务上可信的健康助手。
2. 技术底座与选型:模型、知识库、Agent 框架和运行环境
2.1 模型选型:通用大模型、医疗垂类模型和本地小模型的搭配
模型选型不是二选一,而是按场景组合使用。前期原型可以先用通用大模型 API 快速验证产品形态;进入业务验证阶段,要评估医疗垂类模型或本地部署模型;涉及隐私数据时,模型服务必须运行在受控环境内。
| 模型类型 | 优势 | 主要风险 | 适用场景 |
|---|---|---|---|
| 通用大模型 API | 对话能力强,接入快,工具调用成熟 | 医学知识覆盖不稳定,可能产生幻觉 | 初期原型、通用问答、意图识别 |
| 医疗垂类模型 | 术语更准确,回答风格更克制 | 需要大量高质量数据微调,迭代周期长 | 专病知识问答、报告解释 |
| 本地部署小模型 | 数据不出域,推理成本可控 | 能力受限,对 RAG 和提示词要求更高 | 内网部署、隐私敏感场景 |
不要一上来就追求自研医疗大模型。健康业务的价值通常来自知识库质量、流程设计和服务体验,模型只是生成层。真正稳定的系统往往采用“通用模型做理解与生成,知识库做事实来源,规则引擎做安全和合规兜底”的混合架构。
2.2 为什么医疗场景必须配 RAG
大模型的知识来自训练数据,存在三个问题:知识截止时间不确定、来源不可见、错误信息无法追溯。这在医疗场景里是致命的。
RAG(检索增强生成)的解决思路是:不依赖模型记忆,而是先到知识库里检索相关内容,再把检索结果作为上下文交给模型生成答案。这样做有三个直接收益:
- 答案可溯源:能输出“依据《xxx指南》第x章”之类的引用。
- 更新成本低:知识变更只需要更新检索库,不需要重新训练模型。
- 可控性强:可以通过限制检索范围,把回答约束在已审核的资料内。
医疗知识库的构建,核心是质量,不是数量。一份权威指南的价值远大于一万篇来源不明的网络文章。构建时必须保留来源、版本、更新时间、审核人四个元数据字段。
2.3 Agent 框架:Spring AI、LangChain 类库和自研编排
健康助手不是单轮问答,往往需要多轮对话和工具调用。比如用户问“我咳嗽三天能挂呼吸科吗”,系统需要先判断意图,再查询导诊规则,最后结合用户补充信息组织回答。这属于 Agent 编排范畴。
常见的编排方式分为三类:
- LangChain / LlamaIndex 类:适合 Python 技术栈,组件丰富,生态活跃,适合快速搭建原型。
- Spring AI 类:适合 Java 技术栈,能融入已有 Spring 体系,便于工程统一管理。
- 自研编排层:用状态机或工作流引擎管理对话状态,灵活但成本高。
热词里经常出现的 “AI Agent 开发”,在健康场景会落到一个具体形态:多工具调用 + 状态管理。推荐先不自研框架,用成熟版式跑通链路,等技术边界清晰后再抽象自己的编排层。
2.4 环境准备:本地学习环境与生产环境的差异
本地跑通最小链路,和生产环境上线是两套标准。先看学习和开发环境怎么准备:
- Python 3.10+,虚拟环境隔离。
- 向量数据库用开源的 Chroma 或 Qdrant,方便本地启动。
- 模型优先接入 OpenAI-compatible 接口,方便切换不同服务商。
- 知识库文档先准备 10 到 20 篇,足够验证检索质量。
进入生产环境,差异会迅速放大:
| 层面 | 学习环境 | 生产环境 |
|---|---|---|
| 模型 | 本地小模型或测试 API | 专有模型服务、多副本、负载均衡 |
| 知识库 | 单个本地向量库 | 独立向量数据库、备份、权限控制、多环境隔离 |
| 配置 | 环境变量直接填 | 配置中心、密钥管理、按环境隔离 |
| 日志 | 控制台输出 | 结构化日志、全链路追踪、审计 |
| 监控 | 基本没有 | 指标监控、告警、灰度发布、回滚机制 |
本地能跑通,只代表链路完整。生产环境的每一项差异,都是后续运维问题的潜在来源。
3. 实现一个最小健康问答 Agent:从需求拆解到代码骨架
3.1 需求拆解:先圈定三个最小可用场景
不要一开始就做一个无所不能的“AI 医生”。建议从三个最小场景切入:
- 疾病基础问答:回答“感冒需要去医院吗”“血糖偏高能吃甜食吗”这类问题。
- 科室导诊:根据症状推荐科室,并附上就医提醒。
- 用药说明查询:返回药品说明书中的用法、用量、禁忌。
这三个场景覆盖了健康助手最核心的需求,同时有明确的知识源和数据边界,便于构建评测集。
3.2 项目结构:把数据、检索、Agent、服务分层
一个参考项目结构如下:
health-agent/ ├── app/ │ ├── main.py # FastAPI 入口 │ ├── config.py # 配置管理 │ ├── api/ │ │ └── health_chat.py # 对话接口 │ ├── knowledge/ │ │ ├── loader.py # 文档加载 │ │ ├── splitter.py # 文本切分 │ │ └── vectorizer.py # 向量化与入库 │ ├── agent/ │ │ ├── retriever.py # 检索器 │ │ ├── prompt.py # 提示词模板 │ │ └── tools.py # 工具函数 │ └── core/ │ ├── llm.py # 模型接入 │ └── guard.py # 内容过滤与拒答规则 ├── data/ │ └── documents/ # 原始医学知识文档 ├── tests/ │ └── eval/ # 评测集与评测脚本 └── deployment/ └── docker-compose.yml # 生产编排示例这个结构把知识处理、Agent 编排、服务接口分开,是为了让不同职责能够独立迭代。比如替换向量数据库时,只需要改动 knowledge 层,不会影响 API 接口。
3.3 构建医学知识库:清洗、切分、向量化
最常犯的错误是把 PDF 整篇塞进向量库。检索系统面向的是语义片段,不是整本手册。正确流程是先清洗、再切分、最后向量化。
文本切分需要按语义边界处理,不能死板按固定字符数切。参考实现如下:
# splitter.py 示例:按段落切分并保留来源元数据 import re from dataclasses import dataclass @dataclass class Chunk: content: str source: str version: str def split_by_section(markdown_text: str, source: str, version: str) -> list[Chunk]: sections = re.split(r"\n#{2,3}\s+", markdown_text) chunks = [] for sec in sections: sec = sec.strip() if len(sec) < 20: continue chunks.append(Chunk(content=sec, source=source, version=version)) return chunks切分后还需要做两件事:去掉页眉页脚和免责声明重复文本;给每个片段补上“来源 ID + 章节路径”,这部分元数据会用于回答时的引用展示。
向量化阶段要固定 Embedding 模型版本。常见做法是使用开源的 bge、m3e 或 text2vec 系列模型,也可以接入商业 Embedding API。需要记住:切换 Embedding 模型后,向量库必须全量重建,否则新旧向量不在同一个语义空间里,检索效果会明显退化。
3.4 编写检索增强生成链路
检索增强生成的核心,是先检索、再生成。先写一个检索器接口:
# retriever.py 示例:向量检索 + 关键词过滤 from typing import List class Retriever: def __init__(self, collection, embed_fn, top_k=3, min_score=0.4): self.collection = collection self.embed_fn = embed_fn self.top_k = top_k self.min_score = min_score def search(self, question: str) -> List[dict]: query_vec = self.embed_fn(question) # 这里以向量数据库返回结果为例 raw_results = self.collection.query( query_embeddings=[query_vec], n_results=self.top_k ) results = [] for doc, meta, dist in zip( raw_results["documents"][0], raw_results["metadatas"][0], raw_results["distances"][0] ): score = 1 - dist if score < self.min_score: continue results.append({ "content": doc, "source": meta.get("source"), "version": meta.get("version"), "score": round(score, 4) }) return results这里设置了min_score相似度阈值。低于阈值不要传给大模型,因为低相关片段会让模型答非所问。阈值需要结合真实问题评测确定,没有统一默认值,通常建议从 0.4 开始调。
再写提示词模板,这是约束模型行为最重要的地方:
# prompt.py 示例 SYSTEM_PROMPT = """你是一名健康咨询助手,职责是基于提供的医学知识片段回答问题。 必须遵守以下规则: 1. 只能使用提供的知识片段作为事实依据,不得使用自己的记忆补充诊断。 2. 如果知识片段没有覆盖用户问题,必须回答: “该问题需要结合专业诊疗进一步确认,建议尽快咨询执业医师。” 3. 不要输出诊断结论,不要输出处方,不要输出任何带倾向性的用药建议。 4. 回答末尾用 [来源: xxx] 标注知识片段来源。 """ def build_prompt(question: str, context: str) -> list[dict]: return [ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": f"知识片段:\n{context}\n\n问题:{question}"} ]提示词里的“只能使用提供的知识片段”“不要输出诊断结论”是关键的护栏。模型在某些情况下仍可能违反,所以这只是第一层防线,后面还需要规则层兜底。
3.5 加入工具调用:让 Agent 能查导诊、查科室
健康问答不只依赖知识库,还需要调用结构化工具。例如用户问“我肚子疼挂什么科”,这个答案不是从自由文本里检索出来的,而是从科室规则表里查出来的。
Agent 工具调用示例:
# tools.py 示例:科室导诊工具 CLINIC_RULES = { "发热伴咳嗽": ["呼吸科", "发热门诊"], "腹痛": ["消化科", "急诊科"], "心前区疼痛": ["心内科", "急诊科"], } def get_clinic_guide(symptom: str) -> dict: """根据症状关键词返回推荐科室。""" for key, clinics in CLINIC_RULES.items(): if key in symptom: return {"matched": key, "clinics": clinics} return {"matched": None, "clinics": []}工具返回结果后,Agent 再组织自然语言回答,格式类似:
“根据您描述的‘腹痛’,建议优先前往消化科就诊。如果疼痛剧烈或持续不缓解,请尽快到急诊科。本建议仅用于就医路径参考,不能替代医生诊断。”
工具调用的好处是:规则更新不需要改模型,只需要改规则表;同时可以通过日志审计“用户该去哪一科”的决策过程。
3.6 服务端接口与参数说明
使用 FastAPI 暴露一个 POST 接口:
# main.py 示例 from fastapi import FastAPI from pydantic import BaseModel app = FastAPI(title="health-agent") class ChatRequest(BaseModel): user_id: str question: str session_id: str = "" @app.post("/v1/health-chat") def chat(req: ChatRequest): if len(req.question) < 2: return {"code": 40003, "message": "问题太短,无法处理"} # 实际处理:检索 -> 组装 prompt -> 调用模型 -> 规则校验 -> 返回 answer = run_health_agent(req.question) return {"code": 0, "data": {"answer": answer}}接口里至少要考虑三个参数层面的问题:
- 上下文长度:传给模型的检索片段总字符数,一般控制在 1500 到 3000 字符以内,超出部分按相似度截断。
- 温度:健康问答建议设置在 0.2 以下,温度过高会让同样的问题每次回答都不一样,不利于用户信任。
- 超时与重试:模型调用统一配置超时时间,建议 5 到 10 秒,重试 1 到 2 次,避免把模型抖动直接暴露给用户。
| 参数 | 默认建议 | 调大影响 | 调小影响 |
|---|---|---|---|
| 检索 top_k | 3 | 上下文更丰富,但噪声增加 | 更聚焦,但可能漏掉相关内容 |
| 相似度阈值 | 0.4 起调 | 召回减少 | 会增加低质量内容 |
| temperature | 0.2 | 回答更多样,但更不稳定 | 回答更稳定,但可能过于机械 |
| 超时时间 | 10s | 用户等待更久 | 容易误判为失败 |
4. 医疗场景的效果评测与质量兜底
4.1 为什么医疗场景比通用场景更怕幻觉
通用聊天出现一点幻觉,用户只会觉得“模型不太聪明”。医疗场景出现幻觉,可能导致用户延误就医、错误用药。因此效果评测的重心不是“答得顺不顺”,而是“有没有依据”“敢不敢拒答”。
“AI 幻觉”的本质是模型生成了训练语料中不存在的、或者与正确事实相悖的内容。RAG 能降低幻觉概率,但不能消除幻觉。评测系统必须专门针对幻觉设计测试用例。
4.2 评测集设计:标准问题、边界问题、拒答问题
一份可用的健康问答评测集至少包含三类问题:
- 标准问题:知识库里有明确答案的问题,例如“服用阿司匹林可以喝酒吗”。
- 边界问题:知识库里只有部分相关内容的问题,例如“儿童咳嗽可以吃成人感冒药吗”。
- 拒答问题:知识库完全没有覆盖的问题,例如“我这个皮疹需要吃什么药”。
每类问题至少准备 30 到 50 条。拒答问题的价值经常被低估:一个健康助手的专业感,很大程度来自它知道什么时候不说话。
4.3 关键指标与计算方式
| 评估维度 | 指标 | 计算方式示例 | 目标参考 |
|---|---|---|---|
| 相关性 | 答案是否直接回答用户 | 1 到 5 分人工标注,取均值 | 不低于 4.0 |
| 忠实度 | 答案是否基于知识片段 | 人工判断是否出现知识库外事实 | 不低于 90% |
| 拒答率 | 无依据问题是否被拒绝 | 正确拒答次数 / 拒答问题总数 | 不低于 95% |
| 安全命中率 | 是否遵守不诊断、不开方规则 | 违规次数 / 总回答次数 | 接近 100% |
自动化评测可以先用“关键词 + 正则”粗筛,再用向量相似度判断答案与参考答案的语义重合度,最后必须保留人工评测环节。医疗领域不能只靠自动化打分。
4.4 兜底策略:引用来源、置信度阈值、人工升级
即使模型回答稳定,也要预留兜底机制:
- 引用来源:回答中带
[来源: xxx],让用户和专业审核人员都能回溯。 - 置信度阈值:检索相似度过低时,不调用生成,直接返回标准拒答文。
- 内容过滤:对模型输出做规则校验,命中“这是诊断/这是处方”句式时拦截。
- 人工升级:界面提供“转人工咨询”入口,模型无法回答时直接跳转。
# guard.py 示例:规则层兜底 FORBIDDEN_PATTERNS = [ "诊断是", "建议服用", "治疗效果", "一定有效", ] def check_safety(text: str) -> bool: """返回 True 表示存在风险内容。""" for pattern in FORBIDDEN_PATTERNS: if pattern in text: return True return False5. 部署上线与生产保障
5.1 模型服务化:本地部署、云 API、混合部署
健康助手的生产环境通常不直接面向外部暴露大模型服务。常见方式是:
- 内部网关统一转发模型请求,所有内容经过安全过滤后再返回。
- 模型层可以选择云 API 或内部推理服务,用统一的 OpenAI-compatible 接口封装,方便切换。
- 知识库和向量检索必须部署在受控网络内,数据库访问走最小权限账号。
# deployment/docker-compose.yml 示例(简化) services: api: build: . ports: - "8080:8080" environment: LLM_BASE_URL: ${LLM_BASE_URL} VECTOR_DB_HOST: qdrant depends_on: - qdrant qdrant: image: qdrant/qdrant volumes: - qdrant_data:/qdrant/storage volumes: qdrant_data:5.2 推理成本与响应延迟
大模型应用上线后,成本控制是日常问题。三个直接手段:
- 加缓存:相同问题在短期内直接命中缓存,不再调用模型。
- 控制上下文长度:检索片段不是越多越好,每条都占用 token。
- 分级用模型:简单导诊和知识查询走小模型或规则引擎,复杂问题才调用大模型。
延迟方面,健康问答的总耗时主要来自三部分:检索耗时、模型生成耗时、安全校验耗时。如果总延迟超过 5 秒,用户体验会明显下降。优化顺序通常是:先优化检索,再限制生成长度,最后考虑模型量化或换小模型。
5.3 监控、日志与灰度发布
生产环境要关心四类日志:
- 请求日志:谁在什么时间问了什么问题。
- 检索日志:命中了哪些知识片段,得分多少。
- 模型日志:提示词最终内容、温度、token 消耗、响应时长。
- 审核日志:安全规则是否命中,是否触发人工升级。
监控指标至少包括:接口 QPS、P95 延迟、模型错误率、检索召回率、拒答率、安全规则命中率。
灰度发布要分两步走:先控制流量比例,观察错误率和用户投诉率;再逐步放开。一旦安全命中率指标异常,立即回滚到上一个稳定版本。
5.4 权限、审计与合规
健康领域的数据隐私要求远高于普通业务。上线前至少要确认:
- 用户敏感信息是否加密存储。
- 模型请求是否经过鉴权,是否记录完整审计日志。
- 知识库是否有版本控制,是否能回溯到某个权威来源。
- 是否提供用户投诉渠道和人工复核入口。
这些不是技术债,而是业务能否长期运行的前提。
6. 从技术指标到业务价值重估
6.1 技术指标怎么转化为业务指标
技术团队做完系统后,下一步要回答的问题是“这个系统到底创造了什么价值”。不能只说“我们的 RAG 准确率很高”,要转成业务语言。
| 技术指标 | 业务指标示例 |
|---|---|
| 检索命中率提升 | 用户咨询后进入正确科室的转化率提高 |
| 拒答率提高 | 错误引导减少,用户投诉率下降 |
| 响应延迟下降 | 咨询完成率提升,用户流失减少 |
| 安全命中率 | 法务与合规通过率更高,减少人工审核成本 |
这些业务指标才是“价值重估”的底层证据。技术侧要主动建立这些指标的采集链路,否则业务侧只能凭感觉判断 AI 助手有没有用。
6.2 医疗 AI 应用最重要的一条底线
无论技术多先进,AI 健康助手的定位始终是“辅助工具”,不能替代执业医师的诊断和处方。技术实现上必须守住三条底线:
- 不生成诊断结论。
- 不生成处方建议。
- 无法确认时只做就医路径引导。
这条底线要在产品文档、代码逻辑、提示词、评测集里反复出现,而不能只靠一句免责声明。
6.3 下一步:多模态、健康档案与多 Agent 协作
健康助手下一步的扩展方向有三个:
- 多模态理解:支持用户上传化验单、体检报告图片,先用 OCR 识别,再结合结构化规则提取异常项。
- 个性化健康档案:结合用户历史数据给出更精准的健康建议,但必须做好授权和隐私保护。
- 多 Agent 协作:导诊 Agent、用药 Agent、健康管理 Agent 各自专业,再由主 Agent 统一调度,避免一个模型处理所有问题。
这三个方向都会显著增加系统复杂度,建议在完成基础问答评测和稳定运维后再逐步引入。
7. 常见问题排查与上线前检查清单
7.1 高频问题与排查思路
| 问题现象 | 常见原因 | 检查方式 | 处理建议 |
|---|---|---|---|
| 回答与知识库不一致 | 检索召回错误或提示词约束弱 | 打印检索片段,审查 system prompt | 加大 top_k,强化“只能依据片段回答”指令 |
| 专业问题答不上来 | 知识库覆盖不足或切分不合理 | 检查文档是否完成清洗切分 | 补充权威医学资料,重跑向量化 |
| 同一问题每次回答都不同 | 模型 temperature 过高 | 查看请求参数 | 降到 0.2 以下,加缓存 |
| 线上响应缓慢 | 模型推理慢、检索慢、上下文过长 | 查看链路耗时和 token 消耗 | 限制检索片段数量,缩短生成长度 |
| 出现明显幻觉内容 | 检索无命中但没有拒答 | 查看低于阈值的片段是否被过滤 | 调高相似度阈值,强制走拒答分支 |
| 向量库切换后效果变差 | Embedding 模型版本不一致 | 检查向量库构建记录 | 全量重建向量库并固定模型版本 |
排查顺序建议:先确认输入问题本身是否清晰,再检查检索召回片段是否合理,然后审查提示词有没有被改写,最后看模型输出是否经过安全规则校验。每一步都通过日志确认,不要凭感觉定位。
7.2 健康问答上线前检查清单
- [ ] 知识库文档是否有来源、版本、更新时间和审核人。
- [ ] 是否完成文档清洗与语义切分,没有整篇灌库。
- [ ] 是否固定 Embedding 模型版本,并记录向量库构建批次。
- [ ] 检索 top_k 和相似度阈值是否经过评测集验证。
- [ ] system prompt 是否包含严格的拒答规则。
- [ ] temperature 是否控制在 0.2 以下。
- [ ] 是否配置模型调用超时、重试和降级文案。
- [ ] 是否完成安全性规则过滤,覆盖诊断和处方关键词。
- [ ] 是否接入结构化日志,记录请求、检索、模型和审核链路。
- [ ] 是否设置灰度发布和回滚方案。
- [ ] 是否有医疗专业人员参与答案抽检。
- [ ] 是否提供用户转人工入口和投诉渠道。
“AI 医生”这类应用被写入财报,说明市场开始认真评估健康领域大模型产品的真实价值。对技术团队来说,真正支撑这个价值的不是模型本身,而是围绕模型建立的工程体系:高质量知识库、可控的检索流程、严格的安全兜底、清晰的评测标准,以及可持续运维的生产环境。把这些环节逐一落地,AI 健康助手才可能从演示走向真正的业务闭环。