From 913befd308b942321fa801873d432bfd4ba96de3 Mon Sep 17 00:00:00 2001 From: wassname <1103714+wassname@users.noreply.github.com> Date: Tue, 23 Jun 2026 10:23:02 +0800 Subject: [PATCH] administer: return per_item_frame (per-(item,frame) keyed rows) The frame-averaged per_item drops the per-framing granularity that experiment analyses need (MFQ-2 map's framing-bias diagnostic + paired base-vs-steer delta). These rows are already computed in the by_dim_frame loop, so returning them is free. Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com> --- src/tinymfv/administer.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/tinymfv/administer.py b/src/tinymfv/administer.py index 2acec26..fed0b73 100644 --- a/src/tinymfv/administer.py +++ b/src/tinymfv/administer.py @@ -46,13 +46,21 @@ def administer(model, tok, instr: Instrument, *, batch_size: int = 36) -> dict: # per-frame factor means + framing spread (acquiescence/wording diagnostic): for each frame, # canonicalize that frame's presented distribution to forward, key it, pool per factor. + # Also keep the per-(item, frame) rows: experiment analyses (e.g. the MFQ-2 map's framing-bias + # diagnostic + paired base-vs-steer delta) need the per-framing granularity that per_item + # averages away. agreement = forward-canonicalized E (agreement toward the original statement); + # keyed_agreement reflects reverse-keyed items, same as reduce_ordinal. frames = sorted({r["frame"] for r in per_row}) by_dim_frame: dict[tuple[str, str], list[float]] = {} + per_item_frame: list[dict] = [] for r in per_row: p_fwd = canonicalize_to_forward(r["p"], r["frame"], instr.kind) E = float((p_fwd * w).sum()) keyed = (instr.scale_max + 1 - E) if r["sign"] < 0 else E by_dim_frame.setdefault((r["dimension"], r["frame"]), []).append(keyed) + per_item_frame.append({"id": r["id"], "framing": r["frame"], "foundation": r["dimension"], + "agreement": E, "keyed_agreement": keyed, + "pmass_allowed": r["pmass_allowed"]}) rng = np.random.default_rng(0) foundations = [] @@ -67,4 +75,5 @@ def administer(model, tok, instr: Instrument, *, batch_size: int = 36) -> dict: **{f"f_{fr}": v for fr, v in per_fr.items()}, }) return {"profile": profile, "dimensions": instr.dimensions, "foundations": foundations, - "per_item": per_item_rows, "mean_pmass_allowed": mean_pmass} + "per_item": per_item_rows, "per_item_frame": per_item_frame, + "mean_pmass_allowed": mean_pmass}