
AI Agent 指标别把 null 当 0从数据模型到增量计算一个 AI Agent 仪表盘显示“收藏 0”可能有三种完全不同的真相用户确实没有收藏平台没有提供收藏字段采集任务根本没运行。若把后三者都写成数字 0图表看起来更完整决策却会越来越不可信。本文给出一套可以直接落库和测试的三态模型0 表示已观察到的真实零值null表示当前来源无法可靠提供未采集表示没有观察证据。问题、代价与适用边界这套模型适用于 Agent 可观测性、内容反馈、外部 API 指标和异步采集系统。它解决的是证据语义不替代业务 KPI 的定义也不假设所有平台都提供相同字段。核心结论与关键概念指标值必须和采集状态一起解释。数据库中的可空数字只能表达“值未知”还需要快照时间、来源、采集状态和基线标记来区分为什么未知。一、三种状态分别表达什么1. 数字 0真实观察结果只有当前来源明确返回该字段并且值确实为零时才保存0。例如公开页明确显示评论数为 0这是一条可比较的观察。2. null字段不可得或不可靠当平台不展示展现量、解析节点不存在、字段含义不确定或者当前版本无法稳定读取时保存null。null的意思不是表现差而是不能计算。3. 未采集没有快照采集没运行、登录失效、任务被跳过时不应凭空创建一条全零记录。没有快照本身就是事实应由运行状态表达。二、推荐的数据结构可复现的实现步骤一个最小快照可以这样建模dataclass(frozenTrue)classMetricSnapshot:content_id:strrevision:intcaptured_at:datetime collection_state:Literal[completed,failed,skipped]views:int|Nonelikes:int|Nonecollects:int|Nonecomments:int|None约束建议如下completed才允许进入指标序列failed/skipped保存运行证据不伪造指标快照非负数字包含 0代表真实观察不可得字段保存None快照绑定content_id revision避免改稿前后串线。三、增量计算必须传播 null首次采集只建立基线不能产生增量。第二个真实时间点到来后再逐字段比较defdelta(now:int|None,before:int|None)-int|None:ifnowisNoneorbeforeisNone:returnNoneifnowbefore:returnNone# 标记平台重算或采集异常returnnow-before这里故意不写now or 0。Python 中0是假值这种简写会把真实零与缺失值混在一起。四、失败恢复和异常处理风险、失败恢复与反例指标下降累计指标通常不应下降。出现下降时应记录metric_decreased异常并暂停解释可能原因包括平台重算、文章改绑或解析契约变化。标题或文章 ID 不一致采集前回读公开页标题并验证文章 ID 与稳定内容 ID 的绑定。任何改绑都应停止不能把另一篇文章的数据接入当前序列。用阅读量冒充展现量阅读和展现是不同漏斗层。平台不提供展现时impressionsNone不能复制views让报表“有数”。首次快照就给优化结论只有一个时间点无法判断增长。基线只能证明“此刻是多少”至少两个真实快照才能形成增量假设。五、验收测试验收清单与参考依据真实零值是否保留为 0任一端为 null 时增量是否仍为 null未运行采集时是否不创建全零快照首次快照是否标记 baseline指标下降是否产生异常而非负增量标题、文章 ID、内容 ID 和 revision 是否一致报告是否明确区分“没有互动”和“互动指标不可比较”参考依据RuyiBookCourse 的生产环境 Agent 章节强调KPI 要覆盖技术性能、质量、用户体验和业务影响并在全面上线前建立基线。真实项目实现进一步把这一原则落实为可空字段、基线快照、逐字段增量和异常检测对应测试验证全部互动未知时不能声称获得互动。收束数据系统最危险的错误不一定是数值算错而是把“不知道”写成“零”。保留空值并不丢脸它是在保护下一步决策的证据边界。发布前门禁固定版本知识与真实项目测试均已绑定示例不虚构平台指标不以阅读量替代展现量本轮未认领实验