Twinity-1 / README.md
JacobLinCool's picture
fix pipeline_tag
edfb9ca verified
|
Raw
History Blame Contribute Delete
6.36 kB
---
license: mit
language:
- zh
tags:
- chinese
- traditional-chinese
- taiwan
- text-normalization
- zh-tw
- opencc
library_name: twlat
pipeline_tag: translation
---
# Twinity-1
**中國大陸中文 → 臺灣正體中文的確定性轉換器。8.86M 參數,CPU 單執行緒 11,300 字/秒。**
Twinity-1 不生成文字。字典編譯成 conversion lattice,界定「哪些位置可以改、可以改成什麼」;
模型只在每個歧義位點裁決「這個語境該不該改」;Viterbi 選出全域一致的編輯集合,
最後對原文做**最小 splice**——編輯範圍以外的每一個位元組原樣保留。
因此它結構上**不可能**改寫語句、增刪內容、或破壞外語片段與程式碼。
```python
import twlat
twlat.convert("这个程序有bug,请在服务器上重新部署。")
# '這個程式有 bug,請在伺服器上重新部署。'
```
## 為什麼不用查表或 LLM
| | 查表(OpenCC) | LLM 改寫 | **Twinity-1** |
| --- | --- | --- | --- |
| 語境判斷 | ✗ 無 | ✓ | ✓ |
| 確定性 | ✓ | ✗ | ✓ 100% |
| 只改該改的 | ✓ | ✗ 會潤飾/增刪 | ✓ 最小 splice |
| 外語/程式碼保留 | ✓ | ✗ | ✓ 1,248/1,248 |
| 成本 | $0 | API | $0 |
| 延遲(p95) | <1 ms | 秒級 | 23 ms |
「程序」在軟體語境是**程式**、在法律語境就是**程序**;「里」在「那里」該轉**裡**
在「公里」不能動。查表沒有語境;LLM 有語境但不確定且會多改。
## 評測
TWBench-Neutral(1,496 題/8,438 個歧義位點,gold = 臺灣正體語料原文,
不由任何系統產生;gold 自身誤差經分層盲審量測並逐條修正):
| 系統 | site accuracy | 維持 | 改動 |
| --- | --- | --- | --- |
| OpenCC | 0.9176 | 0.9411 | 0.8604 |
| zhtw-mcp(規則層) | 0.9263 | 0.9510 | 0.8661 |
| 前代 V1(6.06M) | 0.9456 | 0.9694 | 0.8877 |
| 前代 V2(3.32M) | 0.9445 | 0.9565 | 0.9153 |
| **Twinity-1(8.86M)** | **0.9712** | **0.9941** | **0.9153** |
對前代顯著勝出(+2.7pp/+2.6pp,paired bootstrap p < 0.001)。
與 frontier LLM 基線在 320 題子集上**無顯著差異**(0.9782 vs 0.9709,p = 0.34)——
本模型不主張比 LLM 更準,而是在同等準確度下提供確定性、零成本與 23 ms 延遲。
盲測排序(103 題、14 位獨立評審、匿名、正反序雙輪):Twinity-1 平均名次 **1.296**
優於 V2(1.612)與 V1(2.199)。
## 怎麼訓練的
**Confusion-set cloze 自監督**,在 6.5 億字真實臺灣正體語料上:
每個 lattice 位點收合成單一 `[MASK]`,模型預測臺灣書寫者實際用了哪個形式。
這把無標註語料變成上億個監督事件,且消除了「相信輸入表面形式」的捷徑。
雙 pass 架構:masked pass 提供無洩漏的語境證據,clean pass(陸式汙染文本)
提供表面證據與文件級領域向量。候選一律由**與文本共用的字元 embedding**
動態編碼,沒有 per-candidate 查表參數——這是字典熱更新的前提。
架構:d=256,8 層(6 層 dilated TCN dilation 1..128 + 2 層 local attention),
預訓練 120k 步 + finetune 8k 步,RTX 4080 約 2.8 小時。
## 操作點
模型與字典相同,只差「要多少證據才動手」(τ 是對數勝算比門檻):
| preset | 語意 | site acc |
| --- | --- | --- |
| `accuracy` | 20:1 勝算才改,benchmark 最佳 | 0.9712 |
| `balanced` | 2.7:1 即改,**預設** | 0.9668 |
| `taiwanize` | 額外壓制陸式專用詞(視頻/博客/實時) | 0.9640 |
| `aggressive` | 只靠字典硬過濾把關 | 0.9631 |
```python
conv = twlat.Converter(preset="taiwanize")
r = conv.explain("这个视频的信息量很大")
for d in r.decisions:
print(d) # Decision('視頻'→'影片' @[2,4) cross_strait u=2.75)
```
## 熱更新
新增字典條目只需重新編譯 `data/dict/lattice_lexicon.json`**模型權重不動**
實測:訓練時完全沒見過的 50 條規則,zero-shot change accuracy **0.71**
(前代架構同一量測為 0.12)。
## 檔案
| 檔案 | 用途 |
| --- | --- |
| `twinity-1.pt` | 模型權重(8.86M 參數) |
| `data/dict/lattice_lexicon.json` | 編譯後的字典(1,780 confusion group/3,977 詞形)——熱更新入口 |
| `data/dict/char_vocab_v3.json` | 字元表(4,096),OOV 走 hash bucket |
| `data/dict/rules/` | 簡繁字表、臺標變體表、必轉字表 |
| `data/model/tau.json` | 部署操作點的決策門檻 |
| `twlat/` | 推論程式碼(純 Python,相依:torch、numpy、regex、pyahocorasick、opencc) |
## 使用
```bash
pip install torch numpy regex pyahocorasick opencc-python-reimplemented
```
```python
from huggingface_hub import snapshot_download
import os, sys
path = snapshot_download("JacobLinCool/Twinity-1")
os.environ["TWLAT_HOME"] = f"{path}/data"
sys.path.insert(0, path)
import twlat
conv = twlat.Converter(ckpt=f"{path}/twinity-1.pt", device="cpu")
print(conv.convert("这个程序有bug,请在服务器上部署"))
```
CPU 單執行緒最快(`torch.set_num_threads(1)`):11,300 字/秒、p95 23 ms。
執行緒開多反而慢 3–24 倍(小矩陣的執行緒同步成本壓倒運算)。
## 已知限制
1. **陸式專用詞的漏轉**`服務器→伺服器``搜索→搜尋` 等在訓練語料中缺少
change 方向訊號(網爬語料原生大量出現且被標為保留),模型高信心保留。
約佔殘餘 change 錯誤的 25%。修正路徑明確但需重訓。
2. **INT8 量化未達標**(−1.33pp),交付 FP32。
3. **台/臺 由語境決定**而非固定政策——多數語境正確,但官方機關名語域仍有殘餘錯誤。
若你的場景要求一律「臺」,請在後處理強制。
4. 訓練語料含 CC-100 網爬文本,可能帶有其偏誤。
5. 輸入超過 512 字會以滑動視窗處理(stride 384),跨窗的一致性未特別最佳化。
## 授權與致謝
模型權重 MIT。字典衍生自 [zhtw-mcp](https://github.com/sysprog21/zhtw-mcp)(MIT)
與 [OpenCC](https://github.com/BYVoid/OpenCC)(Apache-2.0)——本專案的核心主張之一
正是「這些字典裡的語意資訊被嚴重低估」。訓練語料:維基百科 zh-tw(CC BY-SA 4.0)、
臺灣立法院法律研究資料(OGDL-1.0)、CC-100 繁體。