Metadata-Version: 2.4
Name: taiwan-legal-deid
Version: 0.1.0
Summary: 台灣法律文件去識別化：人名、個資、私人機構換成擬真假名，留對照表可還原（本機 CPU 執行）
Author-email: LawChat <opensource@lawchat.com.tw>
License-Expression: MIT AND Apache-2.0
Project-URL: Repository, https://github.com/lawchat-oss/taiwan-legal-deid
Project-URL: Issues, https://github.com/lawchat-oss/taiwan-legal-deid/issues
Keywords: de-identification,pseudonymization,PII,Taiwan,legal,Traditional Chinese
Classifier: Programming Language :: Python :: 3
Classifier: Natural Language :: Chinese (Traditional)
Classifier: Topic :: Text Processing :: Linguistic
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: LICENSES/Apache-2.0.txt
License-File: LICENSES/MIT-jieba.txt
License-File: NOTICE
Requires-Dist: numpy
Requires-Dist: onnxruntime>=1.16
Requires-Dist: tokenizers>=0.19
Provides-Extra: train
Requires-Dist: mlx; extra == "train"
Requires-Dist: transformers; extra == "train"
Requires-Dist: safetensors; extra == "train"
Provides-Extra: export
Requires-Dist: torch; extra == "export"
Requires-Dist: transformers; extra == "export"
Requires-Dist: safetensors; extra == "export"
Requires-Dist: onnx; extra == "export"
Dynamic: license-file

# taiwan-legal-deid

[English](https://github.com/lawchat-oss/taiwan-legal-deid/blob/main/README.en.md)

台灣法律文件去識別化工具。在自己的電腦上，把文件裡的人名、個資、私人公司換成「看起來像真的」假名，同時留一份對照表；AI 的回覆之後可以用對照表換回原文。

- **只換該換的**：程式先列出可能的人名、個資、機構，再由模型逐一判斷「要換／保留／不是」。法官、檢察官、律師、書記官等執行職務的人名保留，當事人、證人等私人換掉；政府機關保留，私人公司換掉。
- **換成擬真假名，不是 ○○○**：同一個人整份文件換成同一個假名，姓、名分開對應（陳小姐 → 詹小姐）；地址換成同縣市的真實路名；身分證換成檢查碼正確的號碼；生日保留年份（年齡不變）；上市櫃公司的簡稱、「下稱」的別名跟著換。
- **法律模式（預設）**：個人行程日期不動，AI 推算期間、時效才不會出錯；地號保留段名，號碼整案一致地換。
- **在本機 CPU 執行**：不需要 GPU；除了第一次下載模型，不會連網。對照表是你電腦上的 JSON 檔。

> 這是假名化，不是匿名化：有對照表就能換回原文，請把對照表當成個資保管。工具一定會有漏網，對外分享前務必人工檢查。

## 範例

原文（虛構）：

> 原告陳美玲（身分證 F223456781，民國71年3月8日生，住臺中市西屯區文心路三段100號7樓，手機 0912-345-678）與被告岱昀顧問股份有限公司（下稱岱昀公司）間確認僱傭關係存在事件。原告自113年5月2日起任職於岱昀公司，陳小姐主張岱昀公司違法解僱。被告訴訟代理人王大同律師。法官李佳穎。

換完（每次執行的假名不同）：

> 原告詹筱怡（身分證 F202201647，民國71年11月1日生，住臺中市沙鹿區北勢二街二段566之6號7樓，手機 0964-883-566）與被告弘邦顧問股份有限公司（下稱弘邦公司）間確認僱傭關係存在事件。原告自113年5月2日起任職於弘邦公司，詹小姐主張弘邦公司違法解僱。被告訴訟代理人王大同律師。法官李佳穎。

## 安裝

需要 Python 3.10 以上。

```bash
pip install taiwan-legal-deid
```

第一次使用時會從 GitHub Release 下載模型（6 層約 244 MB、3 層約 159 MB），驗過 sha256 後存在 `~/.cache/taiwan-legal-deid`。

## 使用

### 指令列

```bash
taiwan-legal-deid 起訴狀.txt                                  # → 起訴狀.txt.fake.txt（假名版）、起訴狀.txt.map.json（對照表）
taiwan-legal-deid 證物.txt --map 案件對照表.json             # 同一案件沿用對照表：同一個人每份文件都換成同一個假名
taiwan-legal-deid --restore AI回覆.txt 起訴狀.txt.map.json    # AI 回覆換回原文
taiwan-legal-deid 起訴狀.txt --model 3l                       # 較快的 3 層模型
taiwan-legal-deid 病歷.txt --general                          # 一般模式：個人行程日期也整份位移
```

輸入是 UTF-8 純文字；PDF、Word 請先轉成文字。

每份文件旁邊都會留一份它自己的對照表（`<檔名>.map.json`），還原那份文件的 AI 回覆時用它。同一案件共用的對照表（`--map`）偶爾會停用少數對照：前一份文件的假名剛好是後一份文件裡的真名時，那個假名就分不出是誰。

### Python

```python
from taiwan_legal_deid import Detector, Obfuscator, restore

ob = Obfuscator(Detector())            # 預設 6 層；Detector("3l") 較快
fake, mapping = ob.anonymize(text)     # 假名版文字、對照表
original = restore(ai_reply, mapping)  # AI 回覆換回原文
```

同一案件有多份文件時，每份文件建一個新的 `Obfuscator`，把上一份回傳的對照表傳進去（跟指令列的 `--map` 相同）；不要拿同一個 `Obfuscator` 連續處理多份文件。

```python
det = Detector()
mapping = None
for text in texts:
    fake, mapping = Obfuscator(det, mapping=mapping).anonymize(text)  # 還原這份文件的 AI 回覆時，用這次回傳的 mapping
```

只要偵測、不替換：`Detector().detect(text)` 回傳每個值的位置、類型與分數。

### 離線使用

先在有網路的機器執行 `taiwan-legal-deid --download`（加 `--model 3l` 下載 3 層），再把 `~/.cache/taiwan-legal-deid` 整個資料夾複製到離線機器的同一個位置，或用環境變數 `TAIWAN_LEGAL_DEID_HOME` 指到放模型的資料夾。設 `TAIWAN_LEGAL_DEID_OFFLINE=1` 時一律不連網。

## 準確度與速度

數字為 weights-v1（套件 0.1.0）量測，可以用 `python eval/reproduce.py` 重跑（另需 `pip install pyarrow`）。

| | 6 層（預設） | 3 層 |
|---|---|---|
| 合成法律文件：要換的人名完整換掉 | 93.3% | 91.1% |
| 合成法律文件：執行職務的人名保留 | 98.0% | 98.0% |
| 合成法律文件：其他個資完整換掉 | 93.6% | 93.0% |
| tw-PII-bench 測試半：人名以外的個資完整換掉 | 95.7% | 95.1% |
| 速度：一份約 10 萬字的文件，找出並替換（Apple M5 Max CPU） | 約 12 秒 | 約 8 秒 |

**本頁數字皆來自合成測試集；合成資料通常比實際文件單純，實際表現可能較低，對外分享前務必人工檢查。**

- **合成法律文件測試集**（`eval/data/synthetic_legal_test.jsonl`）：75 份虛構的起訴狀、判決、筆錄、存證信函、對話紀錄、Email 等，共 21,823 字。題目在任何評測之前封存，開發時沒有看過裡面的錯題。標了 462 個要換的人名、51 個執行職務的人名、498 個其他個資。每份標了難點類型：1 罕見姓與原住民、外籍人名；2 像一般詞的名字；3 OCR 雜訊；4 同一個值多種寫法；5 該保留與該換的人名並存；6 一般文件。
- **tw-PII-bench**（[lianghsun/tw-PII-bench](https://huggingface.co/datasets/lianghsun/tw-PII-bench)，Liang Hsun Huang，Apache-2.0）：取 `crc32(id) % 2 == 1` 的 453 份，以一般模式計分。人名類別在切分之前整份看過，所以不列。
- 「完整換掉」＝標註的每個字都被換掉，只換一部分算沒換掉。
- 法律模式下，生日完整換掉 95.1%、個人行程日期保留 98.3%（兩個模型相同）。

## 已知限制

- 一定會有漏網（見上表），對外分享前務必人工檢查。
- 只有片假名的日本人名、聊天裡只寫名字或綽號的人，常抓不到。
- 地址的頭尾較難切準（合成測試集的地址完整換掉：6 層 88%、3 層 84%）。
- 律師、法官的名字沒有職稱、單獨列在頁首或名單裡時，有時會被當成要換的人名。
- 很長的網址（超過約 220 字）有時整段抓不到。
- 同一案件共用對照表（`--map`）時，如果前一份文件的假名剛好是後一份文件裡的真名，這個人在後面文件裡的假名或稱呼可能前後不一致；還原時請用各份文件自己的對照表。
- 上市櫃公司的簡稱比全名先出現、又沒有「下稱」時，簡稱和全名可能換成不同的假名。
- 人名和公司名稱用到相同的字時（陳佳穎、佳穎科技有限公司），公司的「下稱」別名可能換成人名的假名，跟公司的假名對不上。
- 部分連鎖店、國營事業的當事人會被判成保留；日本公司（株式会社）、日本地址、和曆日期沒有處理。

## 運作方式

1. **找候選（程式）**：依姓氏表（內政部）與稱謂列出可能的人名切法；身分證、電話、帳號、Email、網址、地址（內政部路名）、日期等個資；公司、商號、社區、學校等機構名稱與上市櫃簡稱。程式只負責多抓，不做判斷。
2. **判斷（模型）**：每段文字只跑一次模型，同時判斷段內每個候選「要換／保留／不是」。模型由 bert-base-chinese 微調，再從 12 層蒸餾成 6 層與 3 層，以 ONNX 在 CPU 執行。
3. **替換（程式）**：依類型產生擬真假值，整份文件一致，同一個值在別處的寫法也一起換。

訓練資料包括公開判決（名冊上的真名先換成假名，模型不看真名）、合成法律文件與程式擴增。訓練程式在 `taiwan_legal_deid/train.py`（MLX，Apple Silicon），要從 repo 執行（會讀寫 repo 裡的 `data/`）；訓練資料不公開。

## 授權

- 程式碼：MIT（`LICENSE`）。
- 模型權重：Apache-2.0（`LICENSES/Apache-2.0.txt`），由 bert-base-chinese（Google，Apache-2.0）微調而來。
- 內含的第三方資料（jieba 詞典、內政部與金管會證期局的政府開放資料）見 `NOTICE`。
- 合成法律文件測試集跟程式碼一樣以 MIT 授權。

## 免責聲明

**不提供擔保。** 本工具的程式依 MIT 授權、模型權重依 Apache-2.0 授權「按現狀」提供，不提供任何明示或默示的擔保。在法律許可的範圍內，維護者對使用本工具或其結果所生的損害不負賠償責任。

本工具協助降低文件中個資外流的風險，但不保證找出所有個人資料，也不構成法律意見。文件是否可以分享、上傳或公開，請自行判斷並人工檢查；使用者仍應自行遵守個人資料保護相關法規。

## 引用

見 `CITATION.cff`。

---

Maintained by [lawchat-oss](https://github.com/lawchat-oss). Contributions welcome.
