pii-guard

skill
Security Audit
Fail
Health Pass
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Community trust — 67 GitHub stars
Code Fail
  • Hardcoded secret — Potential hardcoded credential in .agents/skills/pii-safe-documents/tests/test_pii_safe_workflow.py
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

繁體中文(台灣)個人資料去識別化工具,讓業務文件可以安全地送進 AI 處理 / Reversible Traditional-Chinese (Taiwan) PII de-identification for LLM workflows — fully local

README.md

pii-guard

繁體中文(台灣)個人資料去識別化工具。把文件裡的個資換成可還原的代號,讓你能用雲端 AI 處理機敏文件,處理完再換回來。偵測與還原全程在你自己的機器上跑。


English summary — Reversible PII de-identification for Traditional Chinese (Taiwan) documents.

Most tools that strip PII before an LLM call are network gateways (LiteLLM + Presidio, PrivAiTe, AI Security Gateway) and they work well. None of them handle Taiwanese PII: national ID and ARC numbers, 統一編號 business IDs, local phone formats, or Traditional Chinese personal and organisation names — which need CKIP's Chinese NER rather than an English model with the locale switched.

This fills that gap, and differs in one more way: it produces a redacted file you can keep and hand to someone, not a per-request proxy. Detection is Presidio + CKIP BERT + Taiwan regex; substitution and restoration are plain code, so restoration is exact. A bundled Claude Code skill runs the whole thing without letting the cloud agent read the original.

Everything below is in Traditional Chinese. Start at 安裝.


為什麼還要一個?

處理「送進 LLM 之前先遮個資」的工具已經很多,而且做得好——但它們幾乎都是網路層的 gateway,攔在你的程式和模型供應商之間。

它們沒有處理的是台灣的個資:身分證與居留證字號、統一編號、本地電話格式,以及繁體中文的人名與組織名——後者需要中研院的 CKIP 中文 NER,不是英文模型換個語系就行。

這個專案補的是那一塊。另外還差一件事:它產出的是一份你可以留存、可以交給別人的檔案,不是逐次請求、用完即逝的代理。

實際輸出

下面是真的跑出來的,不是示意圖。輸入:

客戶:王小明(身分證 A123456789,手機 0912345678)
公司:範例科技股份有限公司(統編 12345678)
地址:臺北市中正區測試路 100 號 5 樓
Email:[email protected]
案由:本季顧問合約續約,金額新臺幣 30 萬元,付款分兩期。

uv run python -m pii_guard anonymize input.txt -o out.txt -m map.json 之後:

客戶:<PERSON_1>(身分證 <TW_NATIONAL_ID_1>,手機 <TW_MOBILE_1>)
公司:<ORG_1>(統編 12345678)
地址:<TW_ADDRESS_1> 100 號 5 樓
Email:<EMAIL_ADDRESS_1>
案由:本季顧問合約續約,金額新臺幣 30 萬元,付款分兩期。

這份輸出有兩個瑕疵,我刻意不修掉它再貼上來:

  1. 統編 12345678 沒被遮蔽——八位純數字要靠上下文詞判斷,這次沒命中。
  2. 地址只抓到 臺北市中正區測試路100 號 5 樓 留在外面。

這正是為什麼下面那個 skill 在這條管線之後還加了一層本地模型稽核,以及為什麼有人工補標介面。單靠決定性偵測不夠,這是實話。

另外注意:金額、合約條款、日期都留著。這是刻意的——去掉它們,文件就沒有送進 AI 的意義了。

這不是什麼

想要「所有雲端請求自動遮蔽、不用逐份處理、可批量」——你要的是 gateway,不是這個,請去用 LiteLLM + PresidioPrivAiTe。它們做得比較好,我不打算重做一次。

這個專案適合的是:單份重要文件,你要一份可留存的去識別化版本,而且文件是繁體中文的。

它也不是機密分級工具。它遮的是「能指認到特定個人」的資訊。金額、病情、行程、合約條款只要不指向個人就會留著。不要單憑它宣稱「整份文件可以對外」。

安裝

需要 Python 3.13(3.11 以上可跑)、uv、以及 Ollama(只有 skill 的稽核層需要)。

git clone https://github.com/danyuchn/pii-guard.git
cd pii-guard
uv sync

# 需要 CLI 直接處理 .docx / .xlsx / .pdf 時再加裝
uv sync --extra formats

首次執行會下載 CKIP BERT NER 模型(約 500MB)。未加裝 formats 時,tests/test_file_handlers.py 的 10 個測試會因缺少套件而跳不過,屬預期行為。

Claude Code Skill

本 repo 內含 pii-safe-documents skill,位於 .agents/skills/pii-safe-documents/。它在 CLI 之外做兩件事:

  • 不讓主 agent 讀到原始文件、對照表與還原結果——讀檔、呼叫模型、還原都在獨立的本地行程裡完成,主 agent 只拿到路徑與回執。
  • 在決定性偵測之後加一層本地模型稽核,補上面示範中那類漏網。

安裝方式是連結進 skills 目錄,不要複製:

ln -s "$(pwd)/.agents/skills/pii-safe-documents" ~/.claude/skills/pii-safe-documents
ollama pull ornith-1.5:9b

用連結而非複製,是因為 skill 需要找到它所屬的 repo 才能呼叫 pii-guard 本體。只能複製的環境改設 PII_GUARD_HOME 指向 clone 出來的路徑。

三個步驟

S=.agents/skills/pii-safe-documents/scripts/pii_safe_workflow.py

# 1. 產生去識別化副本
python3 $S redact --input "/絕對路徑/機密文件.txt"

# 2. 人工補標(在你自己的瀏覽器開一頁)
python3 $S annotate --job-id "<job_id>"

# 3. 編輯完成後還原
python3 $S restore --job-id "<job_id>" --input "編輯後的.txt" --output "還原.txt"

第 2 步會在你的瀏覽器開一頁,可以選取任何仍然裸露的文字補遮(全文所有出現位置一起遮),也可以點任何代號、看到背後的值、把它放回去——後者用在被誤判為組織而遮掉的法院、醫院、公司名。

那一頁呼叫端連不上:網址帶一次性 token,在私有子行程內產生、只交給它自己開的瀏覽器,從不印出;回執只有數量,沒有網址。每次編輯都即時落檔並重新驗證整份仍能逐字還原。

在 Claude Code 裡直接說「幫我把這份檔案去識別化」也可以,skill 會照這個流程走。

進階/無瀏覽器環境

mask --terms <詞清單檔>unmask --marker TYPE-N 是同樣兩種操作的指令列版本,review 列出代號與真實值。review 會印出未遮蔽的內容,因此在輸出不是終端機時拒絕執行。purge 刪除一個工作目錄。

準確率

可重現的部分tests/eval/eval_corpus.json 是 53 條合成標註語料,已在版控中,任何人都能跑:

uv run pytest tests/eval -m eval

不可重現的部分:另有兩批真實台灣文件(判決書、監察院個案、政府新聞稿、新聞、通訊錄、裁罰表)共 17 份、71 個手工標註檢查項,在最終版程式碼下全數通過、零洩漏。第二批十份是修完之後才取得、過程中從未用來調校,那批才有驗收意義。

這批數字你無法驗證,因為語料含真實姓名、永遠不會進 git。 請據此打折。

還有一件必須講的:合成語料會系統性高估。原本的合成測試四個模型三個滿分,換成真實判決書後同一批模型立刻現形——9B 把十個人壓成同一個代號。所以上面那 53 條的分數,不要當成真實文件上的表現。

威脅模型

這是防止意外把原文餵給雲端模型的強保護,不是作業系統層級的安全邊界

skill 的隔離做的是:原文與對照表從不經過主 agent 的輸出通道,函式庫的警告訊息(會回吐原文)被丟棄,錯誤只以代碼回報,失敗的工作目錄直接刪除。這些擋掉的是每次都會發生的意外曝光

它擋不住的是:主 agent 與那些檔案是同一個使用者身分cat 得到就是 cat 得到。檔案權限 0600 對擁有者不設防。真正的敵意隔離需要另一個系統帳號或獨立權限的本地 broker,這個 repo 沒有做,也不該假裝有做。

如果你的主 agent 本來就是本地模型(Claude Code 可以指向 Ollama),那上面整段都不適用——原文哪裡都沒去。反過來說,這個專案存在的意義,正是讓你用雲端模型的能力、同時不把個資交出去

架構

原始文件
    ↓
[偵測層] CKIP BERT NER + 台灣 Regex           ← 機率性,會漏
    ↓  (skill 另加:本地模型稽核,多次取樣取聯集)
    ↓  (skill 另加:人工補標介面)
[替換層] 程式碼建立對照表                       ← 決定性
    ↓
去識別化文本 → 送 LLM → AI 回答(含代號)
    ↓
[還原層] 程式碼反向替換                         ← 決定性,逐字精確

關鍵設計原則:偵測層可以是機率性的,但替換與還原全部由程式碼完成,所以還原一定精確。

層次 工具
PII 框架 Microsoft Presidio(MIT)
繁中 NER ckiplab/bert-base-chinese-ner(中研院,102M)
台灣 PII Regex 自建 PatternRecognizer
本地稽核模型 Ollama(預設 ornith-1.5:9b
語言/套件管理 Python 3.13 / uv

支援的 PII 類型:人名、組織、地名(CKIP);身分證、外籍居留證、護照、統一編號、手機、市話、車牌、出生日期、銀行帳號(Regex);Email、信用卡號(Presidio 內建)。

輸入限制:skill 目前只吃 64 KiB 以內的 UTF-8 純文字(.txt .md .csv .tsv .log .dat)。CLI 加裝 formats 後可讀 .docx .xlsx .pdf

速度

skill 的稽核層開啟推理並對每個視窗取樣三次,單份文件實測 10–50 分鐘。這是為了召回率付的代價——關閉推理時,模型會漏掉判決書簽名欄的書記官姓名。

批量處理上百份文件在此設定下不可行。 需要批量請看上面「這不是什麼」。

路線圖

  • Presidio + CKIP NER + 台灣 Regex,MCP server 介面
  • 評估語料與 precision/recall 框架
  • pii-safe-documents skill(主 agent 隔離的可逆去識別化)
  • 人工補標介面(localhost 網頁)
  • 效能:先用決定性規則篩出可疑段落再送模型,讓批量可行
  • 更多文件類型:library 端已能讀 docx/xlsx/pdf,卡在 skill 端——解析套件可能在警告訊息中回吐原文,需移進私有行程並驗證
  • 可公開的準確率:需另建一份可公開語料才能報真實文件上的數字
  • CI

已知問題

  • 尚未實作簡繁折疊:稽核模型若回傳簡體姓名會以 LOCAL_AUDIT_UNRESOLVED 失敗。
  • Presidio 把法院、醫院、公司名判為組織而遮蔽,判決書因此失去部分文件用途。短期用 --allow 逐案放行,或用補標介面放回。
  • 曾出現一次 ROUNDTRIP_INTEGRITY_FAILED,其後未再重現,未能隔離。

已退役

--llm-fallbackOllamaRecognizer(2026-08-21 移除)。它與 skill 的稽核層目的重疊,但沒有任何語料證明它有效,並存只會讓人選錯。要在 CLI 端補回模型稽核,正確做法是下沉 skill 那一套,不是重新啟用這個。

Claude Code PreToolUse hook(移至 examples/claude-code-hook/)。早期做法是攔截讀檔並自動遮蔽,已被 skill 的顯式流程取代。留著是因為它示範了另一種整合思路,但不再維護

作者

Dustin Yuchen Teng(鄧宇辰)——AI 導入顧問與課程講師,在做的事情是把 coding agent 變成實際可用的工作流程。這個專案是其中一條線的產物。

變更紀錄

CHANGELOG.md

授權

MIT。見 LICENSE

Reviews (0)

No results found