.. _gr_ad: 竞价机制与多场景广告 ==================== 在推荐和搜索场景中,OneRec 和 OneSearch 通过端到端生成架构成功解决了级联系统的性能瓶颈。然而,在线广告场景面临着更为复杂的约束:系统不仅需要优化用户体验,还必须平衡平台收益与广告主利益,同时满足竞价机制的经济学约束。传统广告系统采用“召回→排序→创意选择→竞价→位置分配”的多阶段架构,每个环节都有独立的优化目标和复杂的业务规则,这种碎片化设计导致全局次优,且难以适应快速变化的市场需求。 端到端生成式广告系统需要解决三个核心挑战:\ **如何将竞价机制深度融入生成过程**\ 、\ **如何保证广告主的激励相容性(Incentive Compatibility)**\ 、\ **如何在超长异构序列中高效建模用户意图**\ 。本节将介绍两个代表性的工业解决方案:\ **EGA(End-to-end Generative Advertising)**\ 将竞价机制与生成模型统一,通过 Token 级竞价和 POI 级支付的双层设计实现了激励相容性约束;\ **GPR(Generative Pre-trained Recommender)**\ 则通过异构层次化解码器和预训练范式,在微信生态的多场景超长序列中实现了统一的广告生成能力。 EGA:统一竞价与生成 ------------------- 广告生成的约束条件 ~~~~~~~~~~~~~~~~~~ 在介绍 EGA 的技术细节前,我们先通过一个具体场景理解广告与推荐、搜索的本质差异。 假设用户在本地生活平台刷 feed 流时,系统需要在第 3 个位置插入一条广告。候选广告包括附近的餐厅、健身房、美容院等商户,每个商户提交了不同的竞价(bid),且每个商户有多张创意图片可选(美食照片、环境照片、优惠券等)。系统需要在一次前向传播中决定: 1. **展示哪个商户(POI)**\ :从数百个候选中选择与用户兴趣和竞价综合最优的商户 2. **使用哪张创意图**\ :为选中的商户匹配最能吸引该用户的创意素材 3. **如何计算支付**\ :根据竞价和分配结果确定商户需要支付的金额 4. **如何保证公平**\ :确保商户如实出价是最优策略(激励相容性) 这个场景揭示了广告生成的三重约束,它们将 EGA 与 OneRec/OneSearch 区分开来: **约束一:激励相容性(IC)与个体理性(IR)** 在推荐和搜索场景中,系统只需优化用户满意度和平台指标。但在广告场景下,广告主是独立的博弈方,他们会根据系统规则调整竞价策略。如果系统设计不当,广告主可能通过虚报竞价获取更高收益,导致平台收入下降或广告主流失。 激励相容性(IC)要求:广告主如实出价是最优策略。数学上,对于广告主 :math:`i` 的真实估值 :math:`v_i` 和申报竞价 :math:`b_i`\ ,当 :math:`b_i = v_i` 时,其效用最大: .. math:: u_i(v_i; v_i, \mathbf{b}_{-i}) \geq u_i(v_i; b_i, \mathbf{b}_{-i}), \quad \forall b_i \in \mathbb{R}^+ 其中效用定义为 :math:`u_i = (v_i - p_i) \cdot \text{pCTR}_i`\ ,即“点击收益减去支付成本”。个体理性(IR)则要求支付不能超过竞价:\ :math:`p_i \leq b_i`\ 。 传统的 GSP(Generalized Second Price)拍卖通过“按下一位竞价者的价格支付”来保证 IC,但这种规则假设广告之间相互独立,无法处理位置外部性(后续详述)。EGA 的目标是在生成式框架中学习到满足 IC 约束的支付函数。 **约束二:POI 与创意的联合生成** 在搜索场景中,OneSearch 生成的是商品序列,每个商品有固定的标题和图片。但在广告场景下,一个 POI(如某餐厅)可以关联多张创意图片,且不同用户偏好不同的创意风格。例如: - 对美食爱好者:展示精致菜品的特写照片 - 对价格敏感用户:展示“满 100 减 50”的优惠券 - 对家庭用户:展示宽敞的就餐环境 这要求系统不仅要决定“展示哪个 POI”,还要决定“用哪张创意”。两者需要联合优化:POI 决定内容主体(与用户兴趣和竞价相关),创意优化呈现方式(与用户偏好和上下文相关)。 **约束三:分配与支付的解耦设计** 如果直接将竞价作为生成概率的权重,会导致“赢家诅咒”:高竞价广告获得曝光后,按自己的竞价支付,导致广告主倾向于压低出价。传统拍卖通过“按次高价支付”解决这一问题,但在生成式框架中,分配是通过 Softmax 概率实现的,没有明确的“第二名”。 EGA 通过分离分配和支付两个模块解决这一矛盾:分配阶段使用竞价引导生成概率,支付阶段通过独立的神经网络学习满足 IC 约束的支付函数。 兴趣建模与预训练 ~~~~~~~~~~~~~~~~ EGA 采用“预训练 + 竞价微调”的两阶段训练范式。在预训练阶段,模型忽略竞价信息,专注于从用户历史行为中学习兴趣偏好,构建基础的生成能力。这一阶段的目标是让模型回答:“给定用户的历史行为,他接下来可能对哪些 POI 和创意感兴趣?” **双模态语义 ID:离散化 POI 与创意** 与 OneRec 和 OneSearch 类似,EGA 使用 RQ-VAE(Residual Quantized Variational AutoEncoder)将连续的 POI 和创意表示离散化为多层语义 ID。但与它们不同的是,EGA 需要为 POI 和创意构建两套独立的语义空间。 对于 POI(Point of Interest,如餐厅、健身房),其原始表示 :math:`\mathbf{e}_i^{\text{poi}}` 包含: - 类目信息(餐饮、娱乐、生活服务) - 地理位置(经纬度、商圈) - 统计特征(历史 CTR、平均客单价、评分) - 文本描述(商户名称、主营业务) 对于创意图片,其表示 :math:`\mathbf{e}_i^{\text{img}}` 通过预训练的视觉模型提取: - 视觉特征(物体、场景、颜色风格) - 文本信息(OCR 提取的促销文案) - 创意类型(美食图、环境图、优惠券、品牌 logo) RQ-VAE 将这些连续表示编码为分层离散码。假设使用 :math:`C=3` 层残差量化,每层码本大小为 :math:`W=1024`\ ,则每个 POI 被编码为 3 个 token 的序列: .. math:: \mathbf{a}_i^{\text{poi}} = (a_i^{1}, a_i^{2}, a_i^{3}), \quad a_i^{j} \in \{1, 2, \ldots, 1024\} 创意同理得到 :math:`\mathbf{a}_i^{\text{img}}`\ 。用户历史序列中的每个交互可以表示为一个 (POI, 创意) 对: .. math:: \mathcal{S}^u = \{(\mathbf{a}_1^{\text{poi}}, \mathbf{a}_1^{\text{img}}), (\mathbf{a}_2^{\text{poi}}, \mathbf{a}_2^{\text{img}}), \ldots, (\mathbf{a}_B^{\text{poi}}, \mathbf{a}_B^{\text{img}})\} **概率分解的生成策略:先 POI 后创意** 一个直观的想法是将 POI 和创意的 6 个 token(3+3)拼接成一个序列,让模型自回归生成。但 EGA 发现这种方式会导致生成的 POI 和创意不匹配,模型可能生成“餐厅 A 的 POI + 健身房 B 的创意”这种无效组合。 EGA 采用\ **概率分解**\ 策略,将生成过程拆分为两个阶段: .. math:: P(\mathbf{a}_{t+1}^{\text{poi}}, \mathbf{a}_{t+1}^{\text{img}} \mid \mathcal{S}^u_{1:t}) = P(\mathbf{a}_{t+1}^{\text{poi}} \mid \mathcal{S}^u_{1:t}) \cdot P(\mathbf{a}_{t+1}^{\text{img}} \mid \mathbf{a}_{t+1}^{\text{poi}}, \mathcal{S}^u_{1:t}) 这种分解的直觉是:POI 决定“展示什么内容”,创意决定“如何呈现内容”。模型先根据用户兴趣生成 POI,再根据 POI 的特性和用户偏好选择匹配的创意。例如: - 用户喜欢川菜 → 生成川菜餐厅 POI → 为该餐厅选择“麻辣火锅”创意而非“优雅环境”创意 - 用户是健身爱好者 → 生成健身房 POI → 选择“专业器械”创意而非“团课氛围”创意 **Encoder-Decoder 架构:双解码器实现联合生成** EGA 采用经典的 Encoder-Decoder 架构,但使用两个解码器分别生成 POI 和创意。 .. _ega_pretrain: .. figure:: ../img/ega_pretrain.png :width: 500px EGA预训练架构 **编码器**\ 处理用户的历史行为序列。与 OneRec 不同,EGA 的输入序列包含广告和有机内容的混合: .. math:: \mathcal{S}^u = \{(\mathbf{a}_1^{\text{poi}}, \mathbf{a}_1^{\text{img}}, \text{type}_1), \ldots, (\mathbf{a}_B^{\text{poi}}, \mathbf{a}_B^{\text{img}}, \text{type}_B)\} 其中 :math:`\text{type}_i \in \{\text{ad}, \text{organic}\}` 标识该项是广告还是有机内容。编码器通过多层 Transformer 生成上下文表示: .. math:: \mathcal{S}^e = \text{Encoder}(\mathcal{S}^u) \in \mathbb{R}^{B \times d} **POI 解码器**\ 先生成目标 POI 的语义 ID。在训练时,假设目标 POI 为 :math:`\mathbf{a}_{\text{target}}^{\text{poi}} = (a^1, a^2, a^3)`\ ,解码器自回归生成每一层的 token: .. math:: \begin{aligned} a^1 &= \text{POI-Decoder}([\text{BOS}], \mathcal{S}^e) \\ a^2 &= \text{POI-Decoder}([\text{BOS}, a^1], \mathcal{S}^e) \\ a^3 &= \text{POI-Decoder}([\text{BOS}, a^1, a^2], \mathcal{S}^e) \end{aligned} **创意解码器**\ 以生成的 POI 为条件,生成对应的创意 ID。关键设计是:创意解码器的输入包含 POI 的 token 序列,这使得模型能够根据 POI 的语义信息选择匹配的创意: .. math:: \begin{aligned} \mathbf{a}^{\text{img}} &= \text{Creative-Decoder}(\mathbf{a}^{\text{poi}}, \mathcal{S}^e) \\ &= \text{Creative-Decoder}([a^1, a^2, a^3], \mathcal{S}^e) \end{aligned} **MTP(Multi-Token Prediction)模块的作用** 在标准的 Transformer 解码器中,每个时间步只预测下一个 token。但 EGA 发现,POI 的生成和创意的生成存在内在关联,可以通过联合训练提升性能。 MTP 模块在每个解码步同时监督两个解码器: .. math:: \mathcal{L}_{\text{pre-train}} = \mathcal{L}_{\text{NTP}}^{\text{POI}} + \mathcal{L}_{\text{MTP}}^{\text{Creative}} 其中: .. math:: \begin{aligned} \mathcal{L}_{\text{NTP}}^{\text{POI}} &= -\frac{1}{K}\sum_{i=1}^K \sum_{j=1}^3 \log P(a_i^j \mid \mathbf{a}_i^{ i \end{cases} 具体效果: - **Prompt 区域内部(U/O/E-Token)**\ :双向注意力,\ :math:`M_{ij} = 0`\ ,任意两个 token 可以相互看到 - **Target 区域(I-Token)**\ :因果注意力,\ :math:`M_{ij} = -\infty` if :math:`j > i`\ ,保证自回归生成 - **Target 看 Prompt**\ :\ :math:`M_{ij} = 0` if :math:`i \in \text{I-Token}, j \in \text{U/O/E-Token}`\ ,生成时可以访问完整上下文 举例说明:假设序列为 ``[U, E, O, O, I1, I2]``\ ,Attention 矩阵为: :: U E O O I1 I2 U [ 0 0 0 0 X X ] E [ 0 0 0 0 X X ] O [ 0 0 0 0 X X ] O [ 0 0 0 0 X X ] I1 [ 0 0 0 0 0 X ] I2 [ 0 0 0 0 0 0 ] 其中 ``0`` 表示可见,\ ``X`` 表示不可见(-∞)。 **设计 2:Token-Aware Normalization——异构 Token 的独立归一化** U-Token、O-Token、E-Token、I-Token 的分布特性差异巨大: - U-Token 是离散特征(年龄、性别),值域有限 - O-Token 是多模态内容表示,分布连续且方差大 - E-Token 是时间和地理特征,周期性强 - I-Token 是广告表示,与竞价相关 如果对所有 token 使用统一的 LayerNorm,会导致归一化参数无法适应异构分布。GPR 为每种 token 分配独立的归一化层和前馈网络(FFN): .. math:: \begin{aligned} \mathbf{h}^{\text{U}} &= \text{LayerNorm}_{\text{U}}(\mathbf{h}^{\text{U}}) + \text{FFN}_{\text{U}}(\mathbf{h}^{\text{U}}) \\ \mathbf{h}^{\text{O}} &= \text{LayerNorm}_{\text{O}}(\mathbf{h}^{\text{O}}) + \text{FFN}_{\text{O}}(\mathbf{h}^{\text{O}}) \\ \mathbf{h}^{\text{E}} &= \text{LayerNorm}_{\text{E}}(\mathbf{h}^{\text{E}}) + \text{FFN}_{\text{E}}(\mathbf{h}^{\text{E}}) \\ \mathbf{h}^{\text{I}} &= \text{LayerNorm}_{\text{I}}(\mathbf{h}^{\text{I}}) + \text{FFN}_{\text{I}}(\mathbf{h}^{\text{I}}) \end{aligned} 这将每种 token 投影到各自的语义子空间,充分捕获语义多样性。 **设计 3:MoR(Mixture-of-Recursions)——增加推理深度** 为了增强模型的推理能力,GPR 引入 **Mixture-of-Recursions** 机制:在不增加参数的情况下,让某些层递归调用自身多次。 具体而言,对于第 :math:`l` 层,输出为: .. math:: \mathbf{h}^{(l)} = \sum_{r=1}^{R} w_r \cdot \text{Block}^{(l)}(\mathbf{h}^{(l-1)}, r) 其中 :math:`r` 是递归次数,\ :math:`w_r` 是可学习的权重。每次递归调用同一层的参数,但输入是上一次递归的输出。这类似于“多轮思考”,模型对同一信息反复处理,逐步提炼关键信号。 **可选增强:LLM 思维链注入** 对于高价值用户,GPR 可以利用外部 LLM(如 GPT-4)生成用户意图的文本描述: :: 输入:用户最近浏览了火锅教学视频、川菜餐厅广告、旅游vlog LLM 输出:该用户对美食和旅行感兴趣,特别偏好川菜风味,可能在计划近期的旅行或聚餐 这段文本被 Tokenize 后,作为额外的 O-Token 注入序列,丰富意图表示。 HSD 的输出是\ **意图嵌入(Intent Embeddings)** :math:`\mathcal{S}^e \in \mathbb{R}^{L \times d}`\ ,它包含了用户历史行为的高层抽象表示。 **第二层:PTD(Progressive Token-wise Decoder)—— 推理与生成层** 意图嵌入包含了丰富的信息,但也包含大量冗余。PTD 的任务是从意图中提取与当前广告生成任务相关的关键信号,并逐步生成广告的语义 ID。GPR 设计了\ **“Thinking-Refining-Generation”**\ 三段式生成范式。 **阶段 1:Thinking 阶段——提取关键信号** PTD 首先生成 :math:`K` 个 **Thinking Tokens**\ (通常 :math:`K=4`\ ),这些 token 不对应具体的广告内容,而是用于“思考”,从意图嵌入中筛选关键信息。 Thinking Tokens 通过可学习的查询向量初始化: .. math:: \mathbf{q}_{\text{think}} \in \mathbb{R}^{K \times d} 然后通过 Cross-Attention 从意图嵌入中提取信息: .. math:: \mathbf{h}_{\text{think}} = \text{CrossAttention}(\mathbf{q}_{\text{think}}, \mathcal{S}^e, \mathcal{S}^e) Cross-Attention 的效果是:Thinking Tokens 学会关注意图嵌入中与广告生成相关的部分,过滤掉无关信息。例如,如果当前要生成餐饮广告,Thinking Tokens 会关注用户历史中的美食相关行为,而忽略健身、科技等无关行为。 **阶段 2:Refining 阶段——基于扩散的迭代优化** Thinking Tokens 提取的信息可能仍然不够精确。GPR 借鉴大语言模型中的 **Self-Reflection** 机制,引入基于扩散模型的 Refining 模块对推理结果进行迭代优化。 Refining 模块的设计受到 Stable Diffusion 的启发,包含两个步骤: 1. **加噪过程**\ :对 Thinking Tokens 添加高斯噪声 .. math:: \mathbf{h}_{\text{noisy}} = \mathbf{h}_{\text{think}} + \epsilon, \quad \epsilon \sim \mathcal{N}(0, \sigma^2 I) 2. **去噪过程**\ :通过条件去噪 Transformer 迭代移除噪声 .. math:: \mathbf{h}_{\text{refined}} = \text{DenoisingTransformer}(\mathbf{h}_{\text{noisy}}, \mathbf{c}) 其中条件 :math:`\mathbf{c}` 是 Thinking Tokens 的聚合表示: .. math:: \mathbf{c} = \text{SumPooling}(\mathbf{h}_{\text{think}}) 为什么这样设计?加噪-去噪的过程强迫模型“重新组织”推理结果,类似于人类在做决策时的“二次确认”。实验表明,Refining 模块能够提升生成质量 2-3%,尤其对于复杂用户(行为序列长、兴趣多样)的效果提升更明显。 **阶段 3:Generation 阶段——自回归生成语义 ID** 基于 Thinking Tokens 和 Refining Token,PTD 自回归生成目标广告的语义 ID。假设使用 3 层 RQ 编码,生成过程为: .. math:: \begin{aligned} a^1 &= \text{Softmax}(\text{Linear}([\mathbf{h}_{\text{refined}}; \text{BOS}])) \\ a^2 &= \text{Softmax}(\text{Linear}([\mathbf{h}_{\text{refined}}; \text{Embed}(a^1)])) \\ a^3 &= \text{Softmax}(\text{Linear}([\mathbf{h}_{\text{refined}}; \text{Embed}(a^1, a^2)])) \end{aligned} 每一步生成的 token 都作为下一步的输入,形成自回归链。 **第三层:HTE(Hierarchical Token-wise Evaluator)—— 价值评估层** 与 EGA 的奖励模型类似,HTE 负责预测生成广告的业务价值。但 HTE 的独特之处在于:它在\ **每一层 token 生成时就输出价值估计**\ ,而不是等到完整序列生成后才评估。 对于第 :math:`l` 层生成的 token :math:`a^l`\ ,HTE 输出该 token 对应的期望价值: .. math:: v^l = \text{MLP}_{\text{value}}([\mathbf{h}^{(l)}; \text{Embed}(a^l)]) 最终广告的价值是各层价值的聚合: .. math:: \text{final\_value} = w_{1} \cdot \text{pCTR} + w_{2} \cdot \text{pCVR} + w_{3} \cdot \text{eCPM} 其中 pCTR、pCVR 通过类似 EGA 的多任务塔预测,eCPM(effective Cost Per Mille)是广告主的竞价乘以 pCTR。 HTE 在推理时有两个用途: 1. **Beam Search 剪枝**\ :低价值的 token 分支提前终止 2. **Policy Optimization 的 Critic**\ :在强化学习阶段,HTE 作为价值函数估计优势(Advantage) 价值引导的 Beam Search ~~~~~~~~~~~~~~~~~~~~~~ EGA 在推理时使用标准 Beam Search,会生成大量无效候选。GPR 提出 **Value-Guided Trie-based Beam Search**\ ,将价值估计和约束过滤直接集成到解码过程中。 **Trie 树约束:预先过滤无效候选** Trie(字典树)是一种前缀树数据结构,常用于字符串匹配。GPR 将其扩展到语义 ID 空间:根据当前用户的画像和广告的投放约束,构建一棵 Trie 树,其中只包含有效的广告 ID 序列。 **构建过程**\ : 1. **收集约束条件**\ : - 用户画像:年龄 25 岁、女性、北京、美食爱好者 - 广告定向:某餐厅广告定向“20-30 岁女性,一线城市” - 预算状态:某些广告预算已耗尽 - 地域限制:某些广告仅在特定城市投放 2. **过滤广告池**\ :从全量广告库中筛选出满足约束的广告子集 :math:`\mathcal{X}_{\text{valid}}` 3. **提取语义 ID**\ :将 :math:`\mathcal{X}_{\text{valid}}` 中每个广告的 3 层语义 ID 提取出来,例如: :: 广告 A: [23, 456, 789] 广告 B: [23, 456, 801] 广告 C: [23, 512, 234] 4. **构建 Trie 树**\ : :: 根节点 ├── 23 (第1层) │ ├── 456 (第2层) │ │ ├── 789 (第3层, 对应广告A) │ │ └── 801 (第3层, 对应广告B) │ └── 512 (第2层) │ └── 234 (第3层, 对应广告C) **解码约束**\ :在生成第 :math:`l` 层 token 时,只从 Trie 树当前节点的子节点集合中采样,而不是从整个码本(\ :math:`W=1024` 个候选)中采样。这将搜索空间从 :math:`W^3` 缩小到 :math:`|\mathcal{X}_{\text{valid}}|`\ 。 **价值动态调整束宽:高价值分支探索更深** 标准 Beam Search 对所有分支使用固定的束宽 :math:`B`\ 。GPR 根据 HTE 输出的价值动态调整每个分支的探索宽度。 对于第 :math:`l` 层生成的 token :math:`a^l`\ ,其价值为 :math:`v^l`\ (由 HTE 输出)。该分支在下一层的束宽为: .. math:: B_{\text{next}}(a^l) = \max\left(B_{\text{min}}, B_{\text{base}} \times \exp\left(\frac{v^l - \bar{v}}{\tau}\right)\right) 其中: - :math:`\bar{v}` 是当前所有分支的平均价值 - :math:`\tau` 是温度系数,控制束宽差异的程度 - :math:`B_{\text{min}}` 是最小束宽(保证低价值分支不被完全抛弃) 直觉:如果某个 token 的价值远高于平均值(如对应高竞价的热门品类),该分支会被分配更宽的束宽,探索更多可能性;反之,低价值分支提前收缩,节省计算。 **实际效果**\ : - **推理延迟**\ :从 EGA 的 150ms 降至 80ms(降低 47%) - **有效候选占比**\ :从 40% 提升至 95%(大部分无效候选在解码早期被 Trie 树过滤) - **Top-1 准确率**\ :提升 3.2%(价值引导使模型更专注于高质量候选) 多阶段训练策略 ~~~~~~~~~~~~~~ GPR 的训练分为三个阶段,每个阶段有明确的目标和数据来源。 **阶段一:MTP 预训练——学习通用兴趣表示** 这一阶段的目标是从海量的用户行为序列中学习兴趣表示,不引入任何广告特有的信号(如竞价、转化率)。 **数据来源**\ :微信生态的全量用户行为日志,包括: - 视频号:观看、点赞、评论、分享 - 朋友圈:浏览、点赞、评论 - 公众号:阅读、分享、关注 - 广告:点击、转化(但不使用竞价信息) 每条样本是一个用户的行为序列 :math:`\mathcal{S}^u`\ ,目标是预测下一个交互的 POI(或内容)。 **训练目标**\ :Multi-Token Prediction(MTP) .. math:: \mathcal{L}_{\text{pre-train}} = \mathcal{L}_{\text{NTP}}^{\text{POI}} + \mathcal{L}_{\text{MTP}}^{\text{Creative}} 具体而言: .. math:: \begin{aligned} \mathcal{L}_{\text{NTP}}^{\text{POI}} &= -\sum_{t=1}^K \log P(\mathbf{a}_t^{\text{poi}} \mid \mathcal{S}^u_{