Download verify_export.py from IndexTeam/Index-Echo-S2ST-9B: direct link, hf CLI and curl.
- Browser
- Download file 5.17 kB
-
https://huggingface.co/IndexTeam/Index-Echo-S2ST-9B/resolve/main/verify_export.py
- Command line
-
hf download hf://IndexTeam/Index-Echo-S2ST-9B/verify_export.py
-
curl -L -o verify_export.py https://huggingface.co/IndexTeam/Index-Echo-S2ST-9B/resolve/main/verify_export.py
5.17 kB
| #!/usr/bin/env python3 | |
| """dubbing_2b_ml_s2full12_v4_cv3 断网自包含验证: 完整加载 + en/es/ja/ko/zh 各 dub 1 条 + whisper 回测 en(WER)/ko(CER)/zh(CER)。 | |
| 用法: HF_HUB_OFFLINE=1 TRANSFORMERS_OFFLINE=1 MODELSCOPE_OFFLINE=1 \ | |
| python verify_export.py [--model-dir DIR] [--langs en,es,ja,ko,zh] | |
| 验证点: | |
| - 断网完整加载 (HF_HUB_OFFLINE / TRANSFORMERS_OFFLINE / MODELSCOPE_OFFLINE); | |
| - 每语种出一条非静音 wav, 时长合理 (2-15s, 超出仅 WARN); | |
| - 打印每语种判定源语/译文 (ja 额外打印 kata 化后文本) 与参考译文供人工核对; | |
| - input_zh.wav 为英语源 (en->zh 方向, 覆盖 en 源路径), 其余为中文源; | |
| - en 用 whisper-large-v3 回测算 WER; ko/zh 回测算字级 CER。 | |
| """ | |
| import argparse | |
| import json | |
| import os | |
| import sys | |
| os.environ.setdefault('HF_HUB_OFFLINE', '1') | |
| os.environ.setdefault('TRANSFORMERS_OFFLINE', '1') | |
| os.environ.setdefault('MODELSCOPE_OFFLINE', '1') | |
| _HERE = os.path.dirname(os.path.abspath(__file__)) | |
| sys.path.insert(0, _HERE) | |
| WHISPER = os.environ.get('DUBBING_WHISPER', | |
| '/mnt/pfs-write/users/lusheng/Index-MT/models/whisper-large-v3') | |
| def cer(ref, hyp): | |
| """字级 CER (去空格与标点)。""" | |
| import string | |
| drop = set(string.punctuation) | set('。,、!?;:“”‘’()《》…—') | |
| norm = lambda s: [c for c in s.replace(' ', '') if c not in drop] | |
| r, h = norm(ref), norm(hyp) | |
| if not r: | |
| return float('nan') | |
| prev = list(range(len(h) + 1)) | |
| for i, rc in enumerate(r, 1): | |
| cur = [i] | |
| for j, hc in enumerate(h, 1): | |
| cur.append(min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + (rc != hc))) | |
| prev = cur | |
| return prev[-1] / len(r) | |
| def wer(ref, hyp): | |
| import string | |
| norm = lambda s: [w.strip(string.punctuation) for w in s.lower().split() | |
| if w.strip(string.punctuation)] | |
| r, h = norm(ref), norm(hyp) | |
| if not r: | |
| return float('nan') | |
| prev = list(range(len(h) + 1)) | |
| for i, rc in enumerate(r, 1): | |
| cur = [i] | |
| for j, hc in enumerate(h, 1): | |
| cur.append(min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + (rc != hc))) | |
| prev = cur | |
| return prev[-1] / len(r) | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument('--model-dir', default=_HERE) | |
| ap.add_argument('--langs', default='en,es,ja,ko,zh') | |
| args = ap.parse_args() | |
| langs = args.langs.split(',') | |
| assert not os.environ.get('DUBBING_HOME') or \ | |
| os.path.abspath(os.environ['DUBBING_HOME']) == os.path.abspath(args.model_dir) | |
| from modeling_dubbing import DubbingBridgeModel | |
| model = DubbingBridgeModel.from_pretrained(args.model_dir) | |
| print('[verify] model loaded, single process', flush=True) | |
| refs = json.load(open(os.path.join(args.model_dir, 'samples', 'refs.json'))) | |
| report = [] | |
| for lang in langs: | |
| src = os.path.join(args.model_dir, 'samples', f'input_{lang}.wav') | |
| out = os.path.join(args.model_dir, 'samples', f'dub_{lang}.wav') | |
| wav, sr, info = model.dub(src, lang=lang, out_wav=out, return_info=True) | |
| dur = wav.shape[1] / sr | |
| rms = float(wav.float().pow(2).mean().sqrt()) | |
| assert rms > 1e-4, f'{lang}: silent output (rms={rms})' | |
| status = 'OK' if 2.0 <= dur <= 15.0 else 'WARN dur out of 2-15s' | |
| rec = {'lang': lang, 'dur': round(dur, 2), 'rms': round(rms, 4), | |
| 'src_lang': info.get('src_lang'), 'src_line': info['src_line'], | |
| 'tgt_raw': info['tgt_raw'], 'tgt_cv': info['tgt_cv'], | |
| 'ref': refs[lang]['ref'], 'status': status} | |
| report.append(rec) | |
| print(f'[verify:{lang}] dur={dur:.2f}s rms={rms:.4f} src_lang={info.get("src_lang")} {status}', | |
| flush=True) | |
| print(f'[verify:{lang}] src : {info["src_line"]}', flush=True) | |
| print(f'[verify:{lang}] hyp_raw: {info["tgt_raw"]}', flush=True) | |
| print(f'[verify:{lang}] cv_text: {info["tgt_cv"]}' + | |
| (' (ja kata)' if lang == 'ja' else ''), flush=True) | |
| print(f'[verify:{lang}] ref : {refs[lang]["ref"]}', flush=True) | |
| wl = [l for l in ('en', 'ko', 'zh') if l in langs] | |
| if wl: | |
| from transformers import pipeline as hf_pipeline | |
| asr = hf_pipeline('automatic-speech-recognition', model=WHISPER, device=0) | |
| print('[verify] whisper loaded', flush=True) | |
| for lang in wl: | |
| t = asr(os.path.join(args.model_dir, 'samples', f'dub_{lang}.wav'), | |
| generate_kwargs={'language': lang, 'task': 'transcribe'})['text'] | |
| m = wer(refs[lang]['ref'], t) if lang == 'en' else cer(refs[lang]['ref'], t) | |
| name = 'WER' if lang == 'en' else 'CER' | |
| print(f'[verify:{lang}] whisper backtest: {t.strip()!r}', flush=True) | |
| print(f'[verify:{lang}] {name} vs ref: {m:.3f}', flush=True) | |
| report.append({'lang': lang, 'whisper': t, name.lower() + '_vs_ref': round(m, 3)}) | |
| json.dump(report, open(os.path.join(args.model_dir, 'samples', 'verify_report.json'), 'w'), | |
| indent=1, ensure_ascii=False) | |
| print('VERIFY EXPORT DONE', flush=True) | |
| if __name__ == '__main__': | |
| main() | |