Spaces:
Running
Running
| #!/usr/bin/env python | |
| """ | |
| 消融归因冒烟脚本。 | |
| 用法(本地服务已启动): | |
| python scripts/smoke_ablation_attribute.py | |
| python scripts/smoke_ablation_attribute.py --base-url http://localhost:7860 | |
| 验证: | |
| - 正常请求返回 200,score 方向合理(高影响 token 有正 score) | |
| - 各 400 错误场景返回预期状态码 | |
| """ | |
| import argparse | |
| import json | |
| import sys | |
| try: | |
| import requests | |
| except ImportError: | |
| print("requests not installed; run: pip install requests") | |
| sys.exit(1) | |
| _DEFAULT_URL = "http://localhost:7860" | |
| def post(base_url: str, payload: dict) -> requests.Response: | |
| return requests.post(f"{base_url}/api/ablation-attribute", json=payload, timeout=120) | |
| def run(base_url: str) -> int: | |
| failures = 0 | |
| # ------------------------------------------------------------------ # | |
| # Case 1: 正常 top-1(中文,ΔP 方向核对) | |
| # ------------------------------------------------------------------ # | |
| print("\n[1] 正常 top-1 — 中国的首都是") | |
| r = post(base_url, {"context": "中国的首都是", "model": "base", "source_page": "attribution"}) | |
| if r.status_code != 200: | |
| print(f" ✗ status={r.status_code}: {r.text[:200]}") | |
| failures += 1 | |
| else: | |
| body = r.json() | |
| assert body["success"], body | |
| ta = body["token_attribution"] | |
| print(f" ✓ target={body['target_token']!r}, baseline_prob={body['target_prob']:.4f}") | |
| for t in ta: | |
| bar = "+" * max(0, int(t["score"] * 50)) if t["score"] > 0 else "-" * max(0, int(-t["score"] * 50)) | |
| print(f" {t['raw']!r:8s} score={t['score']:+.4f} {bar}") | |
| positive_scores = sum(1 for t in ta if t["score"] > 0) | |
| if positive_scores == 0: | |
| print(" ⚠ 所有 score 均 ≤ 0,结果可疑") | |
| failures += 1 | |
| else: | |
| print(f" ✓ {positive_scores}/{len(ta)} token 有正向贡献") | |
| # ------------------------------------------------------------------ # | |
| # Case 2: 显式 target_prediction | |
| # ------------------------------------------------------------------ # | |
| print("\n[2] 显式 target_prediction=北京") | |
| r = post(base_url, { | |
| "context": "中国的首都是", | |
| "model": "base", | |
| "source_page": "attribution", | |
| "target_prediction": "北京", | |
| }) | |
| if r.status_code != 200: | |
| print(f" ✗ status={r.status_code}: {r.text[:200]}") | |
| failures += 1 | |
| else: | |
| body = r.json() | |
| print(f" ✓ target={body['target_token']!r}, baseline_prob={body['target_prob']:.4f}") | |
| # ------------------------------------------------------------------ # | |
| # Case 3: 互斥目标 → 400 | |
| # ------------------------------------------------------------------ # | |
| print("\n[3] 互斥 target — 预期 400") | |
| r = post(base_url, { | |
| "context": "hello", | |
| "model": "base", | |
| "source_page": "attribution", | |
| "target_prediction": "world", | |
| "target_token_id": 5, | |
| }) | |
| if r.status_code != 400: | |
| print(f" ✗ 预期 400,得到 {r.status_code}") | |
| failures += 1 | |
| else: | |
| print(f" ✓ 400: {r.json()['message']}") | |
| # ------------------------------------------------------------------ # | |
| # Case 4: 非法 model → 400 | |
| # ------------------------------------------------------------------ # | |
| print("\n[4] 非法 model — 预期 400") | |
| r = post(base_url, {"context": "hello", "model": "gpt4", "source_page": "attribution"}) | |
| if r.status_code != 400: | |
| print(f" ✗ 预期 400,得到 {r.status_code}") | |
| failures += 1 | |
| else: | |
| print(f" ✓ 400: {r.json()['message']}") | |
| # ------------------------------------------------------------------ # | |
| # Case 5: 缺 context → 400 | |
| # ------------------------------------------------------------------ # | |
| print("\n[5] 缺 context — 预期 400") | |
| r = post(base_url, {"model": "base", "source_page": "attribution"}) | |
| if r.status_code != 400: | |
| print(f" ✗ 预期 400,得到 {r.status_code}") | |
| failures += 1 | |
| else: | |
| print(f" ✓ 400: {r.json()['message']}") | |
| # ------------------------------------------------------------------ # | |
| # Case 6: 非法 source_page → 400 | |
| # ------------------------------------------------------------------ # | |
| print("\n[6] 非法 source_page — 预期 400") | |
| r = post(base_url, {"context": "hello", "model": "base", "source_page": "nowhere"}) | |
| if r.status_code != 400: | |
| print(f" ✗ 预期 400,得到 {r.status_code}") | |
| failures += 1 | |
| else: | |
| print(f" ✓ 400: {r.json()['message']}") | |
| # ------------------------------------------------------------------ # | |
| # Summary | |
| # ------------------------------------------------------------------ # | |
| print(f"\n{'='*40}") | |
| if failures == 0: | |
| print("✅ All smoke tests passed.") | |
| else: | |
| print(f"❌ {failures} test(s) failed.") | |
| return failures | |
| def main(): | |
| parser = argparse.ArgumentParser(description="Ablation attribution smoke test") | |
| parser.add_argument("--base-url", default=_DEFAULT_URL) | |
| args = parser.parse_args() | |
| sys.exit(run(args.base_url)) | |
| if __name__ == "__main__": | |
| main() | |