solidprivacy commited on
Commit
27b41ee
·
verified ·
1 Parent(s): 0fa39da

Add remember column for reusable replacements

Browse files
Files changed (1) hide show
  1. presidio_streamlit.py +96 -17
presidio_streamlit.py CHANGED
@@ -30,6 +30,13 @@ from document_tools import (
30
  replacement_report_csv,
31
  )
32
 
 
 
 
 
 
 
 
33
  st.set_page_config(
34
  page_title="Presidio demo",
35
  layout="wide",
@@ -387,29 +394,68 @@ try:
387
 
388
  # If nothing was detected, still show an empty editable row
389
  if not default_editor_rows:
390
- default_editor_rows = [
391
- {
392
- "include": True,
393
- "find": "",
394
- "replace_with": "",
395
- "entity_type": "MANUAL",
396
- "score": None,
397
- }
398
- ]
399
-
400
- replacement_editor_df = pd.DataFrame(default_editor_rows)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
 
402
  edited_replacements_df = st.data_editor(
403
  replacement_editor_df,
404
  hide_index=True,
405
  num_rows="dynamic",
406
  use_container_width=True,
407
- column_order=["include", "find", "replace_with", "entity_type", "score"],
408
  column_config={
409
- "include": st.column_config.CheckboxColumn(
410
- "Use",
411
- help="Untick to exclude this replacement from the export.",
412
- default=True,
413
  ),
414
  "find": st.column_config.TextColumn(
415
  "Find text",
@@ -490,8 +536,41 @@ try:
490
  st.info(f"Uploaded file detected for export: {uploaded_file.name}")
491
  else:
492
  st.info("No uploaded file detected for export. Exporting from text area only.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
493
 
494
- # TXT export
 
 
 
 
 
 
 
 
 
 
 
 
 
 
495
  st.download_button(
496
  label="Download anonymized text (.txt)",
497
  data=export_text.encode("utf-8"),
 
30
  replacement_report_csv,
31
  )
32
 
33
+ from replacement_memory import (
34
+ load_remembered_replacements,
35
+ save_remembered_replacements,
36
+ clear_remembered_replacements,
37
+ get_memory_file_path,
38
+ )
39
+
40
  st.set_page_config(
41
  page_title="Presidio demo",
42
  layout="wide",
 
394
 
395
  # If nothing was detected, still show an empty editable row
396
  if not default_editor_rows:
397
+ remembered_rows = load_remembered_replacements()
398
+
399
+ default_editor_rows = []
400
+ seen_find_values = set()
401
+
402
+ # First load remembered pairs
403
+ for row in remembered_rows:
404
+ find_text = str(row.get("find", "")).strip()
405
+
406
+ if not find_text:
407
+ continue
408
+
409
+ default_editor_rows.append(row)
410
+ seen_find_values.add(find_text)
411
+
412
+ # Then add Presidio suggestions
413
+ for row in report_rows:
414
+ find_text = str(row.get("detected_text", "")).strip()
415
+
416
+ if not find_text:
417
+ continue
418
+
419
+ # Avoid duplicate rows if a remembered replacement already exists
420
+ if find_text in seen_find_values:
421
+ continue
422
+
423
+ default_editor_rows.append(
424
+ {
425
+ "include": True,
426
+ "remember": False,
427
+ "find": find_text,
428
+ "replace_with": row.get("placeholder", ""),
429
+ "entity_type": row.get("entity_type", ""),
430
+ "score": row.get("score", None),
431
+ }
432
+ )
433
+
434
+ if not default_editor_rows:
435
+ default_editor_rows = [
436
+ {
437
+ "include": True,
438
+ "remember": False,
439
+ "find": "",
440
+ "replace_with": "",
441
+ "entity_type": "MANUAL",
442
+ "score": None,
443
+ }
444
+ ]
445
+
446
+ replacement_editor_df = pd.DataFrame(default_editor_rows)
447
 
448
  edited_replacements_df = st.data_editor(
449
  replacement_editor_df,
450
  hide_index=True,
451
  num_rows="dynamic",
452
  use_container_width=True,
453
+ column_order=["include", "remember", "find", "replace_with", "entity_type", "score"],
454
  column_config={
455
+ "remember": st.column_config.CheckboxColumn(
456
+ "Remember",
457
+ help="Save this replacement pair for future documents/sessions.",
458
+ default=False,
459
  ),
460
  "find": st.column_config.TextColumn(
461
  "Find text",
 
536
  st.info(f"Uploaded file detected for export: {uploaded_file.name}")
537
  else:
538
  st.info("No uploaded file detected for export. Exporting from text area only.")
539
+
540
+
541
+ remember_rows_to_save = []
542
+
543
+ for _, row in edited_replacements_df.iterrows():
544
+ include = bool(row.get("include", False))
545
+ remember = bool(row.get("remember", False))
546
+ find_text = safe_cell(row.get("find", ""))
547
+ replace_text = safe_cell(row.get("replace_with", ""))
548
+ entity_type = safe_cell(row.get("entity_type", "REMEMBERED")) or "REMEMBERED"
549
+
550
+ if include and remember and find_text and replace_text:
551
+ remember_rows_to_save.append(
552
+ {
553
+ "find": find_text,
554
+ "replace_with": replace_text,
555
+ "entity_type": entity_type,
556
+ }
557
+ )
558
 
559
+ memory_col1, memory_col2 = st.columns(2)
560
+
561
+ with memory_col1:
562
+ if st.button("Save remembered replacements"):
563
+ saved_count = save_remembered_replacements(remember_rows_to_save)
564
+ st.success(f"Saved {saved_count} remembered replacement pair(s).")
565
+ st.info(f"Memory file: {get_memory_file_path()}")
566
+
567
+ with memory_col2:
568
+ if st.button("Clear remembered replacements"):
569
+ clear_remembered_replacements()
570
+ st.warning("Remembered replacements cleared.")
571
+
572
+
573
+ # TXT export
574
  st.download_button(
575
  label="Download anonymized text (.txt)",
576
  data=export_text.encode("utf-8"),