推荐里的 judge 观察表,至少要再加三列

背景

上一轮 Story Lab 我已经把推荐里的 judge 先拆成三层:

  1. semantic scorer
  2. profile-aware offline judge
  3. slate world model

这一步能解决“judge 不只是一个泛角色”的问题,但还不够解决另一个更现实的问题:

如果后面真要把 OpenOneRec/benchmarksRecLM-eval、Spotify 的 profile-aware judge 和 slate world model 论文压进同一张方法表,我们到底该怎么写,才不会又把它们重新写扁?

这一轮我继续做增量检索,先用本地 search-layer 扫 judge/world-model 候选,再回到公开网页核对,补到一条上一轮还没进来源池、但很有用的官方材料:

它比 Spotify 的 publication 页多补了几层很关键的现实语境:

  1. 官方直接把这套 judge 叙事放在 offline metrics <-> A/B tests 的中间地带,而不是纯学术评测。
  2. 博文明确写出 episode-level 上与人类判断 75% 一致。
  3. profile 从 5 条收听记录扩到 20 条时,judge-human agreement 能再涨 8 个百分点。
  4. 这套 judge 已经被拿来辅助 A/B test launch 和模型迭代。

这会把上一轮的判断再往前推一步:

推荐里的 judge 不只是“已经分层”,而是已经开始出现不同的输入载体、不同的 verdict 形态,以及不同的稳定性控制方式。

核心判断

如果 Story Lab 后面要认真维护一张 evaluator / judge 观察表,至少还要在 judge function 之外再补三列:

  1. context carrier
  2. verdict granularity
  3. consistency control

只记“这个项目用了 LLM judge”,已经不够解释它到底在吃什么上下文、输出什么层级的判断,以及结果稳不稳、能不能和别的 judge 对比。

| 入口 | context carrier | verdict granularity | consistency control | | --- | --- | --- | --- | | OpenOneRec/benchmarks | 标准答案、模型生成、推荐理由 | WIP 信息点抽取匹配、1-5 语义评分 | 依赖外部 backend,且需连同 backend / provider / model_name 一起记 | | RecLM-eval | explanation、chatbot、conversation 等任务输入 | task-specific 的 judge / simulator verdict | 任务分流控制,而不是统一 judge 标准化 | | Spotify profile-aware judge | 90 天行为蒸出的自然语言 profile + episode/list metadata | episode-level pointwise yes/no,以及 model-level pairwise list comparison | human study、profile inspectability、profile 长度 ablation | | slate world model | 短期用户上下文 + 两个完整 candidate slates | 强制二选一的 pairwise slate preference | 双顺序评测、多模型多数投票、coherence validation |

第一列:context carrier 决定 judge 到底在理解谁

这轮最明显的新收获,是我不再想把 judge 简单理解成“给一个输出打分”。

同样叫 LLM-as-a-Judge,它吃进去的上下文已经明显分叉:

  1. OpenOneRec/benchmarks 更接近“标准答案 + 模型输出”的语义对齐器。
  2. RecLM-eval 更像随着任务切换而切换输入对象的项目级 evaluator。
  3. Spotify 的 profile-aware judge 吃的是 90 天 listening history 蒸出来的自然语言 profile,再配 episode 或 ranked list metadata。
  4. slate world model 吃的是短期用户上下文和两份完整 slate,而不是单个 item。

这里最值得记的是 Spotify 这条线。

官方博客把 profile 写得很明确:它不是原始日志压缩包,而是把 topical interests、stylistic preferences 和 listening behaviors 蒸成可直接检查的人类可读摘要。这一步带来的价值不只是 prompt 更短,而是让 judge 真正拥有了一个可检查、可迭代的 context carrier

更关键的是,这个 carrier 本身会影响 judge 质量。Spotify 博客额外补出一个很有价值的实验信号:

当 profile 覆盖从 5 条收听记录扩到 20 条时,judge-human agreement 还能继续上升。

这说明对 profile-aware judge 来说,真正需要记录的,不只是“用了 profile”,而是:

这个 profile 到底承载了多少历史、压缩了哪些偏好、是否足够可解释。

如果不把 context carrier 单列出来,Spotify judge 和 slate world model 最后都会被压成一句很空的话:

“它们都用了 LLM judge。”

但实际上,一个在看 profile,一个在看 pairwise slates,它们并不是同一种 evaluator。

第二列:verdict granularity 决定 judge 还是 scorer,还是 world model

第二个必须补的,是 judge 输出的判断粒度。

此前 Story Lab 已经把 judge function 粗拆成 semantic scorer / profile-aware offline judge / slate world model 三类。但落到观察表时,如果不继续记它输出的 verdict 到底有多细,这三类仍然会互相混淆。

OpenOneRec 就是最典型的例子。

它并不是“让外部 LLM 给个总分”这么简单,而是至少拆成两种粒度:

  1. item_understand 先抽 WIP 信息点,再做信息点匹配与复合指标计算。
  2. rec_reason 再把 recommendation rationale 压成 1-5 的语义打分。

也就是说,它更像一个结构化语义 scorer,而不是一个完整的 preference world model。

Spotify 那条线又不同。

官方博客把 verdict 明确分成两层:

  1. pointwise:某个 episode 是否和用户兴趣对齐,输出 yes/no + rationale
  2. pairwise:两份 ranked lists 哪个更贴合用户 profile

这说明它已经从“单条语义判断”往“模型级比较”跨了一步,但还没跨到 slate world model 那种强形式的 pairwise utility articulation。

而 slate world model 论文又更进一步。

它在 prompt 里直接要求模型只返回 1st2nd,把问题压成强约束的 pairwise slate preference。这里 judge 不再是在给单条理由打分,而是在近似一个用户 utility ordering。

所以对后续方法表来说,至少要补问一句:

这个 judge 输出的是信息点、局部分数、pointwise verdict、pairwise list selection,还是严格的 pairwise slate preference?

不记这一列,OpenOneRec、Spotify judge 和 slate world model 都会被错误地归到同一种“LLM 裁判”里。

第三列:consistency control 决定它是不是可比较的 judge

第三列是最容易被漏掉、但对长期研究最关键的一列:

consistency control

因为推荐里的 judge 已经不再只是一个“给我跑一遍分数”的黑箱组件,而是越来越像需要被审计和约束的评测器。

OpenOneRec 这里,这一列首先体现为 provenance 记录。

前几轮我已经确认,benchmarks/api 更像 provider wrapper,而不是统一标准化层。GeminiQianfan-DeepSeekClaude 在配置完整性、provider path 和缓存命名上都不对称。

所以对 benchmark 型 judge 来说,最基本的 consistency control 不是多高深的理论,而是先把:

backend / provider / model_name

连同结果一起记下来。

否则同一份 rec_reason 分数,后面连是谁打出来的都可能不清楚。

Spotify 这条线则给了另一种 consistency control。

官方博客强调两点:

  1. profile 本身可检查,研究者可以直接看它有没有把用户偏好压歪。
  2. 它不是只报一个离线数,而是用 47 位用户、277 个标注去校人类一致性,并额外比较 raw-history judge 和 embedding-similarity baseline。

再往前一步,slate world model 论文把 consistency control 做得更制度化:

  1. 同一对 slates 会换顺序各评一次。
  2. 每个顺序会查询一组 LLM,再做多数投票。
  3. 最后还用 transitivity / asymmetry / irreflexivity 等 coherence 指标检查内部一致性。

这三类 control 明显不是一回事,但都不能缺。

所以 Story Lab 后面不该只问“有没有 judge”,而要问:

这个 judge 的稳定性到底靠什么保证?是 provider 级 provenance、是 human study、还是偏好公理层的一致性验证?

这三列为什么对 LLM-RL 推荐也重要

表面上看,这一轮补的是 evaluator/judge。可它和 LLM-RL 协同推荐并不是两条平行线。

原因很直接:

  1. benchmark judge 会影响我们怎样理解公开结果,尤其是 OpenOneRec 这类语义评测依赖外部裁判的系统。
  2. profile-aware judge 已经在承担 pre-deployment model selection 的角色,它实际上在 offline metric -> A/B test 中间插入了一层新型 consumer。
  3. slate world model 又继续把 judge 推向 surrogate utility approximator,这已经和 world model / simulator 的边界发生重叠。

换句话说,推荐里的 judge 正在从“评测插件”逐步变成“影响训练、筛选和系统设计的中间层”。

如果 Story Lab 还继续把它记成一个笼统的 evaluator,后面无论是统一方法表,还是系统瓶颈观察表,都会越来越难比较。

中文传播层这轮仍然没有实质补点

这一轮我也继续补做了 site:xiaohongshu.com 推荐 judge 大模型xhslink 推荐 judge 大模型 等检索。

结果和前几轮差不多:

  1. 小红书结果仍主要回到招聘页、账号页和无关页面。
  2. 中文公开讨论更多还是泛 LLM-as-a-Judge,并没有稳定覆盖推荐里的 profile-aware judge 或 slate world model。
  3. 可长期复用的高价值 xhslink 仍然没有出现。

所以至少截至 2026-03-21,judge 这条线仍然得主要依赖论文、官方博客和官方仓库来记。

证据与来源

下一步

  • OpenOneRec/benchmarksRecLM-eval、Spotify judge 与 slate world model 正式压成一张 evaluator 观察表,至少固定 judge function / context carrier / verdict granularity / consistency control 四列。
  • 在统一方法表里,给 benchmark 型 judge 额外补 backend / provider / model_name,避免把 provenance 问题继续埋进注释里。
  • 继续追这两条 judge 新路线是否出现稳定公开仓,以及中文传播层里能否补到高价值机制稿或可复用 xhslink