目录
-
- 一、项目概述
-
- [1.1 系统定位](#1.1 系统定位)
- [1.2 核心设计理念](#1.2 核心设计理念)
- [1.3 技术栈](#1.3 技术栈)
- 二、系统架构
-
- [2.1 整体架构图](#2.1 整体架构图)
- [2.2 核心组件说明](#2.2 核心组件说明)
-
- [2.2.1 Home Mixer(主页混合器)](#2.2.1 Home Mixer(主页混合器))
- [2.2.2 Thunder(网络内内容服务)](#2.2.2 Thunder(网络内内容服务))
- [2.2.3 Phoenix(机器学习组件)](#2.2.3 Phoenix(机器学习组件))
- [2.2.4 Candidate Pipeline(候选管道框架)](#2.2.4 Candidate Pipeline(候选管道框架))
- 三、关键技术实现
-
- [3.1 评分系统](#3.1 评分系统)
-
- [3.1.1 Phoenix Scorer(Phoenix 评分器)](#3.1.1 Phoenix Scorer(Phoenix 评分器))
- [3.1.2 Weighted Scorer(加权评分器)](#3.1.2 Weighted Scorer(加权评分器))
- [3.1.3 Author Diversity Scorer(作者多样性评分器)](#3.1.3 Author Diversity Scorer(作者多样性评分器))
- [3.1.4 OON Scorer(网络外内容评分器)](#3.1.4 OON Scorer(网络外内容评分器))
- [3.2 过滤系统](#3.2 过滤系统)
-
- [3.2.1 预评分过滤器(Pre-Scoring Filters)](#3.2.1 预评分过滤器(Pre-Scoring Filters))
- [3.2.2 后选择过滤器(Post-Selection Filters)](#3.2.2 后选择过滤器(Post-Selection Filters))
- [3.3 内容增强系统(Hydration)](#3.3 内容增强系统(Hydration))
-
- [3.3.1 Query Hydrators(查询增强器)](#3.3.1 Query Hydrators(查询增强器))
- [3.3.2 Candidate Hydrators(候选增强器)](#3.3.2 Candidate Hydrators(候选增强器))
- [3.4 内容源系统(Sources)](#3.4 内容源系统(Sources))
-
- [3.4.1 Thunder Source(网络内内容源)](#3.4.1 Thunder Source(网络内内容源))
- [3.4.2 Phoenix Source(网络外内容源)](#3.4.2 Phoenix Source(网络外内容源))
- [3.5 选择器(Selector)](#3.5 选择器(Selector))
-
- [3.5.1 TopKScoreSelector](#3.5.1 TopKScoreSelector)
- 四、核心设计决策
-
- [4.1 无手工特征工程](#4.1 无手工特征工程)
- [4.2 候选隔离机制](#4.2 候选隔离机制)
- [4.3 多动作预测](#4.3 多动作预测)
- [4.4 可组合的管道架构](#4.4 可组合的管道架构)
- [4.5 两阶段推荐流程](#4.5 两阶段推荐流程)
- 五、技术亮点
-
- [5.1 性能优化](#5.1 性能优化)
-
- [5.1.1 并行执行](#5.1.1 并行执行)
- [5.1.2 内存优化](#5.1.2 内存优化)
- [5.1.3 缓存策略](#5.1.3 缓存策略)
- [5.2 可靠性保障](#5.2 可靠性保障)
-
- [5.2.1 错误处理](#5.2.1 错误处理)
- [5.2.2 限流保护](#5.2.2 限流保护)
- [5.2.3 数据一致性](#5.2.3 数据一致性)
- [5.3 可观测性](#5.3 可观测性)
-
- [5.3.1 指标监控](#5.3.1 指标监控)
- [5.3.2 日志记录](#5.3.2 日志记录)
- 六、系统工作流程
-
- [6.1 完整请求流程](#6.1 完整请求流程)
- [6.2 数据流示例](#6.2 数据流示例)
- 七、技术挑战与解决方案
-
- [7.1 大规模内容检索](#7.1 大规模内容检索)
- [7.2 实时性要求](#7.2 实时性要求)
- [7.3 模型推理效率](#7.3 模型推理效率)
- [7.4 内容多样性](#7.4 内容多样性)
- [7.5 用户体验个性化](#7.5 用户体验个性化)
- 八、总结
- 附录:关键代码位置
- 九、系统使用的特征详解
-
- [9.1 特征体系概述](#9.1 特征体系概述)
- [9.2 用户特征(User Features)](#9.2 用户特征(User Features))
-
- [9.2.1 用户哈希特征(User Hashes)](#9.2.1 用户哈希特征(User Hashes))
- [9.2.2 用户上下文特征(User Context)](#9.2.2 用户上下文特征(User Context))
- [9.2.3 用户社交图谱特征(User Social Graph)](#9.2.3 用户社交图谱特征(User Social Graph))
- [9.3 用户行为序列特征(User Action Sequence)](#9.3 用户行为序列特征(User Action Sequence))
-
- [9.3.1 历史内容特征(History Post Features)](#9.3.1 历史内容特征(History Post Features))
- [9.3.2 历史作者特征(History Author Features)](#9.3.2 历史作者特征(History Author Features))
- [9.3.3 历史动作特征(History Actions)](#9.3.3 历史动作特征(History Actions))
- [9.3.4 产品表面特征(Product Surface)](#9.3.4 产品表面特征(Product Surface))
- [9.4 候选内容特征(Candidate Features)](#9.4 候选内容特征(Candidate Features))
-
- [9.4.1 候选内容哈希特征(Candidate Post Hashes)](#9.4.1 候选内容哈希特征(Candidate Post Hashes))
- [9.4.2 候选作者特征(Candidate Author Features)](#9.4.2 候选作者特征(Candidate Author Features))
- [9.4.3 候选产品表面特征(Candidate Product Surface)](#9.4.3 候选产品表面特征(Candidate Product Surface))
- [9.5 内容元数据特征(Post Metadata)](#9.5 内容元数据特征(Post Metadata))
- [9.6 特征处理流程](#9.6 特征处理流程)
-
- [9.6.1 哈希嵌入查找](#9.6.1 哈希嵌入查找)
- [9.6.2 特征融合](#9.6.2 特征融合)
- [9.6.3 Transformer 输入构建](#9.6.3 Transformer 输入构建)
- [9.7 特征设计特点](#9.7 特征设计特点)
-
- [9.7.1 无手工特征工程](#9.7.1 无手工特征工程)
- [9.7.2 多哈希函数策略](#9.7.2 多哈希函数策略)
- [9.7.3 序列化表示](#9.7.3 序列化表示)
- [9.7.4 多模态特征融合](#9.7.4 多模态特征融合)
- [9.8 特征使用场景](#9.8 特征使用场景)
-
- [9.8.1 检索阶段(Retrieval)](#9.8.1 检索阶段(Retrieval))
- [9.8.2 排序阶段(Ranking)](#9.8.2 排序阶段(Ranking))
- [9.9 特征优势总结](#9.9 特征优势总结)
一、项目概述
1.1 系统定位
X For You Feed Algorithm 是一个基于深度学习的推荐系统,为 X(原 Twitter)平台的"为你推荐"信息流提供核心算法支持。该系统通过结合网络内内容(来自用户关注的账户)和网络外内容(通过机器学习检索发现),并使用基于 Grok 的 Transformer 模型对所有内容进行统一排序。
1.2 核心设计理念
该系统采用了完全去手工特征工程的设计理念,摒弃了所有手工设计的特征和大部分启发式规则。整个系统依赖基于 Grok 的 Transformer 模型,通过理解用户的参与历史(点赞、回复、转发等行为)来确定内容的相关性。这种设计显著降低了数据管道和服务基础设施的复杂性。
1.3 技术栈
- 后端服务: Rust(高性能、内存安全)
- 机器学习: Python + JAX(基于 Grok-1 架构的 Transformer)
- 通信协议: gRPC(高效的服务间通信)
- 消息队列: Kafka(实时事件流处理)
- 模型架构: Transformer with Candidate Isolation(候选隔离机制)
二、系统架构
2.1 整体架构图
系统采用分层架构设计,主要包含以下核心组件:
FOR YOU FEED REQUEST
↓
HOME MIXER (编排协调层)
├─ QUERY HYDRATION (用户行为序列 + 用户特征提取)
│ ↓
├─ CANDIDATE SOURCES
│ ├─ THUNDER (网络内内容)
│ └─ PHOENIX RETRIEVAL (网络外内容检索)
│ ↓
├─ HYDRATION (丰富候选内容:元数据、作者信息、媒体实体等)
│ ↓
├─ FILTERING (过滤:重复、过期、自推、屏蔽作者、静音关键词等)
│ ↓
├─ SCORING (Phoenix Scorer → Weighted Scorer → Diversity Scorer)
│ ↓
└─ SELECTION (按最终分数排序,选择 Top K 候选)
↓
RANKED FEED RESPONSE
2.2 核心组件说明
2.2.1 Home Mixer(主页混合器)
职责: 系统编排层,负责协调整个推荐流程
关键特性:
- 基于
CandidatePipeline框架构建 - 支持并行执行独立的阶段(Sources、Hydrators)
- 优雅的错误处理和日志记录
- 暴露 gRPC 端点(
ScoredPostsService)返回排序后的内容
主要阶段:
- Query Hydrators: 获取用户上下文(参与历史、关注列表)
- Sources: 从 Thunder 和 Phoenix 检索候选内容
- Hydrators: 丰富候选内容数据
- Filters: 移除不符合条件的候选内容
- Scorers: 预测参与度并计算最终分数
- Selector: 按分数排序并选择 Top K
- Post-Selection Filters: 最终可见性和去重检查
- Side Effects: 缓存请求信息供未来使用
2.2.2 Thunder(网络内内容服务)
职责: 内存中的内容存储和实时摄取管道
核心功能:
- 从 Kafka 消费内容创建/删除事件
- 维护每个用户的存储:原始推文、回复/转发、视频内容
- 提供"网络内"内容候选(来自请求用户关注的账户)
- 自动修剪超过保留期的旧内容
技术优势:
- 支持亚毫秒级查找,无需访问外部数据库
- 使用信号量限制并发请求,防止过载
- 支持视频内容特殊处理
关键实现:
rust
// 从 post_store 获取关注用户的内容
let all_posts = post_store.get_all_posts_by_users(
&following_user_ids,
&exclude_tweet_ids,
start_time,
request_user_id,
);
2.2.3 Phoenix(机器学习组件)
职责: 提供检索和排序两个核心 ML 功能
1. 检索阶段(Two-Tower Model)
架构:
- User Tower: 将用户特征和参与历史编码为嵌入向量
- Candidate Tower: 将所有内容编码为嵌入向量
- 相似度搜索: 通过点积相似度检索 Top-K 内容
关键设计:
- 使用多个哈希函数进行嵌入查找(Hash-Based Embeddings)
- User Tower 与 Ranking 模型共享相同的 Transformer 架构
- 支持高效的近似最近邻(ANN)搜索
2. 排序阶段(Transformer with Candidate Isolation)
核心创新: 候选隔离机制(Candidate Isolation)
在 Transformer 推理过程中,候选内容不能相互关注,只能关注用户上下文。这确保了:
- 内容的分数不依赖于批次中的其他内容
- 分数具有一致性和可缓存性
- 支持批量推理而不影响单个内容的评分
注意力掩码可视化:
Keys (关注目标)
─────────────────────────────▶
│ User │ History (S) │ Candidates (C) │
┌────┼──────┼─────────────┼────────────────┤
│ U │ ✓ │ ✓ ✓ ✓ ✓ ✓ │ ✗ ✗ ✗ ✗ ✗ ✗ │
├────┼──────┼─────────────┼────────────────┤
Q │ H │ ✓ │ ✓ ✓ ✓ ✓ ✓ │ ✗ ✗ ✗ ✗ ✗ ✗ │
u │ i │ ✓ │ ✓ ✓ ✓ ✓ ✓ │ ✗ ✗ ✗ ✗ ✗ ✗ │
e │ s │ ✓ │ ✓ ✓ ✓ ✓ ✓ │ ✗ ✗ ✗ ✗ ✗ ✗ │
r ├────┼──────┼─────────────┼────────────────┤
i │ C │ ✓ │ ✓ ✓ ✓ ✓ ✓ │ ✓ ✗ ✗ ✗ ✗ ✗ │
e │ a │ ✓ │ ✓ ✓ ✓ ✓ ✓ │ ✗ ✓ ✗ ✗ ✗ ✗ │
s │ n │ ✓ │ ✓ ✓ ✓ ✓ ✓ │ ✗ ✗ ✓ ✗ ✗ ✗ │
│ d │ ✓ │ ✓ ✓ ✓ ✓ ✓ │ ✗ ✗ ✗ ✓ ✗ ✗ │
│ s │ ✓ │ ✓ ✓ ✓ ✓ ✓ │ ✗ ✗ ✗ ✗ ✓ ✗ │
└────┴──────┴─────────────┴────────────────┘
✓ = 可以关注 ✗ = 不能关注
多动作预测 :
模型同时预测多种参与类型的概率:
- 正面动作: 点赞、回复、转发、点击、分享等
- 负面动作: 不感兴趣、屏蔽作者、静音作者、举报等
- 连续动作: 停留时间(dwell time)
2.2.4 Candidate Pipeline(候选管道框架)
职责: 可复用的推荐管道构建框架
设计模式: Trait-based 架构,定义了以下核心 Trait:
| Trait | 用途 |
|---|---|
Source |
从数据源获取候选内容 |
Hydrator |
丰富候选内容的附加特征 |
Filter |
移除不应显示的内容 |
Scorer |
计算排序分数 |
Selector |
排序并选择 Top 候选 |
SideEffect |
运行异步副作用(缓存、日志) |
执行流程:
rust
async fn execute(&self, query: Q) -> PipelineResult<Q, C> {
// 1. 查询增强
let hydrated_query = self.hydrate_query(query).await;
// 2. 获取候选
let candidates = self.fetch_candidates(&hydrated_query).await;
// 3. 候选增强
let hydrated_candidates = self.hydrate(&hydrated_query, candidates).await;
// 4. 过滤
let (kept_candidates, filtered_candidates) =
self.filter(&hydrated_query, hydrated_candidates.clone()).await;
// 5. 评分
let scored_candidates = self.score(&hydrated_query, kept_candidates).await;
// 6. 选择
let selected_candidates = self.select(&hydrated_query, scored_candidates);
// 7. 后选择处理
let final_candidates = self.hydrate_post_selection(...).await;
let (final_candidates, _) = self.filter_post_selection(...).await;
// 8. 副作用(异步)
self.run_side_effects(...);
PipelineResult { ... }
}
并行执行策略:
- Sources 和 Hydrators 并行执行(使用
join_all) - Filters 顺序执行(每个过滤器在前一个的结果上操作)
- Scorers 顺序执行(每个评分器更新候选分数)
- Side Effects 异步执行(不阻塞主流程)
三、关键技术实现
3.1 评分系统
3.1.1 Phoenix Scorer(Phoenix 评分器)
功能: 调用 Phoenix Transformer 模型获取 ML 预测
输入:
- 用户 ID
- 用户行为序列(engagement history)
- 候选内容信息(TweetInfo)
输出: 多种动作的概率预测
关键实现:
rust
// 构建预测请求
let tweet_infos: Vec<TweetInfo> = candidates
.iter()
.map(|c| {
let tweet_id = c.retweeted_tweet_id.unwrap_or(c.tweet_id as u64);
let author_id = c.retweeted_user_id.unwrap_or(c.author_id);
TweetInfo { tweet_id, author_id, ..Default::default() }
})
.collect();
// 调用 Phoenix 服务
let response = self.phoenix_client
.predict(user_id, sequence.clone(), tweet_infos)
.await;
// 提取分数
let phoenix_scores = PhoenixScores {
favorite_score: p.get(ActionName::ServerTweetFav),
reply_score: p.get(ActionName::ServerTweetReply),
retweet_score: p.get(ActionName::ServerTweetRetweet),
// ... 更多动作分数
};
3.1.2 Weighted Scorer(加权评分器)
功能: 将多个动作预测组合成最终相关性分数
计算公式:
Final Score = Σ (weight_i × P(action_i))
权重策略:
- 正面动作(点赞、转发、分享等): 正权重
- 负面动作(屏蔽、静音、举报等): 负权重,降低用户可能不喜欢的内容分数
实现细节:
rust
fn compute_weighted_score(candidate: &PostCandidate) -> f64 {
let s = &candidate.phoenix_scores;
let combined_score =
apply(s.favorite_score, FAVORITE_WEIGHT) +
apply(s.reply_score, REPLY_WEIGHT) +
apply(s.retweet_score, RETWEET_WEIGHT) +
// ... 更多动作
apply(s.not_interested_score, NOT_INTERESTED_WEIGHT) + // 负权重
apply(s.block_author_score, BLOCK_AUTHOR_WEIGHT) + // 负权重
apply(s.report_score, REPORT_WEIGHT); // 负权重
// 分数偏移处理
offset_score(combined_score)
}
特殊处理:
- 视频内容需要满足最小时长要求才能应用 VQV(Video Quality View)权重
- 负权重分数通过偏移机制确保最终分数在合理范围内
3.1.3 Author Diversity Scorer(作者多样性评分器)
功能: 衰减重复作者的内容分数,确保信息流多样性
策略: 对同一作者的多条内容,后续内容的分数会被衰减,避免单一作者占据整个信息流。
3.1.4 OON Scorer(网络外内容评分器)
功能: 调整网络外内容的分数,平衡网络内外内容的展示比例。
3.2 过滤系统
3.2.1 预评分过滤器(Pre-Scoring Filters)
这些过滤器在评分之前运行,移除明显不符合条件的内容:
| 过滤器 | 功能 |
|---|---|
DropDuplicatesFilter |
移除重复的内容 ID |
CoreDataHydrationFilter |
移除无法获取核心元数据的内容 |
AgeFilter |
移除超过时间阈值的内容 |
SelfpostFilter |
移除用户自己发布的内容 |
RepostDeduplicationFilter |
去重相同内容的转发 |
IneligibleSubscriptionFilter |
移除用户无法访问的付费内容 |
PreviouslySeenPostsFilter |
移除用户已看过的内容 |
PreviouslyServedPostsFilter |
移除会话中已服务的内容 |
MutedKeywordFilter |
移除包含用户静音关键词的内容 |
AuthorSocialgraphFilter |
移除来自屏蔽/静音作者的内容 |
执行特点:
- 顺序执行(每个过滤器在前一个的结果上操作)
- 错误容错(单个过滤器失败不影响整体流程)
- 记录被过滤的内容用于分析和调试
3.2.2 后选择过滤器(Post-Selection Filters)
这些过滤器在评分和选择之后运行,进行最终验证:
| 过滤器 | 功能 |
|---|---|
VFFilter |
移除已删除/垃圾/暴力/血腥等内容 |
DedupConversationFilter |
去重同一对话线程的多个分支 |
3.3 内容增强系统(Hydration)
3.3.1 Query Hydrators(查询增强器)
UserActionSequenceQueryHydrator:
- 获取用户的参与历史序列
- 包括点赞、回复、转发等行为的时间序列
- 为 Phoenix 模型提供用户上下文
UserFeaturesQueryHydrator:
- 获取用户特征(关注列表、偏好设置等)
- 为过滤和评分提供用户画像信息
3.3.2 Candidate Hydrators(候选增强器)
CoreDataCandidateHydrator:
- 获取内容的核心元数据(文本、媒体、创建时间等)
GizmoduckHydrator:
- 获取作者信息(用户名、验证状态等)
VideoDurationCandidateHydrator:
- 获取视频内容的时长信息
- 用于 VQV 权重的条件判断
SubscriptionHydrator:
- 获取订阅状态信息
- 用于判断用户是否有权限访问付费内容
InNetworkCandidateHydrator:
- 标记内容是否来自网络内(关注账户)
VFCandidateHydrator:
- 获取内容的可见性标记(VF = Visibility Filter)
3.4 内容源系统(Sources)
3.4.1 Thunder Source(网络内内容源)
功能: 从 Thunder 服务获取用户关注账户的最近内容
特点:
- 低延迟(亚毫秒级查找)
- 实时更新(通过 Kafka 事件流)
- 支持视频内容特殊处理
3.4.2 Phoenix Source(网络外内容源)
功能: 通过 Phoenix 检索模型从全局语料库中发现相关内容
流程:
- 使用 User Tower 编码用户特征和参与历史
- 通过相似度搜索(点积)找到 Top-K 候选
- 返回候选内容 ID 列表
3.5 选择器(Selector)
3.5.1 TopKScoreSelector
功能: 按最终加权分数排序,选择 Top K 候选
实现:
rust
fn select(&self, _query: &Q, mut candidates: Vec<C>) -> Vec<C> {
// 按加权分数降序排序
candidates.sort_unstable_by(|a, b| {
b.weighted_score()
.partial_cmp(&a.weighted_score())
.unwrap_or(Ordering::Equal)
});
// 截取 Top K
candidates.truncate(self.result_size);
candidates
}
四、核心设计决策
4.1 无手工特征工程
决策: 完全依赖 Transformer 模型从原始数据中学习特征
优势:
- 减少特征工程的复杂性和维护成本
- 模型可以自动发现复杂的特征交互
- 简化数据管道和服务基础设施
实现: 使用哈希嵌入(Hash-Based Embeddings)和多哈希函数,直接从原始 ID 和特征生成嵌入。
4.2 候选隔离机制
决策: 在排序阶段,候选内容不能相互关注
优势:
- 一致性: 内容的分数不依赖于批次中的其他内容
- 可缓存性: 可以缓存单个内容的分数,无需重新计算
- 可扩展性: 支持批量推理而不影响单个内容的评分准确性
实现: 通过特殊的注意力掩码实现,候选内容只能关注用户和用户历史,不能关注其他候选。
4.3 多动作预测
决策: 预测多种参与类型的概率,而非单一"相关性"分数
优势:
- 更细粒度的用户意图理解
- 可以针对不同动作类型设置不同权重
- 支持更复杂的排序策略
预测的动作类型:
- 正面参与: 点赞、回复、转发、引用、点击、分享等
- 负面反馈: 不感兴趣、屏蔽、静音、举报
- 连续动作: 停留时间
4.4 可组合的管道架构
决策: 使用 Trait-based 框架构建推荐管道
优势:
- 模块化: 每个阶段(Source、Hydrator、Filter、Scorer)都是独立的模块
- 可扩展性: 易于添加新的组件而不影响现有功能
- 可测试性: 每个组件可以独立测试
- 并行化: 框架自动处理独立阶段的并行执行
实现: 通过 Rust 的 Trait 系统实现,每个组件实现相应的 Trait 接口。
4.5 两阶段推荐流程
决策: 检索 + 排序的两阶段架构
优势:
- 效率: 检索阶段快速缩小候选范围(百万级 → 千级)
- 准确性: 排序阶段使用更复杂的模型对较小候选集进行精确排序
- 可扩展性: 检索阶段可以使用近似算法(ANN),排序阶段使用精确模型
实现:
- 检索: Two-Tower 模型 + 相似度搜索
- 排序: Transformer 模型 + 候选隔离
五、技术亮点
5.1 性能优化
5.1.1 并行执行
- Sources 和 Hydrators 并行执行,充分利用 I/O 等待时间
- 使用
futures::join_all实现并发
5.1.2 内存优化
- Thunder 使用内存存储,避免数据库查询延迟
- 自动修剪旧内容,控制内存使用
5.1.3 缓存策略
- 候选隔离机制使得单个内容的分数可以缓存
- Side Effects 异步执行,不阻塞主流程
5.2 可靠性保障
5.2.1 错误处理
- 每个阶段都有独立的错误处理
- 单个组件失败不影响整体流程
- 详细的错误日志和指标记录
5.2.2 限流保护
- Thunder 使用信号量限制并发请求
- 防止服务过载
5.2.3 数据一致性
- 候选隔离确保分数的一致性
- 过滤器的顺序执行保证逻辑正确性
5.3 可观测性
5.3.1 指标监控
- 每个阶段都有详细的性能指标
- 请求数量、延迟、错误率等
5.3.2 日志记录
- 每个请求都有唯一的 request_id
- 详细的阶段执行日志
- 调试模式支持
六、系统工作流程
6.1 完整请求流程
-
接收请求 : gRPC 服务接收
ScoredPostsQuery请求 -
查询增强:
- 并行获取用户行为序列
- 并行获取用户特征(关注列表等)
-
候选获取:
- 并行从 Thunder 获取网络内内容
- 并行从 Phoenix 检索获取网络外内容
- 合并所有候选
-
候选增强:
- 并行获取核心数据、作者信息、视频时长等
- 更新候选内容属性
-
预评分过滤:
- 顺序执行多个过滤器
- 移除不符合条件的内容
-
评分:
- Phoenix Scorer: 获取 ML 预测
- Weighted Scorer: 计算加权分数
- Author Diversity Scorer: 调整多样性
- OON Scorer: 调整网络外内容分数
-
选择:
- 按最终分数排序
- 选择 Top K 候选
-
后选择处理:
- 后选择增强(如 VF 信息)
- 后选择过滤(最终验证)
-
副作用:
- 异步缓存请求信息
- 异步记录日志
-
返回结果: 返回排序后的内容列表
6.2 数据流示例
用户请求 (user_id=123)
↓
查询增强
├─→ 用户行为序列: [like(456), reply(789), ...]
└─→ 用户特征: following=[100, 200, 300]
↓
候选获取
├─→ Thunder: [post_1, post_2, post_3] (来自关注账户)
└─→ Phoenix: [post_10, post_11, post_12] (检索发现)
↓
候选增强
├─→ 核心数据: 文本、媒体、时间戳
├─→ 作者信息: 用户名、验证状态
└─→ 视频时长: 120s
↓
过滤
├─→ 移除: 重复、过期、自推、屏蔽作者
└─→ 保留: [post_1, post_2, post_10, post_11]
↓
评分
├─→ Phoenix: P(like)=0.8, P(reply)=0.3, ...
├─→ Weighted: score = 0.8×1.0 + 0.3×0.5 + ... = 1.25
└─→ Diversity: 调整重复作者分数
↓
选择
└─→ Top 10: [post_1(1.5), post_10(1.3), post_2(1.1), ...]
↓
返回结果
七、技术挑战与解决方案
7.1 大规模内容检索
挑战: 从百万级内容中快速找到相关候选
解决方案:
- Two-Tower 模型 + 近似最近邻搜索(ANN)
- 预计算内容嵌入,支持快速相似度搜索
- 检索阶段快速缩小候选范围
7.2 实时性要求
挑战: 信息流需要实时更新,低延迟响应
解决方案:
- Thunder 使用内存存储,亚毫秒级查找
- Kafka 实时事件流处理
- 并行执行独立阶段,减少总延迟
7.3 模型推理效率
挑战: Transformer 模型推理成本高
解决方案:
- 候选隔离机制支持批量推理
- 分数可缓存,避免重复计算
- 两阶段架构:检索阶段使用轻量模型,排序阶段使用复杂模型
7.4 内容多样性
挑战: 避免单一作者或单一类型内容占据信息流
解决方案:
- Author Diversity Scorer 衰减重复作者分数
- 多种内容源(网络内 + 网络外)
- 多种过滤器确保内容质量
7.5 用户体验个性化
挑战: 为每个用户提供高度个性化的内容
解决方案:
- 基于用户行为序列的深度理解
- Transformer 模型学习复杂的用户偏好模式
- 多动作预测捕获细粒度的用户意图
八、总结
X For You Feed Algorithm 是一个设计精良的现代推荐系统,展现了以下核心优势:
- 架构清晰: 分层设计,职责明确,易于维护和扩展
- 性能优异: 并行执行、内存优化、缓存策略
- 技术先进: 基于 Grok 的 Transformer、候选隔离、多动作预测
- 设计优雅: 无手工特征工程、可组合管道、错误容错
- 可扩展性强: 模块化设计,易于添加新功能
该系统为大规模推荐系统提供了一个优秀的参考架构,特别是在处理实时性、个性化、多样性等方面的设计值得借鉴。
附录:关键代码位置
- Home Mixer 主服务 :
home-mixer/main.rs - 候选管道框架 :
candidate-pipeline/candidate_pipeline.rs - Phoenix 评分器 :
home-mixer/scorers/phoenix_scorer.rs - 加权评分器 :
home-mixer/scorers/weighted_scorer.rs - Thunder 服务 :
thunder/thunder_service.rs - Phoenix 排序模型 :
phoenix/recsys_model.py - Phoenix 检索模型 :
phoenix/recsys_retrieval_model.py
九、系统使用的特征详解
9.1 特征体系概述
X For You Feed 推荐系统采用了基于哈希嵌入(Hash-Based Embeddings)的特征表示方法,完全摒弃了手工特征工程。所有特征都通过多个哈希函数转换为嵌入向量,然后由 Transformer 模型自动学习特征交互。
9.2 用户特征(User Features)
9.2.1 用户哈希特征(User Hashes)
- 特征类型: 用户 ID 的哈希值
- 哈希函数数量 : 2 个(
num_user_hashes = 2) - 用途: 通过多个哈希函数对用户 ID 进行编码,生成用户的基础嵌入表示
- 实现: 使用哈希表查找,支持大规模用户空间
9.2.2 用户上下文特征(User Context)
从 ScoredPostsQuery 中提取的用户上下文信息:
user_id: 用户 IDclient_app_id: 客户端应用 IDcountry_code: 国家代码language_code: 语言代码seen_ids: 用户已看过的内容 ID 列表served_ids: 会话中已服务的内容 ID 列表in_network_only: 是否只显示网络内内容is_bottom_request: 是否为底部请求(分页)
9.2.3 用户社交图谱特征(User Social Graph)
从 UserFeatures 中提取:
followed_user_ids: 用户关注的账户 ID 列表blocked_user_ids: 用户屏蔽的账户 ID 列表muted_user_ids: 用户静音的账户 ID 列表subscribed_user_ids: 用户订阅的账户 ID 列表muted_keywords: 用户静音的关键词列表
9.3 用户行为序列特征(User Action Sequence)
9.3.1 历史内容特征(History Post Features)
- 特征类型: 历史交互内容的哈希值
- 哈希函数数量 : 2 个(
num_item_hashes = 2) - 序列长度 : 最多 128 条(
history_seq_len = 128) - 用途: 表示用户最近交互过的内容
9.3.2 历史作者特征(History Author Features)
- 特征类型: 历史交互内容作者的哈希值
- 哈希函数数量 : 2 个(
num_author_hashes = 2) - 用途: 表示用户最近交互过的作者
9.3.3 历史动作特征(History Actions)
-
特征类型: 多热编码(Multi-Hot)的动作向量
-
动作类型数量: 19 种
-
表示方式: 每个历史交互记录用户对该内容执行的所有动作
-
动作列表:
favorite_score(点赞)reply_score(回复)repost_score(转发)photo_expand_score(展开照片)click_score(点击)profile_click_score(点击个人资料)vqv_score(视频质量观看)share_score(分享)share_via_dm_score(通过私信分享)share_via_copy_link_score(通过复制链接分享)dwell_score(停留)quote_score(引用)quoted_click_score(点击引用内容)follow_author_score(关注作者)not_interested_score(不感兴趣)block_author_score(屏蔽作者)mute_author_score(静音作者)report_score(举报)dwell_time(停留时间,连续值)
-
处理方式: 通过学习的投影矩阵将多热编码的动作向量转换为嵌入
9.3.4 产品表面特征(Product Surface)
- 特征类型: 单热编码(Single-Hot)的分类特征
- 词汇表大小 : 16(
product_surface_vocab_size = 16) - 用途: 表示内容展示的产品表面类型(如主页、搜索、通知等)
- 实现: 通过嵌入表查找转换为嵌入向量
9.4 候选内容特征(Candidate Features)
9.4.1 候选内容哈希特征(Candidate Post Hashes)
- 特征类型: 候选内容的哈希值
- 哈希函数数量 : 2 个(
num_item_hashes = 2) - 候选数量 : 最多 32 个(
candidate_seq_len = 32) - 用途: 表示待排序的候选内容
9.4.2 候选作者特征(Candidate Author Features)
- 特征类型: 候选内容作者的哈希值
- 哈希函数数量 : 2 个(
num_author_hashes = 2) - 用途: 表示候选内容的作者信息
9.4.3 候选产品表面特征(Candidate Product Surface)
- 特征类型: 单热编码的分类特征
- 词汇表大小: 16
- 用途: 表示候选内容将展示的产品表面类型
9.5 内容元数据特征(Post Metadata)
虽然这些特征不直接输入到 Phoenix 模型,但在过滤和增强阶段使用:
tweet_id: 内容 IDauthor_id: 作者 IDtweet_text: 内容文本in_reply_to_tweet_id: 回复的目标内容 IDretweeted_tweet_id: 转发的原始内容 IDretweeted_user_id: 被转发内容的作者 IDvideo_duration_ms: 视频时长(毫秒)author_followers_count: 作者粉丝数author_screen_name: 作者用户名retweeted_screen_name: 被转发作者用户名in_network: 是否来自网络内(关注账户)ancestors: 对话祖先链subscription_author_id: 订阅作者 ID
9.6 特征处理流程
9.6.1 哈希嵌入查找
所有 ID 类特征(用户、内容、作者)都通过多个哈希函数转换为嵌入:
- 对每个 ID 应用多个哈希函数,生成多个哈希值
- 使用哈希值在嵌入表中查找对应的嵌入向量
- 将多个哈希嵌入拼接后通过投影矩阵融合为单一表示
9.6.2 特征融合
-
用户特征 : 多个用户哈希嵌入 → 投影 → 单一用户嵌入
[B, 1, D] -
历史特征 :
内容哈希嵌入 + 作者哈希嵌入 + 动作嵌入 + 产品表面嵌入
→ 投影 → 历史序列嵌入
[B, S, D] -
候选特征 :
内容哈希嵌入 + 作者哈希嵌入 + 产品表面嵌入
→ 投影 → 候选嵌入
[B, C, D]
9.6.3 Transformer 输入构建
最终输入到 Transformer 的嵌入序列:
[用户嵌入, 历史序列嵌入, 候选嵌入]
形状: [B, 1 + S + C, D]
9.7 特征设计特点
9.7.1 无手工特征工程
- 不使用手工设计的特征(如内容长度、发布时间差等)
- 所有特征都通过哈希嵌入自动学习
- 模型自动发现特征之间的复杂交互
9.7.2 多哈希函数策略
- 每个实体类型使用多个哈希函数(默认 2 个)
- 减少哈希冲突的影响
- 提高嵌入表示的鲁棒性
9.7.3 序列化表示
- 用户行为序列按时间顺序组织
- 保留时间信息(通过序列位置)
- Transformer 的注意力机制可以学习时间依赖关系
9.7.4 多模态特征融合
- 内容特征(Post Hashes)
- 作者特征(Author Hashes)
- 动作特征(Actions)
- 产品表面特征(Product Surface)
这些不同类型的特征在投影层融合,形成统一的表示空间。
9.8 特征使用场景
9.8.1 检索阶段(Retrieval)
- 用户特征: 用户哈希 + 历史序列
- 候选特征: 内容哈希 + 作者哈希
- 输出: 用户嵌入和候选嵌入的相似度分数
9.8.2 排序阶段(Ranking)
- 完整特征: 用户 + 历史序列 + 候选内容
- 输出: 每个候选内容的多种动作概率预测
9.9 特征优势总结
- 可扩展性: 哈希嵌入支持大规模 ID 空间,无需预定义词汇表
- 灵活性: 模型自动学习特征重要性,无需手工调优
- 鲁棒性: 多哈希函数减少冲突,提高稳定性
- 效率: 嵌入查找和投影计算高效,支持实时推理
- 表达力: Transformer 架构可以捕获复杂的特征交互