Skip to content

Commit d5c8382

Browse files
authored
Merge pull request #3214 from madeline-underwood/voice
Voice
2 parents fa9a66a + 07f4bb1 commit d5c8382

7 files changed

Lines changed: 79 additions & 33 deletions

File tree

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
---
2-
title: Overview
2+
title: Understand voice sentiment analysis for on-device AI
33
weight: 2
44
layout: learningpathall
55
---
6+
7+
## Learn voice-based sentiment classification for LLM applications
8+
69
Voice-based LLM applications often rely primarily on transcribed text from speech input, such as in interactions with non-player characters in games or voice assistants. This approach can overlook vocal cues—like tone, pitch, and emotion—present in a speaker’s voice. As a result, responses may feel less natural and may not fully capture the user’s underlying intent.
710

8-
To address this, voice-based sentiment classification analyzes audio input to determine the users emotional state, which is then incorporated into the LLM prompt to enable more context-aware responses. In this Learning Path, you will build a sentiment-aware voice assistant that runs entirely on-device. The application records audio, performs transcription—converting speech into written text—using Whisper, classifies sentiment directly from the voice signal, and combines the transcript and voice-based sentiment to guide responses from a local LLM running with llama.cpp.
11+
To address this, voice-based sentiment classification analyzes audio input to determine the user's emotional state, which is then incorporated into the LLM prompt to enable more context-aware responses. In this Learning Path, you'll build a sentiment-aware voice assistant that runs entirely on-device. The application records audio, performs transcription—converting speech into written text—using Whisper, classifies sentiment directly from the voice signal, and combines the transcript and voice-based sentiment to guide responses from a local LLM running with llama.cpp.
912

10-
![Voice sentiment classification pipeline#center](1_vsapipeline2.png "Voice sentiment classification pipeline")
13+
![Pipeline diagram showing audio input flowing through Whisper transcription and HuBERT sentiment classification, then both text and sentiment being combined into an LLM prompt that generates context-aware responses#center](1_vsapipeline2.png "Voice sentiment classification pipeline")
1114

12-
You will start by building a baseline voice-to-LLM pipeline—capturing audio, transcribing it into text, and using it to generate responses with an LLM. You will then extend this pipeline with a voice-based sentiment classification model. This involves training the model, optimizing it for efficient on-device inference, and integrating it into a unified application.
15+
You'll start by building a baseline voice-to-LLM pipeline—capturing audio, transcribing it into text, and using it to generate responses with an LLM. You'll then extend this pipeline with a voice-based sentiment classification model. This involves training the model, optimizing it for efficient on-device inference, and integrating it into a unified application.

content/learning-paths/mobile-graphics-and-gaming/voice-sentiment-analysis-with-llm/2_set-up-your-environment.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ weight: 3
66
layout: learningpathall
77
---
88

9+
## Prepare the development environment for voice sentiment classification
10+
911
Before building the voice assistant, create a project workspace and set up an isolated `UV` environment. This keeps project dependencies separate from your system installation and makes it easier to reproduce the steps in the rest of the Learning Path.
1012

1113
These instructions support Ubuntu, macOS, and Windows, with Python 3.9 or later and a working microphone.
@@ -42,7 +44,7 @@ py -3 --version
4244

4345
## Set up the Python environment with UV
4446

45-
Install `UV` first so the `uv` command is available in your terminal. `UV` is a fast Python package and environment manager that you will use throughout this Learning Path to create the project environment and install dependencies.
47+
Install `UV` first so the `uv` command is available in your terminal. `UV` is a fast Python package and environment manager that you'll use throughout this Learning Path to create the project environment and install dependencies.
4648

4749
{{< tabpane code=true >}}
4850
{{< tab header="Ubuntu/macOS" language="bash">}}
@@ -152,4 +154,13 @@ Run the following command from the `llama.cpp` directory:
152154

153155
Leave this terminal running while you test the application in later steps. The server listens on a local OpenAI-compatible endpoint that your app will call to generate responses.
154156

155-
At this point, your development environment is ready. You have installed the required audio and build tools, created a `UV` environment, installed the Python dependencies, and started a local `llama.cpp` server. In the next section, you will use this setup to build the baseline voice-to-LLM pipeline by creating a simple Gradio interface, transcribing microphone input with Whisper, and sending the transcript to the local LLM.
157+
## What you've learned and what's next
158+
159+
In this section, you:
160+
161+
- Installed system dependencies for audio processing and building llama.cpp
162+
- Created a UV-managed Python environment with required packages
163+
- Built llama.cpp from source for local LLM inference
164+
- Started the llama-server with a quantized Gemma model
165+
166+
Your development environment is now ready with all tools needed for voice transcription, model training, and local LLM inference. In the next section, you'll build the baseline voice-to-LLM pipeline using Gradio, Whisper, and llama.cpp.

content/learning-paths/mobile-graphics-and-gaming/voice-sentiment-analysis-with-llm/3_build-baseline-voice-to-llm-pipeline.md

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ weight: 4
44
layout: learningpathall
55
---
66

7-
In this section, you will build an end-to-end pipeline that:
7+
## Create the baseline voice-to-LLM pipeline
88

9-
1. Records audio from your microphone
10-
2. Transcribes it to text using Whisper
11-
3. Sends the text to a locally hosted LLM
12-
4. Displays the model's response
9+
In this section, you'll build an end-to-end pipeline that:
10+
11+
- Records audio from your microphone
12+
- Transcribes it to text using Whisper
13+
- Sends the text to a locally hosted LLM
14+
- Displays the model's response
1315

1416
This forms the foundation of your voice assistant.
1517

16-
![Baseline voice-to-LLM pipeline#center](3_vsapipeline1.png "Baseline voice-to-LLM pipeline")
18+
![Diagram showing the baseline pipeline with three stages: audio input from microphone flows to Whisper for transcription, then transcript text is sent to local LLM, which returns a response#center](3_vsapipeline1.png "Baseline voice-to-LLM pipeline")
1719

1820
Before you begin, make sure you have completed the environment setup in the previous section and that your `llama-server` is still running.
1921

@@ -177,7 +179,7 @@ with gr.Blocks() as demo:
177179
demo.launch()
178180
```
179181

180-
## What you should see
182+
## Expected output
181183

182184
After recording audio in the browser:
183185

@@ -191,4 +193,13 @@ After recording audio in the browser:
191193
- Whisper is slow on first run: this is expected due to model download and initialization.
192194
- Microphone not working: check browser permissions for microphone access.
193195

194-
At this point, you have a working voice-to-LLM pipeline. In the next section, you will extend this pipeline by adding a voice sentiment classification model.
196+
## What you've learned and what's next
197+
198+
In this section, you:
199+
200+
- Created a Gradio web interface with microphone input
201+
- Integrated Whisper for speech-to-text transcription
202+
- Connected to a local LLM endpoint using llama.cpp
203+
- Built a working voice-to-LLM pipeline
204+
205+
You now have a baseline voice assistant that transcribes speech and generates responses. In the next section, you'll train a voice sentiment classification model to extend this pipeline with emotion awareness.

content/learning-paths/mobile-graphics-and-gaming/voice-sentiment-analysis-with-llm/4_train-voice-sentiment-model.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ title: Train the voice sentiment classification model
33
weight: 5
44
layout: learningpathall
55
---
6+
## Train a HuBERT model for voice sentiment classification
67
In this section, you will train a model to classify voice sentiment directly from audio. The raw waveform is converted into audio-based features, then passed through a pre-trained HuBERT model with a classification head.
78

89
For this Learning Path, you train the model on the RAVDESS dataset using three sentiment classes: `neutral`, `happy`, and `angry`. This keeps the demo manageable while still showing a realistic transfer-learning workflow. You can extend the same approach to more sentiment classes or other datasets.
@@ -13,7 +14,7 @@ This example uses a simple per-sample training loop for clarity. On CPU, trainin
1314

1415
All code snippets in Steps 2.1 to 2.5 are meant to be added to a single Python file: `train_sentiment_model.py` in your project root (`$HOME/voice-sentiment-assistant`).
1516

16-
Make sure you are located in the project directory:
17+
Make sure you're located in the project directory:
1718

1819
```bash
1920
cd $HOME/voice-sentiment-assistant
@@ -208,7 +209,7 @@ for epoch in range(EPOCHS):
208209
print(f"Validation accuracy: {accuracy:.2f}")
209210
```
210211

211-
At the end of this step, you will have a trained model and a simple validation accuracy printed after each epoch. You should typically see validation accuracy improve over time, although the exact values will vary depending on randomness and hardware.
212+
At the end of this step, you'll have a trained model and a simple validation accuracy printed after each epoch. You should typically see validation accuracy improve over time, although the exact values will vary depending on randomness and hardware.
212213

213214
### Step 2.5 - Save the model
214215

@@ -392,4 +393,13 @@ Run the training script:
392393
python train_sentiment_model.py
393394
```
394395

395-
At this point, you have a trained voice sentiment classification model saved locally. In the next section, you will convert this model to ONNX format and compress it for more efficient inference.
396+
## What you've learned and what's next
397+
398+
In this section, you:
399+
400+
- Downloaded and prepared the RAVDESS speech emotion dataset
401+
- Fine-tuned a HuBERT model for voice sentiment classification
402+
- Validated the model's accuracy on neutral, happy, and angry emotions
403+
- Saved the trained model and feature extractor for inference
404+
405+
You now have a trained voice sentiment model ready for deployment. In the next section, you'll export this model to ONNX format and apply int-8 quantization to optimize it for efficient on-device inference.

content/learning-paths/mobile-graphics-and-gaming/voice-sentiment-analysis-with-llm/5_compress-and-convert-the-model.md

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ title: Convert and quantize the model
33
weight: 6
44
layout: learningpathall
55
---
6-
In this section, you will convert the trained model to ONNX format and compress it for efficient on-device inference. First, export the trained PyTorch model to ONNX. Then apply post-training quantization to reduce model size and improve runtime efficiency.
6+
7+
## Export and optimize the model for on-device inference
8+
9+
In this section, you'll convert the trained model to ONNX format and compress it for efficient on-device inference. First, export the trained PyTorch model to ONNX. Then apply post-training quantization to reduce model size and improve runtime efficiency.
710

811
### Step 3.1 - Export to ONNX
912

@@ -70,7 +73,7 @@ You can verify the exported file with:
7073
ls models/hubert_vsa_ravdess_onnx
7174
```
7275

73-
### Step 3.2 - Quantize model
76+
### Step 3.2 - Quantize the model
7477

7578
This step applies dynamic INT8 quantization to the ONNX model. The model weights are quantized to integer 8 bits ahead of time, while activations are quantized dynamically during inference.
7679

@@ -178,7 +181,7 @@ If this file does not exist on your system, replace `SAMPLE_PATH` with any `.wav
178181

179182
After this step, you have verified that quantized ONNX inference works with your trained model.
180183

181-
You should see a predicted label such as:
184+
The output is similar to:
182185

183186
```text
184187
Predicted: happy
@@ -198,7 +201,7 @@ models/
198201

199202
You can also compare the model metrics before and after quantization.
200203

201-
![Model ONNX conversion and int-8 quantization results#center](4_modelconversionandcompression.png "Model ONNX conversion and int-8 quantization results")
204+
![Diagram showing model file sizes and performance metrics comparing the original ONNX model to the int-8 quantized version, demonstrating reduced size and improved inference speed#center](4_modelconversionandcompression.png "Model ONNX conversion and int-8 quantization results")
202205

203206
Typical results look like:
204207

@@ -211,6 +214,15 @@ Quantized INT8 ONNX model: smaller size, lower memory footprint, faster CPU infe
211214

212215
- ONNX export fails: ensure the trained model exists in `models/hubert_vsa_ravdess`.
213216
- Inference error about missing inputs: confirm that both `input_values` and `attention_mask` are passed to the ONNX session.
214-
- Slow inference: make sure you are using `hubert_vsa_ravdess_int8.onnx` rather than the unquantized ONNX model.
217+
- Slow inference: make sure you're using `hubert_vsa_ravdess_int8.onnx` rather than the unquantized ONNX model.
218+
219+
## What you've learned and what's next
220+
221+
In this section, you:
222+
223+
- Exported the PyTorch sentiment model to ONNX format
224+
- Applied int-8 quantization to reduce model size and improve inference speed
225+
- Verified that the quantized ONNX model produces correct predictions
226+
- Prepared the model for efficient CPU inference on Arm devices
215227

216-
The model is now ready for integration into the voice pipeline in the next section.
228+
You now have an optimized sentiment classification model ready for production use. In the next section, you'll integrate this ONNX model into the voice-to-LLM pipeline to create a complete sentiment-aware voice assistant.

content/learning-paths/mobile-graphics-and-gaming/voice-sentiment-analysis-with-llm/6_integrate-voice-sentiment-classification-model.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,20 @@ title: Integrate the voice sentiment classification model
33
weight: 7
44
layout: learningpathall
55
---
6-
In this section, you will integrate the voice sentiment classification model into the baseline voice-to-LLM pipeline and build a sentiment-aware voice assistant. You will update the prompt sent to the LLM so it includes both the transcript and the predicted sentiment, combining speech, emotion, and language understanding into a single application.
6+
7+
## Build the complete sentiment-aware voice assistant
8+
9+
In this section, you'll integrate the voice sentiment classification model into the baseline voice-to-LLM pipeline and build a sentiment-aware voice assistant. You'll update the prompt sent to the LLM so it includes both the transcript and the predicted sentiment, combining speech, emotion, and language understanding into a single application.
710

811
End-to-end response time may take a few seconds because the application runs Whisper transcription, ONNX sentiment inference, and local LLM generation for each interaction.
912

10-
![Integrated voice-to-LLM pipeline#center](6_vsapipeline4.png "Integrated voice-to-LLM pipeline")
13+
![Integrated pipeline diagram showing audio input splitting into two parallel paths: Whisper produces transcript text and HuBERT produces sentiment label, both feeding into an LLM prompt that generates context-aware responses#center](6_vsapipeline4.png "Integrated voice-to-LLM pipeline")
1114

1215
In Steps 4.1 to 4.4, continue editing the same `app.py` file you created in the baseline pipeline section (`~/voice-sentiment-assistant/app.py`).
1316

1417
### Step 4.1 - Load the voice sentiment classification model
1518

16-
This step initializes the trained and quantized ONNX model, then loads the matching preprocessing components used during training. You will reuse these objects every time you run sentiment inference on new audio.
19+
This step initializes the trained and quantized ONNX model, then loads the matching preprocessing components used during training. You'll reuse these objects every time you run sentiment inference on new audio.
1720

1821
Add these imports and model-loading definitions to `app.py`:
1922
- add the imports with your other imports at the top of the file
@@ -37,7 +40,7 @@ feature_extractor = AutoFeatureExtractor.from_pretrained(MODEL_DIR)
3740
id2label = AutoConfig.from_pretrained(MODEL_DIR).id2label
3841
```
3942

40-
### Step 4.2 - Create sentiment prediction function
43+
### Step 4.2 - Create the sentiment prediction function
4144

4245
Next, create a helper function that takes an audio file path, runs the sentiment model, and returns the predicted label. This adds the emotion-aware part of the assistant.
4346

@@ -101,7 +104,7 @@ def handle_audio(audio_path):
101104
return text, sentiment, answer
102105
```
103106

104-
### Step 4.4 - Update User Interface (UI)
107+
### Step 4.4 - Update user interface (UI)
105108

106109
In this step, update the interface so it displays three outputs: the transcript, the predicted sentiment, and the final LLM response. For consistency with the earlier page, connect the microphone input with `mic.change(...)`.
107110

@@ -244,7 +247,7 @@ A more robust approach is to combine voice with other modalities such as text an
244247
## Troubleshooting
245248

246249
- No sentiment output: check that `ONNX_PATH` points to the quantized ONNX model from the previous section.
247-
- Slow response: make sure you are using `hubert_vsa_ravdess_int8.onnx` and that `llama-server` is already running.
250+
- Slow response: make sure you're using `hubert_vsa_ravdess_int8.onnx` and that `llama-server` is already running.
248251
- LLM not responding: verify that `llama-server` is still available at `http://127.0.0.1:8080`.
249252
- Microphone input not updating: check browser microphone permissions.
250253

content/learning-paths/mobile-graphics-and-gaming/voice-sentiment-analysis-with-llm/_index.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
---
22
title: Build a Sentiment-Aware Voice Assistant with On-Device LLMs
33

4-
draft: true
5-
cascade:
6-
draft: true
7-
84
description: Build an end-to-end, on-device voice assistant that understands both speech and emotion using Whisper, HuBERT, ONNX Runtime, and a local LLM with llama.cpp on Arm.
95

106
minutes_to_complete: 90

0 commit comments

Comments
 (0)