Skip to content

feat(ux): PII plan & result preview - #678

Draft
nina-xu wants to merge 1 commit into
nina-xu/pii-repl-v3-alt-configfrom
nina-xu/pii-plan-preview
Draft

feat(ux): PII plan & result preview#678
nina-xu wants to merge 1 commit into
nina-xu/pii-repl-v3-alt-configfrom
nina-xu/pii-plan-preview

Conversation

@nina-xu

@nina-xu nina-xu commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Pre-Review Checklist

Ensure that the following pass:

  • mise run format && mise run check or via prek validation.
  • mise run test passes locally
  • mise run test:e2e passes locally
  • mise run test:ci-container passes locally (recommended)
  • GPU CI status check passes -- comment /sync on this PR to trigger a run (auto-triggers on ready-for-review)

Pre-Merge Checklist

  • New or updated tests for any fix or new behavior
  • Updated documentation for new features and behaviors, including docstrings for API docs.

Other Notes

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 030967ea-b882-4e30-b001-fc8121f58df0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch nina-xu/pii-plan-preview

Comment @coderabbitai help to get the list of available commands.

@nina-xu
nina-xu force-pushed the nina-xu/pii-plan-preview branch 3 times, most recently from 223064d to 6ec7066 Compare July 30, 2026 19:14
@nina-xu
nina-xu force-pushed the nina-xu/pii-repl-v3-alt-config branch from 49c38bd to baaf407 Compare July 31, 2026 00:49
@nina-xu
nina-xu force-pushed the nina-xu/pii-plan-preview branch 2 times, most recently from 76052e1 to cbea3e1 Compare July 31, 2026 17:47
@nina-xu
nina-xu force-pushed the nina-xu/pii-repl-v3-alt-config branch from d4d85dd to 5b7b975 Compare July 31, 2026 18:31
@nina-xu
nina-xu force-pushed the nina-xu/pii-plan-preview branch 2 times, most recently from 46ae96b to 2e65768 Compare August 3, 2026 19:57
@nina-xu
nina-xu force-pushed the nina-xu/pii-repl-v3-alt-config branch from 7a35de1 to 76b1a7d Compare August 3, 2026 20:20
@nina-xu
nina-xu force-pushed the nina-xu/pii-plan-preview branch from 2e65768 to cd9ddc7 Compare August 4, 2026 13:38
@nina-xu
nina-xu force-pushed the nina-xu/pii-repl-v3-alt-config branch from bb2cfbb to ee88bb7 Compare August 6, 2026 19:30
@nina-xu
nina-xu force-pushed the nina-xu/pii-plan-preview branch from cd9ddc7 to 96938e9 Compare August 6, 2026 19:30
@nina-xu
nina-xu force-pushed the nina-xu/pii-repl-v3-alt-config branch from 20b06cd to ec90e75 Compare August 7, 2026 17:45
@nina-xu
nina-xu force-pushed the nina-xu/pii-plan-preview branch 3 times, most recently from b1b3c97 to b1dc3db Compare August 10, 2026 15:16
@nina-xu
nina-xu force-pushed the nina-xu/pii-repl-v3-alt-config branch from 9c263ae to 542a5b9 Compare August 10, 2026 20:25
@nina-xu
nina-xu force-pushed the nina-xu/pii-plan-preview branch 2 times, most recently from cd980ef to c457f43 Compare August 10, 2026 20:51
@nina-xu
nina-xu force-pushed the nina-xu/pii-repl-v3-alt-config branch from 2c092cf to 591c349 Compare August 11, 2026 13:17
@nina-xu
nina-xu force-pushed the nina-xu/pii-plan-preview branch from c457f43 to 8102024 Compare August 11, 2026 13:26
Notebook widgets for reviewing/editing the replacement plan (YAML +
diagram with section help) and browsing original vs replaced rows,
wired through SafeSynthesizer so previewed plans persist and re-arm
process_data when edited.

Signed-off-by: nina-xu <19981858+nina-xu@users.noreply.github.com>
@nina-xu
nina-xu force-pushed the nina-xu/pii-plan-preview branch from 8102024 to 3c83b6d Compare August 12, 2026 20:43

@binaryaaron binaryaaron left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent-assisted review: generated by @binaryaaron's Agent and reviewed by @binaryaaron.

import yaml

from nemo_safe_synthesizer.config.data import DataParameters
from nemo_safe_synthesizer.config.pii_replacement import (

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift | 👤 Author review required

Repair stale stack symbols before further preview review.

PR 678 does not collect against the current PR 672 head. It still imports config.pii_replacement, constructs ReplacePiiConfig, and uses the removed gender persona attribute. The focused stack check reports ModuleNotFoundError and NameError. Please rebase and update these symbols before further preview review.

logger.runtime.info(f"Wrote previewed PII replacement plan to {plan_path}")

if self._data_processed and updated_plan != self._applied_pii_plan:
self._data_processed = False

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Data Integrity & Integration | 🔴 Critical | 🏗️ Heavy lift | 👤 Author review required

Invalidate processed data after plan edits.

_apply_previewed_plan() changes the plan and clears only _data_processed. train() ignores that flag and can consume the old _training_df, so it can train on data produced by a different plan. Please invalidate the complete processing result and make train() require a current committed result.

cfg = config_from_replace_pii(self._nss_config.replace_pii)
plan = resolve_plan(
self._nss_config.replace_pii,
self._data_source,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Security & Privacy | 🔴 Critical | 🏗️ Heavy lift | 🧭 Human decision required

Preview the training split and require explicit adoption.

Preview discovery runs against _data_source, while process_data() runs replacement after the holdout split. The preview can therefore inspect test rows and produce a plan that differs from the training operation. Widget construction also adopts the plan at once. Please use the exact training split and require an explicit accept action before config or files change.

Comment thread pyproject.toml
]

[project.optional-dependencies]
notebook = [

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win | 🤖 Agent-fix candidate

Make the notebook extra sufficient for its documented import.

The tutorial asks users to install nemo-safe-synthesizer[notebook], which installs anywidget and ipywidgets without datasets. Importing SafeSynthesizer imports datasets at module load, so that documented setup cannot start. Please make the notebook extra sufficient for the documented import and add a clean-install contract test.

original_row = original_df.loc[[idx], cols]
transformed_row = transformed_aligned.loc[[idx], cols]
pair = pd.concat([original_row, transformed_row], axis=0)
pair.index = pd.MultiIndex.from_arrays(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Stability & Availability | 🟡 Minor | ⚡ Quick win | 🤖 Agent-fix candidate

Preserve row identity in result preview.

Result preview reindexes by labels and then assigns a two-element MultiIndex. Duplicate input indexes can produce extra rows and raise ValueError: Length mismatch. Please use stable positional row identity in the comparison frame and add a duplicate-index regression.

self._replace_pii_config = cfg
self._nss_config = self._nss_config.model_copy(update={"replace_pii": cfg})

plan_path = save_plan_to_path(updated_plan, self._workdir.run_dir / PII_REPLACEMENT_PLAN_FILENAME)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift | 👤 Author review required

Make plan adoption atomic.

_apply_previewed_plan() mutates both config fields before it writes the plan file. If persistence fails, memory contains an adopted plan that storage does not contain. Please validate and persist the draft first, then commit config and invalidate derived processing state as one SDK operation. Add a failing-write regression that proves the prior state remains intact.

pairs: list[tuple[str, str]] = []
seen: set[tuple[str, str]] = set()
for ent in free_text_entities:
if ent.get("column") != column:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | 🏗️ Heavy lift | 👤 Author review required

Preserve scope in free-text highlighting.

_free_text_pairs_for_column() keeps only the column when it selects replacements. The renderer then highlights those pairs in every displayed row, even when the replacement belongs to one record or group. Please retain scope and row identity in the render input and add a two-row scoped example.

Comment thread docs/tutorials/index.md
- [Safe Synthesizer 101](safe-synthesizer-101.ipynb) -- learn the fundamentals
- [Differential Privacy](differential-privacy.ipynb) -- enable differential privacy guarantees
- [Time-Series Financial Transactions](time-series-financial-transactions.ipynb) -- synthesize grouped transaction histories
- [PII Replacement](pii-replacement.ipynb) -- optionally preview/edit a PII plan, then continue the pipeline

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win | 👤 Author review required

Make the tutorial match the public API and privacy model.

The tutorial hardcodes /root/datasets/patient_events.csv, reads private _training_df, configures managed personas while describing Faker, and shows original rows without a notebook-output warning. These examples give users a setup that does not match the public API or privacy model. After the stack repair, please use a portable data path and public result, align the backend prose with the code, and warn users before rendering or saving original PII.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants