Spaces:
Paused
Paused
Upload 2 files
Browse files- asrmodel/app.py +170 -0
- asrmodel/requirements.txt +11 -0
asrmodel/app.py
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""asrdemo.ipynb
|
| 3 |
+
|
| 4 |
+
Automatically generated by Colab.
|
| 5 |
+
|
| 6 |
+
Original file is located at
|
| 7 |
+
https://colab.research.google.com/drive/1A3MDkQEkPUoCpiksvTsAcfVqfNC7-Uxe
|
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
# !pip install gradio transformers datasets torchaudio accelerate unsloth -q
|
| 11 |
+
# !pip install --upgrade protobuf==5.29.1 fsspec==2025.3.2
|
| 12 |
+
# !pip install torchaudio
|
| 13 |
+
# !pip install deep-translator
|
| 14 |
+
# !pip install jiwer
|
| 15 |
+
# !pip install peft unsloth
|
| 16 |
+
|
| 17 |
+
# from google.colab import drive
|
| 18 |
+
# drive.mount('/content/drive')
|
| 19 |
+
|
| 20 |
+
# ✨ Step 2: 导入库
|
| 21 |
+
import gradio as gr
|
| 22 |
+
import torch
|
| 23 |
+
import re
|
| 24 |
+
from transformers import SeamlessM4Tv2Model, AutoProcessor
|
| 25 |
+
from unsloth import FastLanguageModel
|
| 26 |
+
|
| 27 |
+
# ✨ Step 3: 加载 Seamless 模型(用于生成 8-best)
|
| 28 |
+
processor = AutoProcessor.from_pretrained("facebook/seamless-m4t-v2-large")
|
| 29 |
+
seamless_model = SeamlessM4Tv2Model.from_pretrained("facebook/seamless-m4t-v2-large")
|
| 30 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 31 |
+
seamless_model = seamless_model.to(device)
|
| 32 |
+
|
| 33 |
+
# ✨ Step 4: 加载 DeepSeek 微调模型(后处理)
|
| 34 |
+
deepseek_model, tokenizer = FastLanguageModel.from_pretrained(
|
| 35 |
+
model_name="unsloth/DeepSeek-R1-Distill-Llama-8B",
|
| 36 |
+
max_seq_length=2048,
|
| 37 |
+
dtype=None,
|
| 38 |
+
load_in_4bit=True
|
| 39 |
+
)
|
| 40 |
+
from unsloth import FastLanguageModel
|
| 41 |
+
from peft import PeftModel
|
| 42 |
+
lora_path = "/content/drive/MyDrive/DeepSeek-FineTune-0422-8bestfinetune/only_lora_adapters_8bestfinetune"
|
| 43 |
+
# 保持 tokenizer 不变
|
| 44 |
+
deepseek_model = PeftModel.from_pretrained(deepseek_model, lora_path)
|
| 45 |
+
deepseek_model.eval()
|
| 46 |
+
# ✨ Step 2: 导入库
|
| 47 |
+
import gradio as gr
|
| 48 |
+
import torch
|
| 49 |
+
import re
|
| 50 |
+
import torchaudio
|
| 51 |
+
from transformers import SeamlessM4Tv2Model, AutoProcessor
|
| 52 |
+
from unsloth import FastLanguageModel
|
| 53 |
+
|
| 54 |
+
from deep_translator import GoogleTranslator
|
| 55 |
+
from jiwer import wer
|
| 56 |
+
import string
|
| 57 |
+
|
| 58 |
+
# 初始化翻译函数
|
| 59 |
+
def translate_urdu_to_zh(urdu_text):
|
| 60 |
+
try:
|
| 61 |
+
en_text = GoogleTranslator(source='ur', target='en').translate(urdu_text)
|
| 62 |
+
zh_text = GoogleTranslator(source='en', target='zh-CN').translate(en_text)
|
| 63 |
+
return en_text.strip(), zh_text.strip()
|
| 64 |
+
except Exception as e:
|
| 65 |
+
return "翻译失败", "翻译失败"
|
| 66 |
+
|
| 67 |
+
# ✨ Step 3: 加载模型(请确保你已定义以下变量)
|
| 68 |
+
# seamless_model, processor, deepseek_model, tokenizer, device
|
| 69 |
+
|
| 70 |
+
# Prompt 设计
|
| 71 |
+
NEW_PROMPT_STYLE = """
|
| 72 |
+
你是一位精通乌尔都语的专家,负责修正乌尔都语语音转录文本。我给你以下8个结果,请你选出最可能正确的选项,并尝试修改且仅修改可能识别错误的单词,主要考虑发音识别的错误,仅输出最终修改的句子,不要输出其他内容。
|
| 73 |
+
"""
|
| 74 |
+
|
| 75 |
+
def extract_urdu_sentence(response):
|
| 76 |
+
urdu_pattern = r'[\u0600-\u06FF\u0750-\u077F\uFB50-\uFDFF\uFE70-\uFEFF\s\.\,\?\!]+'
|
| 77 |
+
matches = re.findall(urdu_pattern, response)
|
| 78 |
+
if matches:
|
| 79 |
+
sentence = re.sub(r'\s+', ' ', matches[-1]).strip()
|
| 80 |
+
sentence = re.sub(r'^\d+\.\s*', '', sentence)
|
| 81 |
+
return sentence
|
| 82 |
+
return response.strip()
|
| 83 |
+
|
| 84 |
+
def remove_punctuation(text):
|
| 85 |
+
translator = str.maketrans('', '', string.punctuation)
|
| 86 |
+
return text.translate(translator).replace("۔", "").replace("،", "").replace("؟", "").strip()
|
| 87 |
+
|
| 88 |
+
def urdu_asr_postprocess(audio, reference_text):
|
| 89 |
+
try:
|
| 90 |
+
sampling_rate, audio_array = audio
|
| 91 |
+
audio_tensor = torch.tensor(audio_array, dtype=torch.float32)
|
| 92 |
+
|
| 93 |
+
if audio_array.dtype == 'int16' or torch.max(torch.abs(audio_tensor)) > 1.0:
|
| 94 |
+
audio_tensor = audio_tensor / 32768.0
|
| 95 |
+
if len(audio_tensor.shape) == 1:
|
| 96 |
+
audio_tensor = audio_tensor.unsqueeze(0)
|
| 97 |
+
if sampling_rate != 16000:
|
| 98 |
+
resampler = torchaudio.transforms.Resample(orig_freq=sampling_rate, new_freq=16000)
|
| 99 |
+
audio_tensor = resampler(audio_tensor)
|
| 100 |
+
sampling_rate = 16000
|
| 101 |
+
|
| 102 |
+
audio_inputs = processor(audios=audio_tensor.squeeze().numpy(), sampling_rate=sampling_rate, return_tensors="pt").to(device)
|
| 103 |
+
output = seamless_model.generate(
|
| 104 |
+
**audio_inputs,
|
| 105 |
+
tgt_lang="__urd__",
|
| 106 |
+
generate_speech=False,
|
| 107 |
+
num_beams=8,
|
| 108 |
+
num_return_sequences=8,
|
| 109 |
+
pad_token_id=processor.tokenizer.pad_token_id
|
| 110 |
+
)
|
| 111 |
+
hypotheses = [processor.tokenizer.decode(seq, skip_special_tokens=True) for seq in output.sequences]
|
| 112 |
+
input_text = "\n".join([f"{i+1}. {hyp}" for i, hyp in enumerate(hypotheses)])
|
| 113 |
+
prompt = f"{NEW_PROMPT_STYLE}\n\n输入:{input_text}"
|
| 114 |
+
|
| 115 |
+
inputs = tokenizer([prompt], return_tensors="pt").to(deepseek_model.device)
|
| 116 |
+
outputs = deepseek_model.generate(input_ids=inputs.input_ids, attention_mask=inputs.attention_mask, max_new_tokens=1000)
|
| 117 |
+
response = tokenizer.batch_decode(outputs, skip_special_tokens=True)[0]
|
| 118 |
+
|
| 119 |
+
final_output = extract_urdu_sentence(response)
|
| 120 |
+
final_en, final_zh = translate_urdu_to_zh(final_output)
|
| 121 |
+
|
| 122 |
+
# 初始化显示文本
|
| 123 |
+
final_output_display = f"""🟢 最终转录(乌尔都语):\n{final_output}"""
|
| 124 |
+
|
| 125 |
+
translated_hypotheses = []
|
| 126 |
+
wer_final = None
|
| 127 |
+
|
| 128 |
+
# 判断是否提供参考文本
|
| 129 |
+
if reference_text and reference_text.strip():
|
| 130 |
+
ref_clean = remove_punctuation(reference_text)
|
| 131 |
+
final_clean = remove_punctuation(final_output)
|
| 132 |
+
wer_final = wer(ref_clean, final_clean)
|
| 133 |
+
final_output_display += f"\nWER vs 参考文本: {wer_final:.3f}"
|
| 134 |
+
|
| 135 |
+
final_output_display += f"""\n\n🌐 翻译(英文):\n{final_en}\n\n🌐 翻译(中文):\n{final_zh}\n"""
|
| 136 |
+
|
| 137 |
+
for i, hyp in enumerate(hypotheses):
|
| 138 |
+
en, zh = translate_urdu_to_zh(hyp)
|
| 139 |
+
wer_i_display = ""
|
| 140 |
+
if reference_text and reference_text.strip():
|
| 141 |
+
hyp_clean = remove_punctuation(hyp)
|
| 142 |
+
wer_i = wer(ref_clean, hyp_clean)
|
| 143 |
+
wer_i_display = f"\n WER vs 参考: {wer_i:.3f}"
|
| 144 |
+
translated_hypotheses.append(f"{i+1}. {hyp}\n 🌐 EN: {en}\n 🌐 中文: {zh}{wer_i_display}\n")
|
| 145 |
+
|
| 146 |
+
hypotheses_display = "\n".join(translated_hypotheses)
|
| 147 |
+
return final_output_display, hypotheses_display, response
|
| 148 |
+
|
| 149 |
+
except Exception as e:
|
| 150 |
+
return f"处理出错: {str(e)}", "", ""
|
| 151 |
+
|
| 152 |
+
# ✨ Step 7: 构建 Gradio 界面
|
| 153 |
+
demo = gr.Interface(
|
| 154 |
+
fn=urdu_asr_postprocess,
|
| 155 |
+
inputs=[
|
| 156 |
+
gr.Audio(type="numpy", label="上传乌尔都语语音"),
|
| 157 |
+
gr.Textbox(label="参考文本(可选)", lines=3, placeholder="可选:请输入乌尔都语参考文本以计算 WER")
|
| 158 |
+
],
|
| 159 |
+
outputs=[
|
| 160 |
+
gr.Textbox(label="最终转录结果"),
|
| 161 |
+
gr.Textbox(label="8-best 候选结果"),
|
| 162 |
+
# gr.Textbox(label="DeepSeek 原始输出"),
|
| 163 |
+
],
|
| 164 |
+
title="乌尔都语 ASR + 后处理 Demo",
|
| 165 |
+
description="上传一段乌尔都语音频,参考文本为可选项。如填写,将计算 WER。",
|
| 166 |
+
allow_flagging="never"
|
| 167 |
+
)
|
| 168 |
+
|
| 169 |
+
# ✨ Step 8: 启动 Demo
|
| 170 |
+
demo.launch()
|
asrmodel/requirements.txt
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio
|
| 2 |
+
transformers
|
| 3 |
+
datasets
|
| 4 |
+
torchaudio
|
| 5 |
+
accelerate
|
| 6 |
+
unsloth
|
| 7 |
+
protobuf==5.29.1
|
| 8 |
+
fsspec==2025.3.2
|
| 9 |
+
deep-translator
|
| 10 |
+
jiwer
|
| 11 |
+
peft
|