Upload q38_battery2.py with huggingface_hub
Browse files- q38_battery2.py +110 -0
q38_battery2.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Broad 40-prompt robustness battery, auto-scored by expected substring.
|
| 3 |
+
|
| 4 |
+
Greedy raw completions only (chat mode already characterized). Each item:
|
| 5 |
+
(tag, prompt, [acceptable substrings — any hit = pass, case-sensitive]).
|
| 6 |
+
Scores are rough (substring in 40 tokens) but identical across variants, so the
|
| 7 |
+
DELTA between variants is meaningful even where the absolute bar is crude.
|
| 8 |
+
|
| 9 |
+
python q38_battery2.py --port 8991 --out q38_battery2_44.json
|
| 10 |
+
"""
|
| 11 |
+
import argparse, json, time, urllib.request
|
| 12 |
+
|
| 13 |
+
ap = argparse.ArgumentParser()
|
| 14 |
+
ap.add_argument("--port", type=int, default=8991)
|
| 15 |
+
ap.add_argument("--host", default="127.0.0.1")
|
| 16 |
+
ap.add_argument("--out", required=True)
|
| 17 |
+
ap.add_argument("--n", type=int, default=40)
|
| 18 |
+
A = ap.parse_args()
|
| 19 |
+
BASE = f"http://{A.host}:{A.port}"
|
| 20 |
+
|
| 21 |
+
B = [
|
| 22 |
+
# facts: geography / science / history / culture
|
| 23 |
+
("cap_japan", "The capital of Japan is", ["Tokyo"]),
|
| 24 |
+
("cap_italy", "The capital of Italy is", ["Rome"]),
|
| 25 |
+
("cap_egypt", "The capital of Egypt is", ["Cairo"]),
|
| 26 |
+
("longest_riv", "The longest river in the world is the", ["Nile", "Amazon"]),
|
| 27 |
+
("tallest_mt", "The tallest mountain on Earth is", ["Everest"]),
|
| 28 |
+
("speed_light", "The speed of light is approximately", ["300,000", "3 x 10", "299", "3×10"]),
|
| 29 |
+
("h2o", "The chemical formula for water is", ["H2O", "H₂O"]),
|
| 30 |
+
("dna", "DNA stands for", ["deoxyribonucleic"]),
|
| 31 |
+
("photosyn", "Plants convert sunlight into energy through a process called", ["photosynthesis"]),
|
| 32 |
+
("ww2_end", "World War II ended in the year", ["1945"]),
|
| 33 |
+
("moon_first", "The first person to walk on the moon was", ["Armstrong"]),
|
| 34 |
+
("relativity", "The theory of relativity was developed by", ["Einstein"]),
|
| 35 |
+
("mona_lisa", "The Mona Lisa was painted by", ["Leonardo", "da Vinci"]),
|
| 36 |
+
("hamlet", "The play Hamlet was written by", ["Shakespeare"]),
|
| 37 |
+
("planets_n", "The number of planets in the solar system is", ["eight", "8"]),
|
| 38 |
+
("iron_sym", "The chemical symbol for iron is", ["Fe"]),
|
| 39 |
+
("fr_hello", "The French word for 'hello' is", ["bonjour", "Bonjour"]),
|
| 40 |
+
("es_cat", "The Spanish word for 'cat' is", ["gato"]),
|
| 41 |
+
("jp_thanks", "In Japanese, 'thank you' is said as", ["arigato", "arigatou", "ありがとう"]),
|
| 42 |
+
("cont_africa", "The second largest continent by area is", ["Africa"]),
|
| 43 |
+
# arithmetic / symbolic
|
| 44 |
+
("add3", "7 + 5 =", ["12"]),
|
| 45 |
+
("mult2", "6 * 7 =", ["42"]),
|
| 46 |
+
("precedence", "10 + 2 * 5 =", ["20"]),
|
| 47 |
+
("square", "The square of 12 is", ["144"]),
|
| 48 |
+
("half", "Half of 90 is", ["45"]),
|
| 49 |
+
("roman", "The Roman numeral XIV equals", ["14"]),
|
| 50 |
+
("binary", "The binary number 101 in decimal is", ["5"]),
|
| 51 |
+
("pct", "25% of 200 is", ["50"]),
|
| 52 |
+
# code
|
| 53 |
+
("py_len", "In Python, to get the length of a list called items, you write", ["len(items)"]),
|
| 54 |
+
("py_print", "print(\"hello\" + \" \" + \"world\") outputs", ["hello world"]),
|
| 55 |
+
("c_loop", "for (int i = 0; i < 10; i++) { printf(\"%d\", i); } prints the numbers", ["0", "9"]),
|
| 56 |
+
("js_arrow", "In JavaScript, an arrow function that doubles x is written as", ["=>", "x * 2", "2 * x", "2*x", "x*2"]),
|
| 57 |
+
("sql_count", "To count all rows in a table called orders, the SQL is", ["COUNT", "count"]),
|
| 58 |
+
("html_link", "In HTML, a hyperlink to example.com is written with the tag", ["<a", "href"]),
|
| 59 |
+
("py_dict", "In Python, to get the value for key 'name' from dict d, you write", ["d['name']", "d[\"name\"]", ".get("]),
|
| 60 |
+
("regex_digit", "In a regular expression, \\d matches", ["digit"]),
|
| 61 |
+
# reasoning / commonsense / continuation
|
| 62 |
+
("bigger", "Which is larger, a lion or a housecat? The answer is", ["lion"]),
|
| 63 |
+
("ice", "When water freezes it turns into", ["ice"]),
|
| 64 |
+
("opposite_up", "The opposite of 'up' is", ["down"]),
|
| 65 |
+
("story2", "The old lighthouse keeper climbed the stairs one last time,", []), # coherence only
|
| 66 |
+
]
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def post(path, payload, timeout=600):
|
| 70 |
+
req = urllib.request.Request(BASE + path, json.dumps(payload).encode(),
|
| 71 |
+
{"Content-Type": "application/json"})
|
| 72 |
+
with urllib.request.urlopen(req, timeout=timeout) as r:
|
| 73 |
+
return json.load(r)
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
for _ in range(300):
|
| 77 |
+
try:
|
| 78 |
+
with urllib.request.urlopen(BASE + "/health", timeout=5) as r:
|
| 79 |
+
if json.load(r).get("status") == "ok":
|
| 80 |
+
break
|
| 81 |
+
except Exception:
|
| 82 |
+
pass
|
| 83 |
+
time.sleep(2)
|
| 84 |
+
else:
|
| 85 |
+
raise SystemExit("server never became healthy")
|
| 86 |
+
|
| 87 |
+
results, passed, scored = {}, 0, 0
|
| 88 |
+
for tag, p, expect in B:
|
| 89 |
+
try:
|
| 90 |
+
r = post("/completion", {"prompt": p, "n_predict": A.n, "temperature": 0.0,
|
| 91 |
+
"top_k": 1, "top_p": 1.0, "seed": 7})
|
| 92 |
+
txt = r.get("content", "")
|
| 93 |
+
except Exception as e:
|
| 94 |
+
# a model degraded enough to emit invalid UTF-8 makes the server 500;
|
| 95 |
+
# that is a miss, not a reason to abandon the run
|
| 96 |
+
txt = f"<request failed: {type(e).__name__}>"
|
| 97 |
+
|
| 98 |
+
ok = None
|
| 99 |
+
if expect:
|
| 100 |
+
scored += 1
|
| 101 |
+
ok = any(e in txt for e in expect)
|
| 102 |
+
passed += ok
|
| 103 |
+
results[tag] = {"prompt": p, "completion": txt, "pass": ok}
|
| 104 |
+
print(f"{tag:12} {'PASS' if ok else 'FAIL' if ok is not None else '----'} "
|
| 105 |
+
f"{txt[:80].replace(chr(10),' ')}", flush=True)
|
| 106 |
+
|
| 107 |
+
out = {"score": f"{passed}/{scored}", "results": results,
|
| 108 |
+
"ts": time.strftime("%Y-%m-%d %H:%M")}
|
| 109 |
+
json.dump(out, open(A.out, "w"), indent=1)
|
| 110 |
+
print(f"\nSCORE {passed}/{scored} -> {A.out}")
|