Sonexa-1-ASR / app.py
Cartik's picture
Update app.py
82ae79b verified
Raw
History Blame Contribute Delete
6.57 kB
import gc
import os
import gradio as gr
import torch
from qwen_asr import Qwen3ASRModel
MODEL_ID = "Cartik/Sonexa-1-ASR"
# ============================================================
# DEVICE
# ============================================================
IS_ZERO_GPU = os.environ.get("SPACES_ZERO_GPU") == "true"
HAS_CUDA = torch.cuda.is_available()
USE_GPU = IS_ZERO_GPU or HAS_CUDA
if USE_GPU:
DEVICE = "cuda"
DTYPE = torch.bfloat16
else:
DEVICE = "cpu"
DTYPE = torch.float32
print("=" * 60)
print("Sonexa ASR")
print("=" * 60)
print(f"Model: {MODEL_ID}")
print(f"ZeroGPU: {IS_ZERO_GPU}")
print(f"CUDA: {HAS_CUDA}")
print(f"Device: {DEVICE}")
print(f"Dtype: {DTYPE}")
print("=" * 60)
# ============================================================
# GRADIO CLIENT PATCH
# ============================================================
#
# Некоторые версии gradio_client падают на JSON Schema,
# где additionalProperties / другие поля имеют значение bool.
#
# Без этого show_api может падать с:
#
# TypeError: argument of type 'bool' is not iterable
#
# В результате API predict становится недоступным.
# ============================================================
try:
import gradio_client.utils as gc_utils
original_json_schema = gc_utils._json_schema_to_python_type
def patched_json_schema_to_python_type(schema, defs=None):
if isinstance(schema, bool):
return "Any"
return original_json_schema(schema, defs)
gc_utils._json_schema_to_python_type = (
patched_json_schema_to_python_type
)
print("Gradio JSON Schema patch applied.")
except Exception as e:
print(f"Gradio patch warning: {e}")
# ============================================================
# GPU DECORATOR
# ============================================================
if USE_GPU:
try:
import spaces
gpu_decorator = spaces.GPU(duration=60)
print("ZeroGPU decorator enabled.")
except ImportError:
print(
"Package 'spaces' not found. "
"GPU decorator disabled."
)
def gpu_decorator(fn):
return fn
else:
def gpu_decorator(fn):
return fn
# ============================================================
# LOAD MODEL
# ============================================================
print("Loading Sonexa ASR model...")
model = Qwen3ASRModel.from_pretrained(
MODEL_ID,
dtype=DTYPE,
device_map="auto" if USE_GPU else "cpu",
)
print("Model loaded successfully!")
# ============================================================
# TRANSCRIBE
# ============================================================
@gpu_decorator
def transcribe(audio, language):
if audio is None:
raise gr.Error(
"Загрузите аудио или запишите его с микрофона."
)
try:
print(f"Audio: {audio}")
print(f"Language: {language}")
with torch.inference_mode():
results = model.transcribe(
audio=audio,
language=language,
)
if isinstance(results, list):
if not results:
return ""
result = results[0]
text = getattr(result, "text", None)
if text is not None:
return str(text)
if isinstance(result, str):
return result
if isinstance(result, dict):
if "text" in result:
return str(result["text"])
if "transcription" in result:
return str(result["transcription"])
return str(result)
if isinstance(results, str):
return results
text = getattr(results, "text", None)
if text is not None:
return str(text)
if isinstance(results, dict):
if "text" in results:
return str(results["text"])
if "transcription" in results:
return str(results["transcription"])
return str(results)
except Exception as e:
print("=" * 60)
print("ASR ERROR")
print(e)
print("=" * 60)
raise gr.Error(
f"Ошибка распознавания: {e}"
)
finally:
gc.collect()
if HAS_CUDA:
torch.cuda.empty_cache()
# ============================================================
# UI
# ============================================================
with gr.Blocks(
title="Sonexa ASR"
) as demo:
gr.Markdown("# Sonexa ASR")
if USE_GPU:
gr.Markdown(
"⚡ Распознавание выполняется на GPU."
)
else:
gr.Markdown(
"⚠️ GPU недоступен — используется CPU."
)
with gr.Row():
with gr.Column():
audio = gr.Audio(
label="Аудио",
sources=[
"upload",
"microphone",
],
type="filepath",
)
language = gr.Dropdown(
choices=[
"Russian",
"English",
"Chinese",
"Japanese",
"Korean",
"German",
"French",
"Spanish",
],
value="Russian",
label="Язык",
)
button = gr.Button(
"Распознать",
variant="primary",
)
with gr.Column():
output = gr.Textbox(
label="Распознанный текст",
lines=10,
)
button.click(
fn=transcribe,
inputs=[
audio,
language,
],
outputs=output,
api_name="predict",
)
# ============================================================
# QUEUE
# ============================================================
demo.queue(
max_size=32,
default_concurrency_limit=1,
)
# ============================================================
# LAUNCH
# ============================================================
demo.launch(
server_name="0.0.0.0",
server_port=7860,
show_api=True,
ssr=False,
)