misono's picture
v4rft requantize (code/bridge/ko_norm.py)
e29cf7d verified
Raw History Blame Contribute Delete
2.41 kB
"""韩语文本归一 (ko 线共享单一真源, 从 gate_ko.py 抽出)。
背景: CV3 前端 (cosyvoice/cli/frontend.py) 分支是二元的 if contains_chinese(text)
→ zh 规范化, else → wetext en TN。韩语没有分支, 走 en 分支会被注入英文
(实测 5000 句真实 ko 语料: changed 24.7%, 纯英文注入 10.5%)。
wittext 本身也没有 ko 模型 (assert lang in (auto,en,zh))。
⇒ ko 侧一律 text_frontend=False + 本模块的数词归一 (门控 CER 0.0522 vs en 分支 0.0702)。
用法: from ko_norm import ko_normalize; t = ko_normalize(raw_ko)
"""
import re
# 韩语数词 (sino-korean, 用于读数字; 万/亿 单位另处理)
SINO = ['영', '일', '이', '삼', '사', '오', '육', '칠', '팔', '구']
UNITS = ['', '십', '백', '천']
BIG = ['', '만', '억', '조']
def _sino4(n):
"""0<n<10000 -> 韩语汉字数词 (일십 -> 십 省略前导 일)。"""
out = []
for pos in range(3, -1, -1):
d = (n // (10 ** pos)) % 10
if d == 0:
continue
out.append(('일' if (d == 1 and pos > 0) else SINO[d]) + UNITS[pos])
return ''.join(out) or SINO[0]
def korean_number(n):
"""整数 -> 韩语数词 (만/억 分节)。"""
if n == 0:
return SINO[0]
parts = []
grp = 0
while n > 0:
chunk = n % 10000
if chunk:
parts.append(_sino4(chunk) + BIG[grp])
n //= 10000
grp += 1
return ''.join(reversed(parts))
KOR_CNT = ('년|월|일|시|분|초|개|명|번|층|살|세|위|등|가지|마리|잔|병|권|장|대|회|주|달|원|위안|엔|달러|'
'킬로|미터|그램|퍼센트|프로|배|점|호|호선|편|화|차|번째|군요|째')
def ko_normalize(t):
"""韩文数字 -> 韩语数词, 保留阿拉伯数字以外的 Latin (如 4K/RTX 型号按 Latin 读)。
策略: 数字后紧跟韩文量词/名词(无空格)时 -> 韩语数词;
数字+Latin 型号(4K/5090/i7) -> 保持原样(让 tokenizer 直读);
纯数字独立 token -> 韩语数词。
"""
def repl(m):
num = m.group(1).replace(',', '')
tail = m.group(2) or ''
if not num.isdigit():
return m.group(0)
return korean_number(int(num)) + tail
# 数字(可带千分位) + 可选紧跟的韩文量词/名词片段
t = re.sub(r'(\d[\d,]*)\s*(%|[' + '가-힣' + r']{0,3})', repl, t)
return t