一键导入
doc-redaction-tabular
Skill for redacting tabular files (CSV/XLSX/Parquet/DOCX) using the Document Redaction app. gradio_client-first with discovery via view_api().
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Skill for redacting tabular files (CSV/XLSX/Parquet/DOCX) using the Document Redaction app. gradio_client-first with discovery via view_api().
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Initial document redaction and downloading server outputs: gradio_client, `/doc_redact` first, path/download traps, and `/redact_document` when needed. Not for CSV review or reapply (see doc-redaction-modifications); parallel multi-page review orchestration → doc-redact-page-review.
After initial redaction (doc-redaction-app): Pass 1 parallel per-page OCR/CSV review (subagents), merge, single /review_apply; optional Pass 2 VLM visual check after Pass 1 outputs.
Review and reapply: two-pass workflow — Pass 1 (OCR/CSV/text, default) then optional Pass 2 (VLM per page). Edit *_review_file.csv, preview, /review_apply, verify. Parallel page orchestration → doc-redact-page-review. Initial redaction → doc-redaction-app.
Copy-paste task prompt template for redact + Pass 1 review jobs. User fills setup placeholders and case-specific redaction requirements at the end; agent follows two-pass model (Pass 1 default, Pass 2 only on flagged pages).
| name | doc-redaction-tabular |
| description | Skill for redacting tabular files (CSV/XLSX/Parquet/DOCX) using the Document Redaction app. gradio_client-first with discovery via view_api(). |
| version | 1.4.0 |
| author | repo-maintained |
| license | AGPL-3.0-only |
| changelog | ["v1.4.0 (Apr 21, 2026): Added /find_duplicate_tabular docs with handle_file caveat. Clarified HF Space '0 entities' quirk. Added Excel multi-sheet handling. Output file naming convention section expanded strategy comparison. Added error handling patterns and edge case notes."] |
Redact tabular and semi-tabular files using the app:
.csv).xlsx, .xls).parquet).docx)Registered endpoints:
/tabular_redact — short, stateless tabular redaction (preferred when present)/redact_data — main tabular redaction (long signature)/find_duplicate_tabular — detect and remove duplicate rowsUse when the document is not a PDF/image and you want redaction applied directly to
a table-like file.
For PDFs/images, use doc-redaction-app with api_name="/redact_document" instead.
gradio_client first — confirmed working for both endpoints.docker cp + raw Gradio HTTP — fallback if gradio_client fails./gradio_api/upload +
/gradio_api/call/... + poll./tabular_redact, long: /redact_data)from gradio_client import Client, handle_file
import os
BASE_URL = "http://host.docker.internal:7861"
client = Client(BASE_URL)
csv_path = "/path/to/table.csv"
output_folder = "/home/user/app/output/" # CONTAINER path
wrapped_files = [handle_file(csv_path)]
result = client.predict(
file_paths=wrapped_files,
in_text="", # required str
anon_strategy="replace with 'REDACTED'", # see strategies
chosen_cols=["Name", "Email"], # columns to anonymize
chosen_redact_entities=[
"PERSON", "PHONE_NUMBER",
"EMAIL_ADDRESS"
],
in_allow_list=[],
latest_file_completed=0, # 0 for single file
out_message="Tabular redaction test", # required str
in_excel_sheets=[], # not Excel; see multi-sheet below
first_loop_state=True, # always True for fresh run
output_folder=output_folder,
in_deny_list=[],
max_fuzzy_spelling_mistakes_num=0,
pii_identification_method="Local",
chosen_redact_comprehend_entities=[],
aws_access_key_textbox="",
aws_secret_key_textbox="",
do_initial_clean=True,
language="en",
progress="",
custom_llm_instructions=["PERSON_NAME"],
api_name="/redact_data"
)
# Returns 4 outputs: (str status, list[filepath], int count, list[filepath])
print(f"Status: {result[0]}")
print(f"Output file: {result[1][0] if result[1] else 'N/A'}")
print(f"Files redacted: {result[2]}")
To discover sheet names, read the file locally first:
import pandas as pd
sheets = pd.ExcelFile(csv_path).sheet_names
# e.g. ['Sheet1', 'Q1_Data', 'Summary']
Pass discovered names to in_excel_sheets:
result = client.predict(
...,
in_excel_sheets=["Sheet1", "Q1_Data"], # sheet name strings
...
)
If the file has no sheets or the list is empty, the app processes all available sheets.
Public deployment: https://seanpedrickcase-document-redaction.hf.space
Same API. Key differences from local Docker:
result[1] and result[3] are local temp paths that
gradio_client already downloaded. Read directly:
output_file = result[1][0]
with open(output_file, "r", encoding="utf-8-sig") as f:
print(f.readline().strip()) # first row (may have BOM)
client.download_file()(singular) does NOT exist on somegradio_clientversions. Use the output paths directly.
On HF Space the entity count (result[2]) may show 0 even when
redaction is applied correctly. Always verify by reading the
output file, not the log count. This is a known display issue
with the spaCy model on HF.
| Path | Works? |
|---|---|
/home/user/app/output/ | Yes — container-internal, app's OUTPUT_FOLDER |
/tmp/test_data/output/ (host) | No — server runs inside the container |
Workaround: Use container paths. Retrieve files via docker cp:
# Find the file
docker exec doc_redaction-redaction-app-llama-1 \
ls -lt /home/user/app/output/ | grep combined_case_notes
# Download
docker cp doc_redaction-redaction-app-llama-1:/home/user/app/output/combined_case_notes_anon_redact_replace.csv ./output.csv
| Strategy | Behavior | Example ("Jane Smith") |
|---|---|---|
replace with 'REDACTED' | Replaces with literal text REDACTED | REDACTED (8 chars) |
redact completely | Removes content (empty cell) | (blank) |
mask | Replaces with asterisks matching original length | ********** (10 chars) |
hash | SHA-256 hash of original value (consistent per entity) | ca85b082d2e6... (94 chars) |
| Use case | Recommended | Why |
|---|---|---|
| GDPR compliance | redact completely | Maximum privacy, no length leakage |
| Audit trail | replace with 'REDACTED' | Clear indication of redaction occurred |
| Data science (preserve structure) | mask or hash | Keeps row/column dimensions intact |
| Cross-row correlation analysis | hash | Same entity → same hash across all rows |
| Legal review (need to know what was there) | replace with 'REDACTED' + log | Redaction text + decision log |
| Machine learning (feature engineering) | mask or hash | Preserves data shape for pipelines |
| Maximum privacy (no length info leaked) | redact completely | No clue about original value length |
| Parameter | Type | Notes |
|---|---|---|
chosen_cols | list[str] | Column names to anonymize. If empty, all columns with PII are processed. Use exact column header names from the CSV/XLSX. |
chosen_redact_entities | list[str] | Local (spaCy + custom recognizers) — full list in ../doc-redaction-app/SKILL.md §2e. Includes TITLES, UKPOSTCODE, STREETNAME, CUSTOM, CUSTOM_FUZZY |
chosen_redact_comprehend_entities | list[str] | AWS Comprehend labels when pii_identification_method="AWS Comprehend" — full list in doc-redaction-app §2e; may also include TITLES, UKPOSTCODE, STREETNAME, CUSTOM, CUSTOM_FUZZY |
in_deny_list / in_allow_list | list[str] | Terms always redacted (CUSTOM / CUSTOM_FUZZY) or never redacted (allow_list). See doc-redaction-app §2e |
max_fuzzy_spelling_mistakes_num | int | 0 = exact match. 1–2 allows fuzzy matching (useful for typos in PII). |
do_initial_clean | bool | True: strips whitespace, normalizes text. Recommended for dirty data. |
pii_identification_method | str | "Local" (spaCy, no API keys) or "AWS Comprehend" (requires AWS creds). |
in_excel_sheets | list[str] | For XLSX files: specific sheet names to process. Empty = all sheets. |
custom_llm_instructions | list[str] | Entity types for LLM fallback (e.g., ["PERSON_NAME", "EMAIL_ADDRESS"]). |
language | str | "en", "fr", "de", etc. Affects spaCy model language settings. |
latest_file_completed | float | 0 for single file, 1.0 when last of a batch (for multi-file runs). |
The default Local PII detection uses spaCy's English model. It may miss short
names with initials like "Alex D." — tested on combined_case_notes.csv (18 rows)
showed only "Jane Smith" (10 chars, full name) was detected in the Social Worker column,
but "Alex D." (7 chars, with initial) in the Client column was not. This is a known
spaCy limitation with short/abbreviated names.
Workarounds:
max_fuzzy_spelling_mistakes_num=1 for partial matches (won't help with initials)custom_llm_instructions with entity types for LLM-based fallback detection (requires external LLM)in_deny_list with known names to exclude from redaction (e.g., your own company name)do_initial_clean=False if cleaning is removing useful contextThe app generates files with predictable naming:
{original_name}_anon_{strategy}.csv
{original_name}_anon_{strategy}.csv_log.csv (decision log)
| Original | Strategy | Output file |
|---|---|---|
combined_case_notes | replace with 'REDACTED' | combined_case_notes_anon_redact_replace.csv |
combined_case_notes | redact completely | combined_case_notes_anon_redact_remove.csv |
combined_case_notes | mask | combined_case_notes_anon_mask.csv |
combined_case_notes | hash | combined_case_notes_anon_hash.csv |
Outputs are written under the container's OUTPUT_FOLDER. Retrieve via:
# Find the file in container
docker exec doc_redaction-redaction-app-llama-1 \
ls -lt /home/user/app/output/ | grep combined_case_notes | head -10
# Download the redacted CSV
docker cp doc_redaction-redaction-app-llama-1:/home/user/app/output/combined_case_notes_anon_redact_replace.csv ./output.csv
The _log.csv file contains one row per PII entity detected:
entity_type,start,end,data_row,column,entity
PERSON,0,10,0,Social Worker,Jane Smith
entity_type — spaCy entity label (PERSON, PHONE_NUMBER, etc.)start,end — character offsets in the cell valuedata_row — 0-indexed row numbercolumn — column nameentity — the detected PII textRead with encoding="utf-8-sig" in Python to strip the BOM
(\ufeff) that may appear at the start of CSV files.
On HF Space the log file path is returned in result[3] (not result[2]).
The entity count (result[2]) may show 0 even when redaction IS applied
correctly. Always verify by reading the output file, not the log count.
Public deployment: https://seanpedrickcase-document-redaction.hf.space
Same API. Key differences from local Docker:
| Aspect | Local Docker | HF Space |
|---|---|---|
| PII detection | Local, Local Inference Server, AWS Comprehend | Local, AWS Comprehend (no inference server) |
| OCR models | tesseract, paddle, hybrid-paddle-inference-server, inference-server | tesseract, paddle only |
| VLM entities | CUSTOM_VLM_FACES, CUSTOM_VLM_SIGNATURE available | NOT available (no GPU/VLM support) |
| efficient_ocr default | True | False (saves compute on free tier) |
| Speed | ~1.5s per request (GPU machine) | ~3–4.5s per request (~2–3× slower, CPU free tier) |
| File validation | Accepts any file type via API | Strict: only .pdf, .jpg, .png, .json, .zip for /redact_document |
| Output access | docker cp from container | Read gradio_client output paths directly (already cached locally) |
| Strategy | Local Docker | HF Space |
|---|---|---|
| replace with REDACTED | ~1.5s | ~3.5s |
| redact completely | ~1.5s | ~3.4s |
| mask | ~1.5s | ~3.6s |
| hash | ~1.5s | ~4.5s |
| Error | Cause | Fix |
|---|---|---|
Cannot save file into a non-existent directory | output_folder path doesn't exist in container | Use /home/user/app/output/ or ensure the directory exists |
| `'meta' field must be explicitly provided. | Raw string passed to files= | Wrap with handle_file(path) |
| `Invalid file type. Please upload. | CSVs rejected by `/redact_document | Use /redact_data for tabular files |
| Timeout after ~3s | HF Space free tier spinning down | Accept ~3.5s runtime. No fix. |
| Entity count shows 0 | HF Space display issue | Read output file to verify. |
import os
from gradio_client import Client, handle_file
def safe_redact(client, csv_path, strategy="replace with 'REDACTED'"):
"""Redact a CSV file with error handling."""
wrapped = [handle_file(csv_path)]
result = client.predict(
file_paths=wrapped,
in_text="",
anon_strategy=strategy,
chosen_cols=["Name", "Email"], # adjust to your columns
out_message="Tabular redaction test",
output_folder="/home/user/app/output/",
api_name="/redact_data"
)
if not result[1]:
raise RuntimeError("No output file returned")
return result
# Usage with error handling
try:
result = safe_redact(client, "/path/to/table.csv", "mask")
print(f"Output: {result[1][0]}")
except Exception as e:
print(f"Redaction failed: {e}")
\ufeff) at the start. Read with encoding="utf-8-sig" in Python.chosen_cols match actual headers."Q1 '23 Data")./redact_data. Use /redact_document for full DOCX processing.latest_file_completed=1.0 only on the last file in a batch to trigger final processing.