diff --git a/prototype/cluster.py b/prototype/cluster.py index 0bc7517..f1e2cff 100644 --- a/prototype/cluster.py +++ b/prototype/cluster.py @@ -307,24 +307,54 @@ class Clusterer: # --------------------------------------------------------------------------- + + # Rank + + # --------------------------------------------------------------------------- + +# Simple per-source authority (higher = more weight in ranking). +# Extend this map for real sources; unknown sources default to 1.0. +SOURCE_AUTHORITY = { + "reuters": 2.0, + "associated press": 2.0, + "apnews": 2.0, + "bbc": 1.8, + "nytimes": 1.7, + "the new york times": 1.7, + "cnn": 1.5, + "theverge": 1.3, + "techcrunch": 1.3, + "arstechnica": 1.3, +} + + +def _get_authority(members: list) -> float: + """Return max authority from member sources (or 1.0).""" + if not members: + return 1.0 + auth = 1.0 + for m in members: + s = (m.source or "").lower() + for key, val in SOURCE_AUTHORITY.items(): + if key in s: + auth = max(auth, val) + return auth + + def compute_scores(stories: list[Story], now: float, alpha: float = 1.8) -> list: """score = authority * (coverage_count + 1) / (age_h + 2)^1.8 (HN-style decay)""" scored = [] for s in stories: age_h = max(0.0, (now - s.first_published) / 3600.0) - rank = 1.0 * (s.coverage_count + 1) / (age_h + 2.0) ** alpha + authority = _get_authority(s.members) + rank = authority * (s.coverage_count + 1) / (age_h + 2.0) ** alpha scored.append((rank, s)) scored.sort(key=lambda x: -x[0]) return scored - -# --------------------------------------------------------------------------- -# LLM summary of top-k only (capped; host llama.cpp/Hermes, never DeepSeek) -# --------------------------------------------------------------------------- - def llm_summarize_topk(scored, topk: int) -> None: base = os.environ.get("LLM_BASE_URL", "http://127.0.0.1:8080/v1").rstrip("/") model = os.environ.get("LLM_MODEL", "hermes")