Download scripts/generate_benchmark.py from Prabu17/askmydocs: direct link, hf CLI and curl.
- Browser
- Download file 5.11 kB
-
https://huggingface.co/spaces/Prabu17/askmydocs/resolve/main/scripts/generate_benchmark.py
- Command line
-
hf download hf://spaces/Prabu17/askmydocs/scripts/generate_benchmark.py
-
curl -L -o generate_benchmark.py https://huggingface.co/spaces/Prabu17/askmydocs/resolve/main/scripts/generate_benchmark.py
5.11 kB
| """ | |
| Generate evals/reports/benchmark.md β a human-readable comparison of all experiments. | |
| Run: | |
| python scripts/generate_benchmark.py | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import sys | |
| from pathlib import Path | |
| ROOT = Path(__file__).resolve().parent.parent | |
| RESULTS_DIR = ROOT / "evals" / "results" | |
| REPORT_PATH = ROOT / "evals" / "reports" / "benchmark.md" | |
| EXPERIMENTS = ["vector", "bm25", "hybrid", "final"] | |
| def _load_results(experiment: str, results_dir: str | Path | None = None) -> dict | None: | |
| """Load the latest results JSON for the given experiment name. | |
| Results are saved to evals/results/experiment_{experiment}_{id}.json | |
| (e.g. experiment_final_a1b2c3d4.json), so we glob for that pattern | |
| directly rather than looking in a subdirectory. | |
| ``results_dir`` overrides the default ``evals/results`` location. | |
| """ | |
| root = Path(results_dir) if results_dir else RESULTS_DIR | |
| if not root.exists(): | |
| return None | |
| # Find all JSON files matching the experiment pattern and pick the latest | |
| pattern = f"experiment_{experiment}_*.json" | |
| files = sorted(root.glob(pattern), key=lambda p: p.stat().st_mtime) | |
| if not files: | |
| return None | |
| return json.loads(files[-1].read_text(encoding="utf-8")) | |
| def _fmt(v: float | None, decimals: int = 4) -> str: | |
| if v is None: | |
| return "N/A" | |
| return f"{v:.{decimals}f}" | |
| def _section(title: str) -> str: | |
| return f"\n## {title}\n" | |
| def _table_row(values: list[str]) -> str: | |
| return "| " + " | ".join(values) + " |" | |
| def _table_header(cols: list[str]) -> str: | |
| return "| " + " | ".join(cols) + " |\n" + "| " + " | ".join("---" for _ in cols) + " |" | |
| def generate_report(results_dir: str | Path | None = None) -> Path: | |
| """Render ``evals/reports/benchmark.md`` from the experiment result files. | |
| Returns the path the report was written to. Callers that only need the | |
| artifact (e.g. the Celery task) should use this; ``main()`` is the CLI | |
| wrapper around it. | |
| ``results_dir`` overrides the default ``evals/results`` location. | |
| """ | |
| REPORT_PATH.parent.mkdir(parents=True, exist_ok=True) | |
| lines: list[str] = [ | |
| "# RAG Evaluation Benchmark", | |
| "", | |
| _section("Experiment Summary"), | |
| _table_header([ | |
| "Experiment", "Questions", "Duration (s)", | |
| "Recall@10", "Hit Rate@5", "Citation Correctness", | |
| ]), | |
| "", | |
| ] | |
| experiments_data: dict[str, dict] = {} | |
| for exp in EXPERIMENTS: | |
| data = _load_results(exp, results_dir) | |
| if data is None: | |
| lines.append( | |
| _table_row([exp, "β", "β", "β", "β", "β", "No results found"]) | |
| ) | |
| continue | |
| experiments_data[exp] = data | |
| agg = data.get("aggregate_retrieval", {}) | |
| cit = data.get("aggregate_citation", {}) | |
| lines.append( | |
| _table_row([ | |
| exp, | |
| str(data.get("question_count", "?")), | |
| f"{data.get('duration_seconds', 0):.1f}", | |
| _fmt(agg.get("recall_at_k")), | |
| _fmt(agg.get("hit_rate")), | |
| _fmt(cit.get("citation_correctness")), | |
| ]) | |
| ) | |
| lines.append("") | |
| # Per-difficulty breakdown | |
| if experiments_data: | |
| lines.append(_section("Per-Difficulty Breakdown")) | |
| for exp, data in experiments_data.items(): | |
| per_diff = data.get("per_difficulty", {}) | |
| if not per_diff: | |
| continue | |
| lines.append(f"\n### {exp}\n") | |
| lines.append(_table_header([ | |
| "Difficulty", "Count", "Recall@10", | |
| "Hit Rate", "Citation Correctness", | |
| ])) | |
| for diff_name in ["easy", "medium", "hard", "unanswerable"]: | |
| dd = per_diff.get(diff_name, {}) | |
| if not dd: | |
| continue | |
| lines.append( | |
| _table_row([ | |
| diff_name, | |
| str(dd.get("count", "?")), | |
| _fmt(dd.get("recall_at_k")), | |
| _fmt(dd.get("hit_rate")), | |
| _fmt(dd.get("citation_correctness")), | |
| ]) | |
| ) | |
| lines.append("") | |
| # Ragas metrics | |
| ragas_exp = experiments_data.get("final", {}) | |
| ragas_metrics = ragas_exp.get("aggregate_ragas", {}) | |
| if ragas_metrics: | |
| lines.append(_section("Ragas Metrics (Experiment D β Full Pipeline)")) | |
| lines.append(_table_header(["Metric", "Value"])) | |
| for key, val in sorted(ragas_metrics.items()): | |
| lines.append(_table_row([key, _fmt(val)])) | |
| lines.append("") | |
| REPORT_PATH.write_text("\n".join(lines) + "\n", encoding="utf-8") | |
| return REPORT_PATH | |
| def main() -> int: | |
| report_path = generate_report() | |
| print(f"Benchmark written to {report_path}") | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |