71 lines
3.0 KiB
Python
71 lines
3.0 KiB
Python
"""Choisit le moteur de transcription d'après le matériel."""
|
|
import ctypes
|
|
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())
|
|
|
|
|
|
# Le nom de la bibliothèque partagée CUDA diffère radicalement par plateforme ET
|
|
# par version : `libcudart.so` (parfois suffixé `.12`, `.11.0`...) sous Linux/macOS,
|
|
# mais `cudart64_12.dll`, `cudart64_110.dll`... sous Windows, où le numéro de version
|
|
# est ENCODÉ DANS LE NOM du fichier. `ctypes.util.find_library` ne résout pas ces DLL
|
|
# versionnées de façon fiable — il cherche un nom canonique qui n'existe pas pour
|
|
# CUDA sous Windows. On essaie donc une liste explicite de noms candidats, du plus
|
|
# récent au plus ancien, et on s'arrête au premier qui charge.
|
|
_NOMS_CUDART_WINDOWS = [
|
|
"cudart64_12.dll",
|
|
"cudart64_110.dll",
|
|
"cudart64_101.dll",
|
|
"cudart64_100.dll",
|
|
]
|
|
_NOMS_CUDART_UNIX = [
|
|
"libcudart.so",
|
|
"libcudart.so.12",
|
|
"libcudart.so.11.0",
|
|
]
|
|
|
|
|
|
def _cuda_disponible(plateforme=None, charger=None):
|
|
"""Sonde la présence du runtime CUDA en tentant de charger sa bibliothèque
|
|
partagée. `plateforme` et `charger` sont injectables : ça rend la sonde
|
|
testable avec une doublure, sans dépendre d'une vraie machine CUDA ni d'un
|
|
vrai Windows. Ne lève jamais — dans le doute, on rend False."""
|
|
plateforme = plateforme if plateforme is not None else sys.platform
|
|
charger = charger if charger is not None else ctypes.CDLL
|
|
noms = _NOMS_CUDART_WINDOWS if plateforme.startswith("win") else _NOMS_CUDART_UNIX
|
|
for nom in noms:
|
|
try:
|
|
charger(nom)
|
|
return True
|
|
except Exception:
|
|
continue
|
|
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)
|
|
if nom in ("faster-cpu", "faster-gpu"):
|
|
# C'est ICI, et nulle part dans TranscripteurFasterWhisper, que le
|
|
# peripherique et le type de calcul sont decides : la classe reste
|
|
# testable sans jamais sonder de vrai materiel.
|
|
from moteur.faster import TranscripteurFasterWhisper
|
|
peripherique = "cuda" if nom == "faster-gpu" else "cpu"
|
|
type_calcul = "float16" if nom == "faster-gpu" else "int8"
|
|
return TranscripteurFasterWhisper(modele, langue, amorce, peripherique, type_calcul)
|
|
raise NotImplementedError(f"Moteur non pris en charge à cette étape : {nom}")
|