aps-agent/tests/golden/test_preference_decay.py

73 lines
2.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ============================================================
# 偏好时间衰减加权黄金测试(plan.md §8.3 / 矩阵 66 行剩余项)
# 覆盖:新样本主导偏好(衰减)、久远样本权重趋近 0、
# 舍入后当天信号近似整数、既有计数语义兼容。
# ============================================================
from __future__ import annotations
import datetime
from pathlib import Path
from server.knowledge.preferences import PreferenceStore
def _store(tmp_path: Path) -> PreferenceStore:
return PreferenceStore(str(tmp_path / "pref.json"))
def _sample(strategy: str, *, days_ago: float, project_id: str | None = "p1") -> dict:
at = (datetime.datetime.now() - datetime.timedelta(days=days_ago)).strftime("%Y-%m-%d %H:%M")
return {"strategy": strategy, "source": "schedule.run", "actor": "u1",
"projectId": project_id, "at": at}
def test_recent_signal_dominates_stale(tmp_path: Path):
"""时间衰减:30 天前的旧偏好不应压过今天的信号(偏好漂移)。"""
ps = _store(tmp_path)
ps.samples = [
_sample("DELIVERY_FIRST", days_ago=30),
_sample("CAPACITY_BALANCE", days_ago=0),
]
scores = ps._decayed_scores("p1")
assert scores["CAPACITY_BALANCE"] > scores["DELIVERY_FIRST"]
assert scores["DELIVERY_FIRST"] < 0.5 # 30 天(>1 半衰期)显著衰减
strategy, _ = ps.preferred_strategy(project_id="p1")
assert strategy == "CAPACITY_BALANCE"
def test_same_source_two_recent_samples_half_life(tmp_path: Path):
"""半衰期:14 天前样本权重约为今天的 0.5。"""
ps = _store(tmp_path)
ps.samples = [
_sample("A", days_ago=14),
_sample("B", days_ago=0),
]
scores = ps._decayed_scores("p1")
ratio = scores["A"] / scores["B"]
assert 0.45 <= ratio <= 0.55, f"半衰期比值应≈0.5,got {ratio}"
def test_today_scores_round_to_ints(tmp_path: Path):
"""当天样本(同源同策略×2)评分≈2(保留既有计数语义兼容)。"""
ps = _store(tmp_path)
ps.samples = [
_sample("DELIVERY_FIRST", days_ago=0),
_sample("DELIVERY_FIRST", days_ago=0),
]
strategy, scores = ps.preferred_strategy(project_id="p1")
assert strategy == "DELIVERY_FIRST"
assert abs(scores["DELIVERY_FIRST"] - 2.0) < 0.01
def test_decay_preserves_apply_weight(tmp_path: Path):
"""来源权重叠加衰减:采用(2×decay) > 试排(1×decay) 同时间。"""
ps = _store(tmp_path)
ps.samples = [
_sample("CAPACITY_BALANCE", days_ago=0),
_sample("DELIVERY_FIRST", days_ago=0),
]
# 同时间同来源权重应相等;改其中一个为采用验证权重
ps.samples[0]["source"] = "scenario.apply"
scores = ps._decayed_scores("p1")
assert abs(scores["CAPACITY_BALANCE"] - 2 * scores["DELIVERY_FIRST"]) < 0.05