config.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. """
  2. 广告智能决策引擎配置 — auto_put_ad_mini
  3. 运营可直接修改此文件调整决策参数。
  4. 当前模式:智能判断
  5. - 基于 f_7日动态ROI 的精细化决策
  6. - AI 推理结合领域知识
  7. - 三级分类:零消耗待关停(规则)+ 待优化评估(智能)+ 正常运行(规则)
  8. """
  9. import os
  10. from pathlib import Path
  11. from agent.core.runner import RunConfig, KnowledgeConfig
  12. # 加载 .env 文件(如果存在)
  13. try:
  14. from dotenv import load_dotenv
  15. load_dotenv(Path(__file__).parent / ".env")
  16. except ImportError:
  17. pass
  18. # ═══════════════════════════════════════════
  19. # Agent 运行配置
  20. # ═══════════════════════════════════════════
  21. MAIN_CONFIG = RunConfig(
  22. model="qwen/qwen3.5-plus-02-15",
  23. temperature=0.3,
  24. max_iterations=50,
  25. name="广告智能调控助手",
  26. tools=[
  27. "fetch_creative_data",
  28. "merge_creative_data",
  29. "calculate_roi_metrics",
  30. "calculate_portfolio_summary",
  31. "get_ads_for_review",
  32. "apply_decisions",
  33. "query_ad_detail", # Mode 2: 查询广告详情
  34. "modify_decisions", # Mode 3: 修改已有决策
  35. "validate_decisions",
  36. "generate_report",
  37. # 执行引擎 + IM 审批(已集成阻塞式审批流):
  38. "execute_decisions",
  39. "check_execution_feedback",
  40. "send_approval_request",
  41. "check_approval_status",
  42. "send_feishu_text_message", # 执行后向您同步 diff / 确认 / 质疑回应
  43. # 飞书文档(报告导入 & 分享):
  44. "import_to_feishu",
  45. # 注:曾考虑用内置 "agent" 工具按 tier 并行委托子 Agent,
  46. # 但框架的 agent 工具只返回文本 summary,主 Agent 拿不回结构化决策,
  47. # 会陷入"无法 apply"的死循环。直接在主 Agent 单次输出完成全部 decisions 更可靠。
  48. ],
  49. skills=["ad-domain", "roi-strategy", "guardrail-rules", "tencent-ad-playbook"],
  50. # extra_llm_params={"extra_body": {"enable_thinking": True}}, # 禁用:千问不支持 thinking
  51. knowledge=KnowledgeConfig(
  52. enable_extraction=False,
  53. enable_completion_extraction=False,
  54. enable_injection=False,
  55. owner="ad_mini_team",
  56. ),
  57. )
  58. SKILLS_DIR = str(Path(__file__).parent / "skills")
  59. TRACE_STORE_PATH = ".trace"
  60. LOG_LEVEL = "INFO"
  61. LOG_FILE = None
  62. # ═══════════════════════════════════════════
  63. # V3 数据窗口配置
  64. # ═══════════════════════════════════════════
  65. DATA_WINDOW_DAYS = 7 # 测试阶段:采集 7 天历史数据
  66. ROI_CALCULATION_DAYS = 7 # f_7日动态ROI 计算窗口
  67. # ═══════════════════════════════════════════
  68. # V3 决策阈值(默认值,可被 SKILL 覆盖)
  69. # ═══════════════════════════════════════════
  70. MIN_DAILY_COST = 100 # 日消耗 >= 100元才参与 ROI 计算
  71. MIN_AD_AGE_DAYS = 3 # 广告创建 >= 3天才参与决策(与 min_periods 对齐)
  72. ROI_LOW_FACTOR = 0.75 # f_7日动态ROI < 全体均值 × 0.75 → 关停
  73. NO_SPEND_THRESHOLD = 10 # 7日消耗均值 < 10元 → 关停
  74. STABLE_SPEND_THRESHOLD = 100 # 稳定消耗定义:>100元/天
  75. # ═══════════════════════════════════════════
  76. # 出价调整配置
  77. # ═══════════════════════════════════════════
  78. BID_ADJUSTMENT_ENABLED = True
  79. BID_DOWN_ROI_FACTOR = 0.90 # ROI < 均值×0.90 → 考虑降价(低于渠道均值10%)
  80. BID_UP_ROI_FACTOR = 1.05 # ROI > 均值×1.05 → 考虑提价(高于渠道均值5%)
  81. BID_UP_MAX_SPEND = 1000 # 提价消耗上限:均值消耗<1000才提价(投手经验原文)
  82. BID_CHANGE_MIN_PCT = 0.03 # 最小调幅 3%(兼容旧代码)
  83. BID_CHANGE_MAX_PCT = 0.10 # 最大单次调幅 10%(兼容旧代码)
  84. BID_UP_MIN_PCT = 0.05 # 提价最小幅度 5%
  85. BID_UP_MAX_PCT = 0.10 # 提价最大幅度 10%
  86. BID_DOWN_MIN_PCT = 0.03 # 降价最小幅度 3%
  87. BID_DOWN_MAX_PCT = 0.05 # 降价最大幅度 5%
  88. BID_DOWN_MIN_SPEND = 500 # 降价消耗门槛:7日日均消耗≥500元
  89. BID_FLOOR_YUAN = 0.05 # 出价下限(元)
  90. BID_CEILING_YUAN = 1.00 # 出价上限(元)
  91. # 广告年龄分段(基于决策树图片)
  92. COLD_START_DAYS = 3 # 冷启动期(≤3天):极度保护,几乎不干预
  93. EARLY_GROWTH_DAYS = 7 # 早期成长期(4-7天):可提价放量(满足ROI+消耗条件)
  94. AD_AGE_MATURE = 7 # 成熟期(>7天):全面调控
  95. # 兼容性(已废弃)
  96. AD_AGE_NEWBORN = COLD_START_DAYS # 兼容旧代码
  97. CAUTIOUS_DAYS = EARLY_GROWTH_DAYS # 兼容旧代码
  98. # 高燃烧预警配置
  99. HIGH_BURN_AGE_THRESHOLD = 3 # 广告年龄>3天才检查
  100. HIGH_BURN_COST_THRESHOLD = 300 # 昨日消耗>300元触发预警
  101. ROI_LOW_MIN_YESTERDAY_COST = 300 # 关停消耗门槛:昨日消耗≥300才检查关停(投手经验2.4)
  102. # ═══════════════════════════════════════════
  103. # 安全护栏配置
  104. # ═══════════════════════════════════════════
  105. GUARDRAILS_ENABLED = True
  106. DRY_RUN_MODE = False # 关闭干运行,让护栏正常放行(实际执行由 EXECUTION_ENABLED 控制)
  107. MAX_ADJUSTMENTS_PER_AD_PER_DAY = 2
  108. MIN_ADJUSTMENT_INTERVAL_HOURS = 6
  109. MAX_DAILY_CUMULATIVE_CHANGE_PCT = 0.20 # 日累计调幅上限 20%
  110. MAX_DAILY_OPS = 10000 # 单日最多操作广告数(实际不限制)
  111. DATA_FRESHNESS_MAX_HOURS = 96 # 数据超过 96 小时视为过期(已从48小时放宽至96小时)
  112. # ═══════════════════════════════════════════
  113. # 执行引擎配置
  114. # ═══════════════════════════════════════════
  115. EXECUTION_ENABLED = False # 主开关!False = 只验证不执行
  116. API_QPS_LIMIT = 8 # 保守QPS(平台上限10)
  117. API_MAX_RETRIES = 3
  118. TIER1_MAX_CHANGE_PCT = 0.00 # Tier1自动执行已禁用(改为0%,所有操作都需审批)
  119. TIER3_MIN_DAILY_SPEND = 1500 # 高价值广告门槛(元/天)
  120. FEEDBACK_CHECK_HOURS = 6
  121. # ═══════════════════════════════════════════
  122. # IM 审批配置(飞书直连)
  123. # ═══════════════════════════════════════════
  124. IM_ENABLED = True # IM 主开关(True 时审批消息发飞书)
  125. IM_APPROVAL_TIMEOUT_MINUTES = 30 # 审批超时(分钟)
  126. IM_APPROVAL_POLL_INTERVAL_SECONDS = 30 # 审批轮询间隔(秒)
  127. # 飞书应用凭据("增长投放"机器人)— 优先从环境变量读取
  128. FEISHU_APP_ID = os.getenv("FEISHU_APP_ID", "cli_a955e97067f85cb3")
  129. FEISHU_APP_SECRET = os.getenv("FEISHU_APP_SECRET", "NQaG4ci1plXRDTgwCqrLJgMLLoA2tdF8")
  130. # 运营审批人飞书信息
  131. FEISHU_OPERATOR_OPEN_ID = os.getenv("FEISHU_OPERATOR_OPEN_ID", "ou_498988d823b61ab89c9afe4310f85bb4")
  132. FEISHU_OPERATOR_CHAT_ID = os.getenv("FEISHU_OPERATOR_CHAT_ID", "oc_88e0a1970a7de02eb5ac225a8b0cedea")
  133. # 投放项目群聊 — 用于接收决策结果通知和审批回复
  134. # 置空则不发送到群,仅发送到个人
  135. FEISHU_AD_PROJECT_CHAT_ID = os.getenv("FEISHU_AD_PROJECT_CHAT_ID", "")
  136. # 腾讯广告默认账户(测试账户)
  137. TENCENT_AD_ACCOUNT_ID = int(os.getenv("TENCENT_AD_ACCOUNT_ID", "80769799"))
  138. # ═══════════════════════════════════════════
  139. # 输出路径配置
  140. # ═══════════════════════════════════════════
  141. OUTPUTS_DIR = Path(__file__).parent / "outputs"
  142. RAW_DATA_DIR = OUTPUTS_DIR / "raw" # 创意级原始 CSV
  143. AD_STATUS_DIR = OUTPUTS_DIR / "ad_status" # 广告状态 CSV
  144. REPORTS_DIR = OUTPUTS_DIR / "reports" # 决策报告
  145. EXECUTION_LOG_DIR = OUTPUTS_DIR / "execution_log" # 执行审计日志
  146. DATA_DIR = OUTPUTS_DIR / "data" # 运行时数据(如调整历史)
  147. ADJUSTMENT_HISTORY_PATH = DATA_DIR / "adjustment_history.json"
  148. # ═══════════════════════════════════════════
  149. # 人群包系数(保留,用于展示)
  150. # ═══════════════════════════════════════════
  151. AUDIENCE_COEFFICIENTS = {
  152. "R500": 3.0,
  153. "R330+": 2.5,
  154. "R330": 2.0,
  155. "R180": 1.5,
  156. "R100": 1.2,
  157. "R50": 1.0,
  158. "R10": 1.0,
  159. "R2": 1.0,
  160. "default": 1.0,
  161. }
  162. # 从广告名称提取 R 值的匹配顺序
  163. AUDIENCE_TIER_PATTERNS = [
  164. ("R500", ["R500", "R_500", "r500"]),
  165. ("R330+", ["回流330+", "回流330+-", "回流q330", "330+全品类", "R330+", "R_330+"]),
  166. ("R330", ["回流330", "R330", "R_330", "定向330", "r330", "r300"]),
  167. ("R180", ["回流180", "R180", "R_180", "定向180", "r180",
  168. "r180-330", "r180-300", "R100-180", "R_100-180", "r100-180"]),
  169. ("R100", ["回流100", "R100", "R_100", "定向100", "r100", "R50-100"]),
  170. ("R50", ["回流50", "R50", "R_50", "r50"]),
  171. ("R10", ["R_10", "R10", "r10"]),
  172. ("R2", ["R_2", "R2", "r2"]),
  173. ]