Procházet zdrojové kódy

feat(v3): 贴题档位罚更狠 45/25→40/20(贴题<0.8 跌档惩罚加重)

按用户设计'贴题稍降即应重罚':relevance scoring_rules 档位
≥0.6 45→40、≥0.4 25→20(满分档 60、<0.4→0 不变)。跌出满分档惩罚从扣 15 分增到 20。
JSON+Excel 同步(byte-equal pass);仅作用于贴题[0.4,0.8)的偏题内容,贴题满分(≥0.8)零影响。
test_rule_pack_reading 断言 75→70(决策不变仍落复看带)、test_replay_gemini_seam 注释 25→20;
09 B表④档位同步。330 passed,replay 快照零重钉,config gate pass。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sam Lee před 6 dny
rodič
revize
20ff711d0d

+ 2 - 2
product_documents/规则包/douyin_rule_packs.v1.json

@@ -365,7 +365,7 @@
             "field_path": "pattern_match_result.relevance_score",
             "operator": "gte",
             "expected_value": 0.6,
-            "score_value": 45,
+            "score_value": 40,
             "missing_policy": "score_0_or_fail_by_dimension",
             "priority": 2,
             "enabled": true,
@@ -377,7 +377,7 @@
             "field_path": "pattern_match_result.relevance_score",
             "operator": "gte",
             "expected_value": 0.4,
-            "score_value": 25,
+            "score_value": 20,
             "missing_policy": "score_0_or_fail_by_dimension",
             "priority": 3,
             "enabled": true,

+ 1 - 1
tech_documents/工程落地/09_V3阶段开发计划.md

@@ -632,7 +632,7 @@ ok
 | 平台热度锚点 | 抖音 赞+评+转+藏 四字段复合 / 视频号 单点赞;各字段一套及格线-满分线 | 把"互动数"换算成 0~1 热度分的**及格线/满分线**(如抖音 1 万赞=0 分起步、100 万赞=满分)。这些锚点是**起步值、待真跑标定**:真实互动分布可能完全不在这区间 → 热度分失真 → 打分跟着失真。(原"写死在 platform_heat.py"已过时:现在锚点搬进各平台 profile,代码里只剩兜底默认) | `platform_profiles/douyin.json:12-19`(抖音四字段复合)/`shipinhao.json:12-16`(视频号单点赞);`platform_heat.py:20` 仅剩兜底默认锚点 |
 | 游走延伸次数 | 翻页 3 / **作者 3 / 作品 3 / tag 3**(2026-06-12 R7 放宽:作者 2→3、tag 1→3) | 一个需求单最多翻 3 页、看 3 个作者各 3 条作品、用 3 个标签二次搜索。原 V1 硬限占位值真跑顶格实证后放宽;理想值(30/10/10)仍留后续标定 | `walk_policy.json:13-18`(edge_budgets,现 3/3/3/3;原 3/2/3/1) |
 | 视频压缩档 | 360p / 1fps / crf33 | 投喂 Gemini 前把视频压到 ~4MB 的清晰度档。(原"只在 mock 跑过"已过时:真跑 16 条压缩全成功转正,见 10 报告) | `video_fetch.py:29`(_FFMPEG_ARGS) |
-| 打分权重/阈值 | 贴题(最多60)+ 热度(最多40),≥70 进池 / 60-69 复看 / <60 拒;置信 <0.6 拒 | **贴题是"门"不是排序器(设计如此)**:按题搜回来的内容贴题都 ≥0.8、拿满 60(满分扎堆=正常、正是要的),只有偏题的才掉档(贴题档位 ≥0.8→60 / ≥0.6→45 / ≥0.4→25 / <0.4→0,即 0.8↓跌一档罚 15 分);贴题合格后真正定进池/复看的是热度——也是设计。**待标定的不是"贴题该有区分度",而是:① 热度锚点(怎么把互动换算成热度分)② 贴题"稍降"罚多狠(<0.8 现仅扣 15,可加重/趋拒)** | `douyin_rule_packs.v1.json:327-347`(scorecard 60:40)/`:436-463`(thresholds 70/60)/`:296`(fit_confidence 0.6) |
+| 打分权重/阈值 | 贴题(最多60)+ 热度(最多40),≥70 进池 / 60-69 复看 / <60 拒;置信 <0.6 拒 | **贴题是"门"不是排序器(设计如此)**:按题搜回来的内容贴题都 ≥0.8、拿满 60(满分扎堆=正常、正是要的),只有偏题的才掉档(贴题档位 ≥0.8→60 / ≥0.6→40 / ≥0.4→20 / <0.4→0,2026-06-12 把 45/25 加重为 40/20,即 0.8↓跌一档罚 20 分);贴题合格后真正定进池/复看的是热度——也是设计。**待标定的只剩 ① 热度锚点(怎么把互动换算成热度分)**(贴题"稍降"惩罚已于 2026-06-12 加重为 40/20) | `douyin_rule_packs.v1.json:327-347`(scorecard 60:40)/`:436-463`(thresholds 70/60)/`:296`(fit_confidence 0.6) |
 | Gemini 配额与并发度 | cap=200 / max_workers=4 | A 表里拍板有依据,但 provenance 自己标了"M7 真负标定 / 实测调"——200 是按"典型 20-40 条留余量"估的、4 是保守起步,**都没经真实流量验证**(真跑可能发现 200 太松烧钱、或 4 太慢/触发限速) | `walk_policy.json:10-11`(cap / max_workers) |
 | 并发度兜底 4 | 配置读不到时默认 4 | 同 A 表第一行;为何是 4 无注释(已在台账记录) | `walk_policy.json:11`(=max_workers,与 A 表首行同一处) |
 

binární
tech_documents/规则包映射/规则包映射配置表.xlsx


+ 1 - 1
tests/test_replay_gemini_seam.py

@@ -34,7 +34,7 @@ def test_replay_default_pool_stub_scores_into_pool(tmp_path):
 
 
 def test_replay_review_stub_scores_by_relevance(tmp_path):
-    # review stub: relevance_score 0.45 → relevance 维只拿 25。叠加各 item 热度后
+    # review stub: relevance_score 0.45 → relevance 维只拿 20(2026-06-12 档位 25→20)。叠加各 item 热度后
     # 仅最高热的一条进 60-69 复看带,其余 <60 被拒(无 pending、无进池)。
     artifacts = replay_case(
         "real_id45",

+ 3 - 3
tests/test_rule_pack_reading.py

@@ -24,14 +24,14 @@ def test_rule_pack_thresholds_drive_decision(tmp_path):
     thresholds[1]["min_score"] = 70
     thresholds[1]["max_score"] = 79
 
-    # M3 2-dim score: relevance 0.6 -> 45, platform_heat 0.6 -> 30 => 75, lands in the
-    # reconfigured 70<=score<=79 review band.
+    # 2-dim score(2026-06-12 贴题档位 45/25→40/20):relevance 0.6 -> 40, platform_heat 0.6 -> 30
+    # => 70, lands in the reconfigured 70<=score<=79 review band.
     bundle = deepcopy(state["evidence_bundles"][0])
     bundle["pattern_match_result"]["relevance_score"] = 0.6
     bundle["content_engagement_metrics"]["platform_heat"] = 0.6
 
     decision = decide(run_id, state["policy_run_id"], 1, bundle, policy_bundle)
-    assert decision["score"] == 75
+    assert decision["score"] == 70
     assert decision["decision_action"] == "KEEP_CONTENT_FOR_REVIEW"
     assert decision["decision_reason_code"] == "content_score_review"
     assert decision["decision_replay_data"]["matched_threshold"] == "70<=score<=79"