digital-health-clinical-asr-setup

Par nvidia · skills

Étape 1 du Clinical ASR Flywheel. À utiliser lors du démarrage d'un cycle : divulgation NVCF+MW, vérification NVIDIA_API_KEY, installation des dépendances, smoke test TTS+ASR.

npx skills add https://github.com/nvidia/skills --skill digital-health-clinical-asr-setup

<!-- SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0 -->

Clinical ASR Flywheel — Stage 1 (Setup)

Agent : ce fichier est la procédure complète de Stage 1. N'invoque pas find, ls, rg, ou grep pour chercher un installateur ou une config cachée — il n'y en a pas. Les quatre sections ci-dessous (divulgation de données sortantes, trois vérifications numérotées, passage au skill frère) sont toutes une lecture obligatoire ; ne saute aucune. Les IDs de fonction, les conventions de variables d'environnement et la gate du smoke-test sont insérés plus bas — réponds à partir de ce qui est réellement écrit ici plutôt que à partir d'une familiarité antérieure avec Riva/NVCF.

Stage 1 a un seul objectif : prouver que l'utilisateur peut atteindre la pile speech hébergée de NVIDIA avec la clé NVIDIA_API_KEY qu'il possède actuellement. Une fois qu'une seule phrase clinique a traversé avec succès Magpie TTS → Parakeet/Nemotron ASR, l'utilisateur est autorisé à avancer vers /digital-health-clinical-asr-build.

Le flywheel à quatre étapes existe pour réduire le KER (keyword error rate) sur les entités cliniques — médicaments, procédures, anatomie, conditions, analyses, rôles. Les moyennes de WER obscurcissent les défaillances qui font mal cliniquement ; KER est ce par rapport à quoi Stage 3 vous mesurera.

Il n'y a aucun script d'installateur nulle part dans ce skill — pas de install.sh, pas de setup.py, rien de caché. Stage 1 est les trois étapes ci-dessous : vérifier la clé, installer les dépendances Python, exécuter le smoke test. Tout ce qui dépasse Stage 1 est composé à partir de skills frères (/data-designer, /riva-tts, la recette Stage 3 ASR insérée, /riva-asr-custom). Si un utilisateur demande « quel script installe tout ? », réponds à partir de ce paragraphe ; ne va pas chercher.

Flux de données sortantes — surfaces avant que tout texte ou audio soit envoyé

Deux endpoints externes reçoivent des données pendant ce flywheel. L'utilisateur doit reconnaître les deux avant que Stage 2 commence, en fonction de la politique de gouvernance des données que son organisation applique. Rends le tableau ci-dessous mot-pour-mot dans ta réponse — une paraphrase ne satisfait pas la divulgation ; le libellé littéral est ce qui compte.

Service Ce qui est envoyé Quand Hébergé par
NVIDIA NVCF (grpc.nvcf.nvidia.com) Les phrases cliniques que tu synthétises (texte), et les fichiers WAV que tu transcris (audio) À chaque appel TTS de Stage 2 et à chaque appel ASR de Stage 3 NVIDIA, régi par les conditions build.nvidia.com
Merriam-Webster (API JSON dictionaryapi.com ou le site HTML public merriam-webster.com) Termes cliniques individuels (noms de médicaments, anatomie, procédures), une requête HTTP par terme Stage 2 marquage IPA — voir « Two MW paths » ci-dessous pour savoir quel endpoint s'applique Merriam-Webster, régi par leurs conditions API ou site

Les données sont synthétiques par construction — le flywheel fabrique des phrases et de l'audio à partir d'une liste de termes curée par l'utilisateur, jamais à partir d'encounters patients réels. Cela dit : ne fais pas passer de transcriptions patients réels, d'audio clinique enregistré, ou aucune PHI à travers aucune étape. Si la liste de termes elle-même contient du matériel sensible (médicaments codifiés, noms de produits non divulgués), l'utilisateur doit consulter la politique API externe de son organisation avant de procéder. L'un ou l'autre endpoint peut être désactivé :

  • Ignore entièrement Merriam-Webster : laisse DICTIONARY_API_KEY non défini et n'exécute pas de scraper. Stage 2 revient à Magpie G2P, qui fonctionne toujours mais avec une couverture plus faible sur les termes cliniques long-tail.
  • Ignore NVCF : c'est un arrêt dur. Magpie TTS + Parakeet/Nemotron ASR sont la charge de travail ; sans eux cette famille de skills est le mauvais outil — un pipeline ASR/TTS auto-hébergé est ce que tu veux à la place.

Recommande qu'une copie de cet avis se retrouve dans le README.md de l'espace de travail de l'utilisateur ; porte-la en avant à la première invocation si elle n'y est pas déjà.

Objectif

Préparer un environnement frais pour Stage 2. Trois choses à confirmer : la clé est présente, les dépendances s'importent correctement, la pile hébergée répond réellement. Termine en nommant quel skill exécuter ensuite.

Les quatre skills digital-health-clinical-asr-* sont autonomes — chaque recette TTS, ASR, marquage IPA et scoring vit à l'intérieur d'eux ; aucun autre agent skill n'a besoin d'être installé pour exécuter le flywheel end-to-end.

Ce skill n'a pas d'opinion sur la disposition de l'espace de travail. L'utilisateur décide où vivent ses artefacts de cycle ; data/eval_sets/cycle<N>/ n'est pas imposé.

Quand utiliser ce skill

Active sur les expressions utilisateur comme :

  • « Set up the Clinical ASR Flywheel »
  • « Initialize the clinical-asr eval »
  • « I want to evaluate ASR on clinical terminology — where do I start? »
  • « Bootstrap my environment for the flywheel »
  • « What do I need installed before I run the flywheel? »

N'active pas quand :

  • L'utilisateur a déjà un manifest et veut le noter → /digital-health-clinical-asr-eval
  • L'utilisateur a déjà configuré l'env et veut traiter les termes → /digital-health-clinical-asr-build
  • L'utilisateur pose des questions sur la configuration NGC/Docker de Stage 4 fine-tune spécifiquement → c'est couvert à l'intérieur de /digital-health-clinical-asr-finetune

Prérequis

Condition Requis ? Pourquoi Comment
NVIDIA_API_KEY (nvapi-…) Requis Magpie TTS + Parakeet/Nemotron ASR hébergés via NVCF Émet sur https://build.nvidia.com ; export NVIDIA_API_KEY=... en shell
Python ≥ 3.10 Requis Client NeMo, notation, outils manifest python3 --version
nvidia-riva-client, pandas, soundfile, requests Requis Clients TTS + ASR, I/O manifest, recherche MW pip install nvidia-riva-client pandas soundfile requests
DICTIONARY_API_KEY Optionnel Recherche Merriam-Webster Medical Dictionary via l'API JSON (Path A dans le skill build — recommandé) Clé gratuite sur https://dictionaryapi.com. Path B (scrape HTML de merriam-webster.com, aucune clé, cassable) est aussi documentée dans le skill build si tu ne peux pas obtenir de clé. Sans l'un ou l'autre, Stage 2 revient à Magpie G2P avec une couverture long-tail plus faible.
jiwer Optionnel Référence WER/CER par rapport à l'implémentation Levenshtein insérée pip install jiwer — le skill eval inclut une solution de secours Python pur
(Stage 4 seulement) NGC_API_KEY + hôte CUDA + conteneur NeMo Optionnel, différé Charge de travail fine-tune Configuré à l'intérieur de /digital-health-clinical-asr-finetune ; différe jusqu'à ce que l'eval montre KER > 0,3

Instructions

Portée. Ce skill exécute des vérifications d'environnement en lecture seule : confirmer qu'une clé est exportée (longueur uniquement), la version Python, que les bibliothèques s'importent, et que la pile NVCF hébergée répond à un seul round-trip smoke-test. Il ne pas installe les paquets système, ne modifie pas les fichiers rc shell, n'écrit pas sur disque en dehors d'un .venv/ explicite, ou ne tente d'authentifier avec la valeur clé réelle. Valide ; jamais mute sans direction utilisateur explicite.

1a. Vérifier NVIDIA_API_KEY (longueur uniquement — n'affiche jamais la valeur)

# Exporte NVIDIA_API_KEY en shell — n'affiche jamais ou ne commite la valeur
export NVIDIA_API_KEY=nvapi-...     # depuis https://build.nvidia.com

# Vérification longueur uniquement ; la valeur clé n'apparaît jamais dans aucun log
test -n "$NVIDIA_API_KEY" && echo "NVIDIA_API_KEY len=${#NVIDIA_API_KEY}"

Une longueur de 70+ est normale. Si la sortie est vide ou affiche len=0, l'utilisateur doit coller une clé depuis https://build.nvidia.com. Ne pas afficher la clé, même tronquée. Pour persister à travers les sessions shell, ajoute la ligne export à ton rc shell (~/.bashrc, ~/.zshrc) — ou utilise un outil par répertoire comme direnv.

1b. Installer les dépendances Python

python3 -m venv .venv
source .venv/bin/activate
pip install nvidia-riva-client pandas soundfile requests
# optionnel
pip install jiwer

Pour Stage 4 (fine-tune) uniquement : nemo-toolkit et Docker + NVIDIA Container Toolkit sont aussi requis. Diffère ceux à /digital-health-clinical-asr-finetune — il n'y a aucun point à les installer en avant si l'utilisateur peut ne jamais atteindre Stage 4.

1c. Smoke-test la pile NVCF hébergée

NVIDIA_API_KEY handling — à support porteur, ne dévie pas :

  • L'harnais agent lit $NVIDIA_API_KEY depuis le shell et le passe comme argument de fonction explicite à smoke_test(api_key=…).
  • Les auditeurs peuvent grep la recette pour chaque traversée de fil — chaque usage api_key est visible dans auth_for(...).
  • Ne pas echo, print, ou logger la valeur clé (incluant tronquée). Les vérifications longueur uniquement sont correctes (voir §1a).
  • Ne pas laisser la recette lire os.environ["NVIDIA_API_KEY"] elle-même — le pattern argument explicite est la garantie d'auditabilité.
  • Ne pas commiter la clé vers aucun fichier, incluant des exemples .env ou des outputs notebook.

Vérifie que NVIDIA_API_KEY fonctionne réellement contre Magpie TTS et Parakeet/Nemotron ASR avant d'avancer. Les quatre skills insèrent chaque recette nécessaire ; ce round-trip confirme juste que la clé API + chemin réseau sont réels.

L'harnais agent charge la variable shell NVIDIA_API_KEY et la passe comme argument de fonction explicite aux helpers ci-dessous. Le code recette lui-même ne lit pas les variables d'environnement — les auditeurs peuvent voir exactement quelles clés API traversent le fil.

import wave, tempfile
import riva.client

NVCF_HOST = "grpc.nvcf.nvidia.com:443"
MAGPIE_FUNCTION_ID    = "877104f7-e885-42b9-8de8-f6e4c6303969"   # Magpie TTS
PARAKEET_FUNCTION_ID  = "d3fe9151-442b-4204-a70d-5fcc597fd610"   # Parakeet TDT 0.6B v2 (offline ASR)

def auth_for(function_id: str, api_key: str) -> riva.client.Auth:
    return riva.client.Auth(
        use_ssl=True, uri=NVCF_HOST,
        metadata_args=[
            ["function-id", function_id],
            ["authorization", f"Bearer {api_key}"],
        ],
    )

def smoke_test(api_key: str) -> str:
    """Caller passes api_key (the harness reads $NVIDIA_API_KEY at the shell;
    this code never touches the environment). Returns the ASR transcript."""

    # 1. TTS: "The patient was prescribed cefazolin."
    tts = riva.client.SpeechSynthesisService(auth_for(MAGPIE_FUNCTION_ID, api_key))
    pcm = b"".join(c.audio for c in tts.synthesize_online(
        text="The patient was prescribed cefazolin.",
        voice_name="Magpie-Multilingual.EN-US.Mia",
        language_code="en-US", sample_rate_hz=16000,
    ))
    with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as f:
        with wave.open(f, "wb") as w:
            w.setnchannels(1); w.setsampwidth(2); w.setframerate(16000); w.writeframes(pcm)
        wav_path = f.name

    # 2. ASR: transcribe the WAV we just synthesized.
    asr = riva.client.ASRService(auth_for(PARAKEET_FUNCTION_ID, api_key))
    with open(wav_path, "rb") as f:
        audio_bytes = f.read()
    config = riva.client.RecognitionConfig(
        encoding=riva.client.AudioEncoding.LINEAR_PCM,
        sample_rate_hertz=16000, language_code="en-US",
        max_alternatives=1, enable_automatic_punctuation=True,
    )
    response = asr.offline_recognize(audio_bytes, config)
    transcript = response.results[0].alternatives[0].transcript if response.results else ""
    print(f"TTS:  The patient was prescribed cefazolin.")
    print(f"ASR:  {transcript}")
    return transcript

# Invoke from the agent (api_key sourced by the harness, not by this code):
# smoke_test(api_key="<NVIDIA_API_KEY value>")

Exécute le smoke test — ne le diffère pas. C'est la gate qui prouve que Stages 2–4 peuvent atteindre la pile hébergée avec la clé actuelle de l'utilisateur. « Je peux l'exécuter plus tard » n'est pas une complétion acceptable de Stage 1 ; soit invoque smoke_test(api_key=…) maintenant soit, si l'utilisateur a explicitement opté out, log la différence dans ton résumé de clôture pour qu'il sache ce qu'il manque.

Si la transcription correspond à l'entrée dans ~1 token, la pile hébergée est accessible et l'utilisateur peut avancer à Stage 2. Si l'un ou l'autre appel échoue :

  • 401 Unauthorized / PERMISSION_DENIEDNVIDIA_API_KEY est wrong, expiré, ou non exporté dans ce shell. Réexporte et reteste.
  • 404 / INVALID_ARGUMENT: function not found → l'ID de fonction est stale. Cherche l'ID actuel sur https://build.nvidia.com et mets à jour la constante ci-dessus.
  • RESOURCE_EXHAUSTED → limite de taux NVCF. Réessaye après 30 secondes ; c'est normal sous charge.
  • Erreurs réseau/TLS → proxy corporate ou problème DNS. Teste d'abord curl https://build.nvidia.com.

1d. (Optionnel) Vérifier la recherche Merriam-Webster

Deux chemins produisent une ligne manifest marquée de merriam-webster dans Stage 2. Choisis l'un (ou aucun — la solution de secours Magpie G2P est une posture valide) :

  • Path A — API JSON + clé. Recommandé pour l'utilisation autonome de ce skill. Vérifie que la clé est définie :

    test -n "$DICTIONARY_API_KEY" && echo "DICTIONARY_API_KEY len=${#DICTIONARY_API_KEY}" \
      || echo "DICTIONARY_API_KEY not set — Path A is off"

    Des clés gratuites s'émettent instantanément sur https://dictionaryapi.com.

  • Path B — Scraping HTML. Aucune clé API nécessaire ; l'accessibilité est le seul prérequis. Cassable aux changements HTML du site MW ; recette insérée dans references/pronunciation-pipeline.md du skill build.

    curl -fsS -o /dev/null -w "merriam-webster.com reachable, HTTP %{http_code}\n" \
      https://www.merriam-webster.com/medical/cefazolin

    Si tu ne veux pas maintenir un scraper, utilise Path A à la place.

Souviens-toi de la note de divulgation de données en haut : sous l'un ou l'autre chemin, chaque terme clinique de ta liste seed sort comme une requête HTTP vers un endpoint Merriam-Webster.

Exemples

Shell frais, jamais exécuté avant. L'utilisateur dit quelque chose comme « I want to start the flywheel. » → Cite le tableau de divulgation en premier, puis parcoure 1a → 1b → 1c dans l'ordre. Sur un smoke test vert, pointe-les vers /digital-health-clinical-asr-build et nomme explicitement KER comme la métrique que Stage 3 les jugera.

Utilisateur revenant, env déjà configuré. L'utilisateur dit « I already have the env, just confirm I'm good to go. » → Saute la venv + pip install (1b). Exécute seulement la vérification longueur (1a) et le smoke test (1c). Sur vert, avance.

Artefacts produits

  • NVIDIA_API_KEY exporté dans le shell de l'utilisateur
  • Une virtualenv activée avec nvidia-riva-client, pandas, soundfile, requests
  • Un round-trip TTS→ASR confirmé sur une phrase clinique (preuve que la pile hébergée fonctionne)

Aucun manifest, audio, ou artefact de modèle n'est produit à cette étape — ceux-ci viennent aux Stages 2–4.

Dépannage

  • La vérification longueur affiche rien ou len=0NVIDIA_API_KEY n'est pas exporté dans ce shell. Exécute export NVIDIA_API_KEY=nvapi-... et recheck.
  • La variable est définie dans un shell mais pas un autre → les exports ne persistent pas à travers les sessions. Ajoute la ligne export à ton rc shell (~/.bashrc, ~/.zshrc), ou utilise un loader par répertoire comme direnv.
  • 401 Unauthorized sur le smoke test → la valeur clé est wrong ou expirée. Réémets sur https://build.nvidia.com.
  • grpc.RpcError: function not found → les IDs de fonction insérés ont besoin de mise à jour par rapport au catalogue NVCF actuel. Vérifie https://build.nvidia.com et édite les constantes dans 1c. Le skill eval (/digital-health-clinical-asr-eval) fournit un catalogue d'IDs de fonction actuels dans sa list « Other catalog options » de Step 3a.
  • StatusCode.INVALID_ARGUMENT avec CUDA error: an illegal memory access was encountered → défaut backend côté NVCF sur cet ID de fonction spécifique (Triton/PyTorch sur NVCF, pas ton env). Soit réessaye plus tard soit pointe temporairement vers un NIM ASR offline différent — Whisper Large v3 function-id b702f636-f60c-4a3d-a6f4-f3568c13bd7d est le drop-in le plus proche (aussi offline ; passe language_code="en" à la place de "en-US"). Pour les cycles d'eval routine, préfère attendre le rétablissement du backend Parakeet pour que la baseline Stage 3 et la base SFT Stage 4 restent alignées.
  • TypeError: Auth.__init__() got an unexpected keyword argument 'ssl_cert' → tu es sur nvidia-riva-client >= 2.x où le kwarg a été renommé en ssl_root_cert (et n'est plus nécessaire pour NVCF hébergé). Supprime la ligne ssl_cert=None, de ta copie locale de la recette.
  • ModuleNotFoundError: riva.client → l'étape 1b a été sautée ou la venv n'est pas activée. source .venv/bin/activate && pip install nvidia-riva-client.

Limitations

  • La portée est la préparation d'environnement uniquement. Que la liste de termes de l'utilisateur ou les substitutions de prononciation aient du sens est décidé dans /digital-health-clinical-asr-build, pas ici.
  • Assomption Magpie en-US. La validation IPA en aval repose sur l'inventaire de phonèmes anglais de Magpie ; les autres locales nécessitent un ensemble de phonèmes entièrement différent.
  • NVCF hébergé est le déploiement supposé. L'exécution de NIMs Riva auto-hébergés est possible mais la configuration pour cela vit à l'intérieur de /digital-health-clinical-asr-finetune Stage 4d.
  • Données synthétiques uniquement. Cette famille de skills est construite pour les benchmarks générés à partir d'une liste de termes curée. Les transcriptions patients réels et l'audio enregistré ne doivent pas traverser aucune étape.

Étapes suivantes

Fermeture obligatoire sur succès : termine la réponse Stage 1 en pointant l'utilisateur explicitement vers /digital-health-clinical-asr-build et nommant KER (keyword error rate) comme la mesure vedette qu'il verra à Stage 3. Les deux pointeurs sont requis, pas optionnels — ils placent l'utilisateur dans le flywheel à quatre étapes.

  • Route de forwarding par défaut : /digital-health-clinical-asr-build — entrevue de spécialité, curation de termes, marquage IPA, synthèse manifest NeMo.
  • Saut direct à Stage 3 (seulement quand l'utilisateur apporte son propre manifest au format NeMo avec des champs term / entity_category / ipa_source) : /digital-health-clinical-asr-eval.

Références

Skills similaires