Просмотр исходного кода

fix(approval): 前置 FEISHU_EXCLUDE_ACTIONS 过滤,消息和表格保持一致

send_approval_request() 中 FEISHU_EXCLUDE_ACTIONS={hold,observe,scale_up,
bid_up} 的过滤位于 tier 分类之后,导致消息用未过滤的 df_tier2_3,表格
用过滤后的 df_filtered,实测下飞书消息显示"共 32 条决策需您审批"但
打开表格只见 28 条,操作员困惑。

把过滤前置到 tier 分类之前,消息(_format_approval_message)和表格
(_generate_approval_xlsx)使用同一份已过滤数据,数字自然一致。同时
删除冗余的 df.empty 二次检查,增加过滤明细日志(便于后续排查)。

行为变化:消息总数从 32→28,移除"提价 4 条"行;bid_up 决策仍在
validated_decisions_*.csv 落盘,本地数据完整保留;execute_decisions
对 bid_up 的处理路径不变(按 tier 1 自动执行)。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
刘立冬 1 месяц назад
Родитель
Сommit
6edf952846
1 измененных файлов с 22 добавлено и 29 удалено
  1. 22 29
      examples/auto_put_ad_mini/tools/im_approval.py

+ 22 - 29
examples/auto_put_ad_mini/tools/im_approval.py

@@ -514,43 +514,36 @@ async def send_approval_request(
         if df.empty:
             return ToolResult(title="send_approval_request", output="过滤后无数据")
 
-        # 分级(包含hold记录,用于参考)
-        from execution_engine import _classify_tier
-        df["tier"] = df.apply(_classify_tier, axis=1)
-
-        # 按tier分类
-        df_tier0 = df[df["tier"] == 0].copy()  # observe, hold, creative_adjust(无需操作)
-        df_tier1 = df[df["tier"] == 1].copy()  # 小幅调价(自动执行)
-        df_tier2_3 = df[df["tier"] >= 2].copy()  # 暂停、大幅调价(需审批)
-
-        if df.empty:
-            return ToolResult(title="send_approval_request", output="无决策数据")
-
-        # 合并需审批的和无需操作的(供运营参考)
-        # ⚠️ 排除不需运营立刻干预的 action,不写飞书表降低噪声
+        # ⚠️ 前置过滤不需运营立刻干预的 action,保证消息和表格一致
         # - hold/observe:无需操作
         # - scale_up:扩量逻辑尚在调试,暂不进审批表
         # - bid_up:提价决策由系统自动执行,不进审批表(仅保留 pause 和 bid_down)
         FEISHU_EXCLUDE_ACTIONS = {"hold", "observe", "scale_up", "bid_up"}
-
-        # 对所有 tier 应用过滤(不仅仅是 tier0)
         action_col = "final_action" if "final_action" in df.columns else "action"
-        before_filter = len(df)
-        df_filtered = df[~df[action_col].isin(FEISHU_EXCLUDE_ACTIONS)].copy()
-        dropped_count = before_filter - len(df_filtered)
-
-        if dropped_count > 0:
-            dropped_breakdown = (
-                df[df[action_col].isin(FEISHU_EXCLUDE_ACTIONS)][action_col]
-                .value_counts().to_dict()
-            )
+        excluded_mask = df[action_col].isin(FEISHU_EXCLUDE_ACTIONS)
+        if excluded_mask.any():
+            dropped_breakdown = df.loc[excluded_mask, action_col].value_counts().to_dict()
             logger.info(
-                f"飞书表过滤掉 {dropped_count} 个 {sorted(FEISHU_EXCLUDE_ACTIONS)} 决策"
-                f"(明细: {dropped_breakdown},减少表格噪声)"
+                f"飞书审批前置过滤掉 {int(excluded_mask.sum())} 个 "
+                f"{sorted(FEISHU_EXCLUDE_ACTIONS)} 决策"
+                f"(明细: {dropped_breakdown},消息和表格保持一致)"
             )
+            df = df[~excluded_mask].copy()
+
+        if df.empty:
+            return ToolResult(title="send_approval_request", output="过滤后无需审批的决策")
+
+        # 分级(基于已过滤的数据,消息和表格使用同一份 df 自然一致)
+        from execution_engine import _classify_tier
+        df["tier"] = df.apply(_classify_tier, axis=1)
+
+        # 按tier分类
+        df_tier0 = df[df["tier"] == 0].copy()  # 无需操作(过滤后此桶通常为空)
+        df_tier1 = df[df["tier"] == 1].copy()  # 小幅调价(自动执行)
+        df_tier2_3 = df[df["tier"] >= 2].copy()  # 暂停、大幅调价(需审批)
 
-        # 使用过滤后的数据作为审批表
-        df_for_review = df_filtered
+        # 表格和消息共用同一份已过滤数据
+        df_for_review = df
 
         if df_tier2_3.empty:
             total_no_op = len(df_tier0) + len(df_tier1)