Spaces:
Running
Running
File size: 3,057 Bytes
27e064c | 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 | """Build the request stream from TAB (public train split, MIT): one request = one sentence of an ECHR judgment.
Documents are shuffled (seed 0) and split by document: HOLDOUT_DOCS documents give the spot-check holdout, the rest give
the stream. Gold spans (TAB annotator 1, the three format types) are kept for reference only; the demo learns from the
teacher, never from gold.
usage: prep.py TAB.parquet OUT_DIR
"""
import json
import random
import re
import sys
import pyarrow.parquet as pq
TYPES = {"DATETIME", "CODE", "QUANTITY"}
N_STREAM, N_HOLDOUT, HOLDOUT_DOCS = 3000, 400, 120
ABBR = r"(?<!\bMr)(?<!\bMrs)(?<!\bMs)(?<!\bDr)(?<!\bno)(?<!\bNo)(?<!\bnos)(?<!\bNos)(?<!\bpp)(?<!\bp)(?<!\bpara)(?<!\bparas)(?<!\bArt)(?<!\bv)(?<!\bSt)(?<!\bJr)(?<!\bi\.e)(?<!\be\.g)(?<!\bseq)(?<!\bop)(?<!\bcit)(?<!\b[A-Z])"
SENT_END = re.compile(ABBR + r"[.;](?=\s+[A-Z(\"'])")
def sentences(text):
out = []
for m in re.finditer(r"[^\n]+", text):
start, para = m.start(), m.group()
s = 0
for e in SENT_END.finditer(para):
out.append((start + s, start + e.end()))
s = e.end()
while s < len(para) and para[s] == " ":
s += 1
if s < len(para):
out.append((start + s, start + len(para)))
return out
def mentions(ann):
for v in (ann or {}).values():
if isinstance(v, dict) and v.get("entity_mentions"):
return v["entity_mentions"]
return []
def main(pqf, out):
docs = pq.read_table(pqf).to_pylist()
random.Random(0).shuffle(docs)
rows = {"holdout": [], "stream": []}
for k, d in enumerate(docs):
part = "holdout" if k < HOLDOUT_DOCS else "stream"
ann = d["annotations"]
if isinstance(ann, str):
ann = json.loads(ann)
ents = [(m["start_offset"], m["end_offset"], m["entity_type"]) for m in mentions(ann) if m.get("entity_type") in TYPES]
for a, b in sentences(d["text"]):
t = d["text"][a:b].strip()
if not (40 <= len(t) <= 400) or t.isupper():
continue
a2 = d["text"].index(t, a)
gold = sorted({(s - a2, e - a2, ty) for s, e, ty in ents if s >= a2 and e <= a2 + len(t)})
rows[part].append({"doc_id": d["doc_id"], "text": t,
"gold": [{"start": s, "end": e, "type": ty, "text": t[s:e]} for s, e, ty in gold]})
rng = random.Random(1)
sel = {"stream": rng.sample(rows["stream"], N_STREAM), "holdout": rng.sample(rows["holdout"], N_HOLDOUT)}
with open(f"{out}/requests.jsonl", "w") as f:
for part, rs in sel.items():
for i, r in enumerate(rs):
f.write(json.dumps({"id": f"{part[0]}{i:04d}", "part": part, **r}) + "\n")
for part, rs in sel.items():
print(part, len(rs), "of", len(rows[part]), "docs", len({r["doc_id"] for r in rs}),
"with gold", sum(1 for r in rs if r["gold"]), "gold spans", sum(len(r["gold"]) for r in rs))
if __name__ == "__main__":
main(sys.argv[1], sys.argv[2])
|