Skip to Content
Mélodium 0.10.3 is now available!
DocsExemplesAssistant vocal IA

Assistant vocal IA

Source: showcase/ai_voice_assistant See in Playground

Cet exemple combine plusieurs capacités ml de la bibliothèque en une seule démonstration, sans s’arrêter pour expliquer chaque concept sous-jacent ; ceux-ci sont couverts individuellement dans le parcours tutoriel. Deux points d’entrée : chat, un serveur HTTP qui transmet la réponse d’un LLM distant token par token, et voice, une boucle complète du microphone jusqu’à la réponse parlée.

Note

Nécessite de véritables clés API (un fournisseur LLM pour les deux points d’entrée, plus ElevenLabs pour voice) et, pour voice, un microphone fonctionnel. voice télécharge également un petit modèle Whisper depuis le HuggingFace Hub au premier lancement et le met en cache localement.

Exécution

chat, un serveur HTTP transmettant la réponse d’un LLM distant token par token :

cd showcase/ai_voice_assistant melodium run Compo.toml chat --api_key sk-... curl -X POST http://127.0.0.1:8080/chat -d "What is Mélodium?"

voice, du microphone vers Whisper local (reconnaissance vocale) vers un LLM distant (réponse en flux) vers une synthèse vocale distante vers answer.mp3 :

cd showcase/ai_voice_assistant melodium run Compo.toml voice --llm_api_key sk-... --tts_api_key el-...

La reconnaissance vocale s’exécute localement (un petit modèle Whisper, récupéré une fois depuis le HuggingFace Hub et mis en cache), donc l’audio brut ne quitte jamais la machine locale : seul le texte transcrit est envoyé au LLM, et seul le texte de la réponse du LLM est envoyé au fournisseur de synthèse vocale.

Optionnel : ajoutez --api-report et un jeton d’API (MELODIUM_API_TOKEN) pour voir la trace complète de cette exécution sur Cadence.CI.

Fonctionnement

chat : transmettre en flux la réponse d’un LLM via HTTP

chat démarre un HttpServer et, exactement comme établi dans l’étape du tutoriel sur le serveur HTTP, conditionne la réponse à connection.started plutôt qu’au démarrage du flux du corps de requête :

treatment respond[llm: RemoteLlm]() input data: Stream<byte> output data: Stream<byte> { decoded: decode() reply: stream[llm=llm]() encoded: encode() Self.data -> decoded.data,text -> reply.prompt,token -> encoded.text,data -> Self.data llmErrors: logErrors(label="llm") reply.error -> llmErrors.messages }

voice : du microphone à la réponse parlée

voice récupère et charge d’abord un modèle Whisper depuis un dépôt HfHub, puis enregistre depuis le microphone avec recordMono et transcrit localement :

model WhisperHub() : HfHub { repo_id = "openai/whisper-tiny" } model Asr() : Whisper {}
fetchAsr: fetch[hub=whisperHub]() loadAsr: load[whisper=asr]() startup.trigger -> fetchAsr.trigger fetchAsr.safetensors -> loadAsr.safetensors fetchAsr.tokenizer -> loadAsr.tokenizer record: recordMono(device=_, sample_rate=_) asrDecode: whisperDecode[whisper=asr]() loadAsr.loaded -> record.trigger loadAsr.loaded -> asrDecode.ready record.signal -> asrDecode.audio

Le texte transcrit alimente un appel stream sur un RemoteLlm, et chaque token est à la fois journalisé et envoyé vers un appel synthesize sur un RemoteTts configuré pour ElevenLabs, dont l’audio est écrit localement :

model Voice(const tts_api_key: string, const voice_id: string) : RemoteTts { backend = "elevenlabs" api_key = |wrap<string>(tts_api_key) model = "eleven_multilingual_v2" voice = voice_id }
reply: stream[llm=llm]() asrDecode.transcribed -> reply.prompt speak: synthesize[tts=tts]() reply.token -> speak.text write: writeLocal(path=output) speak.audio -> write.data

Dépendances

[dependencies] std = "0.10.3" # flux de base, journalisation, structures de données http = "0.10.3" # client et serveur HTTP net = "0.10.3" # aides pour adresses IP encoding = "0.10.3" # encodage / décodage UTF-8 fs = "0.10.3" # lecture/écriture de fichiers locaux record = "0.10.3" # enregistrement au microphone ml = "0.10.3" # LLM, STT, TTS et inférence de modèles locaux