本文是 Heidi、Fireworks 与 NVIDIA 的合作成果。Heidi 在 Fireworks 上对该模型进行了后训练(先做托管式 SFT,再在Fireworks Training API上进行 RL),并通过 Fireworks 上的专用按需部署提供服务,运行在 NVIDIA Blackwell 上。下文的“我们”指 Heidi 的模型团队。

一位临床医生在接诊过程中想确认一线治疗方案、核对按肾功能调整后的剂量,然后回到病人身边。Heidi Evidence 会基于经过筛选的权威来源给出综合答案,每条结论都在行内标注引用,且这一切都发生在起草病历记录的同一工作流内。Evidence 为决策提供支持;临床判断仍由医生掌握。

Heidi 每周支持 270 万次临床就诊,覆盖 110 种语言,因此 Evidence 背后的模型承载着非同寻常的工作负载。单个请求可能包含数万 token 的患者病史和检索到的指南文本。模型必须在“搜索”与“基于已有上下文作答”之间做出选择,读取结果并返回带有密集引用的结构化响应,且延迟要能适配接诊间隙。

在本文中,我们将介绍我们如何针对这一工作负载对NVIDIA Nemotron 3 Ultra进行后训练并完成部署,Fireworks 在两方面都是平台:在 Fireworks 上基于合成智能体轨迹进行监督微调(SFT);在 Fireworks Training API 上做强化学习(RL),其奖励函数围绕临床医生在实时评估中所看重的质量构建;使用 NVIDIA Model Optimizer 进行 NVFP4 量化;在专用 Fireworks 部署上部署量化后的检查点;以及支撑这一结果的度量规范。后训练后的开源模型在实时并排对比中,对当前生产环境中运行 Evidence 的前沿模型胜率约为 54%。基础检查点的胜率约为 42%。

“大多数临床 AI 都建立在封闭模型之上,藏在别人的 API 背后。我们在合成数据上对一个 550B 的开源模型进行了后训练,其奖励机制将临床安全性和忠实性视为硬性门槛,如今在真实临床医生的对比中,它已经超越了前沿模型。拥有权重意味着我们可以固定一个版本、审查每一处变更,并在本地运行同一个检查点。Fireworks 和 NVIDIA 让一个十二人的团队做到了这一点。”
- Yu Liu,Heidi 联合创始人兼 CTO

Evidence 最初基于一个前沿模型发布,该模型表现良好。有两件事推动我们转向一个由我们自己后训练并运营的开源模型。

第一是我们从临床医生那里学到的东西。使用 Evidence 的临床医生会在实时并排(SBS)对比中从两个回复中做出选择,这些结果告诉我们模型在哪些方面存在不足。对于封闭模型,解决办法是修改提示词。而对于我们拥有权重的模型,我们可以改变模型本身。

第二是治理。在临床环境中,我们需要固定模型版本、审查版本之间的变更,并在我们控制的专用算力上运行模型。拥有权重的模型让我们同时具备这三点。在 Fireworks 上,这意味着在按需 GPU 上对我们自己的检查点进行专用部署,而不是使用共享端点;同时,同一套权重也可以在具有数据驻留要求的医院本地运行。

Nemotron 3 Ultra 总参数量为 550B,每个 token 激活 55B。其架构将 Mamba-2 层与混合专家(MoE)层交错排列,并加入少量全注意力层,同时在专家选择之前通过潜在投影对 token 进行路由。这一设计在几个方面与 Evidence 的工作负载相匹配:

  • 长提示词占用的内存更少。每个注意力层都会随提示词长度成比例地增长一个键值(KV)缓存。每个 Mamba-2 层无论提示词长度如何都保持固定大小的循环状态。由于注意力层只占少数,在 30k 到 60k token 时,每个请求的缓存占用仅为同等规模 transformer 所需的一小部分,因此每块 GPU 上可以容纳更多并发的长提示词请求。
  • 长上下文窗口为患者病史加上一整轮检索到的指南材料留出了余量。
  • NVFP4 是原生精度。NVIDIA 将大多数线性层的权重、激活和梯度预训练为 4 位浮点,而将潜在投影、注意力投影、嵌入和多 token 预测(MTP)头保持更高精度。以 NVFP4 部署是该检查点的设计目标。这使训练后量化的问题从“我们会损失多少质量?”转变为“我们是否保留了 NVIDIA 保持更高精度的那些层?”
图 1. Heidi 针对 Nemotron 3 Ultra 的训练后与部署流水线。训练数据为合成数据,由沙盒生成;生产数据仅在评估阶段出现。Fireworks 负责训练与部署;NVIDIA 提供模型、Model Optimizer 和 Blackwell。

该流水线有七个阶段。所有训练数据均为合成数据,在隔离的沙盒环境中生成,与生产环境分离。生产数据仅在评估阶段通过离线安全门之后的 SBS 对比进入流水线。Fireworks 承担流水线的训练端与部署端;Heidi 负责其间的数据生成、奖励与评估。以下每个阶段涵盖我们所做的工作及其背后的决策。

Evidence 运行一个推理-行动循环。模型先写一段简短的作答前推理块,针对 Heidi 精选的临床来源发起搜索调用,阅读返回的段落,并写出带引用的综合回答。所有 SFT 数据均为合成数据。我们在隔离的沙盒环境中生成临床查询和患者上下文,使其匹配 Evidence 在生产中看到的病例组合、查询类型和上下文长度,然后针对生产智能体所用的同一批检索工具生成完整轨迹。训练集中没有进入任何生产数据。

在这些轨迹中,有四种行为最为重要:

  1. 当问题需要最新指南时进行搜索;当患者病史中已有答案时,从上下文中作答。
  2. 将多次搜索合并为一轮并行查询,而不是一串单条顺序查询。
  3. 保持作答前推理简短。临床医生要等待其中的每一个 token。
  4. 生成临床医生在早前评估轮次中更偏好的结构化、行内引用格式。

有一条规则支配着生成过程,我们称之为冷生成纪律。轨迹生成器在编写轨迹时可以看到特权材料:对先前尝试的批评、参考答案、评分标准。而学生的训练提示只能看到生产环境会展示给它的内容,仅此而已。任何泄露都会教学生依赖它在推理时永远无法获得的信息。

每个示例都是一条包含工具调用和工具结果的多轮记录。我们只在助手 token(推理、工具调用和最终答案)上计算损失,并屏蔽用户轮次和工具结果。

json

Copy

12345678910111213

{"messages":[

{"role":"system","content":"<Evidence system prompt>"},

{"role":"user","content":"<synthetic query + synthetic patient context>"},

{"role":"assistant","content":"<brief reasoning>","tool_calls":[

{"id":"c1","type":"function","function":{"name":"search_guidelines",

"arguments":"{\"query\": \"...\", \"region\": \"...\"}"}},

{"id":"c2","type":"function","function":{"name":"search_guidelines",

"arguments":"{\"query\": \"...\"}"}}

]},

{"role":"tool","tool_call_id":"c1","content":"<retrieved passages with source ids>"},

{"role":"tool","tool_call_id":"c2","content":"<retrieved passages with source ids>"},

{"role":"assistant","content":"<structured synthesis with inline [source_id] citations>"}

]}

在任何训练运行之前,我们会将一部分记录样本通过 Nemotron 聊天模板做一次往返转换,并检查渲染出的 token id 和损失掩码。Fireworks 会在任务页面上展示渲染后的样本,正是为此目的。如果模板丢弃了生成提示或弄乱了多轮工具历史,它会在不报错的情况下失败,而得到的模型仍然会报告损失在下降。

我们将轨迹集以 JSONL 格式上传,并针对 Nemotron 3 Ultra 基础检查点启动了 SFT。证据轨迹很长,因此我们将最大上下文长度提高到默认值以上,以避免截断最终答案所引用的检索段落。Heidi 这次运行特有的值在下面的代码片段中以占位符形式出现。

bash

Copy

12345678

firectl dataset create heidi-evidence-sft ./evidence_trajectories.jsonl

firectl sftj create \ --base-model <nemotron-3-ultra-base-model-id> \

--base-model <nemotron-3-ultra-base-model-id> \

--dataset heidi-evidence-sft \

--evaluation-dataset heidi-evidence-sft-holdout \

--output-model heidi-evidence-sft \

--max-context-length <full-trajectory-context-length>

SFT 检查点将针对生产前沿模型的实时 SBS 胜率从约 42% 提升到约 49%。

SFT 赋予智能体其格式和循环行为。RL 则将其推向临床医生在评估中所看重的品质。

我们通过 Fireworks Training API 运行 RL,这让我们可以用 Python 编写训练循环,而由 Fireworks 运行模型计算。分工很清晰:Heidi 的代码负责 rollout 编排、奖励函数和损失;Fireworks 负责训练器集群和 rollout 部署,并在每次优化器步骤后将新的策略权重热加载到该部署中,使 rollout 保持 on-policy。奖励函数及其评分的合成轨迹保留在 Heidi 的环境中,RL 提示词来自与 SFT 相同的合成沙盒生成器。Fireworks 声明客户训练数据绝不会被用于训练 Fireworks 自有或共享的模型,且推理默认零数据保留,这对临床部署很重要。

我们分层构建奖励,先设门槛再评分:

  • 硬性门槛。安全性与忠实性。如果回答在检索到的证据范围之外给出建议,或陈述了其引用无法支持的论断,则无论其他方面得分如何,都会获得最低奖励。策略不能以违反忠实性为代价来换取完整性。
  • 程序化检查。每条引用都必须解析到智能体在该轨迹中检索到的段落。如果轨迹在没有搜索的情况下回答指导性问题,则会受到惩罚;运行冗余搜索轮次的轨迹同样如此。
  • 分级标准。一个开源权重的 LLM 评判器对完整性、引用覆盖率、来源权威性、事实性以及无不解释的矛盾进行评分。相同的标准驱动第 4 步中的离线评估门槛。
  • 临床医生参与的评分细则。我们根据临床医生在以往多轮 SBS 评估中总体上所奖励的内容(哪些回答质量胜出、哪些落败)设计了评分标准,并由 Heidi 的临床团队对合成配对打分,以此验证评判器。任何 SBS 记录都不会进入训练。

python

Copy

1234567

defreward(trajectory,retrieved)->float:

ifnotpasses_safety(trajectory)ornotpasses_faithfulness(trajectory,retrieved):

return0.0# 硬性门槛:奖励下限

judge=judge_score(trajectory,RUBRIC)# 完整性、覆盖度、权威性、

# 事实性、矛盾

prog=programmatic_score(trajectory,retrieved)# 引用可解析、检索规范性

returnW_JUDGE*judge+W_PROG*prog

我们使用了 GRPO 系列中的组相对策略梯度方法:对每个提示采样一组 rollout,用上述奖励为每个 rollout 打分,在组内归一化优势并更新。我们使用了 GSPO(Group Sequence Policy Optimization)并配合自定义损失函数。GSPO 在整个序列而非每个 token 上计算重要性比率,这适合长智能体轨迹——这类轨迹的奖励每条只出现一次。经 RL 对齐的检查点在与生产前沿模型的对比中达到了约 54%。

任何检查点都必须通过内部离线评估才能进入 SBS 循环。我们会让每个候选模型在一个留出的合成评估集上运行,该评估集与训练数据分离,覆盖 Evidence 所服务的病例组合、专科和地区,并对每个回答在临床安全性、对检索来源的忠实度、完整性、准确性、引用有效性和检索规范性上打分。

临床安全性和忠实度是及格/不及格项。如果候选模型在评估集中的任何病例上给出超出其证据范围的建议或错误陈述剂量,无论其他分数如何,都不会继续推进。分级标准必须达到或超过当前生产模型,检查点才能获得 SBS 名额,并且 Heidi 的临床团队要签署确认安全结果。

顺序很重要。SBS 把候选模型放到在职临床医生面前,而偏好投票无法在临床医生恰好没有选择的那条回复中捕捉到不安全的建议。离线评估承担安全责任;SBS 衡量的是已经通过离线评估的回复之间的偏好。由于离线评分标准和 RL 奖励共享相同的标准,我们朝着测试模型的方向训练模型,同时评估集保持在训练之外。

本文中的每个数字都来自生产环境中的实时 SBS 评估。临床医生提出一个问题,看到两条回复并排展示,顺序随机且模型隐藏,然后选择更好的一条或跳过。我们将跳过计为既非胜也非负,并且在任何数字离开团队之前都会审核分母。生产前沿模型在所有三个实验组中作为固定对照,因此我们针对同一个目标衡量每一项提升。每个实验组在一周的采样窗口内收集了约 1,500 次比较。SBS 仅用于评估;没有任何 SBS 记录进入训练。

离线基准测试指导了日常决策,但没有一个能取代这个循环。一个模型可以在医学 QA 集上得分很高,却仍然在临床医生面前输给现有模型,而第二个结果才是对 Evidence 真正重要的。

一个 550B 参数的 BF16 检查点大约有 1.1 TB 的权重。使用 NVIDIA Model Optimizer,我们将 RL 对齐的检查点量化为 NVFP4,使其降至约 352 GB,并保留了预训练时的混合精度结构:NVIDIA 以更高精度保留的层仍然保持更高精度。校准在来自训练所用同一沙盒生成器的合成提示上运行。

为了验证,我们在真实生产对话上测量了 BF16 和 NVFP4 检查点之间的贪心 token 一致率,而不是基准测试分数。两个检查点在 97.35% 的贪心 token 上一致。作为参照,我们在两个 BF16 服务栈之间运行了同样的测试,看到的漂移比 BF16 与 NVFP4 之间还要大。生产分布上的 token 一致率能在漂移刚出现时就标记出来;基准测试分数则反应滞后且带有噪声。基于这些结果,我们预计量化后的质量不劣于原模型,而最终的把关仍是同一个

SBS 循环,用于对训练阶段进行把关。

我们将量化后的检查点作为 Fireworks 上的专用按需部署进行部署,运行在 NVIDIA Blackwell GPU 上。Heidi 拥有权重并固定版本;Fireworks 负责运行服务栈、自动扩缩容和容量。Blackwell 上的 NVFP4 提供了使 550B 模型在每次访问上具备经济性的吞吐量,而专用部署将 Evidence 流量保留在为 Heidi 预留的 GPU 上,而不是共享端点。Fireworks 在特定的加速器、GPU 数量和精度组合上验证每个模型,并以部署形态的形式暴露出来,因此部署从经过验证的配置开始。

bash

复制

1234567

# 将 ModelOpt NVFP4 检查点作为自定义模型上传后:

firectl deployment-shape-version match --model accounts/heidi/models/heidi-evidence-nemotron3-ultra-nvfp4

firectl deployment create accounts/heidi/models/heidi-evidence-nemotron3-ultra-nvfp4 \

--deployment-shape <validated-blackwell-nvfp4-shape> \

--min-replica-count <min> --max-replica-count <max> \

--wait

服务混合架构与服务 transformer 不同。Mamba-2 层携带需要单独缓存处理的循环状态,前缀缓存必须同时覆盖该状态和 KV 缓存,而 MTP 头则开启了投机解码的路径。Fireworks 推理栈为该检查点处理这些架构特定的细节,因此 Heidi 的团队将部署精力花在了质量把关上,而不是引擎调优上。

由于 Heidi 拥有该检查点,同一产物也可以在有数据驻留要求的医院本地运行。

  • 匹配你所服务的分布。当合成数据的病例组合、查询类型和上下文长度与生产环境匹配时,它才真正发挥价值,因此我们按照这一分布来设计沙盒生成器,并在评估中核验了匹配程度。
  • 先设门槛,再谈评分。严格的安全与忠实性门槛防止了策略以牺牲忠实性来换取完整性。没有下限的加权求和会诱发这种取舍。
  • 安全在离线评估,偏好在在线评估。离线评估承担通过/不通过的安全责任,因此 SBS 循环只在已经通过安全门槛的回复之间衡量偏好。
  • 一个 12 人的团队就能对一个 550B 模型进行后训练并交付上线。Fireworks 在训练期间承载了训练器和采样集群,在生产环境承载了服务栈;Heidi 团队则把时间投入到数据生成、奖励和评估上。

经过后训练的 Nemotron 3 Ultra 正处于最终评估阶段,即将进入生产部署。一旦通过,每一位使用证据的临床医生都将获得来自一个开放模型的、最新且带引用的临床推理,该模型的权重由 Heidi 拥有,在 Fireworks 上训练和部署,并构建于 NVIDIA 之上。接下来,我们会根据评估结果指出的下一批缺口迭代 SFT 和 RL 轮次,在 Fireworks 部署上启用 MTP 投机解码,并将同一检查点扩展到本地部署。

Heidi 的模型团队构建了本文所述的数据生成、训练和量化流水线,Heidi 的临床团队负责离线评估和签核。Fireworks 在其平台上支持了训练和部署工作,NVIDIA 支持了 Nemotron 3 Ultra 的后训练和 NVFP4 量化。媒体咨询:media@heidihealth.com。