这次备孕全景评估,起点是一份十页的信息采集问卷和一份七十多页的客户报告。最初看起来像一个很典型的数字化项目:把问卷字段搬进系统,收集答案,再让模型按模板生成报告。

真正做起来以后,我很快发现,问卷、聊天和报告是三种完全不同的东西。问卷追求覆盖率,聊天必须尊重人的节奏,报告则要对事实、评分、措辞和版式负责。把问卷逐项改成聊天问题,只会得到一个披着对话外壳的审讯系统;把聊天记录直接扔给模型,又会得到一份漂亮但会遗漏、重复甚至自相矛盾的报告。

所以这次没有做一个“会聊天的表单”,而是重新搭了一条从服务对话、结构化病例、确定性评分到 HTML/PDF 交付的完整链路。

一个公开 Skill,内部再完成报告交接#

产品层只保留一个公开 Conversation Flow Skill:fertility-assessment。用户从建立服务档案开始,完成女方、男方或夫妻范围的访谈,最后得到报告。fertility-report 只是内部 handoff key,不作为第二个可见 Skill 出现在用户面前。

这个边界很重要。用户的目标是完成一次备孕全景评估,不应该感知系统内部还分成“信息收集 Skill”和“报告生成 Skill”。内部可以拆运行时和责任,外部仍然是一段连续服务。

流程的开头先确认称呼、评估对象和当前目标。用户可以只评估女方、男方,也可以选择夫妻双方;目标可能是自然备孕、辅助生殖,或者复盘过去经历。这个服务档案决定后面启用哪一组十维画像,也决定报告抬头和总结视角。

聊天不能照着问卷逐项盘查#

第一版最明显的问题,是问题太像资料采集。模型容易一口气列出年龄、周期、AMH、AFC、既往妊娠、精液浓度、活力、形态、睡眠、饮酒和职业暴露,用户得到的不是“被服务”,而是“被盘问”。

后来访谈合同被收紧为一轮只问一个高价值主题。每次提问先接住用户刚提供的信息,再说明为什么需要了解下一项。系统最多进行十轮有效采集,激活 Skill 的那一轮不计数;达到上限后强制收束。用户明确表示“不知道”“不方便说”“没有更多补充”时,不再用所谓完整度压着用户继续回答,而是进入唯一一次最终确认。

这里曾经踩过一个很具体的坑:用户说“最近一年睡眠很差,也长期加班,没有其他补充”,系统虽然记住了睡眠和加班,却又追问精液量和 pH。问题不在关键词识别,而在流程没有把“新增事实”和“拒绝继续补充”同时建模。

后来 TaskModel 的分析结果被改成结构化状态:

continue
ready_for_final_confirmation
user_declined_more
user_confirmed_report

Runtime 根据状态确定性收束,不再维护一串容易漏掉表达方式的拒绝正则。混合输入里,新增事实先写入病例,拒绝意图再决定是否结束访谈。

这部分目前仍有一个需要继续盯的边界:没有拒绝的正常用户,曾在第九轮被过早判定为可以生成。它说明“模型觉得资料差不多”不能自动等于流程完成,轮次上限、重复问题守卫和 ready 判断之间还需要更严格的优先级。

对话之后,必须留下结构化病例,而不是只留聊天记录#

为了避免报告阶段重新猜测整段对话,访谈过程中会持续维护一个临时病例状态:

facts
caseRecord.evidenceLedger
caseRecord.answerLog
caseRecord.askedRequirementIds
caseRecord.declinedRequirementIds
missingCriticalFields
uncertainties
contradictions

每条有效事实都有自己的证据编号,例如 E001,记录字段、原始陈述、值、来源、轮次和关联维度。answerLog 保存用户原话,askedRequirementIds 防止重复询问,declinedRequirementIds 则记录哪些内容用户已经明确不愿或无法补充。

这个结构解决了三个问题。

第一,问题生成不需要每轮重新遍历所有聊天记录,而是只查看当前缺口和已经问过的内容。第二,报告模型拿到的不只是归纳后的 facts,还能看到证据账本和用户原始回答,减少“系统明明问过,报告却说未提供”的情况。第三,当内容发生冲突时,系统可以显式保存 contradiction,而不是悄悄挑一句自己喜欢的答案。

报告不是十次模型调用拼起来的#

早期很容易按维度分批生成:每次让模型写一两个维度,最后拼成一份报告。这会造成事实重复、语气漂移和全局判断不一致。AMH、AFC、取卵数可能在四个章节里被重新解释四遍,夫妻双方的联合建议也很难真正建立在同一份事实底座上。

现在个人报告由主模型一次生成完整十维内容;夫妻报告分别生成女方十维、男方十维,再生成一次联合总结。每次调用都拿到完整 facts、evidence ledger 和 answer log。模型负责医学信息的自然语言解释,确定性评分器仍然拥有最终分数解释权。

十维评分最容易误导用户的地方,是资料不足。没有资料不能记成 0 分,因为 0 会被理解成严重异常;但直接显示 5.0,又容易让用户以为系统在没有证据时也能精准判断。

因此低证据维度采用中性参考基准,同时明确降低置信度和资料完整度:

5.0 中性参考基准
暂不可充分评价
置信度:低
资料完整度:0%

分数不代表自然怀孕率、试管成功率或疾病概率。当前标准版本 fertility-rubric-v2.0.0 也不再只是报告里的内部暗号,Skill 页面增加了评分区间、低资料机制、男女十维范围和报告边界的公开说明。

漂亮还不够,报告内容必须有治理层#

第一批 PDF 已经足以让普通客户觉得这是一份正式服务交付,但“能唬住人”不是目标。真正容易露馅的地方,是同一个事实同时出现在“已有依据”“当前关注”和“建议补充”,或者在资料不足时给出具体促排、移植、药物和补充剂方案。

所以模型生成之后,又增加了一层内容治理:

  • 同一栏目和跨栏目进行近似语义去重;
  • “已有依据”只保留事实,“当前关注”只保留由事实推导出的风险;
  • 没有资料的维度不生成臆测风险和通用行动清单;
  • 促排、移植、PGT、药物、补充剂和手术等内容不留在“自己先做”,而是收敛为“就诊时可问”;
  • 报告明确说明这些方向用于信息整理和就诊讨论,不代表具体治疗方案。

医疗免责声明不能成为正文放飞的许可证。报告可以帮助用户把情况讲清楚、把问题准备好,但不能在缺乏临床责任主体的情况下伪装成诊疗方案。

HTML 是产品,PDF 是另一套排版系统#

HTML 预览较早就达到了可用状态,真正折腾人的是 PDF。浏览器的固定页眉页脚会压住正文,章节标题可能留在上一页、内容跑到下一页,夫妻报告还出现过空白页和标题切断。

后来 PDF 渲染从 Playwright 的 page.pdf() 切到 Vivliostyle。封面使用独立 page rule,正文通过 @page 定义页眉、页脚、免责声明和页码。目录页使用标题锚点和 target-counter() 自动生成页码,并进入 PDF 书签层级。

小维度不强制另起一页,否则二十个维度会把报告膨胀得又长又空。标题、分数、置信度、完整度、进度条和核心判断首段被包装为不可拆的开场组:当前页放不下时整组移动到下一页。后来连每个维度上方那条过重的紫色横线也删掉了,只保留更大的章节间距和左侧短色条。

Windows 上还连续遇到两个很现实的问题。安装脚本直接 spawnSync("npm.cmd") 会报 EINVAL;运行时又因为 .cmd + shell:true 和带空格路径,把参数拆成三段,Vivliostyle 报“too many arguments”。这类问题和报告设计无关,却决定了用户最终能不能拿到 PDF。最后的执行方式改成 Windows 显式走 cmd.exe /d /c,非 Windows 再直接启动 CLI。

预览窗属于业务 Artifact,不属于 UChat 核心#

报告生成后,聊天里需要展示 HTML 预览、PDF 状态和保存入口。最初顺手把 SkillReportOutput 挂进了 UChat 的消息层,后来我马上意识到这会破坏刚做完的 UChat 抽象。

现在 UChat 只保留通用 MessageExtensions 插槽,宿主层提供 artifact slot 和 renderer registry,备孕报告自己的标题、HTML 预览、PDF 状态和操作按钮全部留在 SkillReportArtifactRenderer。普通消息没有 renderer 时不占任何高度。

报告预览默认高度也从五百多像素压到约 220 至 300 像素。Mira 的对话区域本来就不高,预览应该让用户确认内容,而不是把整段聊天挤出屏幕。

隐私说明要真实,不要写一句“不收集隐私”糊弄过去#

年龄、激素、精液参数、既往妊娠和治疗经历,本身就是敏感健康信息,所以不能承诺“我们不收集隐私”。更真实的说法是:信息由用户知情、自愿提供,仅用于本次评估和报告生成;可以使用化名,可以跳过任何问题,也可以随时停止。

Mira 是多供应商应用,隐私披露还必须和真实 Provider 配置一致。使用本地模型与使用云模型不是一回事,不能无论当前链路怎样都写“数据不会上传”。夫妻评估也需要提醒提供者确认已获得另一位评估对象的同意。

这部分没有被设计成一套庞大的撤回流程。产品入口和 Skill 说明先把处理目的、可跳过、可停止、云模型链路和夫妻信息边界说清楚。至于“删除对话是否同步删除 Flow state、HTML 和 PDF”,只有底层删除链路真正闭环后,产品文案才有资格承诺。

从问卷到服务,中间差的是一整套责任#

这次备孕评估让我重新确认了一件事:把纸质业务搬进 AI 产品,不是把字段换成聊天气泡,也不是让模型把答案扩写成几十页 PDF。

真正的产品链路包含访谈节奏、拒答语义、病例状态、证据可追溯、评分解释、内容治理、医疗边界、分页系统、隐私披露和聊天宿主边界。任何一层偷懒,最后都会在客户面前变成重复追问、错误事实、过度建议、难看的空白页,或者一句经不起检查的隐私承诺。

现在这套系统已经能够完成女方、男方和夫妻范围的访谈与报告交付,HTML 和 PDF 也有了稳定形态。但第九轮提前收束、更多真实病例下的医学措辞,以及删除链路的完整性仍然需要继续验证。

我不准备因为报告已经“看起来很专业”就宣布完成。对这种会承接用户真实健康经历的产品来说,专业感只是门面;事实不丢、边界不乱、规则能解释,才是它真正能够被使用的理由。

Tomz Dang