paper2skills Playbook

DARA - LLM+RL 双阶段广告预算分配 Agent

Skill-DARA-Agentic-MMM-Optimizer · 15-营销投放分析

causalexperimentoptimizationmulti_agent广告与投放MAS与智能体工程定价与利润WF-B 广告优化WF-D 选品扫描
年化 ROI360-720 万元
实现难度⭐⭐⭐⭐⭐
业务优先级⭐⭐⭐⭐⭐
业务视角
适用角色CMO / 营销负责人 · 广告优化师 · CEO
适用平台Amazon + TikTok + Meta + KOL 四渠道 · Prime Day / Black Friday 预算前置
什么情况下用同时跑 Amazon 广告/TikTok/网红投放/邮件,不知道整体预算怎么分配最高效;网红投放花了大钱但不知道带来多少真实 GMV
成功是什么样的建立全渠道营销归因模型(MMM),每个渠道真实 ROI 可量化,大促前做预算优化模拟
业务痛点
多渠道预算分配靠感觉网红带货效果不知道怎么量化渠道之间互相抢功劳数据打架整体营销 ROI 算不清楚

1. 解决的问题

婴儿推车季节性爆款上线,Google Ads 历史只有 3-5 周数据,传统规则策略难快速找到最优出价时段 - 数据要求:近 3-5 周 Google Ads ROAS 时段数据 + 月度总预算 - DARA 配置:T = 7(一周)或 24(一天时段);Phase 1 LLM 读历史生成日预算向量;Phase 2 每日 ROAS 反馈调整下一日 - 业务价值:冷启动期 ROAS 提升

2. 核心算法逻辑

固定总预算下,广告主需在 T 个时段/渠道间分配预算 $b_1, \ldots, b_T$ 最大化总回报。DARA 双阶段架构:Phase 1 Fewshot Reasoner(LLM 读历史 35 周数据生成初始分配) + Phase 2 Finegrained Optimizer(滑窗 ROI 反馈精调),用 GRPOAdaptive(动态参考策略 RL)训练 LLM,解决冷启动 + 数值精度双难题。

3. 业务应用场景

- 业务问题:婴儿推车季节性爆款上线,Google Ads 历史只有 3-5 周数据,传统规则策略难快速找到最优出价时段 - 数据要求:近 3-5 周 Google Ads ROAS 时段数据 + 月度总预算 - DARA 配置:T = 7(一周)或 24(一天时段);Phase 1 LLM 读历史生成日预算向量;Phase 2 每日 ROAS 反馈调整下一日 - 业务价值:冷启动期 ROAS 提升 15-30%,新品 GMV 增量 30-60 万元/月;以月预算 100 万元计 = 年化收益 360-720 万元

- 业务问题:母婴品牌同投 Google Shopping + Meta DPA,每周需调整两渠道预算比例,但 marginal ROAS 随节促(618/双11)动态变化 - 数据要求:跨渠道历史 ROAS + CPC/CPM + 竞品节奏数据 - DARA 配置:T = 渠道数(2-5);Phase 1 LLM 读历史 + 竞品输出初始权重;Phase 2 实时 ROAS 反馈精调,目标"边际 ROAS 等价" - 业务价值:跨渠道 ROAS 提升 10-20%,大盘 GMV 增量 5-8%;以中型品牌月广告 500 万元计 = 年化增量 600-1200 万元

4. 输入数据要求

请查看原始代码模板获取输入规格。

5. 输出结果

请查看原始代码模板获取输出规格。

6. 业务价值 / ROI

  • 难处:论文无官方代码,GRPO-Adaptive 需基于 TRL 库自行实现
  • 难处:LLM 微调需大量历史数据 + RL 训练经验
  • 难处:Phase 2 实时反馈需要 Google/Meta Ads API 集成

7. 代码模板

代码块数量:1 · 路径:未检测到

"""
DARA-lite: 双阶段 LLM 广告预算分配骨架
论文 arXiv:2601.14711 (WWW 2026, 阿里巴巴)
注: 实际部署需要 OpenAI API 或本地 LLM (Qwen2.5/DeepSeek-R1) + TRL.GRPOTrainer
本骨架使用纯规则模拟 LLM 决策,验证 算法骨架。
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Dict, List, Tuple


@dataclass
class AdChannel:
    name: str
    budget: float
    actual_roas: float


def phase1_reasoner(history: List[AdChannel], total_budget: float, channels: List[str]) -> Dict[str, float]:
    """Few-shot Reasoner: 历史数据 → 初始预算分配
    简化版: 按历史 ROAS 比例分配(实际生产替换为 LLM 调用)
    """
    roas_by_channel: Dict[str, float] = {}
    for h in history:
        roas_by_channel[h.name] = roas_by_channel.get(h.name, 0.0) + h.actual_roas
    counts = {c: sum(1 for h in history if h.name == c) for c in channels}
    avg_roas = {c: roas_by_channel.get(c, 1.0) / max(counts.get(c, 1), 1) for c in channels}
    total_roas = sum(avg_roas.values()) or 1.0
    return {c: total_budget * avg_roas[c] / total_roas for c in channels}


def phase2_optimizer(
    allocation: Dict[str, float],
    feedback: Dict[str, float],
    total_budget: float,
    learning_rate: float = 0.1,
) -> Dict[str, float]:
    """Fine-grained Optimizer: 实时 ROAS 反馈 → 精调
    目标: 各渠道边际 ROAS 趋于相等
    """
    if not feedback:
        return allocation

    avg_roas = sum(feedback.values()) / len(feedback)
    new_alloc = {}
    for c, b in allocation.items():
        roas = feedback.get(c, avg_roas)
        delta = (roas - avg_roas) * learning_rate * b
        new_alloc[c] = max(b + delta, 100.0)

    total = sum(new_alloc.values())
    return {c: v * total_budget / total for c, v in new_alloc.items()}


def simulate_marginal_roas(allocation: Dict[str, float], base_roas: Dict[str, float], saturation: float = 1000.0) -> Dict[str, float]:
    """模拟边际 ROAS 衰减(实际场景从 Ads API 拉取)"""
    return {c: base * (saturation / (saturation + allocation[c])) for c, base in base_roas.items()}


def main() -> None:

8. 论文来源

  • 2601.14711