[English](README.md) | **繁體中文**

# Phonetic Substitution Engine (多語言語音相似替換引擎)

基於語音相似度的多語言專有名詞替換工具。支援 ASR/LLM 後處理、地域慣用詞轉換、縮寫擴展等多種應用場景。
特別針對 **中英混合 (Code-Switching)** 場景進行了優化。

## 💡 核心理念

**本套件不維護任何專有名詞字典，而是提供一個基於語音向量空間的替換引擎。**

此套件的核心機制是將不同語言的文本統一映射到**語音向量空間**（由拼音、IPA 音標組成）。

無論是 ASR（語音識別）、LLM（大型語言模型）或其他場景出現的拼寫錯誤——通常是因為專有名詞罕見導致選字錯誤——本工具都會將其轉換到**拼音/音標維度**。

接著，系統會將這些轉換後的語音特徵，與**使用者提供的專有名詞**（加上系統自動生成的模糊音變體）進行比對，計算可能性，進而精準替換拼寫錯誤。

> ⚠️ **注意**：這不是全文糾錯工具，而是專注於「專有名詞的語音相似替換」。

使用者需自行提供專有名詞字典，本工具會：
1. **自動生成語音變體**：
   - **中文**：自動產生台式口音/模糊音變體（如「北車」→「台北車站」）
   - **英文**：基於 IPA (國際音標) 計算語音相似度（如 "Ten so floor" → "TensorFlow"）
2. **智能詞彙替換**：自動識別語言片段，將語音相似的詞彙替換為您指定的標準專有名詞

**適用場景**：
- **ASR 語音識別後處理**：修正語音轉文字產生的專有名詞錯誤（含中英夾雜）
- **LLM 輸出後處理**：修正大型語言模型因專有名詞罕見而選錯的同音字/近音字
- **專有名詞標準化**：將口語/誤寫的術語還原為正式名稱
- **地域詞彙轉換**：中國慣用詞 ↔ 台灣慣用詞

## 📚 功能特色

### 1. 多語言支援
- **Unified Corrector**: 統一入口，自動處理中英混合文本
- **英文語音替換**: 
    - 使用 IPA (International Phonetic Alphabet) 進行語音相似度比對
    - 支援 Acronyms (縮寫) 的語音還原
- **中文語音替換**:
    - 使用拼音進行模糊音比對
    - 支援台灣國語特有的發音混淆模式

### 2. 自動語音變體生成
- **中文**：自動產生台式口音/模糊音變體
  - 捲舌音 (z/zh, c/ch, s/sh)
  - n/l 不分 (台灣國語)
  - r/l 混淆、f/h 混淆
  - 韻母模糊 (in/ing, en/eng, ue/ie 等)
- **英文**：自動產生 ASR/LLM 常見錯誤變體
  - 音節分割變體 ("TensorFlow" → "Ten so floor")
  - 縮寫展開變體 ("AWS" → "A W S")

### 3. 智能替換引擎
- 滑動視窗匹配算法
- 上下文關鍵字加權機制
- 動態容錯率調整

### 4. 串流處理支援 (ASR/LLM Streaming)
- **累積模式** (`StreamingCorrector`)：適用於 Realtime ASR
  - 支援累積文本持續更新
  - 自動偵測新段落並重置快取
- **Chunk 模式** (`ChunkStreamingCorrector`)：適用於 LLM Streaming
  - 增量輸入，即時輸出已確認的修正
  - 保留重疊區域防止詞彙被切斷

## 📦 安裝

### 使用 uv (推薦)

[uv](https://docs.astral.sh/uv/) 是新一代的 Python 套件管理工具，速度快且功能完整。

```bash
# 安裝 uv (Windows PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

# 安裝 uv (macOS/Linux)
curl -LsSf https://astral.sh/uv/install.sh | sh
```

```bash
# 預設安裝 (包含中英文支援)
uv add phonofix

# 僅中文支援
uv add "phonofix[ch]"

# 僅英文支援 (需先安裝 espeak-ng，見下方說明)
uv add "phonofix[en]"

# 完整安裝 (與預設相同)
uv add "phonofix[all]"
```

### 英文支援說明 (espeak-ng 安裝)

英文語音功能依賴 [espeak-ng](https://github.com/espeak-ng/espeak-ng) 系統套件。

**使用內建安裝腳本 (推薦)**：

本專案提供自動化安裝腳本，會自動下載、安裝並設定環境變數：

```bash
# Windows PowerShell (建議以管理員權限執行)
.\scripts\setup_espeak.ps1

# Windows CMD (建議以管理員權限執行)
scripts\setup_espeak_windows.bat

# macOS / Linux
chmod +x scripts/setup_espeak.sh
./scripts/setup_espeak.sh
```

腳本會自動完成：
1. 檢查/安裝 espeak-ng
2. 設定 `PHONEMIZER_ESPEAK_LIBRARY` 環境變數
3. 驗證 phonemizer 是否正常運作

**手動安裝**：

```bash
# Windows: 從 GitHub 下載安裝程式
# https://github.com/espeak-ng/espeak-ng/releases

# macOS
brew install espeak-ng

# Debian/Ubuntu
sudo apt install espeak-ng

# Arch Linux
sudo pacman -S espeak-ng
```

### 開發環境設定

```bash
# Clone 專案後安裝依賴
uv sync

# 安裝開發依賴
uv sync --dev

# 執行範例
uv run python examples/chinese_examples.py

# 執行測試
uv run pytest
```

## 🧪 開發

```bash
# 執行測試
uv run pytest

# 執行測試並顯示覆蓋率
uv run pytest --cov

# 程式碼格式化
uv run ruff format .

# 程式碼檢查
uv run ruff check .

# 型別檢查
uv run mypy src/phonofix
```

## 🚀 快速開始

### 1. 混合語言替換 (Unified Corrector)

```python
from phonofix import UnifiedEngine

# 定義您的專有名詞字典
terms = [
    "台北車站",      # 中文詞
    "TensorFlow",   # 英文專有名詞
    "Python"
]

# 初始化引擎 (單例模式，建議全域只初始化一次)
engine = UnifiedEngine()

# 建立替換器
corrector = engine.create_corrector(terms)

# ASR 輸出後處理
asr_text = "我在北車用Pyton寫Ten so floor的code"
result = corrector.correct(asr_text)
print(result)
# 輸出: "我在台北車站用Python寫TensorFlow的code"

# LLM 輸出後處理 (LLM 可能因罕見詞而選錯同音字)
llm_text = "我在北車用派森寫code"  # LLM 把 Python 音譯成「派森」
result = corrector.correct(llm_text)
print(result)
# 輸出: "我在台北車站用Python寫code"
```

### 2. 中文專用 (Chinese Engine)

**重要提醒**：本工具不提供預設字典，您需要根據自己的業務場景建立專有名詞清單。

#### 推薦使用方式 - 自動生成別名

使用 `ChineseEngine`，**只需提供您的專有名詞清單**，工具會自動生成所有可能的模糊音變體並進行拼音去重：

#### 最簡格式 - 僅提供關鍵字列表

```python
from phonofix import ChineseEngine

# 步驟 1: 提供您的專有名詞清單（這是您需要維護的字典）
my_terms = ["台北車站", "牛奶", "發揮"]

# 步驟 2: 初始化引擎並建立替換器
# 工具會自動生成所有可能的模糊音變體
# 例如："台北車站" → 自動生成 "北車"、"臺北車站" 等變體
engine = ChineseEngine()
corrector = engine.create_corrector(my_terms)

# 步驟 3: 自動將接近音的詞轉換為正確的專有名詞
result = corrector.correct("我在北車買了流奶,他花揮了才能")
# 結果: '我在台北車站買了牛奶,他發揮了才能'
# 說明: "北車" → "台北車站", "流奶" → "牛奶", "花揮" → "發揮"
```

#### 完整格式 - 別名 + 關鍵字 + 權重

當同一個別名可能對應多個專有名詞時，可使用上下文關鍵字和權重來提高準確度：

```python
# 您的專有名詞字典（根據您的業務場景維護）
my_business_terms = {
    "永和豆漿": {
        "aliases": ["永豆", "勇豆"],  # 手動提供常見別名或錯音
        "keywords": ["吃", "喝", "買", "宵夜"],  # 上下文關鍵字幫助判斷
        "weight": 0.3  # 匹配權重
    },
    "勇者鬥惡龍": {
        "aliases": ["勇鬥", "永鬥"],  # 同音但不同意義
        "keywords": ["玩", "遊戲", "攻略"],
        "weight": 0.2
    }
}

engine = ChineseEngine()
corrector = engine.create_corrector(my_business_terms)

result = corrector.correct("我去買勇鬥當宵夜")
# 結果: '我去買永和豆漿當宵夜'
# 說明: 因為命中「買」和「宵夜」關鍵字，判斷為「永和豆漿」而非「勇者鬥惡龍」
```

**優點**:
- ✅ 自動生成模糊音變體，無需手動維護
- ✅ 自動過濾拼音重複的別名（類似 Set 行為）
- ✅ 支援多種輸入格式，使用靈活
- ✅ 減少配置工作量，專注於核心詞彙

### 進階功能

#### 上下文關鍵字

```python
from phonofix import ChineseEngine

# 使用上下文關鍵字提高準確度
engine = ChineseEngine()
corrector = engine.create_corrector({
    "永和豆漿": {
        "aliases": ["永豆"],
        "keywords": ["吃", "喝", "買", "宵夜", "早餐"]
    },
    "勇者鬥惡龍": {
        "aliases": ["勇鬥"],
        "keywords": ["玩", "遊戲", "電動", "攻略"]
    }
})

result = corrector.correct("我去買勇鬥當宵夜")  # 命中「買」→ 永和豆漿
result = corrector.correct("這款永豆的攻略很難找")  # 命中「攻略」→ 勇者鬥惡龍
```

#### 權重系統

```python
# 使用權重提高優先級
engine = ChineseEngine()
corrector = engine.create_corrector({
    "恩典": {
        "aliases": ["安點"],
        "weight": 0.3  # 高權重,優先匹配
    },
    "上帝": {
        "aliases": ["上帝"],
        "weight": 0.1  # 低權重
    }
})
```

#### 豁免清單

```python
# 設定保護詞彙清單,避免特定詞被修正
engine = ChineseEngine()
corrector = engine.create_corrector(
    terms={
        "台北車站": ["北車"]
    },
    protected_terms=["北側", "南側"]  # 這些詞不會被修正
)

result = corrector.correct("我在北側等你")  # 不會修正為「台北車站側」
```

### 3. 串流處理 (ASR/LLM Streaming)

#### Realtime ASR 串流

適用於語音識別的即時字幕場景，每次傳入累積的完整識別結果：

```python
from phonofix import ChineseEngine, StreamingCorrector

engine = ChineseEngine()
corrector = engine.create_corrector(["台北車站", "牛奶"])

# 建立串流處理器
streamer = StreamingCorrector(corrector, overlap_size=8)

# 模擬 ASR 累積輸入
asr_outputs = [
    "我在胎北",
    "我在胎北車站",
    "我在胎北車站買了流",
    "我在胎北車站買了流奶",
]

for text in asr_outputs:
    result = streamer.feed(text)
    print(f"已確認: {result.confirmed} | 待確認: {result.pending}")

# 結束時取得完整結果
final = streamer.finalize()
print(f"最終: {final}")
# 最終: 我在台北車站買了牛奶
```

#### LLM Streaming 輸出

適用於 LLM 串流輸出，每次傳入新的 chunk：

```python
from phonofix import ChineseEngine, ChunkStreamingCorrector

engine = ChineseEngine()
corrector = engine.create_corrector(["聖靈", "聖經", "恩典"])

# 建立 chunk 模式串流處理器
streamer = ChunkStreamingCorrector(corrector, overlap_size=6)

# 模擬 LLM 串流輸出
llm_chunks = ["聖林", "借著默氏", "寫了這本", "生經，", "是安點。"]

for chunk in llm_chunks:
    result = streamer.feed_chunk(chunk)
    if result.confirmed:
        print(result.confirmed, end="", flush=True)  # 即時輸出

# 結束時輸出剩餘部分
remaining = streamer.finalize()
print(remaining)
# 輸出: 聖靈借著默氏寫了這本聖經，是恩典。
```

#### WebSocket 實際應用

```python
from phonofix import ChineseEngine, StreamingCorrector
import json

engine = ChineseEngine()
corrector = engine.create_corrector(my_terms)

async def handle_asr_websocket(websocket):
    streamer = StreamingCorrector(corrector, overlap_size=10)
    
    async for message in websocket:
        data = json.loads(message)
        
        if data["type"] == "partial":
            result = streamer.feed(data["text"])
            await websocket.send(json.dumps({
                "confirmed": result.confirmed,
                "pending": result.pending,
            }))
            
        elif data["type"] == "final":
            final = streamer.finalize()
            await websocket.send(json.dumps({"final": final}))
            streamer.reset()  # 重置，準備下一段
```

## 📁 專案結構

```
phonofix/
├── src/
│   └── phonofix/                      # 主套件 (src layout)
│       ├── __init__.py                # 主入口，匯出 UnifiedEngine, ChineseEngine 等
│       ├── config.py                  # 全域配置
│       │
│       ├── engine/                    # 引擎層 (單例模式入口)
│       │   ├── base.py                # BaseEngine 抽象類別
│       │   ├── unified_engine.py      # UnifiedEngine - 混合語言
│       │   ├── chinese_engine.py      # ChineseEngine - 中文專用
│       │   └── english_engine.py      # EnglishEngine - 英文專用
│       │
│       ├── backend/                   # 語音後端 (phonemizer/pypinyin 封裝)
│       │   ├── base.py                # PhoneticBackend 抽象類別
│       │   ├── chinese_backend.py     # 中文拼音後端
│       │   └── english_backend.py     # 英文 IPA 後端
│       │
│       ├── correction/                # 修正器層
│       │   ├── unified_corrector.py   # 混合語言修正器
│       │   └── streaming_corrector.py # 串流修正器 (ASR/LLM)
│       │
│       ├── languages/                 # 語言特定實作
│       │   ├── chinese/               # 中文模組
│       │   │   ├── config.py          # 拼音配置 (聲母/韻母/模糊音)
│       │   │   ├── corrector.py       # 中文校正器
│       │   │   ├── fuzzy_generator.py # 模糊音變體生成
│       │   │   ├── number_variants.py # 數字變體處理
│       │   │   └── tokenizer.py       # 中文分詞器
│       │   │
│       │   └── english/               # 英文模組
│       │       ├── config.py          # IPA 配置
│       │       ├── corrector.py       # 英文校正器
│       │       ├── fuzzy_generator.py # 音節分割變體生成
│       │       └── tokenizer.py       # 英文分詞器
│       │
│       ├── router/                    # 語言路由
│       │   └── language_router.py     # 自動偵測中英文區塊
│       │
│       └── utils/                     # 工具模組
│           ├── lazy_imports.py        # 延遲導入 (可選依賴管理)
│           └── logger.py              # 日誌工具
│
├── scripts/                           # 安裝腳本
│   ├── setup_espeak.ps1               # Windows PowerShell 安裝 espeak-ng
│   ├── setup_espeak.sh                # macOS/Linux 安裝 espeak-ng
│   └── setup_espeak_windows.bat       # Windows CMD 安裝 espeak-ng
│
├── examples/                          # 使用範例
│   ├── chinese_examples.py            # 中文校正範例
│   ├── english_examples.py            # 英文校正範例
│   ├── mixed_language_examples.py     # 混合語言範例
│   ├── streaming_demo.py              # 串流處理範例
│   └── timing_demo.py                 # 效能計時範例
│
├── tests/                             # 單元測試
│   ├── test_chinese_corrector.py
│   ├── test_english_corrector.py
│   └── test_unified_corrector.py
│
├── pyproject.toml                     # 專案配置 (phonofix)
├── requirements.txt                   # 依賴清單
└── README.md
```

## 🎯 使用場景

以下範例展示不同業務場景下，如何建立您自己的專有名詞字典：

### 1. ASR 語音識別後處理

**問題**：語音識別常將專有名詞聽錯成發音相近的一般詞彙

```python
# 您的專有名詞字典
terms = ["牛奶", "發揮", "然後", "TensorFlow", "Kubernetes"]

engine = UnifiedEngine()
corrector = engine.create_corrector(terms)

# ASR 輸出：專有名詞被聽錯
asr_output = "我買了流奶，蘭後用Ten so floor訓練模型"
result = corrector.correct(asr_output)
# 結果: "我買了牛奶，然後用TensorFlow訓練模型"
```

### 2. LLM 輸出後處理

**問題**：LLM 可能因專有名詞罕見而選擇發音相近的常用字

```python
# 您的專有名詞字典
terms = ["耶穌", "恩典", "PyTorch", "NumPy"]

engine = UnifiedEngine()
corrector = engine.create_corrector(terms)

# LLM 輸出：罕見專有名詞被替換成同音常用字
llm_output = "耶穌的恩點很大，我用排炬和南派做機器學習"
result = corrector.correct(llm_output)
# 結果: "耶穌的恩典很大，我用PyTorch和NumPy做機器學習"
```

### 3. 地域慣用詞轉換

**您的字典**：維護地域對照表（例如：中國 ↔ 台灣慣用詞）

```python
# 您的地域詞彙字典
region_terms = {
    "馬鈴薯": {"aliases": ["土豆"], "weight": 0.0},
    "影片": {"aliases": ["視頻"], "weight": 0.0}
}

engine = ChineseEngine()
corrector = engine.create_corrector(region_terms)

result = corrector.correct("我用土豆做了視頻")
# 結果: "我用馬鈴薯做了影片"
```

### 4. 縮寫擴展

**您的字典**：維護常用縮寫與全稱對照表

```python
# 您的縮寫字典
abbreviation_terms = {
    "台北車站": {"aliases": ["北車"], "weight": 0.0}
}

engine = ChineseEngine()
corrector = engine.create_corrector(abbreviation_terms)

result = corrector.correct("我在北車等你")
# 結果: "我在台北車站等你"
```

### 5. 專業術語標準化

**您的字典**：維護業務領域的專業術語

```python
# 您的醫療術語字典
medical_terms = {
    "阿斯匹靈": {"aliases": ["阿斯匹林", "二四批林"], "weight": 0.2}
}

engine = ChineseEngine()
corrector = engine.create_corrector(medical_terms)

result = corrector.correct("醫生開了二四批林給我")
# 結果: "醫生開了阿斯匹靈給我"
```

## 📖 完整範例

請參考 `examples/` 目錄，包含多個使用範例：

| 檔案 | 說明 |
|------|------|
| `chinese_examples.py` | 中文語音替換範例 |
| `english_examples.py` | 英文語音替換範例 |
| `mixed_language_examples.py` | 中英混合替換範例 |
| `streaming_demo.py` | 基礎串流處理範例 |
| `realtime_streaming_demo.py` | ASR/LLM 即時串流範例 |
| `timing_demo.py` | 效能計時範例 |

```bash
# 執行中文範例
uv run python examples/chinese_examples.py

# 執行英文範例 (需安裝 espeak-ng)
uv run python examples/english_examples.py

# 執行串流範例
uv run python examples/realtime_streaming_demo.py
```

## 🔧 技術細節

### 語音比對機制

#### 中文：拼音模糊音規則

**聲母模糊群組**
| 群組 | 音素 | 說明 |
|------|------|------|
| 捲舌音 | z ⇄ zh, c ⇄ ch, s ⇄ sh | 台灣國語常見 |
| n/l 不分 | n ⇄ l | 台灣國語特色 |
| r/l 混淆 | r ⇄ l | ASR 常見錯誤 |
| f/h 混淆 | f ⇄ h | 方言影響 |

**韻母模糊對應**
- `in` ⇄ `ing`, `en` ⇄ `eng`, `an` ⇄ `ang`
- `ian` ⇄ `iang`, `uan` ⇄ `uang`, `uan` ⇄ `an`
- `ong` ⇄ `eng`, `uo` ⇄ `o`, `ue` ⇄ `ie`

**特例音節映射**
- `fa` ⇄ `hua` (發/花)
- `xue` ⇄ `xie` (學/鞋)
- `ran` ⇄ `lan`, `yan` (然/蘭/嚴)
- 更多請參考 `src/phonofix/languages/chinese/config.py`

#### 英文：IPA 音標比對

使用 [phonemizer](https://github.com/bootphon/phonemizer) 將英文轉換為 IPA (國際音標)，再計算 Levenshtein 編輯距離。

**常見 ASR/LLM 錯誤類型**
| 錯誤類型 | 範例 | 說明 |
|----------|------|------|
| 音節分割 | "TensorFlow" → "Ten so floor" | 語音辨識分割錯誤 |
| 同音異字 | "Python" → "Pyton" | 拼寫錯誤 |
| 縮寫展開 | "API" → "A P I" | 逐字母發音 |

### Keywords 與 exclude_when 機制

當同一個別名可能對應多個專有名詞時，使用 `keywords` 和 `exclude_when` 進行精確判斷：

```
替換判斷邏輯:
┌─────────────────────────────────────────────────────────┐
│  輸入文本包含別名 (如 "1kg")                              │
│                    ↓                                     │
│  ┌─────────────────────────────────────────────────┐    │
│  │ Step 1: 檢查 exclude_when (排除條件)               │    │
│  │   - 若文本包含任一排除詞 → 不替換 ❌          │    │
│  │   - 例: "1kg水很重" 包含 "水" → 不替換為 EKG      │    │
│  └─────────────────────────────────────────────────┘    │
│                    ↓ (無排除詞匹配)                       │
│  ┌─────────────────────────────────────────────────┐    │
│  │ Step 2: 檢查 keywords (必要條件)                 │    │
│  │   - 若有設定 keywords 且無任何匹配 → 不替換 ❌     │    │
│  │   - 若有設定 keywords 且有匹配 → 替換 ✅          │    │
│  │   - 若未設定 keywords → 替換 ✅                   │    │
│  │   - 例: "1kg設備" 包含 "設備" → 替換為 EKG        │    │
│  └─────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘
```

**重要規則：exclude_when 優先於 Keywords**

即使有 keywords 匹配，只要有 exclude_when 匹配就不替換：

```python
"EKG": {
    "aliases": ["1kg"],
    "keywords": ["設備", "醫療"],      # 必須包含其一才替換
    "exclude_when": ["重", "公斤"],    # 包含任一就不替換
}

# 範例：
"這個設備有 1kg重"  # keywords(設備) ✓ + exclude_when(重) ✓ → 不替換
"這個 1kg設備"      # keywords(設備) ✓ + exclude_when ✗ → 替換為 EKG
"買了 1kg的東西"    # keywords ✗ → 不替換
```

### 替換算法流程

```
輸入文本
    │
    ▼
┌─────────────────────────────────────┐
│ 1. 建立保護遮罩                      │
│    標記 protected_terms 中的詞位置    │
│    這些位置不參與任何替換            │
└─────────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────────┐
│ 2. 語言區塊偵測 (UnifiedCorrector)   │
│    中文區塊 → ChineseCorrector       │
│    英文區塊 → EnglishCorrector       │
└─────────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────────┐
│ 3. 滑動視窗掃描                      │
│    遍歷所有可能的詞長組合            │
└─────────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────────┐
│ 4. 語音相似度計算                    │
│    中文: 拼音比對 (特例→韻母→編輯距離)│
│    英文: IPA 音標編輯距離            │
└─────────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────────┐
│ 5. Keywords/exclude_when 過濾     │
│    - 有 exclude_when 匹配 → 跳過    │
│    - 無 keywords 匹配 → 跳過         │
└─────────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────────┐
│ 6. 計算最終分數                      │
│    分數 = 錯誤率 - 權重 - 上下文獎勵  │
│    (分數越低越好)                    │
└─────────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────────┐
│ 7. 衝突解決                          │
│    依分數排序，選擇最佳不重疊候選     │
└─────────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────────┐
│ 8. 文字替換                          │
│    從後向前替換，避免索引錯位         │
└─────────────────────────────────────┘
    │
    ▼
輸出結果
```

### 動態容錯率

| 詞長 | 容錯率 | 說明 |
|------|--------|------|
| 2 字/字母 | 0.20 | 必須非常準確 |
| 3 字/字母 | 0.30 | 中等嚴格 |
| 4+ 字/字母 | 0.40 | 寬容度較高 |
| 英文混用 | 0.45 | 容錯較高 |

## 🤝 貢獻

歡迎提交 Issue 和 Pull Request!

## 📄 授權

MIT License

## 👨‍💻 作者

JonesHong

## 🙏 致謝

感謝以下專案:
- [pypinyin](https://github.com/mozillazg/python-pinyin)
- [python-Levenshtein](https://github.com/maxbachmann/Levenshtein)
- [Pinyin2Hanzi](https://github.com/letiantian/Pinyin2Hanzi)
- [hanziconv](https://github.com/berniey/hanziconv)
