# auto_put_ad_mini 策略 Review（2026-04-16）

> **作者**：Claude（资深投流专家视角）
> **目的**：对 auto_put_ad_mini 做系统性 review，从业务目标 / 业务理解 / 数据层 / 工程实现 四个维度识别缺口，为后续迭代提供专家级分析留档。
> **使用方式**：后续每轮迭代前回读此文档，确认"当前走到哪一步、下一步该做什么、为什么"。

---

## 目录

- [0. 当前系统成熟度](#0-当前系统成熟度)
- [1. 维度一：业务目标层](#1-维度一业务目标层)
- [2. 维度二：业务理解层](#2-维度二业务理解层)
- [3. 维度三：数据层](#3-维度三数据层)
- [4. 维度四：工程实现层](#4-维度四工程实现层)
- [5. 最高 ROI 的完整升级路径](#5-最高-roi-的完整升级路径)
- [6. 下轮议题候选](#6-下轮议题候选)
- [7. 附录：现状快照](#7-附录现状快照)

---

## 0. 当前系统成熟度

当前系统**架构是对的**（fetch → merge → roi → classify → llm → validate → approval → execute），但**决策成熟度停在 L1-L2**，离"最优效果"还差三块关键升级。

| 级别 | 能力 | 当前状态 |
|------|------|---------|
| L1 | 单指标阈值决策 | ✅ 有 |
| L2 | 多维度组合决策 | 🟡 部分（ROI + 消耗，缺创意 + 生命周期 + 大盘） |
| L3 | **趋势 / 结构感知** | ❌ 无（只看当前快照，不看变化） |
| L4 | **反馈学习** | ❌ 无（决策效果不回流） |
| L5 | **大盘联动** | ❌ 无（缺跨账户基准） |

**核心洞察**：ROI 是结果，不是原因。只盯 ROI 做决策是"**后视镜驾驶**"。真正预示未来的是领先指标（点击率趋势、进入小程序转化率、裂变系数变化、创意级 ROI 分布）。

---

## 1. 维度一：业务目标层

### 1.1 当前目标

> 基于 ROI + 跑量双维度，对在投广告做调价 / 暂停。

### 1.2 专家视角的问题

#### 问题 1：目标函数单一

只有 ROI，但投流的真实目标是"**在预算约束下最大化利润**"。当前系统缺 3 个隐式但关键的目标：

- **规模目标**（消耗利用率）：预算花不出去 = 机会成本丢失
- **多样性目标**（人群池健康度）：过度集中在 R50 快钱人群 → 短期 ROI 高但长期池子枯竭
- **风控目标**（单次调整的 blast radius）：Tier 3 高价值广告一刀切暂停可能造成账户流量断崖

#### 问题 2：没有"时间窗口"的策略分层

- **短期**（小时级）：止损、预算管控
- **中期**（日级）：效率优化
- **长期**（周 / 月级）：结构调整、人群池经营

当前系统只有日级，时间维度折叠。

#### 问题 3："最大化长期 ROI"的"长期"没定义

到底是 7 日？30 日？LTV？每个定义下，决策逻辑不同。

### 1.3 建议补充的目标表达

```
主目标：account_daily_profit = daily_revenue - daily_cost
约束 1：budget_utilization >= 85%（预算别闲置）
约束 2：audience_portfolio_health（各 R 值层有健康广告数）
约束 3：max_blast_radius_per_decision <= 5%（单次调整不动摇 > 5% 的日消耗）
时间窗口：滚动 7 日利润最优，兼顾 30 日趋势不恶化
```

---

## 2. 维度二：业务理解层

当前 skill 已经讲了 R 值含义、回流模型、f_7日动态ROI 公式（上一轮重构加的）。但**还缺 4 块投流专家必备的心智模型**。

### 2.1 广告生命周期的阶段化策略（缺失）

| 阶段 | 时长 | 核心信号 | 核心策略 |
|------|------|---------|---------|
| 冷启动期 | 0-4 天 | 点击率、CVR 爬升速度 | 绝对保护，不做负向（已有） |
| 学习期 | 4-14 天 | ROI 是否收敛 | 观察，谨慎微调 |
| 稳定期 | 14-60 天 | ROI 波动范围 | 正常调控（当前系统主要服务这里） |
| 衰退期 | 60+ 天 | ROI 斜率下降 | 判断是创意疲劳还是人群饱和 |
| 僵尸期 | 任意 | 连续无消耗 | 回收预算 |

当前系统只区分"冷启动 / 正常"，把学习期、衰退期、僵尸期混在"非冷启动"里，**决策粒度太粗**。

### 2.2 创意 vs 广告的归因分离（缺失）

**核心洞察**：在腾讯 3.0"少广告多素材"策略下，**广告层级的 ROI 问题 80% 是创意问题**。

- 当前系统只看广告级 ROI → 做出"降价 / 暂停广告"决策
- 正确姿势：广告 ROI 降 → 先归因到创意（是 A 创意疲劳？还是 B 创意刚上线在冷启？）→ 再决定是换创意还是动广告
- **代码已经采集了 creative_id**，但没做创意级 ROI 聚合 —— **这是最大的数据浪费**

### 2.3 竞价生态感知（缺失）

oCPM 出价是拍卖，ROI 下降的原因可能是：

- **自己的问题**（创意疲劳、人群匹配差）
- **大盘问题**（行业大盘涨、同时段竞品加价）
- **账户层面**（同账户内广告互相抢量）

当前系统全部归因于"自己"，没有"**同时段大盘参考**"，导致大盘涨时所有广告都在降价 → 量更少 → ROI 更差的**死亡螺旋**。

### 2.4 预算 pacing（消耗节奏）（缺失）

腾讯 oCPM 对"提前花完 day_amount"的广告会**自动降量**（防止一小时烧光）。

- 当前系统有 `day_amount` 字段但**未在决策中使用**
- 应该看 `daily_cost / day_amount` = 预算利用率：
  - `< 50%`：广告跑不动（出价低？创意差？人群窄？），**不应再降价**
  - `50-90%`：健康
  - `> 95%` 且时间早：可能触发平台降速，**提价反而有害**

---

## 3. 维度三：数据层

### 3.1 🔴 P0：已经算出来但没给 LLM（立即可补，0 成本）

| 字段 | 现状 | 影响 |
|------|------|------|
| `bid_increased_7d` | `ad_decision.py:400` 算了，没写进 metrics CSV | LLM 无法识别"已干预但无效"的衰退信号 |
| `creative_changed_7d` | 同上 | 同上 |
| `audience_tier`（R 值） | 能从 ad_name 提取，但 metrics CSV 没这一列 | LLM 做人群间比较时要靠 ad_name 文本匹配，容易错 |

**这三个字段是 LLM 做衰退判断 + 人群比较的必需品，现在缺席 = skill 里说了也用不起来**。

### 3.2 🟠 P1：数据已有，差一步聚合（低成本）

| 维度 | 当前现状 | 需要做的 |
|------|---------|---------|
| 创意级 ROI | merged CSV 有 creative_id 和所有指标 | 按 creative_id 聚合 `creative_metrics.csv`，LLM 能看到"哪个创意在拖后腿" |
| 人群包级汇总 | ad_name 可提取 R 值 | 按 R 值分组汇总 ROI 均值 / p25 / p75 / 广告数，提供"R 值基线" |
| 账户级汇总 | 每个 ad 有 account_id | 日级账户消耗、收入、ROI，看账户整体健康度 |
| 预算利用率 | day_amount + daily_cost 都有 | `budget_utilization = cost / day_amount` |
| 趋势（斜率） | 7 日数据都有 | 计算 ROI 最近 3 天 vs 前 4 天的差值 / 变化率，判断是变好还是变差 |

### 3.3 🟡 P2：需要新增数据源（中等成本）

| 数据 | 来源 | 价值 |
|------|------|------|
| 小时级消耗速率 | 腾讯 Reporting API 支持 `group_by=[date,hour]` | 止损 + 预算 pacing |
| 创意上线 / 更新时间 | 腾讯 `dynamic_creatives/get` | 识别"新创意冷启动" vs "老创意衰退" |
| 账户级大盘（所有账户汇总） | 跨账户查询 | 大盘对比基准，避免死亡螺旋 |
| 同 R 值同地域大盘 | ODPS | 同可比人群的基准 |

### 3.4 🟢 P3：结构化运营 feedback（高价值但需基础设施）

| 数据 | 价值 |
|------|------|
| 决策 → 实际效果的回流数据 | 自学习的基础，知道"ROI=1.5 降 5% 的广告，通常 3 天后 ROI 变多少" |
| 运营拒绝 / 修改决策的原因 | 积累人类知识，修正模型偏见 |
| 历史的"救活"案例 | 哪些暂停后又开启的广告后来跑得好，那就不该暂停 |

---

## 4. 维度四：工程实现层

### 4.1 🔴 P0（阻塞业务）

1. **`EXECUTION_ENABLED=False`**：整个系统当前是"纸面决策机"，不实际执行（`config.py:113`）
2. **调整历史 JSON 单点**：频率护栏靠 `outputs/data/adjustment_history.json`，无数据库、无并发安全、重启易丢（`guardrails.py:61`）
3. **护栏钳位后 change_pct 不同步**：`recommended_bid` 被钳到下限，但 `change_pct` 还是原值，报告里数据矛盾（`guardrails.py:316`）

### 4.2 🟠 P1（功能不完整）

4. **没有反馈环**：决策执行后的实际 ROI 变化无回流、无评估 → 无法学习
5. **决策无版本**：同日多次 LLM 调用会覆盖文件，无法追溯"为什么当时做了这个决策"
6. **B 类分类规则和 LLM 决策标准不一致**：B 类触发条件（`roi_review_factor=0.8`）和 skill 里说的"均值×0.5 关停 / 0.8 降价"边界有错位
7. **审批回复靠 LLM 理解自然语言**：鲁棒性差，应加"结构化快捷回复"兜底（例如飞书按钮）

### 4.3 🟡 P2（优化项）

8. LLM 输出无 schema 校验
9. 干运行模式日志丢失
10. 无单元测试
11. A 类广告（零消耗）在多个环节重复检测
12. 没有异常处理的"完全失败"恢复机制
13. 没有数据新鲜度通知（只有 query_ad_detail 有）
14. 报告排序逻辑复杂且脆弱
15. LLM 的 confidence 字段未被后续环节利用
16. 飞书审批超时处理过于简单
17. API 失败重试无明确的幂等性保证
18. 护栏链对并发决策无保护

---

## 5. 最高 ROI 的完整升级路径

> 本轮只做前 4 步。后面 2 步留给下一轮。

1. ✅ **补 P0 数据字段**（3 个字段写进 metrics）→ LLM 立刻能做衰退判断【本轮】
2. ✅ **加创意级 ROI 聚合** → LLM 能归因"广告差 vs 创意差"【本轮】
3. 🟡 **加趋势 / 斜率字段** → 从"快照决策"升级到"趋势决策"【本轮部分覆盖；完整版留下轮】
4. ✅ **补预算利用率 + 账户级 / 人群包级汇总** → 加入预算目标和同组对比【本轮】
5. ❌ **建反馈环** → 记录"决策 t0 → 结果 t+3d"的 pair，给 LLM 做事后复盘【下轮】
6. ❌ **小时级止损 + 生命周期阶段识别** → 升级到 L3 完整形态【下轮】

### 本轮明确不做（用户已确认）

- ❌ 反馈环（决策效果回流、历史案例库）
- ❌ 小时级数据
- ❌ 大盘对比
- ❌ 开启 EXECUTION_ENABLED（先把决策质量做对）

---

## 6. 下轮议题候选

- **反馈环的存储方式**：SQLite 表 vs JSONL vs 时序数据库
- **小时级数据的拉取频率**：每 15 分钟 vs 每小时 vs 按需
- **大盘对比的范围**：自家多账户 vs 行业（需要第三方数据）
- **生命周期阶段识别**：规则式（天数分段）vs 基于指标曲线的状态机
- **LLM 决策的"置信度"字段**是否用于触发不同审批级别
- **审批流的结构化回复兜底**（飞书 interactive message / button）
- **决策趋势/斜率字段**：roi_slope_3d、roi_slope_7d 的具体算法
- **广告生命周期识别**：天数分段阈值、衰退斜率阈值

---

## 7. 附录：现状快照

### 7.1 已实现的关键能力（截至 2026-04-16）

- ✅ 数据拉取：日级创意数据（ODPS）+ 广告状态（腾讯 API）
- ✅ ROI 计算：f_7日动态ROI 完整公式（T0 裂变 + arpu + 回流倍数 + 裂变效率稳定因子）
- ✅ 决策引擎：A/B/C 三类广告分类 + LLM 智能决策
- ✅ 护栏系统：6 道护栏（冷启动 / 新鲜度 / 出价边界 / 频率 / 日上限 / 干运行）
- ✅ 执行引擎：TokenBucket 限流 + 指数退避重试 + 审计日志
- ✅ IM 审批：飞书阻塞式审批 + 自然语言理解回复
- ✅ 三模工作流：Mode 1 全量分析 / Mode 2 定向操作 / Mode 3 反馈修改
- ✅ 领域知识：专家角色定位 + R 值解读 + 实战 knowhow（上一轮刚补的）

### 7.2 当前 metrics CSV 列（16 列）

```
ad_id, account_id, ad_name, create_time, configured_status, bid_amount, creative_count,
cost_7d_total, revenue_7d_total, cost_7d_avg,
动态ROI, 动态ROI_7日均值,
cost_30d_total, cost_30d_avg, stable_spend_days_30d, ad_age_days
```

### 7.3 本轮升级后预期 metrics CSV 列（约 25 列）

在 7.2 基础上追加：

```
# P0 字段（Phase 1）
bid_increased_7d, creative_changed_7d, audience_tier

# 预算 pacing（Phase 2）
day_amount, budget_utilization_7d, budget_headroom_pct

# 额外（可能衍生）
dominant_creative_id, dominant_creative_cost_share,
audience_tier_roi_baseline_p25, audience_tier_roi_baseline_p75
```

### 7.4 关键代码位置速查

| 功能 | 文件:行号 |
|------|---------|
| 数据拉取 SQL 构建 | `tools/data_query.py:78-217` |
| 创意→广告聚合 | `tools/roi_calculator.py:47-118` |
| f_7日动态ROI 公式 | `tools/roi_calculator.py:123-202` |
| ROI 计算入口 | `tools/roi_calculator.py:320-462` |
| 干预信号计算（待迁移） | `tools/ad_decision.py:400-460` |
| A/B/C 分类 | `tools/ad_decision.py:798-920` |
| apply_decisions 合并 | `tools/ad_decision.py:973-1103` |
| modify_decisions upsert | `tools/ad_decision.py:1240-1461` |
| 6 道护栏实现 | `tools/guardrails.py:190-451` |
| AdjustmentHistory | `tools/guardrails.py:61-140` |
| 护栏链执行 | `tools/guardrails.py:458-547` |
| Tier 分级 | `tools/execution_engine.py:193-223` |
| 执行主逻辑 | `tools/execution_engine.py:230-565` |
| 审批请求发送 | `tools/im_approval.py:270-546` |
| 审批回复解析 | `tools/im_approval.py:248-262` |
| 报告生成 | `tools/report_generator.py:182-256` |
| 决策阈值 config | `config.py:70-97` |
| R 值匹配规则 | `config.py:164-175` |

---

## 文档使用指引

**何时回读此文档？**

- 每轮迭代开始前：确认当前走到哪一步，下一步优先级
- 做决策设计时：回看"业务理解层"的四个心智模型
- 遇到疑难决策时：回看"业务目标层"的主目标 + 约束表达
- 工程加固时：回看"工程实现层"的 18 个缺陷清单

**何时更新此文档？**

- 完成一轮迭代后，在[第 5 节升级路径]里把完成项 `🟡` → `✅`
- 新发现的缺口加进[第 6 节下轮议题]
- 重大认知更新（如业务模型变化）需另起一版
