File size: 9,958 Bytes
8c867d9 | 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 | """Large public typed-decision corpora -> MM-Jev train records. Each builder returns a list of records; pipeline.py caches
every part to disk, so a crash / disconnect only redoes the part in flight.
Benchmark sources are removed by name (tasksource): AG News, emotion (DAIR), Banking77, MASSIVE, XNLI.
"""
import ast, json, random, re
from datasets import load_dataset
from mmjev import Seg, options_of
BANNED = re.compile(r"(^|/)(ag_news|emotion|banking77|massive|xnli)(/|$)|multilingual/massive|multilingual/xnli", re.I)
MAX_OPTS, MAX_STATE = 100, 3500
def _rec(task, state, qs, targets):
ys = [int(max(range(len(t)), key=lambda i: t[i])) for t in targets]
return dict(task=task, modality="text", split="train", state=[Seg("text", str(state)[:MAX_STATE])], qs=qs, ys=ys,
targets=targets, raw=None)
def _norm(t):
t = [max(0.0, float(x)) for x in t]
s = sum(t)
return [x / s for x in t] if s > 0 else None
def _parse(x):
if isinstance(x, (list, dict)):
return x
try:
return json.loads(x)
except Exception:
return ast.literal_eval(x)
def row_question(kind, question, options, target):
"""Row-schema (Open-Jev / SargeDev / tasksource): options list + target distribution -> (question, target)."""
options = [str(o) for o in options]
if kind == "noul" and len(target) == 1:
target = [1 - float(target[0]), float(target[0])]
options = ["false", "true"]
target = _norm(target)
if target is None or len(options) != len(target) or not (2 <= len(options) <= MAX_OPTS):
return None
if kind == "noul":
p = target[-1] if len(target) == 2 else target[0]
return {"type": "noul", "instructions": question}, [1 - p, p]
if kind == "score":
return {"type": "score", "instructions": question, "criteria": [o[:160] for o in options]}, target
crit = {}
for i, o in enumerate(options):
if ": " in o and len(o.split(": ", 1)[0]) <= 40:
k, v = o.split(": ", 1)
elif len(o) > 60:
k, v = f"option {i + 1}", o
else:
k, v = o, ""
crit[k.strip()] = v[:300]
if len(crit) != len(options):
return None
return {"type": "choice", "instructions": question, "criteria": crit}, target
def grouped_rows(rows, task, n_groups, rng, state_key="state_json"):
groups = {}
for r in rows:
groups.setdefault(r["group_id"], []).append(r)
keys = list(groups); rng.shuffle(keys)
out = []
for g in keys[:n_groups]:
qs, ts, st = [], [], None
for r in groups[g][:6]:
st = st if st is not None else _parse(r[state_key]) if r[state_key] else ""
got = row_question(r["kind"], r["question"], _parse(r["options"]), _parse(r["target"]))
if got:
qs.append(got[0]); ts.append(got[1])
if qs:
st = st if isinstance(st, str) else json.dumps(st, ensure_ascii=False)
out.append(_rec(task, st, qs, ts))
return out
def openjev_v11(n_ctrl=5000, n_wanli=1500, seed=11):
rng = random.Random(seed)
ds = load_dataset("ZefanCai/Open-Jev-v1.1", "community-hard-mix-v2-redistributable", split="train")
rows = ds.to_list()
wanli = [r for r in rows if "wanli" in (r["source"] or "").lower()]
ctrl = [r for r in rows if "wanli" not in (r["source"] or "").lower()]
return grouped_rows(ctrl, "openjev_v11", n_ctrl, rng) + grouped_rows(wanli, "openjev_v11_wanli", n_wanli, rng)
def openjev_v2(n=3000, seed=12):
ds = load_dataset("ZefanCai/Open-Jev", "release-v2-redistributable", split="train")
return grouped_rows(ds.to_list(), "openjev_v2", n, random.Random(seed))
def bev(cfgs=(("default", 4000), ("hard_50k", 3000), ("numeric_temporal", 1500), ("skills", 2000)), seed=13):
out = []
for cfg, n in cfgs:
ds = load_dataset("avbiswas/bev-decision", cfg, split="train").shuffle(seed=seed).select(range(n))
for ex in ds:
qs_raw = _parse(ex["questions_json"])
qs, ts = [], []
for qid, q in list(qs_raw.items())[:6]:
t, crit, lab = q["type"], q.get("criteria"), q.get("label")
if t == "noul":
p = float(lab) if isinstance(lab, (int, float)) and not isinstance(lab, bool) else float(bool(lab))
qs.append({"type": "noul", "instructions": q["instructions"]}); ts.append([1 - p, p])
elif t == "score":
crit = list(crit)
lv = int(lab) if lab is not None else 0
if not (0 <= lv < len(crit)):
continue
qs.append({"type": "score", "instructions": q["instructions"], "criteria": [str(c) for c in crit]})
ts.append([1.0 if i == lv else 0.0 for i in range(len(crit))])
else:
crit = crit if isinstance(crit, dict) else {str(c): "" for c in crit}
keys = list(crit)
if str(lab) not in keys or not (2 <= len(keys) <= MAX_OPTS):
continue
qs.append({"type": "choice", "instructions": q["instructions"], "criteria": {k: str(v or "") for k, v in crit.items()}})
ts.append([1.0 if k == str(lab) else 0.0 for k in keys])
if qs:
out.append(_rec(f"bev:{cfg}", ex["state"], qs, ts))
return out
def tasksource(n=7000, shards=(0, 4, 8), many_frac=0.45, seed=14):
"""Non-streaming shards (the streaming shuffle walks whole shards); benchmark sources dropped by name;
rows with >= 10 options over-sampled so the K distribution covers intent-style label spaces."""
rng = random.Random(seed)
files = [f"hf://datasets/tasksource/tasksource-jev-typed-decisions/data/train-{i:05d}-of-00012.parquet" for i in shards]
ds = load_dataset("parquet", data_files=files, split="train")
ds = ds.filter(lambda b: [not BANNED.search(s or "") for s in b["source"]], batched=True)
many, few = [], []
for ex in ds.shuffle(seed=seed).select(range(min(len(ds), 60000))):
try:
opts = _parse(ex["options"]) if ex["options"] else ["false", "true"]
tgt = _parse(ex["target"])
except Exception:
continue
got = row_question(ex["kind"], ex["question"], opts, tgt if isinstance(tgt, list) else [1 - tgt, tgt])
if not got:
continue
r = _rec(f"tasksource:{(ex['source'] or '?').split('/')[0]}", ex["state"] or "", [got[0]], [got[1]])
(many if len(got[1]) >= 10 else few).append(r)
k_many = min(len(many), int(n * many_frac))
return rng.sample(many, k_many) + rng.sample(few, min(len(few), n - k_many))
def jev_decisions(n=2000, seed=15):
"""Agent tool / action choice: candidates -> options, target candidate -> gold."""
rng = random.Random(seed)
ds = load_dataset("samatv256/jev-decisions-v1", split="validation", streaming=True)
out, seen = [], 0
for ex in ds:
seen += 1
if seen > 60000 or len(out) >= n:
break
if ex["status"] != "trainable" or rng.random() > 0.25:
continue
try:
cands = _parse(ex["candidates"]); tgt = _parse(ex["target"])
except Exception:
continue
if not (2 <= len(cands) <= 40) or not isinstance(tgt, dict) or not tgt.get("candidate_id"):
continue
keys = [c.get("name") or c.get("id") for c in cands]
ids = [c.get("id") for c in cands]
if tgt["candidate_id"] not in ids or len(set(keys)) != len(keys):
continue
crit = {k: str(c.get("description") or "")[:200] for k, c in zip(keys, cands)}
st = ex["state"] if isinstance(ex["state"], str) else json.dumps(ex["state"], ensure_ascii=False)
st = st[-MAX_STATE:] # keep the most recent part of long agent traces
g = ids.index(tgt["candidate_id"])
out.append(_rec(f"jev_decisions:{ex['decision_type']}", st,
[{"type": "choice", "instructions": "Which action or tool should the agent use next?", "criteria": crit}],
[[1.0 if i == g else 0.0 for i in range(len(keys))]]))
return out
def sargedev(n_v3=15000, n_v1=4000, seed=16):
ds = load_dataset("json", data_files="hf://datasets/SargeDev/jev-distill-corpus-v3/train.jsonl", split="train")
rng = random.Random(seed)
by = {"yuri_v3": [], "yuri_v1": []}
for i, s in enumerate(ds["source"]):
if s in by:
by[s].append(i)
idx = rng.sample(by["yuri_v3"], min(n_v3, len(by["yuri_v3"]))) + rng.sample(by["yuri_v1"], min(n_v1, len(by["yuri_v1"])))
out = []
for ex in ds.select(idx):
got = row_question(ex["kind"], ex["question"], ex["options"], ex["target"])
if got:
out.append(_rec(f"sargedev:{ex['source']}", ex["state"], [got[0]], [got[1]]))
return out
def clinc_full(n=1200, seed=17):
"""CLINC150 with the FULL 150-intent label space (K matched to many-label intent routing)."""
ds = load_dataset("clinc/clinc_oos", "plus", split="train").shuffle(seed=seed)
names = ds.features["intent"].names
labels = [x for x in names if x != "oos"]
ds = ds.filter(lambda e: names[e["intent"]] != "oos").select(range(n))
crit = {x.replace("_", " "): "" for x in labels}
keys = list(crit)
return [_rec("clinc150_full", ex["text"], [{"type": "choice", "instructions": "Which single label best describes the input text?",
"criteria": crit}],
[[1.0 if k == names[ex["intent"]].replace("_", " ") else 0.0 for k in keys]]) for ex in ds]
BUILDERS = {"openjev_v11": openjev_v11, "openjev_v2": openjev_v2, "bev": bev, "tasksource": tasksource,
"jev_decisions": jev_decisions, "sargedev": sargedev, "clinc_full": clinc_full}
|