美团在 MTGR 基础上提出统一推荐基座大模型 MTFM,并首次实现外卖多个主要业务共用统一精排模型。这项工作的关键不只是“减少模型数量”,而是让不同业务场景在同一套表示与参数体系中共享知识,同时保留各自的排序目标和决策边界。
公开摘要没有披露 MTFM 的具体网络结构、训练数据或线上指标,因此下面不会猜测其内部实现,而是围绕“多业务统一精排”这一确定方向,拆解工程上需要解决的问题,并给出一个可以运行和改造的简化示例。
统一精排到底统一了什么
典型推荐链路通常包括召回、粗排、精排和重排。精排模型接收用户、商品、上下文及交叉特征,为候选集合计算更精确的分数。过去,不同入口或业务可能分别维护模型:
- 每个模型拥有独立样本、特征和训练任务;
- 相似的用户偏好被反复学习,低流量场景难以利用高流量场景的数据;
- 特征升级、模型发布和回滚需要在多条链路上重复执行;
- 各模型分数的含义不同,跨场景治理和校准更困难。
统一精排的核心不是把所有样本拼接后训练一个二分类器。更合理的抽象通常包含三层:
- 共享表示层:学习用户、商家、商品和上下文中的共性规律。
- 场景感知层:将业务标识、入口、时段等条件加入模型,避免抹平场景差异。
- 任务或场景输出层:为点击、下单等目标,或不同业务保留独立预测头。
这意味着“统一”与“差异化”必须同时存在。共享不足,模型只是被放进同一个服务;共享过度,则可能让高流量业务支配梯度,损害小业务效果。
真正困难的是数据与目标,而不只是网络结构
多业务模型最容易遇到的是负迁移。两个场景表面上都预测点击,用户意图和曝光机制却可能完全不同。外卖首页中的浏览行为,与明确品类入口中的行为,不能仅凭同名标签就视作同一任务。
落地时应重点检查以下几类问题:
- 标签口径:点击、有效点击、下单和支付是否拥有一致的归因窗口?
- 特征语义:同一个字段在不同业务中是否真的代表同一概念?
- 样本规模:高流量业务是否通过梯度数量压制其他业务?
- 缺失模式:某些特征只在特定场景存在时,缺失值是否泄露场景身份?
- 分数校准:统一模型输出能否直接用于多个入口,还是需要分场景校准?
因此,模型上线前不能只观察整体 AUC。至少要按业务、流量层级、新老用户和高低活跃度分别评估,并关注排序指标、概率校准以及核心业务指标。整体指标上涨,可能只是最大业务的样本占比掩盖了局部退化。
一个可运行的多场景精排原型
下面是一个教学性质的 PyTorch 示例。它不是 MTFM 的实现,也不代表美团采用了这种结构;它只是演示一种可实践的设计:共享底座接收连续特征和场景 ID,不同场景使用独立输出头。
运行前安装 PyTorch:
python -m pip install torch
将以下内容保存为 multi_scenario_ranker.py,然后执行 python multi_scenario_ranker.py:
import torch
from torch import nn
from torch.utils.data import DataLoader, TensorDataset
# 固定随机种子,便于复现实验
torch.manual_seed(42)
NUM_SCENARIOS = 3
FEATURE_DIM = 8
SAMPLES = 6000
# 构造三个场景的模拟样本。真实项目应替换为日志生成的数据集。
x = torch.randn(SAMPLES, FEATURE_DIM)
scenario = torch.randint(0, NUM_SCENARIOS, (SAMPLES,))
# 不同场景共享一部分规律,同时拥有各自偏好。
shared_signal = 1.2 * x[:, 0] - 0.8 * x[:, 1]
scenario_bias = torch.tensor([-0.7, 0.2, 0.9])[scenario]
scenario_signal = torch.stack([
0.9 * x[:, 2],
-1.1 * x[:, 3],
0.7 * x[:, 4] + 0.4 * x[:, 5],
])[scenario, torch.arange(SAMPLES)]
probability = torch.sigmoid(shared_signal + scenario_signal + scenario_bias)
y = torch.bernoulli(probability)
loader = DataLoader(
TensorDataset(x, scenario, y),
batch_size=256,
shuffle=True,
)
class MultiScenarioRanker(nn.Module):
def __init__(self):
super().__init__()
self.scenario_embedding = nn.Embedding(NUM_SCENARIOS, 4)
self.backbone = nn.Sequential(
nn.Linear(FEATURE_DIM + 4, 32),
nn.ReLU(),
nn.Linear(32, 16),
nn.ReLU(),
)
self.heads = nn.ModuleList([
nn.Linear(16, 1) for _ in range(NUM_SCENARIOS)
])
def forward(self, features, scenario_ids):
context = self.scenario_embedding(scenario_ids)
hidden = self.backbone(torch.cat([features, context], dim=1))
# 每个样本只经过它所属场景的输出头。
all_logits = torch.cat([head(hidden) for head in self.heads], dim=1)
return all_logits.gather(1, scenario_ids[:, None]).squeeze(1)
model = MultiScenarioRanker()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
loss_fn = nn.BCEWithLogitsLoss()
for epoch in range(8):
total_loss = 0.0
for features, scenario_ids, labels in loader:
logits = model(features, scenario_ids)
loss = loss_fn(logits, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item() * labels.size(0)
print(f'epoch={epoch + 1} loss={total_loss / SAMPLES:.4f}')
# 对三个场景中的候选分别打分。
model.eval()
with torch.no_grad():
candidates = torch.randn(3, FEATURE_DIM)
candidate_scenarios = torch.tensor([0, 1, 2])
scores = torch.sigmoid(model(candidates, candidate_scenarios))
for sid, score in zip(candidate_scenarios.tolist(), scores.tolist()):
print(f'scenario={sid} score={score:.4f}')
将这个原型迁移到真实系统时,需要替换的远不止模拟数据:
- 用稳定的
scenario_id映射替代示例中的整数; - 加入用户、商家、商品和交叉特征的嵌入表示;
- 根据各业务样本量设置采样比例或损失权重;
- 为点击、下单等不同目标增加多任务输出头;
- 保存特征字典、模型权重和校准参数,确保训练与在线推理一致。
如果高流量场景仍占据绝大多数批次,可以使用加权损失。设每个样本的场景权重为 w_s,二分类损失可改为:
loss_fn = nn.BCEWithLogitsLoss(reduction='none')
scenario_weights = torch.tensor([1.0, 1.8, 2.5])
raw_loss = loss_fn(logits, labels)
loss = (raw_loss * scenario_weights[scenario_ids]).mean()
权重不应凭经验长期固定。更稳妥的做法是结合样本规模、离线指标和线上实验逐步调整,并监控某个业务获得收益时,其他业务是否发生系统性退化。
从单模型实验走向统一基座
统一模型改变的不只是训练任务,还会影响特征平台、模型服务和发布机制。可以按以下顺序降低迁移风险:
- 统一数据定义:先对齐曝光、标签、特征时间和归因窗口,再讨论合并训练。
- 建立分场景基线:保留原模型结果,逐场景比较统一模型的增益与损失。
- 从共享底座开始:先共享稳定的底层表示,对差异明显的业务保留独立头或适配层。
- 限制负迁移:采用平衡采样、损失加权或梯度治理,并按场景监控指标。
- 逐步灰度发布:先覆盖低风险流量,确保模型、特征和降级链路都可回滚。
- 评估系统收益:除了效果指标,还应统计训练成本、推理延迟、显存占用和迭代周期。
MTFM 所代表的方向说明,推荐系统的复用单位正从单个特征、单个模块,进一步走向跨业务的统一精排基座。但统一模型不是天然更优:它用更强的知识共享能力,换来了更复杂的数据治理、目标协调和故障影响面。真正值得追求的不是“一个模型覆盖所有场景”,而是让共享发生在有效的位置,让差异保留在必要的位置。