← 全部讲义 · Open Learning Notes
开源代码精读 · 课件

For You 算法讲义

𝕏(推特)「为你推荐」信息流的完整链路:候选从哪来、Transformer 怎么打分、安全系统如何决定一条帖子能不能被看见 —— 基于 xai-org/x-algorithm 2026 年 8 月开源版本,按行业通用的「召回 → 粗排 → 精排 → 重排 → 混排」漏斗术语讲解。

代码仓库 github.com/xai-org/x-algorithm 技术栈 Rust · JAX 许可 Apache 2.0
第 1 讲

行业范式:经典级联漏斗

先建立参照系。今天各家信息流产品 —— 抖音/TikTok、小红书、YouTube、Instagram Reels —— 的推荐系统,基本都收敛到同一套级联排序架构(cascade ranking):用一层比一层重的模型,把候选量级一级级压下来,让最贵的模型只算最少的帖子。下面这块面板把「量级」和「延迟」放在同一个状态里:上半是漏斗(每层看到多少条),下半是同一状态下的延迟瀑布(每步花多少毫秒)。我们的主角是一条叫 №4711 的帖子,它会在后面每张图里出现。

地图 · 行业范式 › 漏斗 → 延迟 · 主角:帖子 №4711

粗排存在的理由:让重模型只看到最少的帖子。总延时 = 最长的那根串行链。

图 1 · 漏斗与延迟联动面板(行业典型值,示意)。上半对数轴、下半线性轴;点击「粗排」那一行可以把它移出 / 放回,虚线残影提醒它原本在哪。先猜后看:关掉粗排之前,先猜精排那根杆会变多长。

各层职责一句话:召回负责「别漏」(高召回率,宁滥勿缺),粗排负责「省钱」(轻模型控制精排算力),精排负责「排准」(重模型逐条预估),重排负责「好看」(多样性与业务规则),混排负责「营收与生态」(广告与运营内容)。各家叫法略有差异:粗排也叫轻排 / L1,精排也叫 L2 / Heavy Ranker。

系统地图 A · 行业范式 › 级联漏斗(archify 生成,可交互)

同一条漏斗的「系统视角」:用右上角的引导视图,按「候选漏斗 / 特征与历史 / 广告并行」逐条看。

地图 A · 经典推荐级联的数据流地图,由 archify 从类型化 JSON 规格确定性渲染,并通过其 9 项版式校验。全屏打开 ↗ · JSON 规格 · English

延迟分账:从下拉到内容出现

面板下半就是延迟预算的分账。用户下拉刷新的忍耐上限决定了体感总延时:典型请求(P50)约 400ms,尾部(P99)可到 800ms;服务端排序预算按 P99 设,约 300ms。三个让账面 ≠ 体感的机制,都能在面板上亲手验证:

  • 墙钟时间不是各阶段之和。多路召回并行、广告与自然内容并行(把「广告并行」关掉,总延时立刻多出一截)。悬停任一行,会高亮它的上游串行链 —— 只有这条链决定墙钟。
  • 预算按 P99 设,靠降级兜底。切到 P99,网络两头和每个阶段都变长;超预算时括线变红并标出降级手段:丢弃超时的召回通道、精排回退粗排分。
  • 最好的延迟是没有延迟。「下拉秒出」多半是预取:上一次请求时已经准备好下一页,刷新时先展示缓存再后台补新 —— 这 400ms 被挪到了用户看不见的时刻。

反过来读,这张分账表就是架构的成因:精排在关键路径上只分到约 100ms,所以必须单卡毫秒级(把精排模型切到 Transformer 再关掉粗排,看它怎么把预算撑破);召回只分到约 50ms,所以必须亚线性(双塔 + ANN)。带着这个参照系,下一讲看 𝕏 的实际实现 —— 它与范式的几处偏离,恰恰是最值得学的部分。

第 2 讲

𝕏 的全景:一条请求的旅程

每次下拉刷新 For You,都由信息流服务 𝕏-Home Mixer(Rust)现场组装一条时间线。它构建在 candidate-pipeline 框架上,把工作拆成标准化的阶段 —— 来源、水合、过滤、打分、选择、副作用 —— 能并行的阶段并行执行。对照上一讲的经典漏斗,𝕏 的链路是 召回 → 精排 → 重排 → 混排,外加水合与两道过滤 —— 注意少了粗排,后面会解释为什么。先看全景,后面各讲逐段展开:

地图 · 𝕏 请求路径(总图)· ②⑤⑦ 的标题可点击跳到对应讲次

排序决定顺序,可见性决定能否展示 —— 两条线直到 ⑦ 才相遇。

For You 信息流请求 ① 查询水合 Query Hydration 观看者最近的行为序列(模型主输入)· 关注列表 · 拉黑/静音 · 屏蔽词 · 已看过 ② 召回 Candidate Retrieval(多通道并行 · 第 3 讲) 关注内 In-Network 𝕏-Thunder:关注账号的 近期帖子(常驻内存) 关注外 Out-of-Network 𝕏-Phoenix 召回:双塔 ANN 检索 𝕏-SimClusters:互动聚类相似 合并 ≈ 数千条 ③ 特征水合 Feature Hydration 帖子正文与媒体 · 作者信息与账号标签 · 互动计数 · 语言 ④ 打分前过滤 Pre-scoring Filters 跨来源去重 · 超 48 小时 · 自己的帖子 · 拉黑/静音 · 屏蔽词 · 已看过/已下发 剩 ≈ 数百条 ⑤ 精排 Ranking(第 4 讲) PhoenixScorer 多目标预估:Transformer 预测每种行为的概率 RankingScorer 融合公式加权求和 + 打散 · 关注外降权 · 新作者扶持 VMRanker 重排(Re-ranking):DPP 换取相邻帖子的多样性 ⑥ Top-K 截断 按最终分排序,取前 K 条 ⑦ 排序后过滤 Post-selection Filters(第 5 讲) VFFilter 删掉判定 drop 的帖子 · 父帖被删的一并删 · 同一对话只留一支 安全标签 (打标签链路) ⑧ 混排 Blending 排好的帖子 + 广告 · 推荐关注 · 提示卡片,由 BlenderSelector 交错插入 ⑨ 副作用(响应发出后):记录已下发帖子 · 日志 排好序的 For You 时间线
图 2 · 𝕏 的请求路径(总图)。每个阶段都可以独立开关,默认值在 home-mixer/params/param.rs,官方用 cron 脚本把仓库默认值同步为线上生产值。
系统地图 B · 𝕏 请求路径 › 服务与源码(archify 生成,节点可跳转源码)

把讲义里的九个阶段落到真实服务上:上排是离线的打标签路径,下排是每次请求走的路;节点上的 SRC 标记直接链到 x-algorithm 的源码文件。

地图 B · 𝕏 For You 的服务架构地图。源码引用固定在 commit 45b48ba,经 archify 的仓库证据校验(每个引用路径在该版本必须真实存在)。全屏打开 ↗ · JSON 规格 · English

行业漏斗术语对照

行业环节英文本系统对应
召回Candidate Retrieval𝕏-Thunder(关注内)· 𝕏-Phoenix 召回 · 𝕏-SimClusters(关注外)
粗排Pre-ranking / Light Ranking没有独立粗排层 —— 召回已把量级压到数千,规则过滤到数百后精排直接吃下
精排(Heavy) Ranking𝕏-Phoenix 排序模型:pointwise 多目标互动预估
融合Score Fusion / Value ModelRankingScorer 加权求和 + 三项调整
重排Re-ranking𝕏-VMRanker:DPP 多样性重排;同作者打散
混排BlendingBlending Pipeline:广告、推荐关注等非帖子内容的插入
特征水合Feature HydrationQuery / Candidate Hydrators(①③ 两个阶段)
内容安全Trust & Safetyvisibility-filtering + 打标签链路(第 5 讲)

唯一「对不上」的环节值得琢磨:多数大厂在召回和精排之间放一个轻量粗排模型,先把几千条筛到几百条再上重模型。𝕏 用「强召回 + 规则过滤」直接对接精排 —— 候选隔离让精排打分可缓存(第 6 讲),重模型吃几百条的成本可以接受,粗排层就省了。

记住一个贯穿全课的分工:排序决定顺序,可见性决定能否展示。第 ⑤ 步的模型只管「你有多可能喜欢它」;第 ⑦ 步引用的是另一套完全独立的内容安全系统(第 5 讲),两者输入不同、规则不同、服务也不同。

第 3 讲

召回(Candidate Retrieval):数百万 → 数百

三条召回通道(retrieval channels)并行取货:

  • 𝕏-Thunder —— 关注内召回(In-Network):帖子发布时就写进内存,请求来时直接返回你关注账号的近期帖子。它还会接收「已看过」列表,提前剔除。
  • 𝕏-Phoenix 召回 —— 关注外(Out-of-Network,OON)模型召回:双塔模型(Two-Tower)做近似最近邻检索(ANN),是「破圈」内容的主力,详见下图。
  • 𝕏-SimClusters —— 关注外协同召回:按「谁和谁互动同样的内容」给账号与帖子做协同过滤式聚类,再用簇的相似度找候选。
用户塔 输入:互动历史序列 + 粗粒度画像(国家 / 语言) 输出:用户向量 [D] 候选塔 输入:语义 ID(6 层 × 256 码) + 作者 ID 哈希 输出:帖子索引 [N × D] 近邻 检索 索引随 checkpoint 一起保存, 服务启动时直接加载 数百万 → 数百 关注外候选帖子
图 3 · 𝕏-Phoenix 双塔召回(Two-Tower Retrieval)。两塔独立编码,线上只做一次 ANN 向量检索,所以能扛住数百万量级的候选池。

两个值得停下来品的细节:

  • 召回不用用户 ID 向量(use_user_embedding=False)。系统几乎完全用「你最近互动过什么」来表示你 —— 你的兴趣画像每天都在被你自己的行为改写,而不是固化在一个学出来的 ID 嵌入里。
  • 帖子用「语义 ID」表示(Semantic ID):把帖子的多模态嵌入量化成 6 层、每层 256 选 1 的残差编码。同主题的帖子共享编码前缀,于是模型对从没见过的新帖也有组合泛化能力 —— 帖子发出的那一刻就能被召回,物品侧没有冷启动(item cold-start)问题。
第 4 讲

精排与融合:Σ 权重 × 概率

进入精排(ranking)的每条帖子,由 𝕏-Phoenix 排序模型(一个 Transformer,读你的行为序列作上下文)做多目标互动预估(multi-task engagement prediction),逐条(pointwise)输出约二十种行为各自的概率:点赞、回复、转发、引用、分享、各类点击、停留时长、关注作者,以及负反馈(negative feedback)类的「不感兴趣」、静音、拉黑、举报。然后 RankingScorer 用一行融合公式(score fusion / value model)合成最终分:

最终分 = Σ ( 权重i × P(行为i) )

下面是仓库 2026-08 快照里 param.rs 的部分真实默认权重(线上以配置系统为准,官方用 cron 把生产值回写到仓库):

行为权重行为权重
回复+5.0举报−234.0
引用+5.0静音作者−58.8
关注作者+4.0不感兴趣−43.2
分享+2.0拉黑作者−31.2
转发+1.0无停留−0.02
点赞+0.5停留时长(连续值)+0.004
点击+0.4停留(二值)+0.05

常见误读权重乘的是你自己的预测概率,不是原始互动数。看到举报权重是点赞的 468 倍,就推出「1 个举报抵消 468 个赞」是错的 —— 举报本来就是比点赞罕见得多的行为,概率基线低几个数量级,大权重只是让这个稀有信号有机会影响排序。README 和代码注释都专门澄清了这一点。

动手算一算

拖动滑杆,设定模型对「你」在这条帖子上各行为的预测概率,看最终分怎么变。权重取自 param.rs 真实默认值。

最终分 0.000
地图 · 𝕏 请求路径 › ⑤ 精排 › 融合公式 · 主角:№4711

权重是价格,不是选票:一次稀有的举报,能压过一堆便宜的点赞。

图 4 · 左盘是主角帖 №4711(受上方滑杆控制),右盘是对照帖(固定:点赞 8%、回复 1%、转发 2%、关注 0.3%、不感兴趣 0.15%、举报 0.003%,合计 +0.050)。先猜后看:把「举报」从 0.02% 拖到 0.10%,天平会翻向对照帖吗?

融合之后还有三个业务调整,再进入重排(re-ranking):

  • 同作者打散(author diversity):同一作者第二条起分数乘衰减系数(有下限),避免刷屏。
  • 关注外降权(OON discount):未关注账号的帖子乘一个小于 1 的系数;关注账号的转发和回复同样打折。
  • 新作者扶持(冷启动探索,explore):曝光量低于阈值的作者,帖子被提升到目标位置附近,给新人冷启动机会。
  • 多样性重排:𝕏-VMRanker —— 独立重排服务,用行列式点过程(DPP)在帖子嵌入上重排:牺牲一点点分数,换相邻帖子之间更低的相似度,你的时间线才不会连着五条同一个话题。
第 5 讲

可见性:排序之外的另一套系统

模型说「你会喜欢」,不代表就能给你看。这部分对应行业里的内容安全 / 信任与安全(Trust & Safety)体系:一条帖子能否展示,由可见性过滤服务 visibility-filtering 独立裁决,依据是一整条持续运行的打标签链路 —— 内容理解(content understanding)模型给帖子和账号打分,规则引擎写入安全标签(safety labels);它不在请求路径上,请求来时只做读取:

① 内容理解(持续运行,不在请求路径) 帖子与媒体 grox 文本/媒体分类(垃圾、成人、暴力) media-model-proxy 图像/视频模型 clip 媒体嵌入向量 账号 agatha 被拉黑/举报 相对 获赞 bdsm 虚假/滥用行为识别 user-cred-v2 关注图 PageRank ② 打标签规则 scarecrow 事件驱动:某事件发生 + 条件成立 → 打标签(内嵌 botmaker 规则引擎) abuse-enforcement-service 按模型分数行动:打标签 / 验证挑战 / 封号 写入 ③ 标签存储 请求路径上读回 ④ 可见性过滤 · 对每条帖子 × 每个观看者裁决 输入:上面的标签 + 你是否拉黑/静音/关注作者 + 账号状态 + 你的设置与国家 规则按序评估,第一条回答 drop 的规则即终止 ALLOW 正常展示 INTERSTITIAL 点击才展开 DROP 不展示
图 5 · 打标签链路与可见性过滤。图中代号:𝕏-Grox(内容分类)、𝕏-Agatha(账号信誉)、𝕏-BDSM(行为序列风控)、𝕏-UserCred(图谱信誉)、𝕏-Scarecrow/𝕏-Botmaker(规则引擎)。规则清单按评估顺序列在 visibility-filtering/rules/registry.rs
ALLOW正常展示
INTERSTITIAL隔层后展示,如成人或血腥媒体,点击可展开
DROP不展示;其祖先帖被删的回复/引用也一并删
地图 · 𝕏 请求路径 › ⑦ 排序后过滤 › 可见性裁决 · 主角:№4711

排队员排顺序,门卫查名单:拨动「关注」,裁决翻转,队伍顺序纹丝不动。

图 6 · 队列按精排分数排好(№4711 排第 2),门卫按 registry.rs 的规则顺序查名单。「仅对推荐生效」的规则只在观看者未关注作者时才会 drop;成人媒体标签给出 INTERSTITIAL,与是否关注无关。

一个精细的设计:有一组规则只对「推荐」生效 —— 仅当帖子来自你未关注的账号时才可能 drop(比如高召回率抓到的疑似垃圾内容),同一条帖子对关注者照常展示。系统宁可少推荐,也不轻易在粉丝面前隐藏内容。

配套的透明度工具「Under the Hood」让每个人查看自己账号和帖子上影响可见性的标签统计 —— 部分规则文件(如 𝕏-Grox 的提示词、部分 𝕏-Botmaker 规则)为防对抗没有开源,官方以「代码 + 可查询的结果」组合来补足透明度。

第 6 讲

设计取舍

  • 多行为预测,而非单一「相关分」。模型输出约二十个概率,合成是显式、可审计的一步 —— 想调整产品价值观,改的是明文权重,不用重训模型。
  • 候选隔离。排序推理时,候选帖子之间不能互相 attend,只能看观看者上下文。一条帖子的分数不受同批次其他帖子影响,分数因此稳定、可缓存。
  • 哈希嵌入,没有词表。召回和排序都用多个哈希函数查嵌入,新帖、新作者发出即刻可表示,不用维护和更新词表。
  • 排序与可见性彻底分离。不同服务、不同输入、不同规则。安全裁决不会被「用户可能爱看」的分数稀释,反之亦然。
  • 管线框架化。candidate-pipeline 把阶段类型标准化,执行与监控和业务逻辑分离,加一路召回通道或一个过滤器都是插件式的。
第 7 讲

动手实践与思考题

这次开源和 2023 年那次的最大区别:𝕏-Phoenix 目录里是真实的生产训练与推理代码(JAX 训练 + Rust gRPC 推理引擎),配了确定性的合成数据生成器和单卡 nano 配置(home_direct_packed_nano 精排、xrecsys_two_tower_nano 召回),几分钟就能在一张 GPU 上端到端跑通:训练 → 出 checkpoint → 用生产同款引擎对外服务。入口见 phoenix/QUICKSTART.mdphoenix/TRAINING.md

思考题

  1. 为什么召回塔不给每个用户学一个 ID 嵌入?如果加上,对「兴趣快速变化的用户」和「僵尸粉画像」各会发生什么? 提示:行为序列是实时的,ID 嵌入是滞后的;ID 嵌入还会给刷量行为一个可被固化利用的载体。
  2. 举报的权重是 −234,点赞是 +0.5。构造一个数值例子,说明为什么这不等于「1 个举报抵 468 个赞」。 提示:代入典型概率,比如 P(点赞)=10%,P(举报)=0.01%,比较两项贡献的绝对值。
  3. 「只对推荐生效、对关注者不生效」的 drop 规则,换成对所有人生效会有什么代价?反过来全部放开呢? 提示:考虑误伤(高召回意味着假阳性)与订阅关系承载的知情选择。
  4. 候选隔离放弃了「批内比较」的信息。如果允许候选互相 attend,分数会怎么不可缓存?listwise 排序的收益该在哪个环节找补? 提示:VMRanker 的 DPP 重排正是在打分之后做批内多样性。

课件依据 xai-org/x-algorithm 2026-08-14 版 README 与源码整理;文中所有代码链接均固定在 commit 45b48ba;权重等数值为仓库快照默认值,线上以配置系统实际值为准。𝕏-Codename 斜体表示 𝕏 公司内部系统代号,行业通用概念以正体中英对照标注。代码采用 Apache 2.0 许可开源。