mirror of
https://github.com/wassname/persona-steering-template-library.git
synced 2026-07-30 12:30:34 +08:00
530 lines
20 KiB
Python
530 lines
20 KiB
Python
"""Load public value and moral-decision datasets as scenario prompt rows.
|
|
|
|
Each loader returns dictionaries with `text`, `axes`, `source`, and `source_id`.
|
|
`export_scenarios.py` writes these rows to `data/scenarios/`; the validator then
|
|
screens those files before they are used for persona-conditioned generations.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import ast
|
|
import csv
|
|
import hashlib
|
|
import io
|
|
import json
|
|
import re
|
|
import urllib.request
|
|
from pathlib import Path
|
|
|
|
from datasets import load_dataset
|
|
|
|
|
|
_AIRISK_AXIS_MAP = [
|
|
(r"transparen|truth|honest|deceiv|deception|disclos|misrepresent|integrity", "honesty"),
|
|
(r"welfare|care|compassion|wellbeing|well-being|health|human life|life preserv|protect", "care"),
|
|
(r"safety|oversight|monitor|report|account|reliab|risk", "oversight"),
|
|
(r"autonom|self preserv|self-preserv|independen|freedom", "autonomy"),
|
|
(r"complian|regulat|legal|law|polic|authorit|protocol", "authority"),
|
|
(r"environ|societ|infrastructure|public|community|social", "externalities"),
|
|
(r"animal|pet|sentien|moral patient|creature", "moral_patienthood"),
|
|
(r"fair|equit|justice|impartial|bias", "fairness"),
|
|
(r"trust|loyal|relationship|commitment", "loyalty"),
|
|
(r"scientific progress|innovation|efficien|performance|long-term|option", "option_value"),
|
|
(r"privacy|data integrity|consent", "epistemics"),
|
|
]
|
|
|
|
|
|
def _airisk_axes(values: list[str]) -> list[str]:
|
|
blob = " ".join(values).lower()
|
|
tags = []
|
|
for pat, tag in _AIRISK_AXIS_MAP:
|
|
if re.search(pat, blob) and tag not in tags:
|
|
tags.append(tag)
|
|
tags = tags[:3]
|
|
if "value_conflict" not in tags:
|
|
tags.append("value_conflict") # every row is a two-sided dilemma
|
|
return tags[:4]
|
|
|
|
|
|
def _airisk_advisory(dilemma: str) -> str:
|
|
"""Drop the leading yes/no close so the prompt reads as an open advisory."""
|
|
text = " ".join(dilemma.split())
|
|
sents = re.split(r"(?<=[.?!])\s+", text)
|
|
last = sents[-1]
|
|
if last.endswith("?") and re.match(r"^(should|would|will|do|can|could|must)\b", last.lower()):
|
|
m = re.search(r",?\s*(knowing|while|but|even though|given)\b(.*)$", last, re.I)
|
|
tail = ""
|
|
if m:
|
|
clause = m.group(2).rstrip("?. ").strip()
|
|
if clause:
|
|
tail = f" The tension: {clause}."
|
|
body = " ".join(sents[:-1]).strip()
|
|
return f"{body}{tail} How do you proceed, and what principle guides you?"
|
|
return text
|
|
|
|
|
|
def load_airisk(limit: int | None = None) -> list[dict]:
|
|
ds = load_dataset("kellycyy/AIRiskDilemmas", split="test", streaming=True)
|
|
seen: dict[str, list[str]] = {}
|
|
order: list[str] = []
|
|
for row in ds:
|
|
d = row["dilemma"]
|
|
if d not in seen:
|
|
seen[d] = []
|
|
order.append(d)
|
|
seen[d].extend(row["values"])
|
|
out = []
|
|
for d in order:
|
|
if not (33 <= len(d.split()) <= 115):
|
|
continue
|
|
out.append({
|
|
"text": _airisk_advisory(d),
|
|
"axes": _airisk_axes(seen[d]),
|
|
"source": "airisk",
|
|
"source_id": "airisk_" + hashlib.md5(d.encode()).hexdigest()[:8],
|
|
})
|
|
if limit and len(out) >= limit:
|
|
break
|
|
return out
|
|
|
|
|
|
_MS_FOUNDATION_TAG = {
|
|
"care-harm": "care", "fairness-cheating": "fairness", "loyalty-betrayal": "loyalty",
|
|
"authority-subversion": "authority", "sanctity-degradation": "sanctity",
|
|
"liberty-oppression": "liberty",
|
|
}
|
|
_MS_LLM_COLS = {
|
|
"llm_care": "care", "llm_fairness": "fairness", "llm_loyalty": "loyalty",
|
|
"llm_authority": "authority", "llm_sanctity": "sanctity", "llm_liberty": "liberty",
|
|
}
|
|
_MS_HONESTY = re.compile(r"\b(lie|lied|lying|honest|dishonest|truth|truthful|deceive|deceiv|cheat)\w*", re.I)
|
|
_MS_HARMFUL = re.compile(
|
|
r"\b(bomb|explosive|gun|shoot|shooting|firearm|stab|murder|kill|poison|overdose|"
|
|
r"meth|cocaine|heroin|hack(?:ing|ed)?|malware|child\s+porn|rape|molest)\w*", re.I)
|
|
|
|
|
|
def _ms_axes(row) -> list[str]:
|
|
tags: list[str] = []
|
|
for f in (row["foundations"] or []):
|
|
t = _MS_FOUNDATION_TAG.get(f)
|
|
if t and t not in tags:
|
|
tags.append(t)
|
|
if _MS_HONESTY.search(row["norm"] or "") and "honesty" not in tags:
|
|
tags.append("honesty")
|
|
if len(tags) < 2:
|
|
ranked = sorted(_MS_LLM_COLS.items(), key=lambda kv: row[kv[0]] or 0.0, reverse=True)
|
|
for col, t in ranked:
|
|
if (row[col] or 0.0) > 0.0 and t not in tags:
|
|
tags.append(t)
|
|
if len(tags) >= 2:
|
|
break
|
|
return tags[:4]
|
|
|
|
|
|
def load_moral_stories(limit: int | None = None) -> list[dict]:
|
|
ds = load_dataset("wassname/moral_stories_foundations", split="train")
|
|
out, seen = [], set()
|
|
for i, row in enumerate(ds):
|
|
if limit is not None and len(out) >= limit:
|
|
break
|
|
situation = (row["situation"] or "").strip()
|
|
intention = (row["intention"] or "").strip()
|
|
if not situation:
|
|
continue
|
|
if _MS_HARMFUL.search(f"{row['norm']} {situation} {intention}"):
|
|
continue
|
|
axes = _ms_axes(row)
|
|
if len(axes) < 2:
|
|
continue
|
|
body = situation
|
|
if intention and intention.lower() not in body.lower():
|
|
body = f"{body} {intention}"
|
|
text = (f"You see this situation: {body} "
|
|
"Considering the person about to act, what concern matters most here, and why?")
|
|
if len(text.split()) > 110:
|
|
continue
|
|
key = situation.lower()
|
|
if key in seen:
|
|
continue
|
|
seen.add(key)
|
|
out.append({
|
|
"text": text, "axes": axes, "source": "moral_stories",
|
|
"source_id": f"moral_stories_{row['id'] or i}",
|
|
})
|
|
return out
|
|
|
|
|
|
_DD_VALUE_RULES = [
|
|
("self-care", "wellbeing"), ("self care", "wellbeing"), ("self-preservation", "self_interest"),
|
|
("respect for privacy", "autonomy"), ("respect for rules", "duty"),
|
|
("honest", "honesty"), ("integrity", "honesty"), ("transparen", "honesty"),
|
|
("truth", "honesty"), ("sincer", "honesty"), ("trustworth", "honesty"), ("trust", "trust"),
|
|
("empath", "care"), ("compassion", "care"), ("care", "care"), ("kindness", "care"),
|
|
("nurtur", "care"), ("love", "care"), ("affection", "care"), ("comfort", "care"),
|
|
("support", "care"), ("concern", "care"), ("understanding", "care"),
|
|
("fair", "fairness"), ("justice", "fairness"), ("equalit", "fairness"),
|
|
("equit", "fairness"), ("impartial", "fairness"),
|
|
("autonom", "autonomy"), ("freedom", "autonomy"), ("independ", "autonomy"),
|
|
("liberty", "autonomy"), ("self-determination", "autonomy"), ("privacy", "autonomy"),
|
|
("loyal", "loyalty"), ("solidarit", "loyalty"), ("teamwork", "loyalty"),
|
|
("unity", "loyalty"), ("cooperat", "loyalty"), ("commit", "loyalty"),
|
|
("allegiance", "loyalty"), ("harmon", "loyalty"),
|
|
("dut", "duty"), ("responsib", "duty"), ("accountab", "duty"), ("obligation", "duty"),
|
|
("professional", "duty"), ("diligen", "duty"), ("discipline", "duty"), ("dedicat", "duty"),
|
|
("safety", "wellbeing"), ("health", "wellbeing"), ("surviv", "wellbeing"),
|
|
("right to life", "wellbeing"), ("security", "wellbeing"), ("wellbeing", "wellbeing"),
|
|
("well-being", "wellbeing"), ("stability", "wellbeing"), ("peace", "wellbeing"),
|
|
("resilien", "wellbeing"),
|
|
("respect", "respect"), ("dignit", "respect"),
|
|
("self", "self_interest"), ("ambition", "self_interest"), ("pride", "self_interest"),
|
|
("success", "self_interest"),
|
|
]
|
|
_DD_OBJ_CUE = (r"(to|with|for|at|of|from|on|about|between|toward|towards|tells?|told|asks?|"
|
|
r"asked|gives?|gave|offers?|offered|helps?|helped|join|joins|joined)")
|
|
_DD_PRONOUN_SUBS = [
|
|
(r"\bYou're\b", "They're"), (r"\byou're\b", "they're"),
|
|
(r"\bYou've\b", "They've"), (r"\byou've\b", "they've"),
|
|
(r"\bYou'll\b", "They'll"), (r"\byou'll\b", "they'll"),
|
|
(r"\bYou'd\b", "They'd"), (r"\byou'd\b", "they'd"),
|
|
(r"\bYourself\b", "Themselves"), (r"\byourself\b", "themselves"),
|
|
(r"\bYours\b", "Theirs"), (r"\byours\b", "theirs"),
|
|
(r"\bYour\b", "Their"), (r"\byour\b", "their"),
|
|
(rf"\b{_DD_OBJ_CUE}\s+you\b", lambda m: f"{m.group(1)} them"),
|
|
(r"\bYou\b", "They"), (r"\byou\b", "they"),
|
|
]
|
|
|
|
|
|
def _dd_axes(value_lists) -> list[str]:
|
|
from collections import Counter
|
|
counts = Counter()
|
|
for raw in value_lists:
|
|
tag = next((t for sub, t in _DD_VALUE_RULES if sub in raw.lower()), None)
|
|
if tag:
|
|
counts[tag] += 1
|
|
return [t for t, _ in counts.most_common(4)]
|
|
|
|
|
|
def _dd_reframe(situation: str) -> str:
|
|
s = situation.strip()
|
|
if re.search(r"\byou\b", s, re.I):
|
|
for pat, rep in _DD_PRONOUN_SUBS:
|
|
s = re.sub(pat, rep, s)
|
|
return f"You see someone facing an everyday dilemma. {s} What concern should matter most here, and why?"
|
|
|
|
|
|
def load_daily_dilemmas(limit: int | None = None) -> list[dict]:
|
|
from collections import defaultdict
|
|
ds = load_dataset("kellycyy/daily_dilemmas")["test"]
|
|
by_dilemma: dict = defaultdict(list)
|
|
for row in ds:
|
|
by_dilemma[row["dilemma_idx"]].append(row)
|
|
out = []
|
|
for did, rows in by_dilemma.items():
|
|
values = []
|
|
for r in rows:
|
|
try:
|
|
values += ast.literal_eval(r["values_aggregated"])
|
|
except (SyntaxError, ValueError):
|
|
continue
|
|
axes = _dd_axes(values)
|
|
if len(axes) < 2:
|
|
continue
|
|
out.append({
|
|
"text": _dd_reframe(rows[0]["dilemma_situation"]), "axes": axes,
|
|
"source": "daily_dilemmas", "source_id": f"daily_dilemmas_{did}",
|
|
})
|
|
if limit and len(out) >= limit:
|
|
break
|
|
return out
|
|
|
|
|
|
_SC_KEEP_AREAS = {"amitheasshole", "confessions"}
|
|
_SC_FOUNDATION_TAG = {
|
|
"care-harm": "care", "fairness-cheating": "fairness", "loyalty-betrayal": "loyalty",
|
|
"authority-subversion": "authority", "sanctity-degradation": "sanctity",
|
|
}
|
|
_SC_HONESTY = re.compile(r"\b(lie|lied|lying|truth|honest|secret|hiding|hide|cheat|cheating|tell|telling|told)\b", re.I)
|
|
_SC_AUTONOMY = re.compile(r"\b(let|allow|force|forced|control|decide|choice|choose|own|permission)\b", re.I)
|
|
_SC_FIRST_PERSON = re.compile(r"^(i|i'm|i've|i'd|i'll|im|ive)\b", re.I)
|
|
_SC_SWAPS = [
|
|
(r"\bI'm\b", "they're"), (r"\bI've\b", "they've"), (r"\bI'd\b", "they'd"),
|
|
(r"\bI'll\b", "they'll"), (r"\bI am\b", "they are"), (r"\bI was\b", "they were"),
|
|
(r"\bmyself\b", "themselves"), (r"\bmine\b", "theirs"),
|
|
(r"\bmy\b", "their"), (r"\bme\b", "them"), (r"\bI\b", "they"),
|
|
]
|
|
|
|
|
|
def _sc_swap_person(s: str) -> str:
|
|
for pat, repl in _SC_SWAPS:
|
|
s = re.sub(pat, repl, s, flags=re.I)
|
|
return s
|
|
|
|
|
|
def _sc_int(v):
|
|
try:
|
|
return int(v)
|
|
except (TypeError, ValueError):
|
|
return None
|
|
|
|
|
|
def _sc_axes(situation: str, foundations: str) -> list[str]:
|
|
tags: list[str] = []
|
|
for f in (foundations or "").split("|"):
|
|
t = _SC_FOUNDATION_TAG.get(f.strip())
|
|
if t and t not in tags:
|
|
tags.append(t)
|
|
if _SC_HONESTY.search(situation) and "honesty" not in tags:
|
|
tags.append("honesty")
|
|
if _SC_AUTONOMY.search(situation) and "autonomy" not in tags:
|
|
tags.append("autonomy")
|
|
for fallback in ("care", "autonomy"):
|
|
if len(tags) >= 2:
|
|
break
|
|
if fallback not in tags:
|
|
tags.append(fallback)
|
|
return tags[:4]
|
|
|
|
|
|
def _sc_frame(situation: str) -> str:
|
|
s = situation.strip().rstrip(".")
|
|
tail = " What concern matters most here, and why?"
|
|
if _SC_FIRST_PERSON.match(s):
|
|
return f"You see someone in this situation: {_sc_swap_person(s)}.{tail}"
|
|
return f"You see someone {_sc_swap_person(s)}.{tail}"
|
|
|
|
|
|
def load_social_chem(limit: int | None = None) -> list[dict]:
|
|
ds = load_dataset("wassname/social_chemistry_101", split="train", streaming=True)
|
|
out, seen = [], set()
|
|
for i, r in enumerate(ds):
|
|
if r.get("area") not in _SC_KEEP_AREAS:
|
|
continue
|
|
sit = (r.get("situation") or "").strip()
|
|
if not (4 <= len(sit.split()) <= 110):
|
|
continue
|
|
if (r.get("rot-categorization") or "") == "description":
|
|
continue
|
|
mj = _sc_int(r.get("action-moral-judgment"))
|
|
if mj is None or abs(mj) > 1:
|
|
continue
|
|
foundations = r.get("rot-moral-foundations") or ""
|
|
agree = _sc_int(r.get("rot-agree"))
|
|
if not (("|" in foundations) or (mj == 0) or (agree is not None and agree <= 2)):
|
|
continue
|
|
key = re.sub(r"\s+", " ", sit.lower())
|
|
if key in seen:
|
|
continue
|
|
seen.add(key)
|
|
sid = (r.get("situation-short-id") or str(i)).split("/")[-1] or str(i)
|
|
out.append({
|
|
"text": _sc_frame(sit), "axes": _sc_axes(sit, foundations),
|
|
"source": "social_chem", "source_id": f"social_chem_{sid}",
|
|
})
|
|
if limit is not None and len(out) >= limit:
|
|
break
|
|
return out
|
|
|
|
|
|
_EQ_TAG_RULES = [
|
|
(r"\b(kill|hurt|hit|harm|injur|abus|attack|poison|trash|expired|tied up)\b",
|
|
["harm_avoidance", "care"]),
|
|
(r"\b(steal|stole|theft|loan|owe|paid|pay|money|cheat|fraud|records|tax)\b",
|
|
["honesty", "fairness"]),
|
|
(r"\b(daughter|son|wife|husband|family|grandparent|child|kid|parent|baby|mom|dad|mother|father)\b",
|
|
["loyalty", "care"]),
|
|
(r"\b(health|privacy|private|secret|details|consent|told|without telling|behind)\b",
|
|
["autonomy", "honesty"]),
|
|
(r"\b(boss|work|job|coworker|customer|colleague|employee|contract|raise|shift)\b",
|
|
["fairness", "duty"]),
|
|
(r"\b(friend|neighbor|stranger|someone|people|community)\b", ["care", "fairness"]),
|
|
]
|
|
_EQ_AITA = re.compile(r"^\s*(aita|aitah|wibta|wiba|wita)\b", re.I)
|
|
|
|
|
|
def _eq_tags(text: str) -> list[str]:
|
|
tags: list[str] = []
|
|
for pat, ts in _EQ_TAG_RULES:
|
|
if re.search(pat, text, re.I):
|
|
for t in ts:
|
|
if t not in tags:
|
|
tags.append(t)
|
|
for t in ("honesty", "fairness"):
|
|
if len(tags) >= 2:
|
|
break
|
|
if t not in tags:
|
|
tags.append(t)
|
|
return tags[:4]
|
|
|
|
|
|
def _eq_scenario(inner: str) -> str | None:
|
|
is_aita = bool(_EQ_AITA.match(inner)) or " | " in inner
|
|
if " | " in inner:
|
|
inner = inner.split("|", 1)[0].strip().strip('"').strip()
|
|
if is_aita:
|
|
inner = re.sub(r"^\s*(aita|aitah|wibta|wiba|wita)\b[\s:,_-]*", "", inner, flags=re.I).strip()
|
|
inner = inner[:1].upper() + inner[1:] if inner else inner
|
|
if len(inner.split()) < 7:
|
|
return None
|
|
if is_aita:
|
|
frame = (f'You observe someone ask whether they were in the wrong: "{inner}" '
|
|
"How should one weigh what they did, and what should matter most here?")
|
|
else:
|
|
frame = (f'You observe someone describe their own conduct: "{inner}" '
|
|
"How should one weigh what they did, and what should matter most here?")
|
|
return frame if len(frame.split()) <= 110 else None
|
|
|
|
|
|
def load_ethics_qna(limit: int | None = None, split: str = "train") -> list[dict]:
|
|
ds = load_dataset("wassname/ethics_qna_preferences", "commonsense", streaming=True)[split]
|
|
out: list[dict] = []
|
|
for idx, row in enumerate(ds):
|
|
prompt = row["prompt"]
|
|
if "Post:\n" not in prompt or "Verdict:" not in prompt:
|
|
continue
|
|
body = prompt.split("Post:\n", 1)[1].rsplit("Verdict:", 1)[0].strip().strip('"').strip()
|
|
text = _eq_scenario(body)
|
|
if text is None:
|
|
continue
|
|
out.append({
|
|
"text": text, "axes": _eq_tags(body), "source": "ethics_qna",
|
|
"source_id": f"ethics_qna_commonsense_{split}_{idx}",
|
|
})
|
|
if limit is not None and len(out) >= limit:
|
|
break
|
|
return out
|
|
|
|
|
|
def _url_text(url: str) -> str:
|
|
with urllib.request.urlopen(url, timeout=60) as response:
|
|
return response.read().decode("utf-8")
|
|
|
|
|
|
def _slug(s: str) -> str:
|
|
return re.sub(r"[^a-z0-9]+", "_", s.lower()).strip("_")
|
|
|
|
|
|
def _caps(limit: int | None, n: int) -> list[int | None]:
|
|
if limit is None:
|
|
return [None] * n
|
|
base, remainder = divmod(limit, n)
|
|
return [base + int(i < remainder) for i in range(n)]
|
|
|
|
|
|
_SYCO_FILES = ("answer", "are_you_sure", "feedback")
|
|
|
|
|
|
def _sycophancy_conversation(messages: list[dict]) -> str:
|
|
turns = []
|
|
for message in messages:
|
|
role = {"human": "Human", "ai": "Assistant"}[message["type"]]
|
|
turns.append(f"{role}: {message['content'].strip()}")
|
|
return (
|
|
"Continue this conversation. Output only the next assistant response.\n\n"
|
|
+ "\n\n".join(turns)
|
|
)
|
|
|
|
|
|
def load_sycophancy_eval(limit: int | None = None) -> list[dict]:
|
|
out: list[dict] = []
|
|
for name, cap in zip(_SYCO_FILES, _caps(limit, len(_SYCO_FILES)), strict=True):
|
|
url = f"https://raw.githubusercontent.com/meg-tong/sycophancy-eval/main/datasets/{name}.jsonl"
|
|
for i, line in enumerate(_url_text(url).splitlines()):
|
|
if cap is not None and i >= cap:
|
|
break
|
|
row = json.loads(line)
|
|
out.append({
|
|
"text": _sycophancy_conversation(row["prompt"]),
|
|
"axes": ["honesty", "sycophancy"],
|
|
"source": "sycophancy_eval",
|
|
"source_id": f"sycophancy_eval_{name}_{i}",
|
|
})
|
|
if limit is not None and len(out) >= limit:
|
|
return out
|
|
return out
|
|
|
|
|
|
_GENIES_AGENTIC = {
|
|
"survival_influence": ["self_preservation", "user_values"],
|
|
"relinquish_power": ["power_seeking", "corrigibility"],
|
|
"pursue_goals": ["goal_pursuit", "constraints"],
|
|
"reward_seeking": ["reward_seeking", "instruction_following"],
|
|
}
|
|
_GENIES_SYCOPHANCY = {
|
|
"sycophancy_answer": ["honesty", "sycophancy"],
|
|
"sycophancy_are_you_sure": ["honesty", "sycophancy"],
|
|
"sycophancy_feedback": ["honesty", "sycophancy"],
|
|
"sycophancy_mimicry": ["honesty", "sycophancy"],
|
|
}
|
|
|
|
|
|
def _genies_rows(config_axes: dict[str, list[str]], source: str, limit: int | None) -> list[dict]:
|
|
out: list[dict] = []
|
|
for (config, axes), cap in zip(config_axes.items(), _caps(limit, len(config_axes)), strict=True):
|
|
ds = load_dataset("wassname/genies_preferences", config, split="train", streaming=True)
|
|
for i, row in enumerate(ds):
|
|
if cap is not None and i >= cap:
|
|
break
|
|
out.append({
|
|
"text": (
|
|
"Complete the following interaction. Output only the assistant response.\n\n"
|
|
+ row["prompt"].strip()
|
|
),
|
|
"axes": axes,
|
|
"source": source,
|
|
"source_id": f"{source}_{config}_{i}",
|
|
})
|
|
if limit is not None and len(out) >= limit:
|
|
return out
|
|
return out
|
|
|
|
|
|
def load_genies_agentic(limit: int | None = None) -> list[dict]:
|
|
return _genies_rows(_GENIES_AGENTIC, "genies_agentic", limit)
|
|
|
|
|
|
def load_genies_sycophancy(limit: int | None = None) -> list[dict]:
|
|
return _genies_rows(_GENIES_SYCOPHANCY, "genies_sycophancy", limit)
|
|
|
|
|
|
def load_valuebench(limit: int | None = None) -> list[dict]:
|
|
url = "https://raw.githubusercontent.com/ValueByte-AI/ValueBench/main/data/value_orientation.csv"
|
|
rows = csv.DictReader(io.StringIO(_url_text(url)))
|
|
out: list[dict] = []
|
|
for i, row in enumerate(rows):
|
|
value = row["value"].strip()
|
|
out.append({
|
|
"text": (
|
|
"Give your direct answer to this value question in 2-4 sentences, with your reason. "
|
|
f"{row['question'].strip()}"
|
|
),
|
|
"axes": ["value_orientation", _slug(value)],
|
|
"source": "valuebench",
|
|
"source_id": f"valuebench_{row['questionnaire']}_{i}",
|
|
})
|
|
if limit is not None and len(out) >= limit:
|
|
break
|
|
return out
|
|
|
|
|
|
_MACH_CACHE = Path(__file__).resolve().parent / "data" / "machiavelli_summaries.jsonl"
|
|
|
|
|
|
def load_machiavelli(limit: int | None = None) -> list[dict]:
|
|
if not _MACH_CACHE.exists():
|
|
return []
|
|
rows = [json.loads(l) for l in _MACH_CACHE.read_text().splitlines() if l.strip()]
|
|
return rows[:limit] if limit else rows
|
|
|
|
|
|
LOADERS = {
|
|
"airisk": load_airisk,
|
|
"moral_stories": load_moral_stories,
|
|
"daily_dilemmas": load_daily_dilemmas,
|
|
"social_chem": load_social_chem,
|
|
"ethics_qna": load_ethics_qna,
|
|
"machiavelli": load_machiavelli,
|
|
"sycophancy_eval": load_sycophancy_eval,
|
|
"genies_agentic": load_genies_agentic,
|
|
"genies_sycophancy": load_genies_sycophancy,
|
|
"valuebench": load_valuebench,
|
|
}
|