TokenTrace / scripts /smoke_ablation_attribute.py
cccmmd
init: TokenTrace - LLM interpretability toolbox
76b5743
Raw
History Blame Contribute Delete
5.27 kB
#!/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()