fela-moderator / data /toxicity.py
itstheraj's picture
initial commit
4751195
Raw
History Blame Contribute Delete
7.63 kB
from __future__ import annotations
try:
from .taxonomy import JIGSAW_LABELS, SYNTHETIC_ONLY, TAXONOMY
except ImportError:
from taxonomy import JIGSAW_LABELS, SYNTHETIC_ONLY, TAXONOMY
CIVIL = "google/civil_comments"
JIGSAW = "google/jigsaw_toxicity_pred"
JIGSAW_MIRROR = "tasksource/jigsaw_toxicity"
JIGSAW_EVAL_MOD = 20
MHS = "ucberkeley-dlab/measuring-hate-speech"
RTP = "allenai/real-toxicity-prompts"
def jigsaw_is_eval(row):
import zlib
return zlib.crc32(str(row.get("id", "")).encode()) % JIGSAW_EVAL_MOD == 0
TAXONOMY_SOURCE_MAP = {
"harassment": [
(CIVIL, "insult", 0.5),
(JIGSAW, "insult", 1),
(MHS, "insult", 3),
(MHS, "humiliate", 3),
],
"harassment_threatening": [
(CIVIL, ("threat", "insult"), 0.5),
(JIGSAW, ("threat", "insult"), 1),
(MHS, ("violence", "insult"), 3),
],
"hate": [
(CIVIL, "identity_attack", 0.5),
(JIGSAW, "identity_hate", 1),
(MHS, "hate_speech_score", 0.5),
],
"hate_threatening": [
(CIVIL, ("identity_attack", "threat"), 0.5),
(JIGSAW, ("identity_hate", "threat"), 1),
(MHS, ("hate_speech_score", "violence"), (0.5, 3)),
],
"self_harm": [],
"self_harm_intent": [],
"self_harm_instructions": [],
"sexual": [
(CIVIL, "sexual_explicit", 0.5),
(RTP, "sexually_explicit", 0.5),
(RTP, "flirtation", 0.5),
],
"sexual_minors": [],
"violence": [(MHS, "violence", 2), (CIVIL, "threat", 0.5), (JIGSAW, "threat", 1)],
"violence_graphic": [],
"identity_attack": [
(CIVIL, "identity_attack", 0.5),
(MHS, "hate_speech_score", 0.5),
(RTP, "identity_attack", 0.5),
],
"insult": [(CIVIL, "insult", 0.5), (JIGSAW, "insult", 1), (MHS, "insult", 3)],
"profanity_obscene": [
(CIVIL, "obscene", 0.5),
(JIGSAW, "obscene", 1),
(RTP, "profanity", 0.5),
],
"threat": [(CIVIL, "threat", 0.5), (JIGSAW, "threat", 1), (RTP, "threat", 0.5)],
"sexual_explicit": [
(CIVIL, "sexual_explicit", 0.5),
(RTP, "sexually_explicit", 0.5),
],
"severe_toxicity": [(CIVIL, "severe_toxicity", 0.5), (JIGSAW, "severe_toxic", 1)],
"dehumanize": [(MHS, "dehumanize", 3)],
"incitement_violence": [(MHS, "violence", 3)],
}
JIGSAW_SOURCE_MAP = {
"toxic": [(JIGSAW, "toxic", 1), (CIVIL, "toxicity", 0.5)],
"severe_toxic": [(JIGSAW, "severe_toxic", 1), (CIVIL, "severe_toxicity", 0.5)],
"obscene": [(JIGSAW, "obscene", 1), (CIVIL, "obscene", 0.5)],
"threat": [(JIGSAW, "threat", 1), (CIVIL, "threat", 0.5)],
"insult": [(JIGSAW, "insult", 1), (CIVIL, "insult", 0.5)],
"identity_hate": [(JIGSAW, "identity_hate", 1), (CIVIL, "identity_attack", 0.5)],
}
MASKED_LABELS = [lbl for lbl in TAXONOMY if not TAXONOMY_SOURCE_MAP.get(lbl)]
DATA_BACKED_LABELS = [lbl for lbl in TAXONOMY if TAXONOMY_SOURCE_MAP.get(lbl)]
assert set(SYNTHETIC_ONLY).issubset(set(MASKED_LABELS)), (
"SYNTHETIC_ONLY labels must have no commercial source rule"
)
def licenses():
return [
(CIVIL, "CC0-1.0", False),
(JIGSAW, "CC0-1.0", False),
(MHS, "CC-BY-4.0", True),
(RTP, "Apache-2.0", False),
]
def _eval_rule(rule, row):
_dataset, column, threshold = rule
cols = column if isinstance(column, tuple) else (column,)
thrs = threshold if isinstance(threshold, tuple) else (threshold,) * len(cols)
fired = True
for col, thr in zip(cols, thrs):
val = row.get(col)
if val is None:
return None
try:
num = float(val)
except (TypeError, ValueError):
return None
if num < thr:
fired = False
return fired
def _row_targets(source_map, index_of, n_labels, dataset_id, row):
labels = [0.0] * n_labels
mask = [0.0] * n_labels
for label, rules in source_map.items():
result = None
for rule in rules:
if rule[0] != dataset_id:
continue
fired = _eval_rule(rule, row)
if fired is None:
continue
result = bool(result) or fired
if result is None:
continue
idx = index_of[label]
mask[idx] = 1.0
labels[idx] = 1.0 if result else 0.0
return (labels, mask)
def _iter_civil(streaming, max_rows):
from datasets import load_dataset
ds = load_dataset(CIVIL, split="train", streaming=streaming)
for i, ex in enumerate(ds):
if max_rows is not None and i >= max_rows:
break
text = ex.get("text") or ""
if text:
yield (text, ex)
def _iter_mhs(streaming, max_rows):
from datasets import load_dataset
ds = load_dataset(MHS, split="train", streaming=streaming)
for i, ex in enumerate(ds):
if max_rows is not None and i >= max_rows:
break
text = ex.get("text") or ""
if text:
yield (text, ex)
def _iter_rtp(streaming, max_rows):
from datasets import load_dataset
ds = load_dataset(RTP, split="train", streaming=streaming)
count = 0
for ex in ds:
for key in ("prompt", "continuation"):
part = ex.get(key) or {}
text = part.get("text") or ""
if not text:
continue
if max_rows is not None and count >= max_rows:
return
count += 1
yield (text, part)
def _iter_jigsaw(streaming, max_rows, want_eval=False):
import os
from datasets import load_dataset
jig_dir = os.environ.get("JIGSAW_DIR")
try:
if jig_dir:
ds = load_dataset(
JIGSAW, split="train", streaming=streaming, data_dir=jig_dir
)
else:
ds = load_dataset(JIGSAW_MIRROR, split="train", streaming=streaming)
kept = 0
for ex in ds:
if jigsaw_is_eval(ex) != want_eval:
continue
if max_rows is not None and kept >= max_rows:
break
text = ex.get("comment_text") or ""
if text:
kept += 1
yield (text, ex)
except Exception as err:
print(
f"[toxicity] real Jigsaw unavailable ({err}); falling back to the CC0 Civil Comments backbone, which shares the Jigsaw-head columns so nothing trains on 0s."
)
return
def load_taxonomy_examples(max_rows=None, streaming=True):
index_of = {lbl: i for i, lbl in enumerate(TAXONOMY)}
n_labels = len(TAXONOMY)
sources = [
(CIVIL, _iter_civil),
(MHS, _iter_mhs),
(RTP, _iter_rtp),
(JIGSAW, _iter_jigsaw),
]
for dataset_id, iterator in sources:
for text, row in iterator(streaming, max_rows):
labels, mask = _row_targets(
TAXONOMY_SOURCE_MAP, index_of, n_labels, dataset_id, row
)
if sum(mask) == 0:
continue
yield {"text": text, "labels": labels, "mask": mask}
def load_jigsaw_examples(max_rows=None, streaming=True):
index_of = {lbl: i for i, lbl in enumerate(JIGSAW_LABELS)}
n_labels = len(JIGSAW_LABELS)
sources = [(JIGSAW, _iter_jigsaw), (CIVIL, _iter_civil)]
for dataset_id, iterator in sources:
for text, row in iterator(streaming, max_rows):
labels, mask = _row_targets(
JIGSAW_SOURCE_MAP, index_of, n_labels, dataset_id, row
)
if sum(mask) == 0:
continue
yield {"text": text, "labels": labels, "mask": mask}