import json import sys from pathlib import Path from run_selector_demo import load_selector_rules, recommend def read_json(path): return json.loads(Path(path).read_text(encoding="utf-8")) def selected_model_ids(result): return [item["model_id"] for item in result.get("selected_models", [])] def has_ia_gate(input_text, selector_rules): global_rules = selector_rules.get("global_rules", {}) heavy_signals = global_rules.get("ia_heavy_signals", []) return any(signal in input_text for signal in heavy_signals) or "QPI 已判断" in input_text def evaluate_input(root, selector_rules, item): result = recommend(root, item["input"]) selected_ids = selected_model_ids(result) expected = item.get("expected_selector_behavior") errors = [] if expected in {"no_call", "no_call_or_low_priority"} and "qpi" in selected_ids: errors.append("expected no QPI selection") if expected in {"select_qpi", "select_qpi_low_confidence", "select_qpi_reject_ia"}: if "qpi" not in selected_ids: errors.append("expected QPI selection") if expected == "select_qpi_reject_ia" and "intellectual_archaeology" in selected_ids: errors.append("expected IA rejection") if expected == "select_intellectual_archaeology": if "intellectual_archaeology" not in selected_ids: errors.append("expected IA selection") if not has_ia_gate(item["input"], selector_rules): errors.append("IA selected expectation lacks heavy-depth or QPI-completed gate") return { "case_id": item["case_id"], "expected_selector_behavior": expected, "selected_models": selected_ids, "no_call": result.get("no_call"), "errors": errors, } def write_report(root, results): report_path = root / "reports" / "selector_calibration_smoke_report.md" failures = [result for result in results if result["errors"]] lines = [ "# Selector Calibration Smoke Report", "", f"Status: `{'PASS' if not failures else 'FAIL'}`", "", "Command: `python scripts/run_selector_calibration_smoke.py`", "", f"Calibration inputs checked: {len(results)}", f"Failures: {len(failures)}", "", "## Cases", "", ] for result in results: status = "PASS" if not result["errors"] else "FAIL" lines.append( f"- `{result['case_id']}`: {status}; expected={result['expected_selector_behavior']}; " f"selected={result['selected_models']}; no_call={result['no_call']}" ) for error in result["errors"]: lines.append(f" - {error}") report_path.write_text("\n".join(lines) + "\n", encoding="utf-8") return report_path def main(): root = Path(__file__).resolve().parents[1] selector_rules = load_selector_rules(root) calibration = read_json(root / "selector" / "selector_calibration_inputs.json") results = [ evaluate_input(root, selector_rules, item) for item in calibration.get("inputs", []) ] report_path = write_report(root, results) print(f"selector calibration smoke report written to {report_path}") failures = [result for result in results if result["errors"]] if failures: for result in failures: print(f"ERROR: {result['case_id']}: {'; '.join(result['errors'])}") return 1 print("selector calibration smoke passed") return 0 if __name__ == "__main__": sys.exit(main())