refactor(display): consume structured rewrite columns in native shape#144
refactor(display): consume structured rewrite columns in native shape#144memadi-nv wants to merge 4 commits into
Conversation
Signed-off-by: memadi <memadi@nvidia.com>
Greptile SummaryThis PR removes the defensive type-coercion ladder (
Confidence Score: 5/5Safe to merge — the display layer now faithfully reflects the dict shape the pipeline already writes, and the warning guard is correctly scoped with isinstance. The simplification is well-targeted: removing coercion paths that were masking upstream bugs, not removing legitimate defensive guards. The isinstance-based warning correctly distinguishes NaN rows (no warning) from malformed dicts (warning), and both branches are directly covered by new tests. No data loss, no silent breakage for the happy path. No files require special attention; both changed files are straightforward and covered by the updated tests. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[row.get COL_JUDGE_EVALUATION] --> B{isinstance dict?}
B -- No NaN / None / other --> C[_extract_judge_scores returns empty]
B -- Yes --> D[_extract_judge_scores iterates keys]
D --> E{Each value: dict with score?}
E -- No --> F[skip entry]
E -- Yes --> G[append name, int score]
G --> H{judge_scores non-empty?}
F --> H
H -- Yes --> I[Render Judge: scores in HTML]
H -- No --> J[warning: unexpected keys logged]
J --> K[No Judge section rendered]
C --> K
Reviews (4): Last reviewed commit: "address feedback" | Re-trigger Greptile |
Signed-off-by: memadi <memadi@nvidia.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
lipikaramaswamy
left a comment
There was a problem hiding this comment.
Looks good from an engineering perspective. I reviewed the display refactor and the updated tests; the change is scoped and aligns the renderer with the native dict shape produced by the rewrite pipeline. One small nit, recommend updating to future proof.
I did not run a live model-backed rewrite flow, so approving assuming you did :)
Signed-off-by: memadi <memadi@nvidia.com>
Summary
Maintain native shape for structured rewrite columns
Motivation
The rewrite pipeline (
LLMJudgeColumnConfig,LLMStructuredColumnConfig) already writes plain Python dicts into the dataframe via pydanticmodel_dump(). The display layer was defensively re-normalizing these columns from three possible shapes —None, pydantic model, or JSON string — which masked upstream bugs and duplicated work.This PR removes the defensive coercion and trusts the native dict shape throughout the display path.
Changes
src/anonymizer/interface/display.py_extract_judge_scores: no moreNoneshort-circuit,model_dump()fallback, orjson.loadsattempt. The function now expects a plaindictand returns[]otherwise._normalize_disposition; it now expects a plain dict with"sensitivity_disposition"as a list, filtering entries viaisinstance(e, dict)instead of callinggetattr(e, "model_dump", dict)().float(...)wrappers aroundutility,leakage, andweighted_leakage_ratein_render_scores_section— values are already numeric at this stage.COL_JUDGE_EVALUATIONis present but yields no scores, so unexpected shapes surface instead of silently rendering nothing._extract_judge_scoresand_normalize_dispositionto document the expected native dict shape.tests/interface/test_display.pyPRIVACY_RUBRIC,QUALITY_RUBRIC, andNATURALNESS_RUBRICconfigs (imported fromfinal_judge) instead of hardcoded strings, preventing test-vs-runtime drift if a rubric is renamed.SensitivityDispositionSchema(...).model_dump()with a fullEntityDispositionSchema, matching the exact dict thatLLMStructuredColumnConfigwrites at runtime. Replaces the hand-rolled partial dict.COL_SENSITIVITY_DISPOSITIONconstant instead of a hardcoded"_sensitivity_disposition"key.COL_SENSITIVITY_DISPOSITION, the three rubric configs, and the two rewrite schemas.Net effect
display.py: −24 / +18 lines (simpler, one observability signal added).test_display.py: +35 / −21 lines (fixtures pinned to real schemas/constants).Test plan
pytest tests/interface/test_display.pypasses locally.Testing
make testpasses locallymake checkpasses locally (format + lint + typecheck + lock-check)Documentation
make docs-buildpasses locallyRelated Issues
Closes #70