feat(report): make the effect column selectable (--effect-col) - #34
feat(report): make the effect column selectable (--effect-col)#34dchaudhari7177 wants to merge 2 commits into
Conversation
report.py hardcoded the effect column as formality, so a sweep of any other shipped concept (sentiment, verbosity) could not be reported without editing the module. Thread effect_column through the CSV reader and both loaders, add it to build_report, and expose it as steer-report --effect-col. The default stays "formality", so existing callers and the committed M0 artifacts are unaffected. The requested column is folded into the existing missing-columns guard rather than getting its own check, so a wrong name fails before any row is parsed and the error now also lists the columns the CSV does carry. Closes bamdadd#30
bamdadd
left a comment
There was a problem hiding this comment.
Thanks for this — the feature itself is clean: DEFAULT_EFFECT_COLUMN is threaded through _read_sweep_rows into both loaders and build_report, the default is preserved so existing M0 artifacts are unaffected, and it's well covered (2 CLI tests + 3 report tests). pytest/ruff/mypy all green locally.
One change before merge: an invalid --effect-col value surfaces as an uncaught ValueError traceback and exits 1:
ValueError: artifacts/dose_response.csv is missing columns: ['nope'] (available: [...])
The message content is good, but the delivery is inconsistent with how the CLI now handles user input errors. The missing-CSV guard a few lines above goes through parser.error() → clean one-line message, exit 2, and #21/#22/#23 all moved CLI input errors to that pattern. A user typo in --effect-col should do the same.
Please route the bad-column case through parser.error() (either pre-validate the column against the header, or catch the ValueError around the build_report call and re-raise via parser.error), and add/adjust a CLI test asserting exit code 2 and no traceback. After that this is good to merge.
An invalid --effect-col reached the user as an uncaught ValueError from mid-parse in report.py, exiting 1 with a traceback. The message content was right, but the delivery was inconsistent with every other CLI input error -- the missing-CSV guards a few lines above, and bamdadd#21/bamdadd#22/bamdadd#23, all go through parser.error() for a clean one-line message and exit 2. Pre-validate the column against both sweep headers instead, next to the existing existence checks. report.sweep_columns() splits the header read out of _read_sweep_rows so the check does not duplicate the parse; the in-parse guard stays as the library-level backstop for direct load_dose_curve callers. Checking both CSVs matters because the column is read from each: a name only one sweep carries now names which file is short.
|
Good catch — fixed in cbd7b28.
I went with pre-validation rather than wrapping Two CLI tests: the existing one now asserts exit 2, the message, and no traceback; a new one covers a column present in the dose sweep but not the layer sweep, since both are read with the same name — that case now names which CSV is short. Full suite, ruff and mypy green locally. One note unrelated to this PR: three |
Closes #30.
Problem
report.pypinned the effect column at module scope (_COL_EFFECT = "formality") and_read_sweep_rowsreadrow[_COL_EFFECT]directly. A sweep for either of the other two shipped concepts —sentiment,verbosity— could not be reported at all: the missing-columns guard rejected the CSV before parsing, and the only workaround was editing the module.This already bites the committed artifacts. 14 of the 24 sweep CSVs in
artifacts/cannot be rendered onmain— the cross-model sentiment/verbosity runs and the redosed layer sweeps emit the effect column aseffectrather thanformality:With this PR,
steer-report --dose-csv artifacts/dose_response_sentiment_qwen.csv ... --effect-col effectrenders them.Change
effect_columnis threaded through the read path and defaulted to"formality"everywhere, so nothing about current behaviour changes:_read_sweep_rows(path, x_column, effect_column="formality")load_dose_curve(path, effect_column="formality")load_layer_curve(path, x_column="layer", effect_column="formality")build_report(..., effect_column="formality")steer-report --effect-col NAME(defaultformality), passed straight through_COL_EFFECTbecomesDEFAULT_EFFECT_COLUMN(the CLI needs it to build its--helptext and default), and_SWEEP_COLUMNSnow holds only the columns that are the same for every concept —seed,repetition,ppl— with the x column and the effect column added per call.Error path
The requested column is folded into the existing missing-columns check rather than getting a second guard, so a wrong name fails before any row is parsed instead of raising a bare
KeyErrormid-file. The message now also lists what the CSV does carry:Tests
CPU-only, no model and no download — the fixtures are the existing canned CSVs with the header renamed.
test_effect_column_is_selectable— asentimentdose CSV and layer CSV parse correctly witheffect_column="sentiment", and the coherence columns are unaffected.test_effect_column_defaults_to_formality— the samesentimentCSV still fails the guard on the default, so the default really is unchanged.test_unknown_effect_column_names_the_available_columns— asserts the requested name, the wordavailable, and the real column all appear in the message.test_cli_effect_col_reports_a_non_formality_sweep— end to end throughsteer-report: the committed M0 artifacts with the header renamedformality→sentimentrender byte-identical markdown to the unrenamed run under the default.test_cli_effect_col_unknown_column_is_reported— the CLI surfaces the namedValueError.Checks
ruff check .,ruff format --check .,mypy src,pytest -qall pass (68 passed).Two notes on running the suite on Windows, neither caused by this change:
mypy srcreports a syntax error insidenumpy/__init__.pyiif numpy happens to be in the environment (it comes in with the optionalreportextra, not with thedevgroup) because the config targetspython_version = "3.11".mypy --python-version 3.12 srcis clean; CI does not install numpy, so it is clean there too.tests/test_cli.pytests that actually render a card fail on Windows under a non-UTF-8 locale, on cleanmainas well as here:build_reportcallsPath.write_textwith noencoding=, so theΔin the side-effects table and the⚠️in the trap warnings hit cp1252. I verified this by stashing my changes and re-running. It is a separate bug and I'll send a separate PR for it rather than fold an unrelated fix in here; withPYTHONUTF8=1the full suite is green locally.Deliberately out of scope
The rendered card still labels the series generically ("effect (behaviour score)") rather than naming the concept. Doing that properly means carrying the column name into
ReportDataand through both renderers and both plots, which is a wider change than this issue asks for — happy to follow up if you want it.