# auto_put_ad_mini — 智能投放 Agent 架构全解析 > 基于 Reson Agent 框架的腾讯广告智能调控系统 > 数据驱动 + AI推理 + 安全护栏 + 自然语言审批 --- ## 📐 架构总览 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 用户/运营人员 │ │ "分析广告" | "广告XXX降价10%" | "不要暂停" │ └───────────────────────────────┬─────────────────────────────────┘ │ ┌──────────▼──────────┐ │ Agent运行引擎 │ │ (AgentRunner) │ │ │ │ • LLM调用 (qwen) │ │ • 工具注册/调用 │ │ • Skill加载 │ │ • 轨迹追踪 │ └──────────┬──────────┘ │ ┌─────────────────────┼─────────────────────┐ │ │ │ ┌───────▼────────┐ ┌────────▼────────┐ ┌───────▼────────┐ │ system.prompt │ │ Skills/知识库 │ │ Tools/工具集 │ │ ─────────────│ │ ───────────── │ │ ───────────── │ │ • Mode路由 │ │ roi-strategy.md │ │ data_query.py │ │ • 决策流程 │ │ guardrail_rules │ │ roi_calculator │ │ • 审批逻辑 │ │ ad_domain.md │ │ ad_decision │ │ • 错误处理 │ │ (领域知识注入) │ │ guardrails │ └────────────────┘ └─────────────────┘ │ execution_engine│ │ im_approval │ │ report_generator│ └────────────────┘ │ ┌────────────────────────────────┼────────────┐ │ │ │ ┌────────▼─────────┐ ┌───────────▼──────────┐ │ │ 数据层 (ODPS) │ │ 外部服务集成 │ │ │ ───────────── │ │ ────────────── │ │ │ • 创意数据 │ │ • 飞书机器人 │ │ │ • 广告状态 │ │ • 腾讯广告 API │ │ │ • Merged数据 │ │ (分级执行+回调) │ │ └──────────────────┘ └─────────────────────┘ │ │ ┌────────────────────────────────────────────┘ │ ┌────────▼────────┐ │ 持久化存储 │ │ ───────────── │ │ • metrics_*.csv│ │ • decisions_* │ │ • reports_* │ │ • 调整历史记录 │ └─────────────────┘ ``` --- ## 🔄 完整执行流程详解 ### Mode 1: 全量分析工作流(主流程) 用户说 **"分析广告"** 时触发,执行以下步骤: #### 第1步:数据拉取 (`fetch_creative_data`) ```python # 工具: examples/auto_put_ad_mini/tools/data_query.py 输入: days=7 (拉取最近7天) 处理: 1. 检查本地已有数据(跳过重复拉取) 2. 对于缺失日期,从ODPS拉取创意级数据 3. 同时拉取广告状态数据 (ad_status) 输出: - outputs/raw/creative_YYYYMMDD.csv (每日创意数据) - outputs/ad_status/ad_status_YYYYMMDD.csv (每日广告状态) 数据特点: • 创意级粒度 (一个广告有多个创意) • 包含ROI计算必需字段: cost, open_count, fission0_count, total_revenue, etc. ``` #### 第2步:数据合并 (`merge_creative_data`) ```python # 将创意数据 + 广告状态 合并 输入: days=7 处理: 1. 读取 creative_YYYYMMDD.csv 2. 读取 ad_status_YYYYMMDD.csv 3. LEFT JOIN (创意 + 广告状态) 输出: - outputs/merged/merged_YYYYMMDD.csv 字段包括: • ad_id, creative_id, account_id, ad_name • cost, view_count, click_count • open_count, fission0_count, total_return_count, total_revenue • bid_amount, configured_status, create_time ``` #### 第3步:ROI计算 (`calculate_roi_metrics`) ```python # 工具: examples/auto_put_ad_mini/tools/roi_calculator.py 输入: end_date="20260415" (默认yesterday) 处理: 1. 加载最近30天的 merged 数据(容错缺失) 2. 聚合到广告级 (GROUP BY ad_id, date) 3. 计算 f_7日动态ROI (考虑裂变效率稳定性) 4. 计算 7日汇总 (cost_7d_avg, revenue_7d_total) 5. 计算 30日汇总 (stable_spend_days_30d) 核心公式: T0裂变系数 = fission0_count / open_count arpu = total_revenue / total_return_count 当日裂变收益率 = fission0_count * arpu / cost 当日回流倍数 = total_return_count / open_count 裂变效率稳定因子 = 回流倍数_7日均值 / T0裂变系数_7日均值 f_7日动态ROI = 当日裂变收益率 * 裂变效率稳定因子 输出: - outputs/metrics_20260415.csv (1570行, 每个广告一行) 关键指标: • 动态ROI (单日值) • 动态ROI_7日均值 (决策参考值!) • cost_7d_avg, cost_7d_total • ad_age_days (广告年龄) ``` #### 第4步:广告分类 (`get_ads_for_review`) ```python # 工具: examples/auto_put_ad_mini/tools/ad_decision.py 输入: metrics_csv (步骤3输出) 处理: 1. 计算全体 ROI 分布 (mean, p25, p50, p75, p90) 2. 检测衰退信号 (提价、换创意、消耗下降) 3. 分为 A/B/C 三类: A类 (极端差, 自动关停): • 7日均消耗 < 1元 (几乎零活动) B类 (边缘, 需AI推理): • ROI < 全体均值 × 0.8 (偏低) • 或检测到衰退信号 C类 (正常, 自动保持): • 其余广告 输出: JSON结构化数据 { "summary": {total, class_a, class_b, class_c}, "distribution": {roi_mean, p25, p50, p75, p90}, "bid_adjustment": {bid_down_line, bid_up_line}, "class_a": [...], # 自动关停列表 "class_b": [...], # 需要推理的广告(含详细指标) "class_c_summary": {...} } ``` #### 第5步:AI推理决策 (Agent自主推理) ```python # Agent读取B类广告数据 + roi-strategy.md技能 # 对每个广告进行推理,输出决策JSON 决策逻辑框架: IF ad_age_days < 4天: → hold (冷启动绝对保护) ELIF ad_age_days < 7天: → 仅允许小幅降价 ≤5% (谨慎期) ELIF ROI < 全体均值 × 0.5: → pause (极低ROI, 关停) ELIF ROI < 全体均值 × 0.8 AND cost_7d_avg ≥ 100元: → bid_down -3%~-10% (降价, 越接近关停线降幅越大) ELIF ROI > 全体均值 × 1.2 AND cost_7d_avg < 中位数 × 0.5: → bid_up +3%~-10% (高ROI低消耗, 提价放量) ELSE: → hold (保持) 输出格式: [ { "ad_id": 90289631207, "action": "pause", "dimension": "ROI过低", "reason": "f_7日动态ROI=1.18 < 均值3.29×0.5=1.64, 日消耗1524元, 持续亏损", "confidence": "high" }, { "ad_id": 32912382309, "action": "bid_down", "dimension": "ROI偏低-降价", "reason": "动态ROI_7日均值=1.81 < 均值3.29×0.8=2.63, 建议降8%至0.30元", "confidence": "medium", "recommended_change_pct": -0.08 }, ... ] ``` #### 第6步:保存决策 (`apply_decisions`) ```python # 工具: examples/auto_put_ad_mini/tools/ad_decision.py 输入: decisions (AI推理的JSON) + metrics_csv 处理: 1. 解析AI输出的JSON 2. 合并 A类自动关停 + B类AI决策 + C类自动保持 3. 过滤已暂停广告 (AD_STATUS_SUSPEND) 4. 计算出价变更(current_bid × (1 + recommended_change_pct)) 输出: - outputs/reports/llm_decisions_20260415.csv 字段: ad_id, action, dimension, reason, confidence, recommended_change_pct, current_bid, recommended_bid, ad_age_days ``` #### 第7步:安全护栏验证 (`validate_decisions`) ```python # 工具: examples/auto_put_ad_mini/tools/guardrails.py 输入: llm_decisions_20260415.csv 处理: 逐条检查6道护栏 护栏1: 数据新鲜度 IF 数据年龄 > 48小时: → Block所有非hold操作 护栏2: 冷启动保护 IF ad_age_days < 4天: → Block所有pause/bid_down IF ad_age_days < 7天: → bid_down限制 ≤5% 护栏3: 出价边界 IF recommended_bid < 0.5元: → Modified (钳位到0.5元) IF recommended_bid > 200元: → Modified (钳位到200元) 护栏4: 频率限制 IF 今日已调整次数 ≥ 2: → Block IF 距上次调整 < 6小时: → Block IF 今日累计调幅 > 20%: → Block 护栏5: 每日操作上限 IF 今日已操作广告数 ≥ 200: → 按ROI严重度排序, Block低优先级 护栏6: 干运行模式 IF DRY_RUN_MODE = True: → 所有操作标记dry_run (Modified) 输出: - outputs/reports/validated_decisions_20260415.csv 新增字段: guardrail_status: approved | modified | blocked guardrail_reason: 拦截原因说明 final_action: 护栏处理后的最终动作 final_bid: 护栏处理后的最终出价 ``` #### 第8步:飞书审批请求 (`send_approval_request`) ```python # 工具: examples/auto_put_ad_mini/tools/im_approval.py # ⚠️ 仅当有通过护栏的非hold操作时才调用 输入: wait_for_reply=True (阻塞等待审批) 处理: 1. 读取 validated_decisions (guardrail_status=approved) 2. 按风险分级: Tier 1 (≤5%调幅): 仅通知, 不需审批 Tier 2 (pause, bid_down>5%): 需审批 Tier 3 (日消耗>1500元): 强制审批 3. 构造飞书消息 (卡片式, 带数据表格) 4. 发送到飞书群组 (FEISHU_OPERATOR_CHAT_ID) 5. 阻塞等待运营回复 (轮询检查, 超时30分钟) 飞书消息格式: 【广告调控审批】2026-04-15 📊 决策摘要 • 总决策数: 38个 • Tier 1 (自动): 10个 (小幅调价 ≤5%) • Tier 2 (需审批): 20个 (暂停/降价>5%) • Tier 3 (高价值): 8个 (日消耗>1500元) 🔻 高风险广告 (需审批) 1. 广告90289631207: ROI=1.18, 消耗=1524元/天 → 暂停 2. 广告37429627354: ROI=2.37, 消耗=1228元/天 → 降价5% ... ⏰ 请在30分钟内回复: - "批准" / "通过" → 全部批准 - "拒绝" / "取消" → 全部拒绝 - "广告XXX不要暂停" → 修改特定决策 审批结果: - approved_decisions: 通过的决策列表 - rejected_decisions: 拒绝的决策列表 - modified_decisions: 修改后的决策列表 ``` **自然语言审批理解 (关键特性):** ```python # Agent具备自然语言理解能力, 可以处理灵活的人类指令 运营说: "批准" → 解析为: 全部批准 运营说: "广告90289631207不要暂停, 改为降价10%" → 解析为: modify_decisions([ {"ad_id": 90289631207, "new_action": "bid_down", "new_change_pct": -0.10} ]) → 重新validate → 重新发审批 运营说: "只批准降价的, 暂停的全部拒绝" → 解析为: 过滤 action=bid_down → approved 过滤 action=pause → rejected 运营说: "为什么要暂停广告90289631207?" → Agent回答: "该广告f_7日动态ROI=1.18 < 关停线1.64,日消耗1524元, 已持续亏损,建议暂停止损" → 等待运营最终确认 ``` #### 第9步:执行决策 (`execute_decisions`) ```python # 工具: examples/auto_put_ad_mini/tools/execution_engine.py # ⚠️ 仅在运营审批通过后调用 输入: 运营审批通过的决策列表 处理: 1. 分批执行 (QPS限制=8, 批次大小=50) 2. 根据action调用腾讯广告API: • pause → /v3.0/adgroups/update (configured_status=SUSPEND) • bid_down/bid_up → /v3.0/adgroups/update (bid_amount=final_bid) 3. 错误处理 + 重试 (最多3次) 4. 记录执行日志 输出: - outputs/execution_log/execution_20260415.json 执行结果: { "timestamp": "2026-04-15 14:30:00", "total": 38, "success": 36, "failed": 2, "details": [ { "ad_id": 90289631207, "action": "pause", "status": "success", "api_response": {...} }, { "ad_id": 32912382309, "action": "bid_down", "status": "failed", "error": "API限流, 重试后成功" } ] } ``` #### 第10步:生成报告 (`generate_report`) ```python # 工具: examples/auto_put_ad_mini/tools/report_generator.py 输入: validated_decisions_20260415.csv 处理: 1. 汇总统计 (总数, pause/bid_down/hold分布) 2. 按ROI严重度排序 3. 生成Excel (带条件格式、颜色标注) 输出: - outputs/reports/decision_20260415.csv (纯数据) - outputs/reports/decision_20260415.xlsx (带格式) Excel样式: • 绿色: ROI优秀 (>均值×1.2) • 黄色: ROI偏低 (均值×0.5~0.8) • 红色: ROI极低 (<均值×0.5) • 冻结首行, 自动筛选 ``` --- ### Mode 2: 定向操作工作流 用户提及 **具体广告ID + 操作意图** 时触发(如 "广告90289631207降价10%"): ``` 1. query_ad_detail(ad_id) → 查询当前数据+全局上下文 2. AI推理 → 根据用户意图+当前状态生成决策JSON 3. modify_decisions() / apply_decisions() → 保存决策 (upsert模式) 4. validate_decisions() → 护栏验证 5. send_approval_request() → IM发给运营确认 6. execute_decisions() → 执行 ``` --- ### Mode 3: 反馈修改工作流 用户对已有决策提出修改意见时触发(如 "广告XXX不要暂停"): ``` 1. modify_decisions(modifications) → 修改指定条目 支持: • 精确修改: [{"ad_id": "XXX", "new_action": "bid_down", "new_change_pct": -0.05}] • 批量修改: [{"filter": "all_pause", "new_action": "hold"}] 2. validate_decisions() → 重新验证 3. send_approval_request() → 重新发IM 4. execute_decisions() → 执行 ``` --- ## 🛡️ 安全护栏系统详解 护栏是整个系统的**核心安全机制**,防止AI做出错误决策。 ### 护栏1: 数据新鲜度检查 ```python 规则: IF (当前时间 - 数据时间) > 48小时: → Block所有非hold操作 原因: • 广告数据实时性强, 过期数据会导致错误决策 • 超过48小时的数据已失去参考价值 示例: 数据: 20260415 (58小时前) 当前: 20260417 10:26 → Block所有pause/bid_down, 转为hold ``` ### 护栏2: 冷启动保护 ```python 规则: IF ad_age_days < 4天: → Block所有负向操作 (pause, bid_down) IF 4天 ≤ ad_age_days < 7天: → pause仍然Block → bid_down限制最大降幅5% 原因: • 新广告需要时间学习用户画像 • 初始出价通常比目标CPA高20%, 需等系统优化 • 过早干预会打断学习过程 示例: 广告90289631207: ad_age_days=5天, AI建议pause → Block (谨慎期不允许暂停) → 转为hold ``` ### 护栏3: 出价边界 ```python 规则: IF recommended_bid < 0.5元: → Modified (钳位到0.5元) IF recommended_bid > 200元: → Modified (钳位到200元) 原因: • 低于0.5元竞争力不足, 无法获得曝光 • 高于200元风险过高, 可能是计算错误 示例: AI建议: bid_down -50%, current_bid=0.8元 → recommended_bid=0.4元 → Modified: final_bid=0.5元 ``` ### 护栏4: 频率限制 ```python 规则: IF 今日已对该广告调整次数 ≥ 2: → Block IF 距上次调整时间 < 6小时: → Block IF 今日累计调幅 > 20%: → Block 原因: • 频繁调整会触发平台模型重学习 • 超过10%单次调幅会导致流量崩塌 • 需要给系统足够时间反馈效果 示例: 广告32912382309: 今日已降价1次 (-5%), 距离上次调整3小时 AI再次建议降价 (-3%) → Block (间隔不足6小时) ``` ### 护栏5: 每日操作上限 ```python 规则: IF 今日已操作广告数 ≥ 200: → 按ROI严重度排序 → Block低优先级广告 原因: • 避免一次性大规模调整 • 分散风险, 逐步优化 优先级: 1. pause (极低ROI, 持续亏损) 2. bid_down (ROI接近关停线) 3. bid_up (高ROI低消耗) ``` ### 护栏6: 干运行模式 ```python 规则: IF DRY_RUN_MODE = True: → 所有操作标记dry_run → 不实际调用API 用途: • 测试阶段验证决策逻辑 • 模拟执行, 查看效果预测 ``` --- ## 🔌 外部服务集成 ### 1. 腾讯广告 API v3.0 **Token管理 (动态获取):** ```python # tools/ad_api.py def _get_access_token(account_id): """ 优先从内部API获取 (30分钟缓存) 失败时降级使用 .env 静态token """ url = f"https://api.piaoquantv.com/ad/put/tencent/getAccessToken?accountId={account_id}" response = requests.get(url) if response.ok: return response.json()["data"]["accessToken"] else: return os.getenv("TENCENT_AD_ACCESS_TOKEN") ``` **广告操作API:** ```python # 暂停广告 POST /v3.0/adgroups/update { "account_id": 80769799, "adgroup_id": 90289631207, "configured_status": "AD_STATUS_SUSPEND" } # 修改出价 POST /v3.0/adgroups/update { "account_id": 80769799, "adgroup_id": 32912382309, "bid_amount": 30 # 单位: 分 (0.30元) } ``` ### 2. 飞书机器人 **应用信息:** ```python APP_ID = "cli_a955e97067f85cb3" APP_SECRET = "NQaG4ci1plXRDTgwCqrLJgMLLoA2tdF8" OPERATOR_OPEN_ID = "ou_498988d823b61ab89c9afe4310f85bb4" CHAT_ID = "oc_88e0a1970a7de02eb5ac225a8b0cedea" ``` **消息发送:** ```python # 卡片式消息 POST https://open.feishu.cn/open-api/im/v1/messages { "receive_id": CHAT_ID, "msg_type": "interactive", "content": { "config": {"wide_screen_mode": true}, "header": { "title": {"tag": "plain_text", "content": "【广告调控审批】"} }, "elements": [ {"tag": "markdown", "content": "**决策摘要**\n..."}, {"tag": "hr"}, {"tag": "action", "actions": [ {"tag": "button", "text": "批准", "type": "primary"}, {"tag": "button", "text": "拒绝", "type": "danger"} ]} ] } } ``` **审批轮询:** ```python # 每30秒检查一次运营回复 while not timeout: messages = get_chat_history(CHAT_ID) for msg in messages: if msg.sender == OPERATOR_OPEN_ID: # 自然语言理解运营意图 intent = parse_approval_intent(msg.content) if intent.type == "approve": return ApprovalResult(approved=True) elif intent.type == "modify": return ApprovalResult(modified=intent.modifications) ``` ### 3. ODPS (数据源) **数据拉取:** ```python # tools/data_query.py def _fetch_from_odps(bizdate, account_id): """ 从MaxCompute (ODPS)拉取创意数据 """ sql = f""" SELECT bizdate, ad_id, creative_id, ad_name, cost, open_count, fission0_count, total_return_count, total_revenue, view_count, valid_click_count, conversions_count FROM creative_data_table WHERE bizdate = {bizdate} AND account_id = {account_id} """ odps_client = ODPSClient(project="loghubods") df = odps_client.query_to_dataframe(sql) return df ``` --- ## 📊 数据流转全景 ``` [ODPS数据仓库] ↓ creative_data (创意级, 每日2.5MB) ↓ [data_query.py] fetch_creative_data ↓ outputs/raw/creative_YYYYMMDD.csv (原始创意数据) ↓ [data_query.py] merge_creative_data ↓ outputs/merged/merged_YYYYMMDD.csv (创意+广告状态合并) ↓ [roi_calculator.py] calculate_roi_metrics • 加载最近30天 merged 数据 • 聚合到广告级 (GROUP BY ad_id, date) • 计算 f_7日动态ROI • 计算 7日/30日汇总指标 ↓ outputs/metrics_20260415.csv (1570行广告级指标) ↓ [ad_decision.py] get_ads_for_review • 计算全体ROI分布 • 检测衰退信号 • 分类 A/B/C ↓ JSON结构化数据 (发给AI) ↓ [Agent AI推理] 52个B类广告逐个分析 ↓ decisions JSON (AI输出) ↓ [ad_decision.py] apply_decisions • 合并A/B/C类决策 • 过滤已暂停广告 • 计算出价变更 ↓ outputs/reports/llm_decisions_20260415.csv (613条决策) ↓ [guardrails.py] validate_decisions • 6道护栏逐条检查 • 拦截/修正/通过 ↓ outputs/reports/validated_decisions_20260415.csv (带护栏状态) ↓ [im_approval.py] send_approval_request • 过滤 approved 决策 • 分级 (Tier 1/2/3) • 发送飞书卡片 • 阻塞等待审批 ↓ [运营审批] 自然语言回复 ↓ [execution_engine.py] execute_decisions • 调用腾讯广告API • 记录执行日志 ↓ outputs/execution_log/execution_20260415.json (执行结果) ↓ [report_generator.py] generate_report • 汇总统计 • Excel美化 ↓ outputs/reports/decision_20260415.xlsx (最终报告) ``` --- ## 🎯 关键设计亮点 ### 1. 智能引擎 vs 规则引擎 ```python # config.py USE_RULE_ENGINE = False # 规则引擎 (固定阈值, 快速) USE_AI_ENGINE = True # 智能引擎 (AI推理, 灵活) 优劣对比: 规则引擎: ✅ 速度快 (秒级) ✅ 可解释性强 ❌ 无法处理复杂场景 ❌ 阈值需人工调整 智能引擎: ✅ 自适应 (动态阈值) ✅ 处理复杂因果关系 (ROI+消耗+趋势) ✅ 自然语言交互 ❌ 速度较慢 (分钟级) ❌ 需要LLM调用成本 ``` ### 2. 分级执行策略 ```python # 风险分层审批, 平衡效率与安全 Tier 1 (自动执行, 无需审批): • 出价调整 ≤ 5% • 日消耗 < 500元 → 实时生效, 仅通知运营 Tier 2 (需审批): • pause • bid_down > 5% • bid_up > 5% → 发飞书等待审批 Tier 3 (强制审批): • 日消耗 > 1500元 (高价值广告) • 出价调整 > 10% (高风险操作) → 运营必须回复 ``` ### 3. 自然语言审批 ```python # 打破传统"批准/拒绝"二元模式 # Agent理解运营的自然语言指令, 灵活调整 示例1: 运营: "广告90289631207改为降价5%, 不要暂停" → modify_decisions([{ "ad_id": 90289631207, "new_action": "bid_down", "new_change_pct": -0.05 }]) → validate → 重新发审批 示例2: 运营: "ROI低于1.5的全部暂停, 其他批准" → filter decisions where ROI < 1.5 → pause → filter decisions where ROI >= 1.5 → approved → execute 示例3: 运营: "这个广告为什么要暂停? 我觉得还有机会" → Agent解释: "该广告ROI=1.18, 低于关停线1.64, 已持续23天消耗 1524元/天, 总亏损>1万元, 建议暂停止损" → 运营: "那降价20%试试" → Agent: "降价20%超过单次调幅上限10%, 已调整为-10%" → modify_decisions → 重新验证 → 执行 ``` ### 4. 闭环反馈机制 ```python # 执行后6小时检查效果, 持续优化 [execution_engine.py] execute_decisions → 记录执行时间戳 ↓ [execution_engine.py] check_execution_feedback (6小时后) → 拉取最新数据 → 对比执行前后ROI变化 → 计算决策准确率 ↓ 决策准确率统计: • pause正确率: 95% (暂停后ROI无改善) • bid_down正确率: 80% (降价后ROI提升) • bid_up正确率: 70% (提价后收入增长) ↓ 反馈到下次决策: • 调整阈值 (如ROI关停线从0.5→0.6) • 优化调幅策略 (如降价步长从-8%→-10%) ``` ### 5. 容错与降级 ```python # 多层级容错机制 数据层: • ODPS拉取失败 → 使用本地缓存 • merged数据缺失 → 跳过缺失日期, 使用可用数据 API层: • 腾讯广告API限流 → 自动重试 (指数退避) • Token过期 → 自动刷新 审批层: • 飞书审批超时 (30分钟) → 自动取消, 保留决策供下次执行 • 网络错误 → 降级为邮件审批 ``` --- ## 📈 性能优化 ### 1. 数据加载优化 ```python # 避免重复拉取数据 def fetch_creative_data(days=7): for i in range(days): date = (today - timedelta(days=i)).strftime("%Y%m%d") csv_path = RAW_DIR / f"creative_{date}.csv" if csv_path.exists() and csv_path.stat().st_size > 1000: logger.info(f"跳过已有数据: {date}") continue # 跳过已存在的数据 # 仅拉取缺失数据 df = _fetch_from_odps(date, account_id) df.to_csv(csv_path) ``` ### 2. ROI计算缓存 ```python # 增量计算, 避免重复处理 metrics_cache = {} def calculate_roi_metrics(end_date): cache_key = end_date if cache_key in metrics_cache: return metrics_cache[cache_key] # 计算新数据 result = _do_calculation(end_date) metrics_cache[cache_key] = result return result ``` ### 3. API批量调用 ```python # 减少网络往返 # ❌ 逐个调用 (慢) for decision in decisions: update_ad(decision.ad_id, decision.final_bid) # ✅ 批量调用 (快) batch_update_ads([ {"adgroup_id": d.ad_id, "bid_amount": d.final_bid} for d in decisions ]) ``` --- ## 🚀 未来扩展方向 ### 1. 接入完整 auto_put_ad 体系 ``` auto_put_ad_mini (当前) → auto_put_ad (完整版) ┌───────────────────┐ ┌─────────────────────────────┐ │ 监控调控 Agent │ 接入 │ 受众策略 Agent │ │ • ROI分析 │ ───────→ │ 创意策略 Agent │ │ • 出价调整 │ │ 预算策略 Agent │ │ • 广告暂停 │ │ ★ 监控调控 Agent (mini升级) │ └───────────────────┘ │ 数据分析 Agent │ │ 系统运维 Agent │ │ 自学习/反馈环 │ └─────────────────────────────┘ ``` ### 2. 机器学习增强决策 ```python # 训练预测模型 from sklearn.ensemble import RandomForestRegressor # 特征工程 features = [ "cost_7d_avg", "roi_7d_avg", "ad_age_days", "bid_amount", "audience_tier", "creative_count", "cost_trend", "roi_trend" ] # 训练目标: 预测未来7天ROI model = RandomForestRegressor() model.fit(X_train[features], y_train["future_7d_roi"]) # 决策辅助 future_roi_if_bid_down = model.predict(current_features + [-0.10]) if future_roi_if_bid_down > current_roi: recommend("bid_down", -0.10) ``` ### 3. A/B测试框架 ```python # 对比不同策略效果 def ab_test_bid_strategy(): """ 将广告随机分为A/B组 A组: 激进策略 (降幅10%) B组: 保守策略 (降幅5%) """ group_a = random.sample(low_roi_ads, 20) group_b = random.sample(low_roi_ads, 20) execute_decisions(group_a, bid_change_pct=-0.10) execute_decisions(group_b, bid_change_pct=-0.05) # 7天后对比 roi_improvement_a = compare_roi(group_a, after=7) roi_improvement_b = compare_roi(group_b, after=7) if roi_improvement_a > roi_improvement_b: adopt_strategy("aggressive") ``` ### 4. 多目标优化 ```python # 当前: 单一优化ROI # 未来: 多目标优化 (ROI + Volume + Risk) from scipy.optimize import minimize def objective(bid): roi = predict_roi(bid) volume = predict_volume(bid) risk = calculate_risk(bid) # 加权目标函数 return -1 * ( 0.5 * roi + # 50%权重: ROI 0.3 * volume + # 30%权重: 规模 -0.2 * risk # 20%权重: 风险(负向) ) optimal_bid = minimize(objective, x0=current_bid) ``` --- ## 🔧 故障排查指南 ### 常见问题1: 数据拉取失败 ```bash # 症状 ERROR - fetch_creative_data失败: No columns to parse from file # 原因 • ODPS查询返回空结果 • 网络连接失败 • Token过期 # 解决 1. 检查ODPS连接: odps_client.test_connection() 2. 检查Token有效性: _get_access_token(account_id) 3. 查看空文件: ls -lh outputs/raw/*.csv | grep "4B" 4. 删除空文件: rm outputs/raw/creative_20260416.csv 5. 重新拉取: python3 execute_once.py ``` ### 常见问题2: 护栏拦截所有决策 ```bash # 症状 护栏验证: blocked 599个, approved 1个 原因: [数据新鲜度] 数据已过期(58小时前,上限48小时) # 原因 使用了过期数据 (20260415), 超过48小时新鲜度上限 # 解决 1. 拉取最新数据: fetch_creative_data(days=2) 2. 计算最新ROI: calculate_roi_metrics(end_date="yesterday") 3. 重新分析: execute_once.py ``` ### 常见问题3: 飞书审批未触发 ```bash # 症状 流程执行完成, 但没有发送飞书消息 # 原因 • 所有决策被护栏拦截 → 无需审批 • EXECUTION_ENABLED=False → 不执行操作 • 飞书Token过期 # 检查 1. 查看validated_decisions: guardrail_status列是否全是blocked 2. 检查config.py: EXECUTION_ENABLED = True 3. 测试飞书API: send_test_message() ``` ### 常见问题4: AI推理偏保守 ```bash # 症状 52个B类广告, AI只建议暂停2个, 其余全hold # 原因 • ROI阈值设置过严格 • 置信度要求过高 # 调整 1. 降低关停线: ROI_LOW_FACTOR = 0.5 → 0.6 (config.py) 2. 修改Skill提示: "对置信度medium的也可以暂停" (roi-strategy.md) 3. 增加样本: 提供历史决策案例供AI参考 ``` --- ## 📚 文件结构总览 ``` examples/auto_put_ad_mini/ ├── run.py # 交互式运行入口 (支持多轮对话) ├── execute_once.py # 单次执行入口 (自动化运行) ├── config.py # 核心配置 (阈值、开关、API凭据) ├── presets.json # 预设参数 ├── .env # 环境变量 (Token、密钥) │ ├── prompts/ │ └── system.prompt # Agent系统提示词 (模式路由、决策流程) │ ├── skills/ │ ├── roi_strategy.md # ROI决策框架 (注入给AI的领域知识) │ ├── guardrail_rules.md # 护栏规则说明 │ └── ad_domain.md # 广告领域知识 (腾讯广告API、营销概念) │ ├── tools/ │ ├── data_query.py # 数据拉取+合并 (ODPS → CSV) │ ├── roi_calculator.py # ROI计算 (f_7日动态ROI核心算法) │ ├── ad_decision.py # 决策引擎 (A/B/C分类 + AI决策保存) │ ├── guardrails.py # 安全护栏 (6道检查) │ ├── execution_engine.py # 执行引擎 (调用腾讯广告API) │ ├── im_approval.py # 飞书审批 (阻塞式自然语言审批) │ ├── report_generator.py # 报告生成 (Excel美化) │ ├── feishu_doc.py # 飞书文档导入 (可选) │ └── ad_api.py # 腾讯广告API封装 (底层调用) │ └── outputs/ ├── raw/ # 原始数据 (creative_*.csv, ad_status_*.csv) ├── merged/ # 合并数据 (merged_*.csv) ├── ad_status/ # 广告状态快照 ├── reports/ # 决策报告 │ ├── llm_decisions_*.csv # AI原始决策 │ ├── validated_decisions_*.csv # 护栏验证后 │ ├── decision_*.csv # 最终决策(CSV) │ └── decision_*.xlsx # 最终决策(Excel) ├── execution_log/ # 执行审计日志 ├── data/ │ └── adjustment_history.json # 调整历史记录 └── metrics_*.csv # 广告级ROI指标 (核心数据) ``` --- ## ✅ 总结 auto_put_ad_mini 是一个**生产级的智能广告调控系统**,具备: 1. **智能决策**: AI推理 + 领域知识 + 数据驱动 2. **安全保障**: 6道护栏 + 分级审批 + 容错降级 3. **灵活交互**: 自然语言审批 + 3种模式 + 实时修正 4. **可扩展性**: 双引擎架构 + 模块化设计 + 闭环反馈 **当前状态**: 可独立运行,完成"数据→决策→执行"闭环 **未来定位**: 接入完整auto_put_ad体系,成为监控调控Agent核心 --- **文档版本**: v1.0 **最后更新**: 2026-04-17 **作者**: Claude Sonnet 4.5