Skip to content

RecsysTwoTowerModel(召回模型)

生产版双塔召回构件:RecsysTwoTowerModelConfig、RecsysCandidateTower、MolScorer、用户塔与服务前向;旧 PhoenixRetrievalModel 已删除

Updated

是什么

RecsysTwoTowerModel 是 Phoenix 双塔召回模型的代码构件。它是一个 Haiku hk.Module,定义在 phoenix/xrex/models/recsys_two_tower_model.py:1610。配置类是同一文件中的 RecsysTwoTowerModelConfig(:2854)。本页说明类结构与方法;双塔召回的工作原理见 Phoenix 召回:双塔检索架构。

旧构件的去向。 旧页面描述的 PhoenixRetrievalModel、CandidateTower、RetrievalOutput(phoenix/recsys_retrieval_model.py)与测试文件 test_recsys_retrieval_model.py 已在 2026-08-13 删除。现在的候选塔是 RecsysCandidateTower。召回不再返回 RetrievalOutput,而由 forward 直接返回各语料区间的 top-K。

用户塔不是独立的类。它是一个 RecsysAggregatedModel 实例,与排序模型用同一个类、同一个 transformer,只是不带候选段(recsys_two_tower_model.py:3138-3152)。见 RecsysAggregatedModel(排序模型)。

配置:RecsysTwoTowerModelConfig

该类用 @configclass 声明,位于 recsys_two_tower_model.py:2854-3150:

字段 含义 类默认值
user_tower_config 用户塔,一个 RecsysAggregatedModelConfig 必填
candidate_tower_config 候选塔,RecsysCandidateModelConfig 必填
use_in_batch_negatives 把批内其他用户的候选用作负样本 True
num_global_negatives_per_example 每个样本的全局负样本数 0(各预设设为 64)
logq_correction_scale log-Q 校正系数 2.0
fixed_temperature 固定温度;0 表示可学习(初值 0.1) 0.0
own_negative_logit_offset 自身负反馈候选计入分母时的偏移 0.0
positive_count_user_weight_power 按正样本数给用户加权时的幂 0.0
mask_in_batch_false_negatives 剔除批内假负样本 False
user_query_heads 用户查询头数;0 表示平均池化 0
mol_item_components 等 mol_* MoL 打分的组件数、适配器秩、门控隐藏层 0(关)
positive_actions / hard_negative_actions / soft_negative_actions home 头的正样本、硬负样本、软负样本动作 点赞 / 7 种负反馈 / 未停留
immersive_*、ld_*、tweet_click_positive_actions 其他头的动作清单 见 :2918-2965
head_names / head_dataset_mapping 候选头名称;语料到头的映射 ["home"] / None
w_fav / w_ld / w_tweet_click 服务时各打分槽位的权重 1.0 / 0.0 / 0.0
safety_filter_mode 安全标签过滤 "off"

计算属性如下(:2977-3012):

  • blend_heads:head_names 中属于 ("ld", "tweet_click") 的头。这类头称为混合头:它们不负责语料,只增加打分槽位(:75-80)。
  • num_table_slots = 1 + len(blend_heads):索引每行分成的段数。
  • query_head_weights = (w_fav, w_ld?, w_tweet_click?):服务时每段的权重。

make()(:3112-3150)先做两项校验:head_names 数量与候选头数一致;混合头不能是第 0 个头,也不能负责语料。然后它构造用户塔、候选塔和模型。

预设位于 phoenix/xrex/configs/xrecsys_two_tower.py:439-580:xrecsys_two_tower、xrecsys_two_tower_immersive_only(_gb300)、xrecsys_two_tower_combined(_gb300)、xrecsys_two_tower_home_only、xrecsys_two_tower_nano。另有 xrecsys_reply_two_tower_v2.py(回复召回,本站未展开)。

RecsysCandidateTower(候选塔)

该类是 hk.Module,位于 recsys_two_tower_model.py:180-331。它的配置 RecsysCandidateModelConfig(:334-394)包含 emb_table_width、enable_linear_proj、max_posts(默认 10,240,000)和 num_candidate_heads。

方法 位置 行为
_concat_then_mlp :203-246 展平 → Linear(2W) → SiLU → Linear(W) → L2 归一化;头 h > 0 使用独立的参数名
_project_then_sum :248-320 帖子、作者、SID 的每个 token 各乘一个 [W, W] 投影后相加 → L2 归一化
_mean_pool :329-331 取均值 → L2 归一化,无参数
__call__ :322-327 按 use_project_then_sum → enable_linear_proj → 均值的优先顺序选择一种方式

RecsysCandidateModelConfig.make_post_embeddings(num_table_slots)(:365-394)创建形状为 [max_posts, emb_table_width × num_table_slots] 的 bfloat16 索引参数,即 checkpoint 里的 post_embeddings。

MolScorer(MoL 打分)

该类是 NamedTuple,位于 recsys_two_tower_model.py:710-884。mol_item_components > 0 时启用(combined 预设为 1):

  • item_components:每条帖子经低秩适配器生成若干个单位向量(:720-727)。
  • mix:计算“每个用户查询头 × 每个帖子组件”的余弦相似度,送进隐藏层为 32 的门控 MLP,经 softmax 后加权求和(:729-737)。
  • serving_side_tables:为服务预计算每条帖子的范数与门控偏置。这些值存进 checkpoint,或在启动时计算(:825-862)。
  • 配套 CUDA 核 xrex/cuda/mol_epilogue/ 执行融合打分与 int8 量化(:924-1003)。

RecsysTwoTowerModel 方法

方法 位置 作用
build_user_inputs :1621-1815 构造用户塔输入;feature_prep_enabled 时使用特征准备路径(不含候选),否则用 block_history_reduce
candidate_token_stack :1894-1907 构造候选 token 栈:可选帖子哈希、作者哈希、SID token
build_candidate_embeddings :1909-1916 把 token 栈送入指定头的候选塔
build_candidate_embeddings_from_lookups :1918-1949 构建索引时使用:从已查出的嵌入直接计算候选向量
__call__ :1951-1969 返回用户表示、各头的候选表示和统计量
candidate_representations :1971-1988 为每个候选头各计算一次
user_representation :1990-2128 transformer → 平均池化或查询头池化 → L2 归一化
_query_heads_pool / _packed_query_heads :2157-2215 带时间衰减的多查询头注意力池化
_mol_scorer :2217-2252 构造 MolScorer 参数
forward :2279-2600 服务前向:逐槽位打分并加权 → 掩码 → top_k_by_key
loss :2719-2815 每个头调用一次 retrieval_loss 后相加,再加激活 L2 正则
metrics :2817-2851 召回率 @K 等指标

模块级函数:retrieval_loss(:1035-1380,采样 softmax 对比损失)、positive_and_negative_masks(:675-702)、score_over_slots(:150-177,按槽位加权求和)。

与排序模型的异同

维度 召回 RecsysTwoTowerModel 排序 RecsysAggregatedModel
序列 前缀 + 历史,无候选 前缀 + 历史 + 候选
用户 ID 嵌入 生产预设关闭 开
帖子 ID 嵌入 生产预设关闭,改用 SID + 作者 开,另加 SID
输出 单位向量(或 4 个查询向量) 64 个动作 logit + 8 个连续值
损失 对比损失 多标签 BCE + 连续损失
稠密优化器 AdamW(phoenix/TRAINING.md:21-25) 旗舰与 nano 用 Muon

设计决策

决策 理由
用户塔直接复用排序模型类 两个模型共用主干与输入机制,只在输出头上不同(phoenix/README.md:250-257)
混合头占用独立槽位 新目标(如 10-13 的 ld)不改动原有头的向量;服务时用权重调整比例
MoL 打分可选 点积计算成本低;MoL 让一个用户能匹配多种兴趣。源码未写理由,此为推测

源码锚点

  • phoenix/xrex/models/recsys_two_tower_model.py:1610-2851 —— RecsysTwoTowerModel
  • phoenix/xrex/models/recsys_two_tower_model.py:2854-3150 —— RecsysTwoTowerModelConfig
  • phoenix/xrex/models/recsys_two_tower_model.py:180-394 —— 候选塔及其配置
  • phoenix/xrex/models/recsys_two_tower_model.py:710-1003 —— MolScorer 与服务端打分
  • phoenix/xrex/models/recsys_two_tower_model.py:1035-1380 —— retrieval_loss
  • phoenix/xrex/configs/xrecsys_two_tower.py:251-580 —— 预设

相关页面

Type to search…

↑↓ navigate↵ selectEsc close