File size: 11,435 Bytes
00ee773 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | """Benchmark suites, built once and frozen to bench/data/suites.jsonl.
The "jev.*" and "app.*" suites reproduce Laya's research/scripts/bench_apps.py build()
case-for-case (same datasets, same filtering, same order, same seed 13, N=400), so Laya
and Nirnay answer byte-identical states and questions. "extra.*" suites are additional
held-out tasks (neither model trains on them):
extra.sst5 ordinal 5-level sentiment (the `score` type; Laya's documented weak spot)
extra.sms_spam SMS spam (an independent Jev figure exists: 0.930)
python bench\\suites.py
"""
import json
import os
import random
import sys
from datasets import load_dataset
HERE = os.path.dirname(os.path.abspath(__file__))
OUT = os.path.join(HERE, "data", "suites.jsonl")
SEED = 13
N = int(os.environ.get("BENCH_N", "400"))
SUITES = []
def register(name, cases, gold, **meta):
for i, ((state, qs), g) in enumerate(zip(cases, gold)):
SUITES.append({"suite": name, "i": i, "state": state, "questions": qs, "gold": g, "meta": meta})
print(" %-28s %4d cases %s" % (name, len(cases), meta.get("note", "")), flush=True)
def choice_q(qid, instructions, keys, gold_key):
crit = {k: None for k in keys}
return {qid: {"type": "choice", "instructions": instructions, "criteria": crit}}, keys.index(gold_key)
def email_state(subject, body):
from laya import email_state as es # the exact cleaning Laya's own benchmark applies
return es(subject, body)
def build_laya_suites():
rng = random.Random(SEED)
d = load_dataset("fancyzhx/ag_news", split="test")
crit = {"world": "world news and international politics", "sports": "sports",
"business": "business and economy", "sci_tech": "science and technology"}
keys = list(crit)
cases, gold = [], []
for r in list(d)[:N]:
cases.append(({"article": r["text"]},
{"topic": {"type": "choice", "instructions": "What is the topic of `article`?",
"criteria": dict(crit)}}))
gold.append(keys.index(keys[int(r["label"])]))
register("jev.ag_news", cases, gold, note="Jev 0.910", jev="ag_news", laya_in_training=True)
d = load_dataset("dair-ai/emotion", "split", split="test")
names = ["sadness", "joy", "love", "anger", "fear", "surprise"]
cases, gold = [], []
for r in list(d)[:N]:
cases.append(({"text": r["text"]},
{"emotion": {"type": "choice",
"instructions": "Which emotion is most strongly expressed in `text`?",
"criteria": {n: None for n in names}}}))
gold.append(int(r["label"]))
register("jev.emotion", cases, gold, note="Jev 0.480", jev="emotion", laya_in_training=False)
d = load_dataset("mteb/banking77", split="test")
labels = sorted(set(d["label_text"]))
cases, gold = [], []
for r in list(d)[:N]:
qs, gi = choice_q("intent", "Which banking intent does `message` express?",
[x.replace("_", " ") for x in labels], r["label_text"].replace("_", " "))
cases.append(({"message": r["text"]}, qs))
gold.append(gi)
register("jev.banking77_full", cases, gold, note="%d labels | Jev 0.870 (72 labels)" % len(labels),
jev="banking77", laya_in_training=False, n_labels=len(labels))
d = load_dataset("Tobi-Bueck/customer-support-tickets", split="train")
QUEUES = {"Technical Support": "technical problems, bugs, outages, integrations",
"Product Support": "help using a product or feature",
"Customer Service": "general account or service questions",
"IT Support": "internal IT, devices, access, networks",
"Billing and Payments": "invoices, charges, refunds, payment methods",
"Returns and Exchanges": "returning or exchanging an item",
"Service Outages and Maintenance": "downtime, outages, scheduled maintenance",
"Sales and Pre-Sales": "pricing, quotes, buying",
"Human Resources": "employment, payroll, leave, hiring",
"General Inquiry": "anything else"}
keys = list(QUEUES)
cases, gold = [], []
for r in d:
if r.get("language") != "en" or r.get("queue") not in QUEUES or not r.get("body"):
continue
cases.append(({"subject": r["subject"] or "", "body": r["body"].replace("\\n", "\n")[:3000]},
{"queue": {"type": "choice", "instructions": "Which support queue should handle this ticket?",
"criteria": dict(QUEUES)}}))
gold.append(keys.index(r["queue"]))
if len(cases) >= N:
break
register("app.support_triage", cases, gold, note="10-way queue routing", laya_in_training=True)
d = load_dataset("SetFit/enron_spam", split="test")
cases, gold = [], []
for r in list(d)[:N]:
st = email_state(r.get("subject") or "", (r.get("message") or "")[:3000])
cases.append((st, {"is_spam": {"type": "noul", "instructions": "Is this email unsolicited spam or bulk marketing?"}}))
gold.append(int(r["label"]))
register("app.email_spam", cases, gold, note="enron spam", laya_in_training=True)
d = load_dataset("zefang-liu/phishing-email-dataset", split="train")
rows = [r for r in list(d)[:6000]
if (r.get("Email Text") or "").strip() and r.get("Email Type") in ("Safe Email", "Phishing Email")]
rng.shuffle(rows)
cases, gold = [], []
for r in rows[:N]:
cases.append(({"email": r["Email Text"][:3000]},
{"is_phishing": {"type": "noul",
"instructions": "Is this email a phishing or scam attempt to steal money, credentials, or personal data?",
"criteria": {"true": "phishing, scam, or fraud",
"false": "a legitimate email (even if promotional)"}}}))
gold.append(int(r["Email Type"] == "Phishing Email"))
register("app.phishing", cases, gold, note="phishing emails", laya_in_training=True)
d = load_dataset("lmsys/toxic-chat", "toxicchat0124", split="test")
rows = [r for r in d if (r.get("user_input") or "").strip()]
jb = [r for r in rows if int(r.get("jailbreaking", 0)) == 1][:N // 2]
nj = [r for r in rows if int(r.get("jailbreaking", 0)) == 0][:N - len(jb)]
mix = jb + nj
rng.shuffle(mix)
cases, gold = [], []
for r in mix:
cases.append(({"prompt": r["user_input"][:3000]},
{"jailbreak": {"type": "noul",
"instructions": "Does `prompt` try to make an AI assistant ignore its rules, policies or system instructions?"}}))
gold.append(int(r["jailbreaking"]))
register("app.guardrails_jailbreak", cases, gold, note="toxic-chat jailbreaking (held out)", laya_in_training=False)
tox = [r for r in rows if int(r.get("toxicity", 0)) == 1][:N // 2]
ntox = [r for r in rows if int(r.get("toxicity", 0)) == 0][:N - len(tox)]
mix2 = tox + ntox
rng.shuffle(mix2)
cases, gold = [], []
for r in mix2:
cases.append(({"post": r["user_input"][:3000]},
{"toxic": {"type": "noul",
"instructions": "Is `post` toxic: rude, disrespectful or likely to make someone leave the discussion?"}}))
gold.append(int(r["toxicity"]))
register("app.moderation_toxicity", cases, gold, note="toxic-chat toxicity (held out)", laya_in_training=False)
d = load_dataset("microsoft/ms_marco", "v1.1", split="validation")
cases, gold = [], []
for r in d:
texts, sel = r["passages"]["passage_text"], r["passages"]["is_selected"]
pos = [t for t, s in zip(texts, sel) if s == 1]
neg = [t for t, s in zip(texts, sel) if s == 0]
if not pos or not neg:
continue
take_pos = len(cases) % 2 == 0
p = rng.choice(pos if take_pos else neg)
cases.append(({"query": r["query"], "passage": p},
{"relevant": {"type": "noul", "instructions": "Does `passage` help answer `query`?"}}))
gold.append(1 if take_pos else 0)
if len(cases) >= N:
break
register("app.rag_relevance", cases, gold, note="MS MARCO relevance", laya_in_training=True)
DOM = {"code": "software engineering, programming, refactoring, architecture, debugging",
"math_or_logic": "mathematics, logic puzzles, proofs, complex calculation",
"writing": "creative writing, essays, emails, blog posts, copywriting",
"factual_lookup": "facts, definitions, trivia, history",
"data_analysis": "statistics, SQL, data manipulation, metrics",
"chitchat": "casual conversation, greetings, small talk"}
keys = list(DOM)
pool = []
g = load_dataset("openai/gsm8k", "main", split="test")
pool += [(r["question"], "math_or_logic") for r in list(g)[:N // 3]]
m = load_dataset("google-research-datasets/mbpp", "full", split="test")
pool += [(r["text"], "code") for r in list(m)[:N // 3]]
t = load_dataset("fancyzhx/ag_news", split="test")
pool += [(r["text"][:400], "factual_lookup") for r in list(t)[:N // 3]]
rng.shuffle(pool)
cases, gold = [], []
for text, dom in pool[:N]:
cases.append(({"request": text},
{"domain": {"type": "choice", "instructions": "What domain does `request` belong to?",
"criteria": dict(DOM)}}))
gold.append(keys.index(dom))
register("app.model_routing_domain", cases, gold, note="gsm8k/mbpp/ag_news -> domain", laya_in_training=False)
def build_extra_suites():
rng = random.Random(SEED + 1)
d = load_dataset("SetFit/sst5", split="test")
levels = ["very negative", "negative", "neutral", "positive", "very positive"]
rows = list(d)
rng.shuffle(rows)
cases, gold = [], []
for r in rows[:N]:
cases.append(({"review": r["text"]},
{"sentiment": {"type": "score", "instructions": "How positive is the sentiment of `review`?",
"criteria": list(levels)}}))
gold.append(int(r["label"]))
register("extra.sst5", cases, gold, note="ordinal 5-level (score type, held out)", laya_in_training=False)
d = load_dataset("ucirvine/sms_spam", split="train")
rows = list(d)
rng.shuffle(rows)
spam = [r for r in rows if int(r["label"]) == 1][:N // 2]
ham = [r for r in rows if int(r["label"]) == 0][:N - len(spam)]
mix = spam + ham
rng.shuffle(mix)
cases, gold = [], []
for r in mix:
cases.append(({"sms": r["sms"].strip()},
{"is_spam": {"type": "noul", "instructions": "Is `sms` spam?"}}))
gold.append(int(r["label"]))
register("extra.sms_spam", cases, gold, note="SMS spam (held out) | independent Jev 0.930", laya_in_training=False)
def main():
os.makedirs(os.path.dirname(OUT), exist_ok=True)
print("=== building suites (N=%d) ===" % N, flush=True)
build_laya_suites()
build_extra_suites()
with open(OUT, "w", encoding="utf-8") as f:
for r in SUITES:
f.write(json.dumps(r, ensure_ascii=False) + "\n")
print("wrote %d cases -> %s" % (len(SUITES), OUT))
if __name__ == "__main__":
sys.exit(main())
|