Extrait la transcription derriere le contrat Transcripteur
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
5c4477fe1d
commit
734bba31da
33
moteur/__init__.py
Normal file
33
moteur/__init__.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
"""Choisit le moteur de transcription d'après le matériel."""
|
||||||
|
import platform
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def nom_moteur_pour(plateforme, machine, cuda_disponible):
|
||||||
|
"""Décide du moteur. Fonction PURE : aucune interrogation de la machine ici,
|
||||||
|
ce qui rend les quatre configurations testables depuis un seul poste."""
|
||||||
|
if plateforme.startswith("darwin") and machine in ("arm64", "aarch64"):
|
||||||
|
return "mlx"
|
||||||
|
return "faster-gpu" if cuda_disponible else "faster-cpu"
|
||||||
|
|
||||||
|
|
||||||
|
def detecter_moteur():
|
||||||
|
"""Interroge la machine, puis délègue la décision à `nom_moteur_pour`."""
|
||||||
|
return nom_moteur_pour(sys.platform, platform.machine(), _cuda_disponible())
|
||||||
|
|
||||||
|
|
||||||
|
def _cuda_disponible():
|
||||||
|
try:
|
||||||
|
import ctypes
|
||||||
|
ctypes.CDLL("libcudart.so")
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def choisir_transcripteur(nom, modele, langue, amorce):
|
||||||
|
"""Rend l'implémentation du contrat Transcripteur portant ce nom."""
|
||||||
|
if nom == "mlx":
|
||||||
|
from moteur.mlx import TranscripteurMLX
|
||||||
|
return TranscripteurMLX(modele, langue, amorce)
|
||||||
|
raise NotImplementedError(f"Moteur non pris en charge à cette étape : {nom}")
|
||||||
27
moteur/mlx.py
Normal file
27
moteur/mlx.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
"""Transcription par MLX-Whisper — GPU Apple Silicon uniquement."""
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from core import clean_transcript
|
||||||
|
|
||||||
|
|
||||||
|
class TranscripteurMLX:
|
||||||
|
"""Implémentation du contrat Transcripteur pour Apple Silicon."""
|
||||||
|
|
||||||
|
def __init__(self, modele, langue, amorce):
|
||||||
|
self.modele = modele
|
||||||
|
self.langue = langue
|
||||||
|
self.amorce = amorce
|
||||||
|
|
||||||
|
def warmup(self):
|
||||||
|
"""Charge le modèle une fois, sur une seconde de silence."""
|
||||||
|
self.transcrire(np.zeros(16000, dtype="float32"))
|
||||||
|
|
||||||
|
def transcrire(self, audio):
|
||||||
|
import mlx_whisper
|
||||||
|
resultat = mlx_whisper.transcribe(
|
||||||
|
audio,
|
||||||
|
path_or_hf_repo=self.modele,
|
||||||
|
language=self.langue,
|
||||||
|
initial_prompt=self.amorce,
|
||||||
|
)
|
||||||
|
return clean_transcript(resultat.get("text", ""))
|
||||||
31
tests/test_moteur.py
Normal file
31
tests/test_moteur.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
"""La fabrique choisit le moteur d'après le matériel — décision pure, testable
|
||||||
|
depuis n'importe quelle machine."""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from moteur import choisir_transcripteur, nom_moteur_pour
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("plateforme, machine, cuda, attendu", [
|
||||||
|
("darwin", "arm64", False, "mlx"),
|
||||||
|
("darwin", "x86_64", False, "faster-cpu"),
|
||||||
|
("win32", "AMD64", True, "faster-gpu"),
|
||||||
|
("win32", "AMD64", False, "faster-cpu"),
|
||||||
|
])
|
||||||
|
def test_la_decision_suit_le_materiel(plateforme, machine, cuda, attendu):
|
||||||
|
assert nom_moteur_pour(plateforme, machine, cuda) == attendu
|
||||||
|
|
||||||
|
|
||||||
|
def test_apple_silicon_prend_mlx_meme_sans_cuda():
|
||||||
|
assert nom_moteur_pour("darwin", "arm64", cuda_disponible=False) == "mlx"
|
||||||
|
|
||||||
|
|
||||||
|
def test_la_fabrique_rend_un_transcripteur_complet():
|
||||||
|
t = choisir_transcripteur(nom="mlx", modele="mlx-community/whisper-medium",
|
||||||
|
langue="fr", amorce="")
|
||||||
|
assert callable(t.warmup) and callable(t.transcrire)
|
||||||
|
|
||||||
|
|
||||||
|
def test_un_moteur_inconnu_est_refuse_clairement():
|
||||||
|
with pytest.raises(NotImplementedError) as e:
|
||||||
|
choisir_transcripteur(nom="vosk", modele="x", langue="fr", amorce="")
|
||||||
|
assert "vosk" in str(e.value)
|
||||||
Loading…
Reference in New Issue
Block a user