mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-20 21:48:47 +02:00
La façade sert /api/transcribe et /api/dictate/* quand LOKI_DICTATE=rust (expérimental ; le Go reste le défaut) et supervise elle-même le serveur de transcription sherpa-onnx : lancé à la demande sur la boucle locale, GPU masqués et sans le jeton interne, prêt dès que sa socket répond, mort au démarrage expliquée, éteint après dix minutes d'inactivité ou quand les réglages changent. Modèles Parakeet téléchargés et décompressés au fil de l'eau (tar.bz2, entrées hors du dossier refusées, liens ignorés), protocole WebSocket identique (en-tête de 8 octets, trames de 10 Kio). Côté Go, facade_dictate.go remet ces routes à la façade quand elles arrivent par le tunnel du relais, et asrShutdownVite (libération de la VRAM, optimiseur) lui demande l'arrêt par l'API interne. Parité : parity_dictate_test.go tire du Go la lecture de treize WAV, les chemins d'archive, réglages, catalogue, arguments et treize appels de route, rejoués par tests/dictate.rs ; supervision testée contre un faux sherpa-onnx qui parle le protocole. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
4.1 KiB
4.1 KiB
Lot 9 — dictée vocale tenue par la façade
Contexte
La dictée vocale vivait dans le Go :
dictate_config.go: réglages ;dictate_models.go: catalogue Parakeet, téléchargement et extraction ;dictate_server.go: supervision desherpa-onnx-offline-websocket-serveret protocole WebSocket ;web_transcribe.go: routes.
Lot 9 : la façade la tient quand LOKI_DICTATE=rust (expérimental ; sans la
variable rien ne change).
Ce que sert la façade (rust/loki-rs/src/dictate.rs)
| Route | Rôle |
|---|---|
POST /api/transcribe |
un WAV (≥ 1000 octets, ≤ 32 Mio) entre, le texte sort ; modèle absent : 503 {downloading, pct} et téléchargement lancé (relancé après un échec, qui est dit) |
GET|POST /api/dictate/config |
modèle (validé contre le catalogue) et réactivité ; enregistrer arrête le serveur, qui repart au prochain mot avec le nouveau modèle |
GET /api/dictate/models |
catalogue trié par taille, présence des quatre fichiers |
GET|POST /api/dictate/models/download |
un téléchargement à la fois, progression sur les octets reçus |
GET /api/dictate/state |
serveur allumé (et depuis quand), modèle, présence, téléchargement |
POST /internal/facade/v1/dictate/stop |
(le Go, jeton interne) arrêt sans attendre derrière un démarrage |
Même mécanique que le Go :
Archive .tar.bz2
- Décompressée au fil du téléchargement, dans un dossier
.partrenommé à la fin. - Entrées absolues ou qui remontent refusées, liens ignorés.
Serveur de transcription
- Lancé à la demande sur un port libre de la boucle locale, GPU masqués, sans le jeton interne dans son environnement.
- Prêt dès que sa socket répond.
- Une mort au démarrage est rapportée avec sa cause et la dernière ligne du journal ; un processus qui ne répond pas fait échouer le démarrage au bout de 2 minutes.
- Éteint après dix minutes d'inactivité.
shutdown_fasttue le processus qui démarre au lieu d'attendre le verrou.
Protocole
- En-tête de 8 octets (fréquence, nombre d'octets), échantillons float32 en trames de 10 Kio, une trame texte en retour.
- Annotations (
[musique],(rires)) écartées.
Côté Go (facade_dictate.go)
withFacadeChatremet les routes du tunnel et de la redistribution E2E à la façade. Si elle ne répond pas : 502 « dictée indisponible : … ».asrShutdownVitepasse par la façade quand elle tient la dictée : son serveur n'est pas un enfant de ce process. Cela couvre la libération de la VRAM et l'arrêt du moteur principal par l'optimiseur.
Écarts assumés
- Messages d'erreur de transport (WebSocket, HTTP) et de décompression au format des crates Rust.
- Fin de connexion sans réponse : « lecture du résultat : connexion fermée ».
Parité
internal/loki/parity_dictate_test.go tire du Go ce journal :
- treize WAV : mono, bloc
LISTintercalé, stéréo moyenné, flottant 32 bits, données tronquées, impaires, vides, et les refus ; - les chemins d'archive ;
- les marqueurs ;
- les réglages par défaut ;
- les arguments du serveur ;
- les adresses des modèles ;
- la présence ;
- treize appels de route.
Le tout est rangé dans tests/parity_dictate/dictate.json et rejoué par
tests/dictate.rs, les routes par la façade. Une mutation (premier canal au
lieu de la moyenne) fait échouer le rejeu.
tests/dictate.rs couvre aussi :
- le protocole contre un faux serveur WebSocket (en-tête, découpage 10240 + 10240 + 3528, marqueurs, réponse illisible, serveur injoignable) ;
- l'extraction (lien ignoré, entrée qui remonte refusée sans rien laisser, archive corrompue) ;
- le téléchargement depuis un faux serveur (100 %, HTTP 404, modèle inconnu, un seul à la fois) ;
- la supervision d'un faux sherpa-onnx (script Python qui parle le
protocole) :
- transcription de bout en bout par la façade ;
- même serveur réutilisé ;
- arrêt demandé par le Go, et refusé sans le jeton ;
- réglage changé ;
- les démarrages ratés : sortie en code 3 avec sa dernière ligne, serveur muet, arrêt « vite » qui tue le démarrage, binaire introuvable, modèle absent.