"""节点 3/6:打分(score)。 归一化(按 source/kind 分组 min-max)-> 跨源融合(combine)-> 综合分阈值预筛。 纯逻辑节点,with_fallback 兜底。 """ from typing import Any, Dict, List from graph.scoring import combine, normalize from graph.validate import with_fallback @with_fallback("score") def score_node(state: Dict[str, Any]) -> Dict[str, Any]: rows: List[Dict[str, Any]] = state.get("filtered_rows") or [] config = state["config"] weights = config.get("weights") or {} llm_cfg = config.get("llm_screen") or {} min_score = float(llm_cfg.get("min_score", 0.0)) normalize(rows) combined = combine(rows, weights) combined = [c for c in combined if float(c.get("score", 0)) >= min_score] stats = dict(state.get("stats") or {}) stats["score"] = {"combined": len(combined)} return {"scored_rows": combined, "stats": stats}