Exportation ONNX du modèle de reconnaissance vocale SenseVoice-Small : un guide technique complet

SenseVoice-Small représente un modèle de pointe pour la reconnaissance vocale multilingue. Il excelle non seulement dans la transcription de la parole, mais intègre également la détection d'émotions et d'événements audio. Entraîné sur plus de 400 000 heures de données multilingues, il prend en charge plus de 50 langues et surpasse les performances du modèle Whisper dans des évaluations comparatives.

1. Caractéristiques et atouts principaux du modèle

  • Reconnaissance multilingue : Couverture de plus de 50 langues dont le chinois, le cantonais, l'anglais, le japonais, le coréen, etc.
  • Sortie enrichie : Fournit la transcription textuelle, idnetifie les émotions et les événements sonores (musique, applaudissements, rires, etc.).
  • Inférence rapide : Grâce à une architecture non autoregressive de bout en bout, le traitement d'un segment audio de 10 secondes ne prend que 70 millisecondes.
  • Déploiement simplifié : Offre une solution complète de mise en production, compatible avec divers langages côté client.

2. Configuration de l'environnement et obtention du modèle

2.1 Prérequis système et installation des dépendances

Assurez-vous que votre environnement répond aux exigences suivantes :

# Création d'un environnement virtuel (recommandé)
python -m venv envsensevoice
source envsensevoice/bin/activate  # Linux/Mac
# ou envsensevoice\Scripts\activate  # Windows

# Installation des bibliothèques essentielles
pip install torch torchaudio modelscope onnx onnxruntime gradio soundfile

2.2 Téléchargement du modèle SenseVoice-Small

Récupérez le modèle pré-entraîné depuis ModelScope :

from modelscope import snapshot_download

chemin_modele = snapshot_download('damo/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch')
print(f"Modèle téléchargé dans : {chemin_modele}")

3. Procédure d'exportation au format ONNX

3.1 Préparation du script d'exportation

Le script ci-dessous convertit le modèle PyTorch en format ONNX :

import torch
from modelscope.models import Model
from modelscope.preprocessors import Preprocessor

# Chargement du modèle source
modele_charge = Model.from_pretrained('damo/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch')
modele_charge.eval()

# Création d'une entrée factice
entree_factice = torch.randn(1, 16000)  # Audio de 1 seconde, échantillonnage à 16kHz

# Export vers le format ONNX
torch.onnx.export(
    modele_charge,
    entree_factice,
    "sensevoice_petit.onnx",
    export_params=True,
    opset_version=13,
    do_constant_folding=True,
    input_names=['flux_audio'],
    output_names=['sortie_texte'],
    dynamic_axes={
        'flux_audio': {0: 'taille_lot', 1: 'longueur_audio'},
        'sortie_texte': {0: 'taille_lot', 1: 'longueur_texte'}
    }
)

print("Exportation ONNX terminée.")

3.2 Quantification du modèle (étape optionnelle mais recommandée)

L'application de la quantification améliore la vitesse d'inférence et réduit l'empreinte mémoire :

import onnx
from onnxruntime.quantization import quantize_dynamic, QuantType

chemin_modele_onnx = "sensevoice_petit.onnx"
chemin_modele_quantifie = "sensevoice_petit_quantifie.onnx"

# Application de la quantification dynamique
quantize_dynamic(
    chemin_modele_onnx,
    chemin_modele_quantifie,
    weight_type=QuantType.QUInt8
)

print("Quantification terminée.")

4. Construction d'une interface web avec Gradio

4.1 Développement de l'application WebUI

import gradio as gr
import numpy as np
from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks

# Initialisation du pipeline d'inférence
pipeline_asr = pipeline(
    task=Tasks.auto_speech_recognition,
    model='damo/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch'
)

def transcrire_fichier_audio(fichier_audio):
    """Fonction de transcription vocale"""
    if fichier_audio is None:
        return "Veuillez téléverser ou enregistrer un fichier audio."
    
    resultat = pipeline_asr(fichier_audio)
    return resultat['texte']

# Création de l'interface Gradio
with gr.Blocks(title="Reconnaissance vocale SenseVoice") as application:
    gr.Markdown("# 🎙️ Démonstration de reconnaissance vocale SenseVoice-Small")
    gr.Markdown("Téléversez un fichier audio ou enregistrez votre voix pour tester la reconnaissance multilingue.")
    
    with gr.Row():
        with gr.Column():
            entree_audio = gr.Audio(
                sources=["upload", "microphone"],
                type="filepath",
                label="Téléversement ou enregistrement audio"
            )
            bouton = gr.Button("Lancer la reconnaissance", variant="primary")
        
        with gr.Column():
            zone_texte = gr.Textbox(
                label="Résultat de la transcription",
                lines=5,
                placeholder="Le texte transcrit apparaîtra ici..."
            )
    
    gr.Examples(
        examples=["exemple_audio1.wav", "exemple_audio2.wav"],
        inputs=entree_audio,
        label="Fichiers d'exemple"
    )
    
    bouton.click(
        fn=transcrire_fichier_audio,
        inputs=entree_audio,
        outputs=zone_texte
    )

if __name__ == "__main__":
    application.launch(server_name="0.0.0.0", server_port=7860)

5. Optimisation des performances d'inférence

5.1 Inférence via ONNX Runtime

import onnxruntime as ort
import numpy as np
import soundfile as sf

class MoteurSenseVoiceONNX:
    def __init__(self, chemin_modele):
        self.session = ort.InferenceSession(
            chemin_modele,
            providers=['CPUExecutionProvider']  # Possibilité d'utiliser CUDA/TensorRT
        )
        
    def preparer_donnees_audio(self, chemin_fichier):
        """Prétraitement des données audio"""
        donnees_audio, taux_echantillonnage = sf.read(chemin_fichier)
        if taux_echantillonnage != 16000:
            # Logique de rééchantillonnage à ajouter
            pass
        donnees_normalisees = donnees_audio.astype(np.float32) / 32768.0
        return donnees_normalisees.reshape(1, -1)
    
    def effectuer_prediction(self, chemin_fichier):
        """Exécution de l'inférence"""
        audio_prepare = self.preparer_donnees_audio(chemin_fichier)
        nom_entree = self.session.get_inputs()[0].name
        resultat = self.session.run(None, {nom_entree: audio_prepare})
        return resultat[0]

# Exemple d'utilisation
moteur = MoteurSenseVoiceONNX("sensevoice_petit_quantifie.onnx")
prediction = moteur.effectuer_prediction("test.wav")
print(f"Résultat : {prediction}")

5.2 Stratégies d'optimisation

# 1. Utilisation d'un modèle quantifié
session_optimisee = ort.InferenceSession(
    "sensevoice_petit_quantifie.onnx",
    providers=['CPUExecutionProvider']
)

# 2. Traitement par lots (si supporté)
def infrence_par_lot(liste_chemins):
    lot_audio = np.concatenate([preparer_donnees_audio(chemin) for chemin in liste_chemins])
    return session_optimisee.run(None, {nom_entree: lot_audio})

# 3. Accélération matérielle (si disponible)
session_gpu = ort.InferenceSession(
    chemin_modele,
    providers=['CUDAExecutionProvider', 'CPUExecutionProvider']
)

6. Scénarios d'application concrets

6.1 Transcription multilingue de la parole

def transcrire_multilingue(fichier, langue='auto'):
    """
    Transcription multilingue
    Paramètre 'langue' : 'zh' (chinois), 'en' (anglais), 'ja' (japonais), 'ko' (coréen), 'auto' (détection automatique)
    """
    resultat = pipeline_asr(fichier)
    return {
        'texte': resultat['texte'],
        'langue_detectee': resultat.get('langue', 'inconnue'),
        'score_confiance': resultat.get('confiance', 0.9)
    }

6.2 Intégration de la reconnaissance des émotions

def analyser_discours_et_emotions(fichier):
    """Combine la transcription et l'analyse des émotions"""
    resultat_transcription = pipeline_asr(fichier)
    
    # Logique d'analyse des émotions à implémenter
    detection_emotion = {
        'emotion': 'positive',  # Valeur exemple
        'confiance': 0.85
    }
    
    return {
        'transcription': resultat_transcription['texte'],
        'emotion_detectee': detection_emotion['emotion'],
        'confiance_emotion': detection_emotion['confiance']
    }

7. Résolution des problèmes courants

7.1 Difficultés de chargement du modèle

Problème : Échec du téléchargement

# Solution : Spécifier un miroir de téléchargement
pip install modelscope -i https://mirror.baidu.com/pypi/simple

Problème : Manque de mémoire

# Solution : Recourir à un modèle quantifié ou réduire la taille du lot
moteur_optimise = MoteurSenseVoiceONNX("sensevoice_petit_quantifie.onnx")

7.2 Problèmes de tratiement audio

Problème : Format audio non pris en charge

import librosa

def convertir_format_audio(entree, sortie, taux_cible=16000):
    """Convertit le fichier audio vers un format standard"""
    donnees, taux = librosa.load(entree, sr=taux_cible)
    sf.write(sortie, donnees, taux_cible)
    return sortie

Étiquettes: SenseVoice Reconnaissance Vocale ONNX exportation modèle Gradio

Publié le 18 juillet à 00h42