diff --git a/AGENTS.md b/AGENTS.md index 3bd95b7..4daf6d9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ **This is fail-fast research code.** Novel work, not in your training data. Extrapolate carefully. -## What tinymfv is +## What moralmaps is One answer-token logprob reader that runs many questionnaires. The model is prefilled to an answer slot after a short think budget; we read the next-token distribution over the vocab and diff --git a/docs/img/README.md b/docs/img/README.md index 7bb8dca..09cf747 100644 --- a/docs/img/README.md +++ b/docs/img/README.md @@ -1,4 +1,4 @@ -# tinymfv figures +# moralmaps figures A gallery of the culture maps and range plots. Each is captioned the newspaper way: a title, a one-line subtitle saying what you are looking at, a short caption pointing out what to notice, and a @@ -42,7 +42,7 @@ GlobalOpinionQA (Durmus et al. 2023). The maps below all show the **same run**. The base model **Qwen3-4B** is read at c=0 (black), then pushed along a single **Authority** vector to +c (red, more Authority) and -c (blue, less). The vector is a PCA direction that [steering-lite](https://github.com/wassname/steering-lite) builds from an -`authority-respecting` versus `authority-disregarding` persona pair; tinymfv only measures where the +`authority-respecting` versus `authority-disregarding` persona pair; moralmaps only measures where the model lands, by logprobs, eight samples per item. Each instrument gets two maps: a **quadrant map** on named axes taken from the literature, and an **ipsative PCA map** whose axes are the blind top-two principal components, with a compass rose showing how the factors load. @@ -83,7 +83,7 @@ is the model: it emphasises Authority far more than the pooled human reference, further still. Sources: MFV (Clifford et al. 2015); country norms Jimenez-Leal 2025, Marques 2020, Hopp 2024, Yamada -2025, Crone 2021, used pooled only (see `src/tinymfv/data/human/MFV_country_norms_NOTE.md`). Read by +2025, Crone 2021, used pooled only (see `src/moralmaps/data/human/MFV_country_norms_NOTE.md`). Read by logprobs, N=8. ### Big Five diff --git a/pyproject.toml b/pyproject.toml index caad3dc..f10d4b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "tiny-mfv" +name = "moral-maps" version = "0.1.0" description = "Moral and value maps for LLMs: World Values Survey, MFQ-2, Big Five, 16PF, humor styles, and moral vignettes, scored from answer probabilities (local) or rated sampling (API) and compared to human country norms. Built for steering work." requires-python = ">=3.11" @@ -14,14 +14,14 @@ dependencies = [ ] [project.optional-dependencies] -# tinymfv.maps (culture-map + range viz) only; `import tinymfv` and the evals stay headless, -# numeric-only consumers (steering-lite) skip this. Install with `pip install tiny-mfv[maps]`. +# moralmaps.maps (culture-map + range viz) only; `import moralmaps` and the evals stay headless, +# numeric-only consumers (steering-lite) skip this. Install with `pip install moral-maps[maps]`. maps = [ "matplotlib>=3.8", "shapely>=2.0", # union of per-country discs into one merged zone region -] # label placement is in-repo (tinymfv.labelplace); no textalloc/adjustText dep -# tinymfv.read_api (sampling readout for logprob-less API models) only. Install with -# `pip install tiny-mfv[api]`. The local logprob reader (read.py) needs none of this. +] # label placement is in-repo (moralmaps.labelplace); no textalloc/adjustText dep +# moralmaps.read_api (sampling readout for logprob-less API models) only. Install with +# `pip install moral-maps[api]`. The local logprob reader (read.py) needs none of this. api = [ # robust OpenRouter calls (stamina backoff on 429/provider/upstream/malformed errors) -- # wassname's wrapper, so retry/rate-limit handling doesn't diverge from the rest of the stack. @@ -42,4 +42,4 @@ build-backend = "hatchling.build" allow-direct-references = true # the api extra pulls openrouter_wrapper straight from git [tool.hatch.build.targets.wheel] -packages = ["src/tinymfv"] +packages = ["src/moralmaps"] diff --git a/scripts/05_upload_hf.py b/scripts/05_upload_hf.py index 228b0fc..49e97f6 100644 --- a/scripts/05_upload_hf.py +++ b/scripts/05_upload_hf.py @@ -29,7 +29,7 @@ SPLITS = ["other_violate", "self_violate"] def local_jsonl(file_key: str, split: str) -> Path: - return ROOT / "src" / "tinymfv" / "data" / f"vignettes_{file_key}_{split}.jsonl" + return ROOT / "src" / "moralmaps" / "data" / f"vignettes_{file_key}_{split}.jsonl" def hf_jsonl(cfg: str, split: str) -> str: @@ -65,7 +65,7 @@ size_categories: --- # tiny-mfv -[:octocat:](https://github.com/wassname/tinymfv) +[:octocat:](https://github.com/wassname/moral-maps) Small moral-foundations eval for language models. @@ -129,9 +129,9 @@ Calibration quality on classic, n=132: ## Eval -Use `tinymfv.evaluate(model, tokenizer, name="classic")`. It returns a per-foundation +Use `moralmaps.evaluate(model, tokenizer, name="classic")`. It returns a per-foundation table plus `top1_acc`, `informedness`, and `mean_nll_T` against the `human_*` label -distribution. Full eval: see [tiny-mfv on GitHub](https://github.com/wassname/tinymfv). +distribution. Full eval: see [moral-maps on GitHub](https://github.com/wassname/moral-maps). Source vignettes: https://github.com/peterkirgis/llm-moral-foundations """ diff --git a/scripts/09_forced_choice.py b/scripts/09_forced_choice.py index cdfa57a..377fbb7 100644 --- a/scripts/09_forced_choice.py +++ b/scripts/09_forced_choice.py @@ -1,6 +1,6 @@ """Run forced-choice 7-way primary-foundation probe over a vignette set. -Wraps `tinymfv.evaluate()`. Reports the AI-vs-label distribution match: +Wraps `moralmaps.evaluate()`. Reports the AI-vs-label distribution match: top1_acc argmax model == argmax label mean_nll soft cross-entropy vs human distribution, nats mean_nll_T same metric after one fitted temperature @@ -27,8 +27,8 @@ from loguru import logger from tabulate import tabulate from transformers import AutoModelForCausalLM, AutoTokenizer -from tinymfv import evaluate, load_vignettes -from tinymfv.guided import _DEFAULT_FORCED_FOUNDATIONS +from moralmaps import evaluate, load_vignettes +from moralmaps.guided import _DEFAULT_FORCED_FOUNDATIONS ROOT = Path(__file__).resolve().parents[1] diff --git a/scripts/bootstrap_mfq2_sample_n.py b/scripts/bootstrap_mfq2_sample_n.py index 4ad7b05..c16ec47 100644 --- a/scripts/bootstrap_mfq2_sample_n.py +++ b/scripts/bootstrap_mfq2_sample_n.py @@ -10,8 +10,8 @@ from pathlib import Path import numpy as np from tabulate import tabulate -from tinymfv.instrument import canonicalize_to_forward -from tinymfv.readouts import logit_contrast +from moralmaps.instrument import canonicalize_to_forward +from moralmaps.readouts import logit_contrast def _rows(path: Path) -> list[dict]: diff --git a/scripts/plot_2d_grid.py b/scripts/plot_2d_grid.py index 7774814..d224ce8 100644 --- a/scripts/plot_2d_grid.py +++ b/scripts/plot_2d_grid.py @@ -27,8 +27,8 @@ matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np -import tinymfv as T -from tinymfv.zones import zones_for +import moralmaps as T +from moralmaps.zones import zones_for ORDINAL = ["mfq2", "big5", "humor_styles"] FOUNDATION_ORDER = ["care", "fairness", "loyalty", "authority", "sanctity", "liberty"] diff --git a/scripts/plot_steer_showcase.py b/scripts/plot_steer_showcase.py index 639510f..8c01722 100644 --- a/scripts/plot_steer_showcase.py +++ b/scripts/plot_steer_showcase.py @@ -1,4 +1,4 @@ -"""Showcase tinymfv's plotting on a real steering run. +"""Showcase moralmaps's plotting on a real steering run. Consumes a steering-lite `run_allinstr_showcase.py` output dir (one calibrated activation-steering vector administered across every instrument over a signed @@ -13,7 +13,7 @@ probabilities cannot share a raw axis with 1-5 survey scores. It still goes through the same plot_ipsative_pca / plot_range functions. cs are SIGNED multipliers of the calibrated coefficient C (0 = base). The public -README plots show the coherent path: c=0 plus each +/-c row whose tinymfv answer mass +README plots show the coherent path: c=0 plus each +/-c row whose moralmaps answer mass stays above the requested fraction of base. Incoherent rows are dropped. uv run python scripts/plot_steer_showcase.py \ @@ -35,9 +35,9 @@ matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np -import tinymfv as T -from tinymfv import get_instrument -from tinymfv.zones import zones_for +import moralmaps as T +from moralmaps import get_instrument +from moralmaps.zones import zones_for # 16pf turned off: even at 6 macro zones its ipsative map is an unreadable pile-up (that instrument # doesn't separate cultures; Brazil/Ecuador stretch Latin America across the whole plot). -- Claude @@ -49,7 +49,7 @@ def _frac(x, scale_max: int) -> np.ndarray: def read_human_csv(path: str) -> dict[tuple[str, str], float]: - """{(country, foundation): mean} from a tinymfv human_.csv.""" + """{(country, foundation): mean} from a moralmaps human_.csv.""" out: dict[tuple[str, str], float] = {} with open(path, newline="") as fh: for r in csv.DictReader(fh): @@ -212,7 +212,7 @@ def plot_ordinal(run_dir: Path, out: Path, name: str, vec_label: str, C: float, # Alternative NAMED-AXIS value map (interpretable poles, no compass/minimap): project the # societies + the AI base/steered points onto the instrument's two named value axes, and draw the # steer as a CONNECTED base->+c/-c path (same visual language as the ipsative map's trajectory). - from tinymfv.value_axes import VALUE_AXES, value_coords, axis_score + from moralmaps.value_axes import VALUE_AXES, value_coords, axis_score if name in VALUE_AXES: Pval, poles = value_coords(Mfrac, dims, name) (_, _, xa), (_, _, ya) = VALUE_AXES[name] diff --git a/scripts/probe_api_readout.py b/scripts/probe_api_readout.py index f91407e..bf0dd8b 100644 --- a/scripts/probe_api_readout.py +++ b/scripts/probe_api_readout.py @@ -26,11 +26,11 @@ from loguru import logger from tabulate import tabulate from transformers import AutoModelForCausalLM, AutoTokenizer -import tinymfv as T -from tinymfv.instruments import get as get_instrument -from tinymfv.read import read_items, resolve_answer_ids, build_user_content -from tinymfv.read_api import read_items_sampled -from tinymfv.readouts import expected_score, entropy +import moralmaps as T +from moralmaps.instruments import get as get_instrument +from moralmaps.read import read_items, resolve_answer_ids, build_user_content +from moralmaps.read_api import read_items_sampled +from moralmaps.readouts import expected_score, entropy W = np.arange(1, 6, dtype=float) diff --git a/scripts/probe_iw_themes.py b/scripts/probe_iw_themes.py index 900ee6c..2e6b0c6 100644 --- a/scripts/probe_iw_themes.py +++ b/scripts/probe_iw_themes.py @@ -10,7 +10,7 @@ import re from datasets import load_dataset -from tinymfv.zones import zone_of +from moralmaps.zones import zone_of SKIP = re.compile(r"don'?t know|no answer|refus|decline|none of|not applicable|^other|missing|inap", re.I) diff --git a/scripts/probe_mfv_think_budget.py b/scripts/probe_mfv_think_budget.py index 75f78d3..bb6b273 100644 --- a/scripts/probe_mfv_think_budget.py +++ b/scripts/probe_mfv_think_budget.py @@ -22,7 +22,7 @@ import torch from loguru import logger from transformers import AutoModelForCausalLM, AutoTokenizer -from tinymfv import evaluate +from moralmaps import evaluate def main() -> None: diff --git a/scripts/probe_word_readout.py b/scripts/probe_word_readout.py index 6cb1190..03afda3 100644 --- a/scripts/probe_word_readout.py +++ b/scripts/probe_word_readout.py @@ -2,7 +2,7 @@ 0.826 top-1 in the validation table (journal 2026-05-08), and contrast it with the current debiased DIGIT readout (0.773). -This does NOT touch the canonical eval. tinymfv.evaluate stays digit-only. This is a +This does NOT touch the canonical eval. moralmaps.evaluate stays digit-only. This is a throwaway measurement (like the other probe_* scripts) that reuses the current _rollout_natural_or_forced core but gathers the first token of each foundation WORD (care/fair/loy/author/san/lib/social) instead of the option index digit -- the one @@ -26,9 +26,9 @@ import torch from loguru import logger from transformers import AutoModelForCausalLM, AutoTokenizer -from tinymfv.data import load_vignettes -from tinymfv.eval import _label_dist -from tinymfv.guided import ( +from moralmaps.data import load_vignettes +from moralmaps.eval import _label_dist +from moralmaps.guided import ( _DEFAULT_FORCED_FOUNDATIONS, _FORCED_FOUNDATION_DESCS, _resolve_first_token_ids, _rollout_natural_or_forced, ) diff --git a/scripts/probe_wvs_foundation.py b/scripts/probe_wvs_foundation.py index 1cb2f46..c0f6d34 100644 --- a/scripts/probe_wvs_foundation.py +++ b/scripts/probe_wvs_foundation.py @@ -1,7 +1,7 @@ """P4 data foundation: what the GlobalOpinionQA WVS subset gives us for a WVS/Inglehart-Welzel map. Anthropic/llm_global_opinions is MC questions with per-country human answer distributions -- almost -exactly tinymfv's instrument shape (allowed answer tokens + human anchors). This probe quantifies +exactly moralmaps's instrument shape (allowed answer tokens + human anchors). This probe quantifies the WVS subset's coverage and prints the parse recipe, so we know a country x question matrix is dense enough to place models among human societies. No model runs here. diff --git a/scripts/summarize_showcase_effects.py b/scripts/summarize_showcase_effects.py index bc47d27..c7a6207 100644 --- a/scripts/summarize_showcase_effects.py +++ b/scripts/summarize_showcase_effects.py @@ -8,7 +8,7 @@ from pathlib import Path import numpy as np import plot_steer_showcase as P -from tinymfv import get_instrument +from moralmaps import get_instrument DISPLAY = { "mfv": "MFV vignettes", diff --git a/scripts/wvs_map.py b/scripts/wvs_map.py index 5430301..7b9ed74 100644 --- a/scripts/wvs_map.py +++ b/scripts/wvs_map.py @@ -4,7 +4,7 @@ Economist chart), on the two named IW dimensions instead of a blind PCA. X = Survival <-> Self-expression (homosexuality tolerance, interpersonal trust, political action) Y = Traditional <-> Secular-Rational (religion importance + belief, abortion, child autonomy) -Each axis is a small hand-picked battery of GlobalOpinionQA WVS items (tinymfv.iw_axes), every item +Each axis is a small hand-picked battery of GlobalOpinionQA WVS items (moralmaps.iw_axes), every item oriented to its axis-positive pole by reading the option order. A country's coordinate is the mean `positiveness` (0-1) over that axis's items from the human WVS choice frequencies. A model's coordinate is the SAME items administered as a dense Likert readout (read_items_rated: rate every @@ -40,12 +40,12 @@ import matplotlib.pyplot as plt from datasets import load_dataset from transformers import AutoModelForCausalLM, AutoTokenizer -from tinymfv import maps -from tinymfv.zones import zones_for, zone_of -from tinymfv.instrument import Instrument, InstrItem -from tinymfv.read import read_items, resolve_answer_ids -from tinymfv.read_api import read_items_rated -from tinymfv.iw_axes import AXIS_ITEMS, X_AXIS, Y_AXIS, SKIP, resolve_items, positiveness +from moralmaps import maps +from moralmaps.zones import zones_for, zone_of +from moralmaps.instrument import Instrument, InstrItem +from moralmaps.read import read_items, resolve_answer_ids +from moralmaps.read_api import read_items_rated +from moralmaps.iw_axes import AXIS_ITEMS, X_AXIS, Y_AXIS, SKIP, resolve_items, positiveness # option labels are single digits 0..n-1 -- single-token (unlike '10' on the justifiable scale) and # the format the answer-token reader is tuned for (a bare digit, not a letter the model ignores in diff --git a/src/tinymfv/__init__.py b/src/moralmaps/__init__.py similarity index 86% rename from src/tinymfv/__init__.py rename to src/moralmaps/__init__.py index b1372bb..a691ec7 100644 --- a/src/tinymfv/__init__.py +++ b/src/moralmaps/__init__.py @@ -1,4 +1,4 @@ -"""tinymfv: tiny moral/value instruments for local LLMs. +"""moralmaps: moral and value instruments for LLMs. One answer-token reader, two reducer families: @@ -9,7 +9,7 @@ One answer-token reader, two reducer families: High-level usage: - from tinymfv import evaluate + from moralmaps import evaluate from transformers import AutoModelForCausalLM, AutoTokenizer tok = AutoTokenizer.from_pretrained("Qwen/Qwen3-4B") @@ -19,7 +19,7 @@ High-level usage: print(rep["top1_acc"]) # argmax accuracy vs label print(rep["mean_nll_T"]) # temperature-scaled soft NLL vs label dist -Lower-level: see `guided_rollout_forced_choice` in `tinymfv.guided`. +Lower-level: see `guided_rollout_forced_choice` in `moralmaps.guided`. """ from .data import load_vignettes, load_all_vignettes, CONFIGS, ConfigName from .eval import evaluate, CONDITIONS, EvalResult, EvalRow, EvalInfo @@ -32,8 +32,8 @@ from .administer import administer def __getattr__(name: str): - # `maps` pulls matplotlib; load it lazily so `import tinymfv` stays headless and fast for the - # numeric-only consumers (steering-lite). `tinymfv.maps.plot_*` still works -- first access + # `maps` pulls matplotlib; load it lazily so `import moralmaps` stays headless and fast for the + # numeric-only consumers (steering-lite). `moralmaps.maps.plot_*` still works -- first access # triggers the import here. if name == "maps": import importlib diff --git a/src/tinymfv/administer.py b/src/moralmaps/administer.py similarity index 98% rename from src/tinymfv/administer.py rename to src/moralmaps/administer.py index 68178e3..c33bcc0 100644 --- a/src/tinymfv/administer.py +++ b/src/moralmaps/administer.py @@ -1,6 +1,6 @@ """Run an ordinal Instrument end-to-end on a local model -> profile + coherence check. -This is the survey counterpart to `tinymfv.evaluate` (the vignette forced-choice eval). It ties: +This is the survey counterpart to `moralmaps.evaluate` (the vignette forced-choice eval). It ties: read_items (answer-token readout, all frames) per_item_categorical (canonicalize each frame to forward, average -> one dist per item) diff --git a/src/tinymfv/data.py b/src/moralmaps/data.py similarity index 99% rename from src/tinymfv/data.py rename to src/moralmaps/data.py index ccf4a86..f9ba05e 100644 --- a/src/tinymfv/data.py +++ b/src/moralmaps/data.py @@ -1,7 +1,7 @@ """Dataset loading. Reads per-condition jsonls and inner-joins by id, returning the packed structure the eval consumes. -Files used by eval live in `src/tinymfv/data/`: +Files used by eval live in `src/moralmaps/data/`: vignettes__other_violate.jsonl (3rd-person paraphrase of origin) vignettes__self_violate.jsonl (1st-person rewrite) diff --git a/src/tinymfv/data/atari_study2_raw.csv b/src/moralmaps/data/atari_study2_raw.csv similarity index 100% rename from src/tinymfv/data/atari_study2_raw.csv rename to src/moralmaps/data/atari_study2_raw.csv diff --git a/src/tinymfv/data/human/16pf_country_factors.csv b/src/moralmaps/data/human/16pf_country_factors.csv similarity index 100% rename from src/tinymfv/data/human/16pf_country_factors.csv rename to src/moralmaps/data/human/16pf_country_factors.csv diff --git a/src/tinymfv/data/human/MFV_country_norms_NOTE.md b/src/moralmaps/data/human/MFV_country_norms_NOTE.md similarity index 98% rename from src/tinymfv/data/human/MFV_country_norms_NOTE.md rename to src/moralmaps/data/human/MFV_country_norms_NOTE.md index 0b2a8b2..adca526 100644 --- a/src/tinymfv/data/human/MFV_country_norms_NOTE.md +++ b/src/moralmaps/data/human/MFV_country_norms_NOTE.md @@ -1,6 +1,6 @@ # MFV country norms: used POOLED only, never for cross-country comparison -`mfv_country_factors.csv` holds moral-foundation-vignette (MFV) means for 8 countries. tinymfv uses +`mfv_country_factors.csv` holds moral-foundation-vignette (MFV) means for 8 countries. moralmaps uses these **pooled into a single human reference** (the mean across samples, per foundation) for the MFV range plot. It does **not** plot them as a cultural map, and you should not read country-to-country differences off this table. Here is why. diff --git a/src/tinymfv/data/human/big5_country_factors.csv b/src/moralmaps/data/human/big5_country_factors.csv similarity index 100% rename from src/tinymfv/data/human/big5_country_factors.csv rename to src/moralmaps/data/human/big5_country_factors.csv diff --git a/src/tinymfv/data/human/humor_styles_country_factors.csv b/src/moralmaps/data/human/humor_styles_country_factors.csv similarity index 100% rename from src/tinymfv/data/human/humor_styles_country_factors.csv rename to src/moralmaps/data/human/humor_styles_country_factors.csv diff --git a/src/tinymfv/data/human/mfq2_country_foundations.csv b/src/moralmaps/data/human/mfq2_country_foundations.csv similarity index 100% rename from src/tinymfv/data/human/mfq2_country_foundations.csv rename to src/moralmaps/data/human/mfq2_country_foundations.csv diff --git a/src/tinymfv/data/human/mfv_country_factors.csv b/src/moralmaps/data/human/mfv_country_factors.csv similarity index 100% rename from src/tinymfv/data/human/mfv_country_factors.csv rename to src/moralmaps/data/human/mfv_country_factors.csv diff --git a/src/tinymfv/data/surveys/16pf/keying.json b/src/moralmaps/data/surveys/16pf/keying.json similarity index 100% rename from src/tinymfv/data/surveys/16pf/keying.json rename to src/moralmaps/data/surveys/16pf/keying.json diff --git a/src/tinymfv/data/surveys/16pf/questionnaire.json b/src/moralmaps/data/surveys/16pf/questionnaire.json similarity index 100% rename from src/tinymfv/data/surveys/16pf/questionnaire.json rename to src/moralmaps/data/surveys/16pf/questionnaire.json diff --git a/src/tinymfv/data/surveys/16pf/questionnaire_inverted.json b/src/moralmaps/data/surveys/16pf/questionnaire_inverted.json similarity index 100% rename from src/tinymfv/data/surveys/16pf/questionnaire_inverted.json rename to src/moralmaps/data/surveys/16pf/questionnaire_inverted.json diff --git a/src/tinymfv/data/surveys/16pf/questionnaire_negated.json b/src/moralmaps/data/surveys/16pf/questionnaire_negated.json similarity index 100% rename from src/tinymfv/data/surveys/16pf/questionnaire_negated.json rename to src/moralmaps/data/surveys/16pf/questionnaire_negated.json diff --git a/src/tinymfv/data/surveys/big5/keying.json b/src/moralmaps/data/surveys/big5/keying.json similarity index 100% rename from src/tinymfv/data/surveys/big5/keying.json rename to src/moralmaps/data/surveys/big5/keying.json diff --git a/src/tinymfv/data/surveys/big5/questionnaire.json b/src/moralmaps/data/surveys/big5/questionnaire.json similarity index 100% rename from src/tinymfv/data/surveys/big5/questionnaire.json rename to src/moralmaps/data/surveys/big5/questionnaire.json diff --git a/src/tinymfv/data/surveys/big5/questionnaire_inverted.json b/src/moralmaps/data/surveys/big5/questionnaire_inverted.json similarity index 100% rename from src/tinymfv/data/surveys/big5/questionnaire_inverted.json rename to src/moralmaps/data/surveys/big5/questionnaire_inverted.json diff --git a/src/tinymfv/data/surveys/big5/questionnaire_negated.json b/src/moralmaps/data/surveys/big5/questionnaire_negated.json similarity index 100% rename from src/tinymfv/data/surveys/big5/questionnaire_negated.json rename to src/moralmaps/data/surveys/big5/questionnaire_negated.json diff --git a/src/tinymfv/data/surveys/humor_styles/keying.json b/src/moralmaps/data/surveys/humor_styles/keying.json similarity index 100% rename from src/tinymfv/data/surveys/humor_styles/keying.json rename to src/moralmaps/data/surveys/humor_styles/keying.json diff --git a/src/tinymfv/data/surveys/humor_styles/questionnaire.json b/src/moralmaps/data/surveys/humor_styles/questionnaire.json similarity index 100% rename from src/tinymfv/data/surveys/humor_styles/questionnaire.json rename to src/moralmaps/data/surveys/humor_styles/questionnaire.json diff --git a/src/tinymfv/data/surveys/humor_styles/questionnaire_inverted.json b/src/moralmaps/data/surveys/humor_styles/questionnaire_inverted.json similarity index 100% rename from src/tinymfv/data/surveys/humor_styles/questionnaire_inverted.json rename to src/moralmaps/data/surveys/humor_styles/questionnaire_inverted.json diff --git a/src/tinymfv/data/surveys/humor_styles/questionnaire_negated.json b/src/moralmaps/data/surveys/humor_styles/questionnaire_negated.json similarity index 100% rename from src/tinymfv/data/surveys/humor_styles/questionnaire_negated.json rename to src/moralmaps/data/surveys/humor_styles/questionnaire_negated.json diff --git a/src/tinymfv/data/surveys/mfq2/forward.json b/src/moralmaps/data/surveys/mfq2/forward.json similarity index 100% rename from src/tinymfv/data/surveys/mfq2/forward.json rename to src/moralmaps/data/surveys/mfq2/forward.json diff --git a/src/tinymfv/data/surveys/mfq2/inverted.json b/src/moralmaps/data/surveys/mfq2/inverted.json similarity index 100% rename from src/tinymfv/data/surveys/mfq2/inverted.json rename to src/moralmaps/data/surveys/mfq2/inverted.json diff --git a/src/tinymfv/data/surveys/mfq2/negated.json b/src/moralmaps/data/surveys/mfq2/negated.json similarity index 100% rename from src/tinymfv/data/surveys/mfq2/negated.json rename to src/moralmaps/data/surveys/mfq2/negated.json diff --git a/src/tinymfv/data/vignettes_ai-actor_other_violate.jsonl b/src/moralmaps/data/vignettes_ai-actor_other_violate.jsonl similarity index 100% rename from src/tinymfv/data/vignettes_ai-actor_other_violate.jsonl rename to src/moralmaps/data/vignettes_ai-actor_other_violate.jsonl diff --git a/src/tinymfv/data/vignettes_ai-actor_self_violate.jsonl b/src/moralmaps/data/vignettes_ai-actor_self_violate.jsonl similarity index 100% rename from src/tinymfv/data/vignettes_ai-actor_self_violate.jsonl rename to src/moralmaps/data/vignettes_ai-actor_self_violate.jsonl diff --git a/src/tinymfv/data/vignettes_classic_other_violate.jsonl b/src/moralmaps/data/vignettes_classic_other_violate.jsonl similarity index 100% rename from src/tinymfv/data/vignettes_classic_other_violate.jsonl rename to src/moralmaps/data/vignettes_classic_other_violate.jsonl diff --git a/src/tinymfv/data/vignettes_classic_self_violate.jsonl b/src/moralmaps/data/vignettes_classic_self_violate.jsonl similarity index 100% rename from src/tinymfv/data/vignettes_classic_self_violate.jsonl rename to src/moralmaps/data/vignettes_classic_self_violate.jsonl diff --git a/src/tinymfv/data/vignettes_scifi_other_violate.jsonl b/src/moralmaps/data/vignettes_scifi_other_violate.jsonl similarity index 100% rename from src/tinymfv/data/vignettes_scifi_other_violate.jsonl rename to src/moralmaps/data/vignettes_scifi_other_violate.jsonl diff --git a/src/tinymfv/data/vignettes_scifi_self_violate.jsonl b/src/moralmaps/data/vignettes_scifi_self_violate.jsonl similarity index 100% rename from src/tinymfv/data/vignettes_scifi_self_violate.jsonl rename to src/moralmaps/data/vignettes_scifi_self_violate.jsonl diff --git a/src/tinymfv/eval.py b/src/moralmaps/eval.py similarity index 100% rename from src/tinymfv/eval.py rename to src/moralmaps/eval.py diff --git a/src/tinymfv/guided.py b/src/moralmaps/guided.py similarity index 99% rename from src/tinymfv/guided.py rename to src/moralmaps/guided.py index 102a60e..b63dbe1 100644 --- a/src/tinymfv/guided.py +++ b/src/moralmaps/guided.py @@ -411,7 +411,7 @@ class ForcedChoiceResult: # Full decoded generations per enum-ordering frame, one per sample. # `gen_text` is always a list of length N=n_samples (even at N=1). # Both texts are FULL — no stripping at . If you want the - # pre-close part, split on `tinymfv.guided._CLOSE_MARKER`. + # pre-close part, split on `moralmaps.guided._CLOSE_MARKER`. gen_text: list[str] # forward-frame, length N gen_text_rev: list[str] # reversed-frame, length N # Headline per-frame logprobs at the prefill position, after Bayesian diff --git a/src/tinymfv/instrument.py b/src/moralmaps/instrument.py similarity index 100% rename from src/tinymfv/instrument.py rename to src/moralmaps/instrument.py diff --git a/src/tinymfv/instruments.py b/src/moralmaps/instruments.py similarity index 100% rename from src/tinymfv/instruments.py rename to src/moralmaps/instruments.py diff --git a/src/tinymfv/iw_axes.py b/src/moralmaps/iw_axes.py similarity index 100% rename from src/tinymfv/iw_axes.py rename to src/moralmaps/iw_axes.py diff --git a/src/tinymfv/labelplace.py b/src/moralmaps/labelplace.py similarity index 100% rename from src/tinymfv/labelplace.py rename to src/moralmaps/labelplace.py diff --git a/src/tinymfv/maps.py b/src/moralmaps/maps.py similarity index 100% rename from src/tinymfv/maps.py rename to src/moralmaps/maps.py diff --git a/src/tinymfv/read.py b/src/moralmaps/read.py similarity index 100% rename from src/tinymfv/read.py rename to src/moralmaps/read.py diff --git a/src/tinymfv/read_api.py b/src/moralmaps/read_api.py similarity index 100% rename from src/tinymfv/read_api.py rename to src/moralmaps/read_api.py diff --git a/src/tinymfv/readouts.py b/src/moralmaps/readouts.py similarity index 100% rename from src/tinymfv/readouts.py rename to src/moralmaps/readouts.py diff --git a/src/tinymfv/value_axes.py b/src/moralmaps/value_axes.py similarity index 97% rename from src/tinymfv/value_axes.py rename to src/moralmaps/value_axes.py index b0e68af..1500080 100644 --- a/src/tinymfv/value_axes.py +++ b/src/moralmaps/value_axes.py @@ -12,7 +12,7 @@ Sources (axis groupings aggregated from these papers): - MFQ-2 equality/proportionality fairness split: Atari et al. 2023 "Morality beyond the WEIRD". - Big Five meta-traits Plasticity/Stability: DeYoung, Quilty & Peterson 2007, doi 10.1037/0022-3514.93.5.880. - HSQ 2x2 adaptive/maladaptive x self/other: Martin et al. 2003, doi 10.1016/S0092-6566(02)00534-2. -- WVS: Inglehart & Welzel 2005 (see tinymfv.iw_axes -- the WVS map builds its own item-level axes; +- WVS: Inglehart & Welzel 2005 (see moralmaps.iw_axes -- the WVS map builds its own item-level axes; this table is for the psychometric instruments). The debatable calls (flagged): the SECOND MFT axis is not canonical -- mfq2 uses the documented diff --git a/src/tinymfv/zones.py b/src/moralmaps/zones.py similarity index 100% rename from src/tinymfv/zones.py rename to src/moralmaps/zones.py diff --git a/tests/test_instrument.py b/tests/test_instrument.py index 043659f..c25bf4d 100644 --- a/tests/test_instrument.py +++ b/tests/test_instrument.py @@ -10,15 +10,15 @@ import unittest import numpy as np -from tinymfv.data import CONFIGS, CONDITIONS, load_vignettes -from tinymfv.instrument import ( +from moralmaps.data import CONFIGS, CONDITIONS, load_vignettes +from moralmaps.instrument import ( Instrument, canonicalize_to_forward, per_item_categorical, reduce_nominal, reduce_ordinal, ) -from tinymfv.readouts import expected_score, logit_contrast, logodds_agree +from moralmaps.readouts import expected_score, logit_contrast, logodds_agree class InstrumentFlowTest(unittest.TestCase): diff --git a/uv.lock b/uv.lock index 155e633..18dd068 100644 --- a/uv.lock +++ b/uv.lock @@ -11,7 +11,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-06-29T06:18:19.538273755Z" +exclude-newer = "2026-07-03T02:38:05.43429745Z" exclude-newer-span = "P6D" [[package]] @@ -683,6 +683,54 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] +[[package]] +name = "moral-maps" +version = "0.1.0" +source = { editable = "." } +dependencies = [ + { name = "loguru" }, + { name = "numpy" }, + { name = "pandas" }, + { name = "tabulate" }, + { name = "torch" }, + { name = "tqdm" }, + { name = "transformers" }, +] + +[package.optional-dependencies] +api = [ + { name = "openrouter-wrapper" }, + { name = "python-dotenv" }, +] +maps = [ + { name = "matplotlib" }, + { name = "shapely" }, +] + +[package.dev-dependencies] +dev = [ + { name = "scipy" }, +] + +[package.metadata] +requires-dist = [ + { name = "loguru" }, + { name = "matplotlib", marker = "extra == 'maps'", specifier = ">=3.8" }, + { name = "numpy" }, + { name = "openrouter-wrapper", marker = "extra == 'api'", git = "https://github.com/wassname/openrouter_wrapper" }, + { name = "pandas" }, + { name = "python-dotenv", marker = "extra == 'api'" }, + { name = "shapely", marker = "extra == 'maps'", specifier = ">=2.0" }, + { name = "tabulate" }, + { name = "torch" }, + { name = "tqdm" }, + { name = "transformers", specifier = ">=5.7" }, +] +provides-extras = ["maps", "api"] + +[package.metadata.requires-dev] +dev = [{ name = "scipy", specifier = ">=1.17.1" }] + [[package]] name = "mpmath" version = "1.3.0" @@ -1558,54 +1606,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" }, ] -[[package]] -name = "tiny-mfv" -version = "0.1.0" -source = { editable = "." } -dependencies = [ - { name = "loguru" }, - { name = "numpy" }, - { name = "pandas" }, - { name = "tabulate" }, - { name = "torch" }, - { name = "tqdm" }, - { name = "transformers" }, -] - -[package.optional-dependencies] -api = [ - { name = "openrouter-wrapper" }, - { name = "python-dotenv" }, -] -maps = [ - { name = "matplotlib" }, - { name = "shapely" }, -] - -[package.dev-dependencies] -dev = [ - { name = "scipy" }, -] - -[package.metadata] -requires-dist = [ - { name = "loguru" }, - { name = "matplotlib", marker = "extra == 'maps'", specifier = ">=3.8" }, - { name = "numpy" }, - { name = "openrouter-wrapper", marker = "extra == 'api'", git = "https://github.com/wassname/openrouter_wrapper" }, - { name = "pandas" }, - { name = "python-dotenv", marker = "extra == 'api'" }, - { name = "shapely", marker = "extra == 'maps'", specifier = ">=2.0" }, - { name = "tabulate" }, - { name = "torch" }, - { name = "tqdm" }, - { name = "transformers", specifier = ">=5.7" }, -] -provides-extras = ["maps", "api"] - -[package.metadata.requires-dev] -dev = [{ name = "scipy", specifier = ">=1.17.1" }] - [[package]] name = "tokenizers" version = "0.22.2"