Mistral lanceerde onlangs zijn eerste open-source multimodale audiomodellen, Voxtral Small en Voxtral Mini, gebouwd op de Mistral 3B‑architectuur en specifiek geoptimaliseerd voor taken rond audiobegrip en transcriptie.
In deze blog richt ik me op Voxtral Mini 3B, een compact open‑source model ontworpen voor realtime audio-naar-tekst taken zoals transcriptie, samenvatting en Q&A. Dankzij het efficiënte formaat en ondersteuning voor redeneren met lange context is Voxtral Mini bijzonder krachtig in combinatie met high-throughput inference-frameworks zoals vLLM, wat het ideaal maakt voor snelle, offline audio-applicaties.
In deze tutorial laat ik je zien hoe je:
Voxtral Mini 3B uitvoert met vLLM op Colab Pro
Een via ngrok getunnelde API‑endpoint uitrolt om je model overal te kunnen benaderen
Een Streamlit‑gebaseerde audio-assistent bouwt die transcriptie, samenvatting en Q&A uitvoert op basis van ruwe audio-invoer
We houden onze lezers op de hoogte van het laatste AI‑nieuws met The Median, onze gratis vrijdagse nieuwsbrief met de belangrijkste verhalen van de week. Abonneer je en blijf scherp in een paar minuten per week:
Wat is Mistrals Voxtral?
Voxtral is Mistrals volledig open‑source audiomodelfamilie, ontworpen voor krachtige spraakbegrip. Voxtral is er in twee modelgroottes:
Voxtral Small: 24 B parameters, ideaal voor productie op schaal in de enterprise
Voxtral Mini: 3 B parameters, geoptimaliseerd om lokaal te draaien op edge‑apparaten
Voxtral accepteert ruwe audio-invoer (zoals .wav of .mp3) en is getraind om efficiënt transcripties en samenvattingen te genereren uit gesproken content. Voxtral is een kleinere variant, geoptimaliseerd voor snelle inference en offline deployment.
Het volgt Mistrals modelformaat en is compatibel met high-throughput inference‑frameworks zoals vLLM, waardoor het een uitstekende keuze is voor realtime transcriptie of lichtgewicht spraaktoepassingen.
Voxtral Mini 3B uitvoeren met vLLM
In deze sectie laat ik je zien hoe je Voxtral Mini 3B serveert met vLLM op een Colab Pro met T4‑GPU ingeschakeld. vLLM is gekozen vanwege de high-throughput, lage-latentie serveercapaciteiten, ideaal voor modellen zoals Voxtral die snelle streamingantwoorden met audio-ondersteuning vereisen.
Daarnaast gebruiken we PyNGrok om de vLLM‑server via een publiek endpoint bloot te stellen, zodat deze toegankelijk is voor applicaties op je lokale machine.
Stap 1: Dependencies installeren
Laten we beginnen met het installeren van de dependencies in onze Colab‑omgeving. Voer de volgende opdracht uit in de Colab‑cel:
!uv pip install -U transformers accelerate "vllm[audio]"--torch-backend=auto --extra-index-url https://wheels.vllm.ai/nightlyMogelijk gemaakt door
We beginnen met het installeren van de vereiste libraries met uv, een snellere Python‑pakketinstaller. Dit haalt de nightly‑versie van vllm[audio] op, die experimentele ondersteuning bevat voor audio‑taalmodellen zoals Voxtral. Als je uv niet in je omgeving hebt geïnstalleerd, installeer dan eerst uv met de volgende code:
Vervolgens installeren we het pakket mistral-common, dat essentiële utilities biedt om met Voxtral en andere modellen uit de Mistral‑familie te werken. Dit pakket bevat tokenizers die aansluiten op de officiële implementaties en Pydantic‑gebaseerde validatie voor berichtstructuren.
!pip install mistral-common --upgrade
!python -c "import mistral_common; print(mistral_common.__version__)"Mogelijk gemaakt door
Het pakket mistral-common bevat utility‑modules voor Voxtral en andere modellen uit de Mistral‑familie. Het omvat tokenizers, getypeerde berichten in Pydantic‑formaten en audio‑hulpfuncties. Deze stap zorgt voor compatibiliteit met Voxtrals interne verwerking van audio-invoer en gestructureerde berichten.
Stap 3: VLLM instellen
Nu de basis‑dependencies voor Mistral klaar zijn, richten we vLLM in door de hoofdrepository te clonen.
Stap 3.1: De vLLM‑repository klonen
We clonen de officiële vLLM‑GitHub‑repository, die toegang geeft tot ingebouwde audio‑voorbeelden en dient als basis om offline of gehoste inference te starten.
Stap 3.2: Een voorbeeld van audio‑inference uitvoeren
Laten we een snelle sanity check doen om te controleren of onze setup klopt.
!python vllm/examples/offline_inference/audio_language.py --num-audios 2--model-type voxtralMogelijk gemaakt door
Ik draaide het offline‑voorbeeld audio_language.py, dat audio‑taalinference uitvoert op twee vooraf gedefinieerde samples met het Voxtral‑model en bevestigt of audiodecodering en generatie correct werken.
Stap 4: PyGrok instellen
Nu vLLM is ingesteld, configureren we PyNGrok om de vLLM‑server op Colab via een publiek toegankelijke internet‑URL beschikbaar te maken.
Scroll omlaag onder het tabblad Connect en kopieer de authenticatietoken (verborgen in de afbeelding hieronder) en sla deze op als secret in Colab Secrets.
Vervolgens installeren we PyNGrok in de colab‑omgeving en stellen we de authenticatietoken in met de NGROK‑token die we eerder hebben gekopieerd. Werk je aan een prototype, dan kun je de token hier direct doorgeven.
!pip install pyngrok -q
from pyngrok import ngrok
ngrok.set_auth_token("NGROK_TOKEN")Mogelijk gemaakt door
Stap 5: Het model serven
Dit is de belangrijkste stap, waarin we het Voxtral Mini 3B‑model starten via vLLM.
!vllm serve mistralai/Voxtral-Mini-3B-2507--tokenizer_mode mistral --config_format mistral --load_format mistral --max-model-len4864Mogelijk gemaakt door
De code bevat een aantal belangrijke flags:
--tokenizer_mode mistral: Gebruikt de Mistral‑specifieke tokenizer voor nauwkeurige tokenisatie.
--config_format mistral en --load_format mistral: Deze flags zorgen ervoor dat zowel de modelconfiguratie als de gewichten in Mistrals aangepaste formaat worden geladen, zodat de compatibiliteit behouden blijft.
--max-model-len 4864: Stelt de maximale invoercontextlengte in op 4864 tokens.
Let op: laat deze cel actief, dit is een draaiende modelserver.
Stap 6: Het publieke NGrok‑endpoint ophalen
Zodra je vLLM‑server draait, voer je de volgende code regel voor regel uit in een Python‑terminal:
from pyngrok import ngrok
ngrok.set_auth_token(NGROK_TOKEN)
public_url = ngrok.connect(8000)print("Public endpoint:", public_url)Mogelijk gemaakt door
De bovenstaande code stelt het model bloot aan het internet op een tijdelijke publieke URL zoals:
Een demo voor audiotranscriptie en samenvatting bouwen
In deze sectie bouwen we een Streamlit‑UI die:
Audio als invoer neemt (upload door gebruiker)
Deze naar het model stuurt via de vLLM‑server
De transcriptie, samenvatting toont en de gebruiker vragen laat stellen
Stap 1: Dependencies instellen
Voordat we de app bouwen, definiëren we alle vereiste dependencies in een requirements.txt‑bestand. Dit zorgt voor consistente omgevingen bij lokale runs of Colab‑notebooks.
streamlit>=1.28.0
openai>=1.0.0
mistral-common>=0.0.12
huggingface-hub>=0.19.0
pyngrok>=6.0.0
requests>=2.28.0
pydub>=0.25.1 Mogelijk gemaakt door
Daarom hebben we elk van deze nodig:
streamlit: Deze library helpt bij het bouwen van de interactieve audio‑interface.
openai: maakt verbinding met de Voxtral‑compatibele vLLM‑server via de SDK van OpenAI.
mistral-common: Biedt Voxtral‑specifieke utilities zoals AudioChunk en TextChunk.
pyngrok: Stelt onze lokale vLLM‑server bloot aan het internet, zodat de Streamlit‑app er toegang toe heeft.
Pydub: Helpt bij het converteren van audiobestanden voor inference.
huggingface-hub en requests: Worden gebruikt voor het ophalen van model en config (indien nodig).
Stap 2: De omgevingsvariabele instellen
Om de configuratie overzichtelijk en draagbaar te houden, slaan we API‑gegevens op als omgevingsvariabelen. Je kunt ze definiëren in een .env‑bestand:
VOXTRAL_API_KEY=dummy-key
VOXTRAL_API_BASE=NGROK_TOKEN/v1
VOXTRAL_MODEL_NAME=mistralai/Voxtral-Mini-3B-2507Mogelijk gemaakt door
VOXTRAL_API_BASE moet wijzen naar je draaiende vLLM‑instantie, wat localhost kan zijn (http://localhost:8000) of een ngrok‑public endpoint zoals https://80xxxxxxxxxx.ngrok-free.app.
Let op: zorg dat je /v1 achter de API‑basis plakt voor OpenAI‑compatibiliteit.
Stap 3: Het config‑bestand instellen
Om je app modulair, eenvoudig aanpasbaar en klaar voor productie te maken, definiëren we een centrale configuratieklasse in config.py. Dit bestand beheert modelinstellingen, API‑toegang, ondersteunde audioformaten, talen en UI‑voorkeuren.
Stap 3.1: Omgevingsvariabelen laden
Voordat we de config‑klasse definiëren, laden we eventuele omgevingsvariabelen uit een .env‑bestand. Zo houd je gevoelige info buiten de code.
import os
from typing import Optional
from pathlib import Path
# Load environment variables from .env file
env_file = Path(".env")if env_file.exists():withopen(env_file,'r')as f:for line in f:if line.strip()andnot line.startswith('#'):
key, value = line.strip().split('=',1)
os.environ[key]= valueMogelijk gemaakt door
Deze snippet controleert of er een .env‑bestand in de hoofdmap staat. Zo ja, dan leest hij sleutel‑waardeparen en zet die als omgevingsvariabelen. Deze waarden zijn nu toegankelijk met os.getenv(), zodat secrets niet hardcoded in de app belanden.
Stap 3.2: De Config‑klasse definiëren
Nu bundelen we alle instellingen in een overzichtelijke Config‑klasse voor gemakkelijke toegang en hergebruik.
classConfig:# API Configuration
VOXTRAL_API_KEY:str= os.getenv("VOXTRAL_API_KEY","EMPTY")
VOXTRAL_API_BASE:str= os.getenv("VOXTRAL_API_BASE","http://localhost:8000/v1")# Model Configuration
MODEL_NAME:str= os.getenv("VOXTRAL_MODEL_NAME","voxtral-mini-3b-2507")# Default Parameters
DEFAULT_TEMPERATURE:float=0.2
DEFAULT_TOP_P:float=0.95# Audio Configuration
MAX_AUDIO_SIZE_MB:int=100
SUPPORTED_AUDIO_FORMATS:list=['mp3','wav','m4a','flac','ogg']
SUPPORTED_LANGUAGES:list=["English","Spanish","French","German","Italian","Portuguese","Russian","Chinese","Japanese","Korean","Arabic","Hindi"]# UI Configuration
STREAMLIT_THEME:dict={"primaryColor":"#1f77b4","backgroundColor":"#ffffff","secondaryBackgroundColor":"#f0f2f6","textColor":"#262730","font":"sans serif"}@classmethoddefget_api_config(cls)->dict:return{"api_key": cls.VOXTRAL_API_KEY,"base_url": cls.VOXTRAL_API_BASE,"model_name": cls.MODEL_NAME
}@classmethoddefvalidate_config(cls)->bool:ifnot cls.VOXTRAL_API_BASE:returnFalsereturnTrue@classmethoddefget_language_code(cls, language_name:str)-> Optional[str]:
language_mapping ={"English":"en","Spanish":"es","French":"fr","German":"de","Italian":"it","Portuguese":"pt","Russian":"ru","Chinese":"zh","Japanese":"ja","Korean":"ko","Arabic":"ar","Hindi":"hi"}return language_mapping.get(language_name)Mogelijk gemaakt door
Samen fungeert deze Config‑klasse als het gecentraliseerde controlecentrum voor je Voxtral‑app. Of je nu modelparameters configureert, audioformaten beheert of het app‑thema instelt: deze opzet zorgt voor een nette abstractie, herbruikbaarheid en onderhoudbaarheid van de code.
De klasse bevat:
get_api_config()‑methode: Deze methode centraliseert alle API‑gerelateerde gegevens. Waar je app ook een call naar het Voxtral‑model maakt, je kunt simpelweg Config.get_api_config() gebruiken om alles in één keer op te halen.
validate_config()‑methode: Voor je inference start, kun je hiermee controleren of essentiële configuratiewaarden (zoals de basis‑URL) correct zijn ingesteld. Zo kun je problemen vroegtijdig opvangen en de gebruiker waarschuwen.
get_language_code()‑methode: Hiermee schakel je naadloos meertalige Q&A in door gebruiksvriendelijke talenamen uit de UI (bijv. “French”) te mappen naar gestandaardiseerde ISO‑taalcodes (bijv. “fr”). Als een niet‑ondersteunde taal wordt doorgegeven, retourneert deze veilig None.
Stap 4: De Streamlit‑app bouwen
We doorlopen elke sub‑stap die de interface en logica van de app opbouwt.
Stap 4.1: Lay‑out en styling instellen
In deze stap initialiseren we de Streamlit‑frontend, laden we dependencies en stellen we de CSS‑stijl in. Dit vormt de visuele en functionele basis van de app.
import streamlit as st
import tempfile
import os
from mistral_common.protocol.instruct.messages import TextChunk, AudioChunk, UserMessage
from mistral_common.audio import Audio
from openai import OpenAI
import time
from config import Config
# Page configuration
st.set_page_config(
page_title="Voxtral Audio Assistant",
page_icon="🎵",
layout="wide",
initial_sidebar_state="expanded")# Custom CSS
st.markdown("""
<style>
.main-header {
font-weight: bold;
text-align: center;
}
.section-header {
font-weight: bold;
}
.info-box {
background-
border-radius: 0.5rem;
border-left: 4px solid #1f77b4;
}
.success-box {
background-
border-radius: 0.5rem;
border-left: 4px solid #28a745;
}
.chat-message {
border-radius: 0.5rem;
}
.user-message {
background-
border-left: 4px solid #2196f3;
}
.assistant-message {
background-
border-left: 4px solid #9c27b0;
}
</style>
""", unsafe_allow_html=True)Mogelijk gemaakt door
In de bovenstaande Python‑ en CSS‑code:
Importeren we essentiële libraries voor UI, bestandsafhandeling en audio-/tekstberichtopmaak met Voxtrals mistral_common‑pakket.
Configureren we vervolgens de lay‑out van de Streamlit‑app: een interface met twee panelen en een standaard uitgevouwen zijbalk.
Tot slot injecteren we aangepaste CSS om verschillende UI‑onderdelen visueel te scheiden, zoals headers, audiosecties, chatballonnen en samenvattingsvakken. Dit verbetert de visuele hiërarchie van de app met opgemaakte titels, infoberichten en onderscheidende chatballonnen voor gebruiker vs. assistent.
Stap 4.2: Sessie en client initialiseren
Vervolgens zorgen we dat de app consistent werkt bij herladen door sessievariabelen en de client te initialiseren.
definit_session_state():
defaults ={'transcription':"",'summary':"",'chat_history':[],'audio_file_path':None}for key, default_value in defaults.items():if key notin st.session_state:
st.session_state[key]= default_value
definitialize_client():
config = Config.get_api_config()
client = OpenAI(
api_key=config["api_key"],
base_url=config["base_url"],)# Test connectiontry:
models = client.models.list()return client
except Exception as e:
st.error(f"Failed to connect to Voxtral API: {str(e)}")
st.info("Make sure your ngrok tunnel is running in Google Colab")returnNoneMogelijk gemaakt door
Deze code zet de interne status van de applicatie op en behandelt de verbinding met de Voxtral‑API‑server. Twee kernonderdelen:
Sessie‑initialisatie: Zorgt dat gebruikersgegevens zoals transcripties, samenvattingen en geüploade audiobestanden correct blijven bestaan tijdens interacties en herladen.
Client‑initialisatie: Maakt verbinding met het lokaal gehoste Voxtral Mini 3B‑model via het OpenAI‑compatibele endpoint dat door vLLM wordt blootgesteld (via Ngrok). Als de verbinding faalt, verschijnt er een foutmelding in de UI.
Stap 4.3: Audio chunking en realtime transcriptie
Deze stap verzorgt de kernlogica voor het voorbereiden van het audiobestand en het genereren van een transcriptie met Voxtral Mini 3B.
deffile_to_chunk(file_path:str)-> AudioChunk:
audio = Audio.from_file(file_path, strict=False)return AudioChunk.from_audio(audio)deftranscribe_audio(client, audio_file_path):try:withopen(audio_file_path,"rb")as f:
response = client.audio.transcriptions.create(file=f,
model=Config.MODEL_NAME,
response_format="text",
stream=True)
transcription =""
progress_bar = st.progress(0)
status_text = st.empty()# Collect all chunks first to get total count
chunks =list(response)
total_chunks =len(chunks)for i, chunk inenumerate(chunks):
delta = chunk.choices[0].get("delta",{}).get("content")if delta:
transcription += delta
progress =min((i +1)/max(total_chunks,1),1.0)
progress_bar.progress(progress)
status_text.text(f"Transcribing... {len(transcription)} characters")
progress_bar.empty()
status_text.empty()return transcription
except Exception as e:
st.error(f"Error during transcription: {str(e)}")returnNoneMogelijk gemaakt door
Er zijn hier twee belangrijke functies:
Conversie naar audiochunk: Eerst converteren we het geüploade audiobestand naar het AudioChunk‑formaat, de vereiste invoer voor Voxtrals API.
Streamingtranscriptie met voortgangsfeedback: We sturen de audio gestreamd naar het model (stream=True) en decoderen hem chunk‑voor‑chunk. Een voortgangsbalk werkt dynamisch bij terwijl tokens binnenkomen, zodat gebruikers realtime feedback krijgen over de voortgang van de transcriptie.
Stap 4.4: Samenvatting uit audio genereren
Deze stap stuurt de audio‑invoer samen met een tekstuele prompt naar het Voxtral‑model, dat een beknopte, gestructureerde samenvatting van de audiocontent retourneert.
defgenerate_summary(client, audio_file_path):try:
audio_chunk = file_to_chunk(audio_file_path)
text_chunk = TextChunk(text="Please provide a comprehensive summary of this audio content, highlighting the key points and main themes discussed.")
user_msg = UserMessage(content=[audio_chunk, text_chunk]).to_openai()
response = client.chat.completions.create(
model=Config.MODEL_NAME,
messages=[user_msg],
temperature=Config.DEFAULT_TEMPERATURE,
top_p=Config.DEFAULT_TOP_P,)return response.choices[0].message.content
except Exception as e:
st.error(f"Error generating summary: {str(e)}")returnNoneMogelijk gemaakt door
De bovenstaande code gebruikt enkele kernmethoden en functies om een samenvatting te genereren uit de geüploade audio:
audio_chunk: Eerst converteren we het geüploade bestand naar een AudioChunk voor Voxtrals audioprocessing.
text_chunk: Vervolgens gebruiken we een tekstprompt om het model te instrueren de inhoud duidelijk en volledig samen te vatten.
UserMessage: Dit combineert de audio_chunk en text_chunk tot één multimodaal bericht in een OpenAI‑compatibel formaat.
Response.choices[0].message.content: Dit object haalt de daadwerkelijke samenvattingstekst uit het antwoord van het model.
Stap 4.5: Meertalige Q&A over audio
Nu we de samenvatting hebben, stellen we gebruikers in staat om natuurlijke taalvragen te stellen over de geüploade audiocontent. Dit benut Voxtrals multimodale capaciteiten door audio met tekstprompts te combineren om contextbewuste antwoorden te genereren.
De volgende functie ondersteunt ook meertalige antwoorden door de prompt dynamisch aan te passen op basis van de geselecteerde taal.
defask_question(client, audio_file_path, question, language="English"):try:
audio_chunk = file_to_chunk(audio_file_path)if language !="English":
question =f"Please answer the following question in {language}: {question}"
text_chunk = TextChunk(text=question)
user_msg = UserMessage(content=[audio_chunk, text_chunk]).to_openai()
response = client.chat.completions.create(
model=Config.MODEL_NAME,
messages=[user_msg],
temperature=Config.DEFAULT_TEMPERATURE,
top_p=Config.DEFAULT_TOP_P,)return response.choices[0].message.content
except Exception as e:
st.error(f"Error asking question: {str(e)}")returnNoneMogelijk gemaakt door
Dit is wat er hier gebeurt:
De functie ask_question() laat gebruikers elke vraag stellen over de geüploade audio.
Ze begint met het converteren van het geüploade bestand naar een AudioChunk met de herbruikbare functie file_to_chunk(), zodat de audio in het door Voxtrals multimodale API verwachte formaat staat.
Vervolgens controleert ze de geselecteerde taal. Als het niet Engels is, wordt de vraag van de gebruiker voorafgegaan door een instructie om in de gewenste taal te antwoorden (bijv. Hindi of Spaans).
De vraag van de gebruiker wordt verpakt in een TextChunk, en zowel audio als tekst worden gebundeld in een multimodaal UserMessage.
We sturen dit bericht naar het model, samen met temperature‑ en top‑p‑waarden uit de configuratie om de generatiekwaliteit te sturen.
Het model retourneert vervolgens een enkel antwoord.
Stap 4.6: De zijbalk instellen
De zijbalk fungeert als controlepaneel waarmee gebruikers sessie‑instellingen beheren, de uitvoertaal selecteren, de verbinding met de Voxtral‑API testen en het antwoordgedrag van het model aanpassen via intuïtieve sliders.
defrender_sidebar():with st.sidebar:
st.markdown('<h3 class="section-header">Configuration</h3>', unsafe_allow_html=True)# Connection status
st.markdown('<h4>Connection Status</h4>', unsafe_allow_html=True)if st.button("Test Connection"):
client = initialize_client()if client:
st.success("Connected to Voxtral API")else:
st.error("Connection failed")# Language selection
selected_language = st.selectbox("Select language for Q&A:", Config.SUPPORTED_LANGUAGES)# Model configuration
st.markdown('<h4>Model Settings</h4>', unsafe_allow_html=True)
temperature = st.slider("Temperature",0.0,1.0, Config.DEFAULT_TEMPERATURE,0.1)
top_p = st.slider("Top P",0.0,1.0, Config.DEFAULT_TOP_P,0.05)if st.button("Clear Session"):for key in['transcription','summary','chat_history','audio_file_path']:
st.session_state[key]=""if key in['transcription','summary']else[]if key =='chat_history'elseNone
st.rerun()return selected_language, temperature, top_pMogelijk gemaakt door
Uitleg bij de bovenstaande code:
Zijbalk: Met st.sidebar openen we een inklapbare zijbalk waarin we configuratietools voor de app plaatsen.
Verbindingstest: Een knop “Test Connection” triggert de functie initialize_client(), die probeert verbinding te maken met de Voxtral‑API en succes of falen meldt met Streamlit‑alerts.
Taalkeuze: Een dropdown laat gebruikers een van de 12 ondersteunde talen kiezen. Deze keuze bepaalt later in welke taal het model antwoordt.
Modelparameters: Met een slider kan de gebruiker parameters sturen zoals:
temperature: Stuurt creativiteit. Lagere waarden maken antwoorden deterministischer, hogere waarden gevarieerder.
top_p: Stuurt nucleus sampling, wat de generatie beperkt tot de meest waarschijnlijke tokens.
Sessiereset: Met “Clear Session” reset je alle sessiestatusvariabelen en start je de app opnieuw.
Stap 4.7: Sectie voor uploaden en verwerken van audio
In deze sectie kunnen gebruikers audiobestanden uploaden (zoals .mp3, .wav, enz.), die tijdelijk worden opgeslagen. Na uploaden kunnen ze kiezen om de audio te transcriberen of een samenvatting op hoog niveau te genereren.
We hebben een modulaire structuur nodig voor eenvoudig uploaden, verwerken en het persistent opslaan van resultaten tijdens interacties. Zo heb ik het gedaan:
Bestandsuploader: Eerst hebben we een drag‑en‑drop uploader nodig die meerdere audioformaten accepteert zoals gedefinieerd in Config.SUPPORTED_AUDIO_FORMATS. Na uploaden wordt het bestand naar een tijdelijk bestand geschreven en opgeslagen in st.session_state.audio_file_path.
Client‑initialisatie: Er wordt een Voxtral‑compatibele client geïnitialiseerd om samenvatten en transcriberen mogelijk te maken.
Knoppen voor samenvatting en transcriptie: Vervolgens definiëren we twee knoppen:
Generate summary: Stuurt bij klikken de geüploade audio naar het model met een samenvattingsprompt. Er verschijnt een spinner en bij succes wordt de output opgeslagen in st.session_state.summary.
Transcribe audio: Stuurt het audiobestand naar de transcriptie‑endpoint. Realtime voortgang wordt getoond met een spinner en het resultaat wordt opgeslagen in st.session_state.transcription.
Tot slot worden beide resultaten weergegeven in een tekstvak.
Stap 4.8: Interactieve meertalige Q&A
Deze stap laat gebruikers vragen stellen over de geüploade audio in meerdere talen (bijv. Engels, Hindi, Spaans). De geselecteerde taal wordt gebruikt om het antwoord van het model te formatteren, en elk vraag‑antwoordpaar wordt opgeslagen in een door de sessie beheerde gespreksgeschiedenis en weergegeven met chatballonnen.
defrender_qa_section(selected_language):
st.markdown('<h3 class="section-header">Multilingual Q&A</h3>', unsafe_allow_html=True)if st.session_state.audio_file_path:
st.markdown(f'<div class="info-box">Selected language: <strong>{selected_language}</strong></div>', unsafe_allow_html=True)
question = st.text_input(f"Ask a question about the audio (in {selected_language}):",
placeholder="e.g., What is the main topic discussed?")if st.button("Ask Question",type="primary")and question:
client = initialize_client()with st.spinner("Processing your question..."):
answer = ask_question(client, st.session_state.audio_file_path, question, selected_language)if answer:# Chat history
st.session_state.chat_history.append({"question": question,"answer": answer,"language": selected_language,"timestamp": time.strftime("%H:%M:%S")})
st.success("Question answered!")else:
st.error("Failed to get answer. Please try again.")if st.session_state.chat_history:
st.markdown('<h4>Conversation History</h4>', unsafe_allow_html=True)for chat inreversed(st.session_state.chat_history):
st.markdown(f'<div class="chat-message user-message"><strong>Question:</strong> {chat["question"]}</div>', unsafe_allow_html=True)
st.markdown(f'<div class="chat-message assistant-message"><strong>Answer:</strong> {chat["answer"]}</div>', unsafe_allow_html=True)
st.markdown("---")else:
st.markdown('<div class="info-box">Please upload an audio file to start asking questions.</div>', unsafe_allow_html=True)Mogelijk gemaakt door
Uitleg bij de bovenstaande code:
Ask Question‑knop: Een tekstveld laat gebruikers een vraag typen in de geselecteerde taal en op de knop Ask Question klikken. Na klikken wordt:
De Voxtral‑compatibele client geïnitialiseerd.
De vraag samen met de geüploade audio naar het model gestuurd.
Een spinner getoond terwijl je wacht op het antwoord van het model.
Afhandeling van antwoorden: Als er een antwoord binnenkomt, wordt het:
Opgeslagen in st.session_state.chat_history met een timestamp.
Weergegeven met rol‑specifieke opmaak met de eerdere aangepaste CSS (gebruiker vs. assistent).
Als het model faalt, verschijnt een duidelijke foutmelding.
Gespreksgeschiedenis: Als er eerdere Q&A‑paren zijn, worden die in omgekeerd chronologische volgorde getoond met een scheiding.
Stap 4.9: De app starten
Deze laatste stap brengt alle eerder gedefinieerde componenten samen, waaronder het initialiseren van de sessiestatus, het renderen van de zijbalk, het afhandelen van uploads, transcripties, samenvattingen en Q&A met een tweekoloms‑lay‑out.
Zodra de server draait en alle dependencies zijn geïnstalleerd, zorgt deze stap ervoor dat de app via Streamlit in de browser wordt bediend en klaar is voor interactie.
defmain():
st.markdown('<h1 class="main-header">🎵 Voxtral Audio Assistant</h1>', unsafe_allow_html=True)# Initialize session state
init_session_state()# Render sidebar and get configuration
selected_language, temperature, top_p = render_sidebar()
col1, col2 = st.columns([1,1])with col1:
render_audio_processing()with col2:
render_qa_section(selected_language)
st.markdown("---")
st.markdown("""
<div style="text-align: center;">
<p>Powered by <strong>Voxtral Mini 3B</strong> | Built with Streamlit</p>
<p>Supports multiple languages for audio analysis and Q&A</p>
</div>
""", unsafe_allow_html=True)if __name__ =="__main__":
main()Mogelijk gemaakt door
De functie main() fungeert als instappunt voor de app. Ze beheert de lay‑out, regelt het renderen en zorgt dat alle sessievariabelen en UI‑componenten correct zijn geïnitialiseerd. Dit is een samenvatting van wat de hierboven gedefinieerde functies doen:
init_session_state(): Bereidt standaardwaarden voor zoals transcription, summary en chat_history om de app‑status te behouden tijdens interacties.
render_sidebar(): Laadt configuratiewidgets zoals de taalselector, verbindingstest en modelparameters.
render_audio_processing(): Laat gebruikers audiobestanden uploaden en verwerken voor transcriptie en samenvatting.
render_qa_section(): Maakt ten slotte meertalig vraag‑en‑antwoord mogelijk op geüploade audio.
Zorg dat hij bereikbaar is via de URL die is opgegeven in VOXTRAL_API_BASE in je config.py. Zodra alle dependencies zijn geïnstalleerd, start je de Streamlit‑applicatie met de volgende opdracht in de terminal:
Je browser opent de interface automatisch. De app is nu volledig functioneel met audio‑upload, realtime transcriptie, samenvattingen en meertalige Q&A, aangedreven door Voxtral Mini 3B.
Je vindt alle code die we hier hebben behandeld in deze GitHub‑repository die ik heb opgezet.
Conclusie
Voxtral Mini 3B is een efficiënt, open‑weight model voor spraaktranscriptie en ‑begrip. In deze tutorial hebben we het gedraaid met vLLM, een API opgezet en een audio‑samenvattingsapp gebouwd met Streamlit.
Of je nu een podcast‑samenvatter, vergaderassistent of spraakcommando‑app bouwt, Voxtral Mini kan dienen als fundament voor snelle en lokale audioredenatie.
Ik ben een Google Developers Expert in ML (Gen AI), een Kaggle 3x Expert en een Women Techmakers Ambassador met meer dan 3 jaar ervaring in tech. In 2020 heb ik een healthtech-startup mee opgericht en ik volg een master computer science aan Georgia Tech, met als specialisatie machine learning.
Mistral lanceerde onlangs zijn eerste open-source multimodale audiomodellen, Voxtral Small en Voxtral Mini, gebouwd op de Mistral 3B‑architectuur en specifiek geoptimaliseerd voor taken rond audiobegrip en transcriptie.
In deze blog richt ik me op Voxtral Mini 3B, een compact open‑source model ontworpen voor realtime audio-naar-tekst taken zoals transcriptie, samenvatting en Q&A. Dankzij het efficiënte formaat en ondersteuning voor redeneren met lange context is Voxtral Mini bijzonder krachtig in combinatie met high-throughput inference-frameworks zoals vLLM, wat het ideaal maakt voor snelle, offline audio-applicaties.
In deze tutorial laat ik je zien hoe je:
We houden onze lezers op de hoogte van het laatste AI‑nieuws met The Median, onze gratis vrijdagse nieuwsbrief met de belangrijkste verhalen van de week. Abonneer je en blijf scherp in een paar minuten per week:
Wat is Mistrals Voxtral?
Voxtral is Mistrals volledig open‑source audiomodelfamilie, ontworpen voor krachtige spraakbegrip. Voxtral is er in twee modelgroottes:
Bron: Mistral
Voxtral accepteert ruwe audio-invoer (zoals .wav of .mp3) en is getraind om efficiënt transcripties en samenvattingen te genereren uit gesproken content. Voxtral is een kleinere variant, geoptimaliseerd voor snelle inference en offline deployment.
Het volgt Mistrals modelformaat en is compatibel met high-throughput inference‑frameworks zoals vLLM, waardoor het een uitstekende keuze is voor realtime transcriptie of lichtgewicht spraaktoepassingen.
Voxtral Mini 3B uitvoeren met vLLM
In deze sectie laat ik je zien hoe je Voxtral Mini 3B serveert met vLLM op een Colab Pro met T4‑GPU ingeschakeld. vLLM is gekozen vanwege de high-throughput, lage-latentie serveercapaciteiten, ideaal voor modellen zoals Voxtral die snelle streamingantwoorden met audio-ondersteuning vereisen.
Daarnaast gebruiken we PyNGrok om de vLLM‑server via een publiek endpoint bloot te stellen, zodat deze toegankelijk is voor applicaties op je lokale machine.
Stap 1: Dependencies installeren
Laten we beginnen met het installeren van de dependencies in onze Colab‑omgeving. Voer de volgende opdracht uit in de Colab‑cel:
We beginnen met het installeren van de vereiste libraries met uv, een snellere Python‑pakketinstaller. Dit haalt de nightly‑versie van
vllm[audio]op, die experimentele ondersteuning bevat voor audio‑taalmodellen zoals Voxtral. Als jeuvniet in je omgeving hebt geïnstalleerd, installeer dan eerstuvmet de volgende code:Stap 2: Mistral-Common installeren
Vervolgens installeren we het pakket
mistral-common, dat essentiële utilities biedt om met Voxtral en andere modellen uit de Mistral‑familie te werken. Dit pakket bevat tokenizers die aansluiten op de officiële implementaties en Pydantic‑gebaseerde validatie voor berichtstructuren.Het pakket mistral-common bevat utility‑modules voor Voxtral en andere modellen uit de Mistral‑familie. Het omvat tokenizers, getypeerde berichten in Pydantic‑formaten en audio‑hulpfuncties. Deze stap zorgt voor compatibiliteit met Voxtrals interne verwerking van audio-invoer en gestructureerde berichten.
Stap 3: VLLM instellen
Nu de basis‑dependencies voor Mistral klaar zijn, richten we vLLM in door de hoofdrepository te clonen.
Stap 3.1: De vLLM‑repository klonen
We clonen de officiële vLLM‑GitHub‑repository, die toegang geeft tot ingebouwde audio‑voorbeelden en dient als basis om offline of gehoste inference te starten.
Stap 3.2: Een voorbeeld van audio‑inference uitvoeren
Laten we een snelle sanity check doen om te controleren of onze setup klopt.
Ik draaide het offline‑voorbeeld
audio_language.py, dat audio‑taalinference uitvoert op twee vooraf gedefinieerde samples met het Voxtral‑model en bevestigt of audiodecodering en generatie correct werken.Stap 4: PyGrok instellen
Nu vLLM is ingesteld, configureren we PyNGrok om de vLLM‑server op Colab via een publiek toegankelijke internet‑URL beschikbaar te maken.
Vervolgens installeren we PyNGrok in de colab‑omgeving en stellen we de authenticatietoken in met de NGROK‑token die we eerder hebben gekopieerd. Werk je aan een prototype, dan kun je de token hier direct doorgeven.
Stap 5: Het model serven
Dit is de belangrijkste stap, waarin we het Voxtral Mini 3B‑model starten via vLLM.
De code bevat een aantal belangrijke flags:
--tokenizer_mode mistral: Gebruikt de Mistral‑specifieke tokenizer voor nauwkeurige tokenisatie.--config_format mistralen--load_format mistral: Deze flags zorgen ervoor dat zowel de modelconfiguratie als de gewichten in Mistrals aangepaste formaat worden geladen, zodat de compatibiliteit behouden blijft.--max-model-len 4864: Stelt de maximale invoercontextlengte in op 4864 tokens.Let op: laat deze cel actief, dit is een draaiende modelserver.
Stap 6: Het publieke NGrok‑endpoint ophalen
Zodra je vLLM‑server draait, voer je de volgende code regel voor regel uit in een Python‑terminal:
De bovenstaande code stelt het model bloot aan het internet op een tijdelijke publieke URL zoals:
Sla deze URL op; die gebruik je in de lokale
config.pyom verbinding te maken met het externe model. Beëindig na afloop de verbinding door:Een demo voor audiotranscriptie en samenvatting bouwen
In deze sectie bouwen we een Streamlit‑UI die:
Stap 1: Dependencies instellen
Voordat we de app bouwen, definiëren we alle vereiste dependencies in een
requirements.txt‑bestand. Dit zorgt voor consistente omgevingen bij lokale runs of Colab‑notebooks.Daarom hebben we elk van deze nodig:
AudioChunkenTextChunk.Stap 2: De omgevingsvariabele instellen
Om de configuratie overzichtelijk en draagbaar te houden, slaan we API‑gegevens op als omgevingsvariabelen. Je kunt ze definiëren in een
.env‑bestand:VOXTRAL_API_BASEmoet wijzen naar je draaiende vLLM‑instantie, wat localhost kan zijn (http://localhost:8000) of een ngrok‑public endpoint zoals https://80xxxxxxxxxx.ngrok-free.app.Let op: zorg dat je
/v1achter de API‑basis plakt voor OpenAI‑compatibiliteit.Stap 3: Het config‑bestand instellen
Om je app modulair, eenvoudig aanpasbaar en klaar voor productie te maken, definiëren we een centrale configuratieklasse in
config.py. Dit bestand beheert modelinstellingen, API‑toegang, ondersteunde audioformaten, talen en UI‑voorkeuren.Stap 3.1: Omgevingsvariabelen laden
Voordat we de config‑klasse definiëren, laden we eventuele omgevingsvariabelen uit een
.env‑bestand. Zo houd je gevoelige info buiten de code.Deze snippet controleert of er een
.env‑bestand in de hoofdmap staat. Zo ja, dan leest hij sleutel‑waardeparen en zet die als omgevingsvariabelen. Deze waarden zijn nu toegankelijk metos.getenv(), zodat secrets niet hardcoded in de app belanden.Stap 3.2: De Config‑klasse definiëren
Nu bundelen we alle instellingen in een overzichtelijke
Config‑klasse voor gemakkelijke toegang en hergebruik.Samen fungeert deze
Config‑klasse als het gecentraliseerde controlecentrum voor je Voxtral‑app. Of je nu modelparameters configureert, audioformaten beheert of het app‑thema instelt: deze opzet zorgt voor een nette abstractie, herbruikbaarheid en onderhoudbaarheid van de code.De klasse bevat:
get_api_config()‑methode: Deze methode centraliseert alle API‑gerelateerde gegevens. Waar je app ook een call naar het Voxtral‑model maakt, je kunt simpelweg Config.get_api_config() gebruiken om alles in één keer op te halen.validate_config()‑methode: Voor je inference start, kun je hiermee controleren of essentiële configuratiewaarden (zoals de basis‑URL) correct zijn ingesteld. Zo kun je problemen vroegtijdig opvangen en de gebruiker waarschuwen.get_language_code()‑methode: Hiermee schakel je naadloos meertalige Q&A in door gebruiksvriendelijke talenamen uit de UI (bijv. “French”) te mappen naar gestandaardiseerde ISO‑taalcodes (bijv. “fr”). Als een niet‑ondersteunde taal wordt doorgegeven, retourneert deze veilig None.Stap 4: De Streamlit‑app bouwen
We doorlopen elke sub‑stap die de interface en logica van de app opbouwt.
Stap 4.1: Lay‑out en styling instellen
In deze stap initialiseren we de Streamlit‑frontend, laden we dependencies en stellen we de CSS‑stijl in. Dit vormt de visuele en functionele basis van de app.
In de bovenstaande Python‑ en CSS‑code:
mistral_common‑pakket.Stap 4.2: Sessie en client initialiseren
Vervolgens zorgen we dat de app consistent werkt bij herladen door sessievariabelen en de client te initialiseren.
Deze code zet de interne status van de applicatie op en behandelt de verbinding met de Voxtral‑API‑server. Twee kernonderdelen:
Stap 4.3: Audio chunking en realtime transcriptie
Deze stap verzorgt de kernlogica voor het voorbereiden van het audiobestand en het genereren van een transcriptie met Voxtral Mini 3B.
Er zijn hier twee belangrijke functies:
AudioChunk‑formaat, de vereiste invoer voor Voxtrals API.stream=True) en decoderen hem chunk‑voor‑chunk. Een voortgangsbalk werkt dynamisch bij terwijl tokens binnenkomen, zodat gebruikers realtime feedback krijgen over de voortgang van de transcriptie.Stap 4.4: Samenvatting uit audio genereren
Deze stap stuurt de audio‑invoer samen met een tekstuele prompt naar het Voxtral‑model, dat een beknopte, gestructureerde samenvatting van de audiocontent retourneert.
De bovenstaande code gebruikt enkele kernmethoden en functies om een samenvatting te genereren uit de geüploade audio:
audio_chunk: Eerst converteren we het geüploade bestand naar eenAudioChunkvoor Voxtrals audioprocessing.text_chunk: Vervolgens gebruiken we een tekstprompt om het model te instrueren de inhoud duidelijk en volledig samen te vatten.UserMessage: Dit combineert deaudio_chunkentext_chunktot één multimodaal bericht in een OpenAI‑compatibel formaat.Response.choices[0].message.content: Dit object haalt de daadwerkelijke samenvattingstekst uit het antwoord van het model.Stap 4.5: Meertalige Q&A over audio
Nu we de samenvatting hebben, stellen we gebruikers in staat om natuurlijke taalvragen te stellen over de geüploade audiocontent. Dit benut Voxtrals multimodale capaciteiten door audio met tekstprompts te combineren om contextbewuste antwoorden te genereren.
De volgende functie ondersteunt ook meertalige antwoorden door de prompt dynamisch aan te passen op basis van de geselecteerde taal.
Dit is wat er hier gebeurt:
ask_question()laat gebruikers elke vraag stellen over de geüploade audio.AudioChunkmet de herbruikbare functiefile_to_chunk(), zodat de audio in het door Voxtrals multimodale API verwachte formaat staat.TextChunk, en zowel audio als tekst worden gebundeld in een multimodaalUserMessage.Stap 4.6: De zijbalk instellen
De zijbalk fungeert als controlepaneel waarmee gebruikers sessie‑instellingen beheren, de uitvoertaal selecteren, de verbinding met de Voxtral‑API testen en het antwoordgedrag van het model aanpassen via intuïtieve sliders.
Uitleg bij de bovenstaande code:
st.sidebaropenen we een inklapbare zijbalk waarin we configuratietools voor de app plaatsen.initialize_client(), die probeert verbinding te maken met de Voxtral‑API en succes of falen meldt met Streamlit‑alerts.temperature: Stuurt creativiteit. Lagere waarden maken antwoorden deterministischer, hogere waarden gevarieerder.top_p: Stuurt nucleus sampling, wat de generatie beperkt tot de meest waarschijnlijke tokens.Stap 4.7: Sectie voor uploaden en verwerken van audio
In deze sectie kunnen gebruikers audiobestanden uploaden (zoals .mp3, .wav, enz.), die tijdelijk worden opgeslagen. Na uploaden kunnen ze kiezen om de audio te transcriberen of een samenvatting op hoog niveau te genereren.
We hebben een modulaire structuur nodig voor eenvoudig uploaden, verwerken en het persistent opslaan van resultaten tijdens interacties. Zo heb ik het gedaan:
Config.SUPPORTED_AUDIO_FORMATS. Na uploaden wordt het bestand naar een tijdelijk bestand geschreven en opgeslagen inst.session_state.audio_file_path.st.session_state.summary.st.session_state.transcription.Stap 4.8: Interactieve meertalige Q&A
Deze stap laat gebruikers vragen stellen over de geüploade audio in meerdere talen (bijv. Engels, Hindi, Spaans). De geselecteerde taal wordt gebruikt om het antwoord van het model te formatteren, en elk vraag‑antwoordpaar wordt opgeslagen in een door de sessie beheerde gespreksgeschiedenis en weergegeven met chatballonnen.
Uitleg bij de bovenstaande code:
Ask Question‑knop: Een tekstveld laat gebruikers een vraag typen in de geselecteerde taal en op de knop Ask Question klikken. Na klikken wordt:st.session_state.chat_historymet een timestamp.Stap 4.9: De app starten
Deze laatste stap brengt alle eerder gedefinieerde componenten samen, waaronder het initialiseren van de sessiestatus, het renderen van de zijbalk, het afhandelen van uploads, transcripties, samenvattingen en Q&A met een tweekoloms‑lay‑out.
Zodra de server draait en alle dependencies zijn geïnstalleerd, zorgt deze stap ervoor dat de app via Streamlit in de browser wordt bediend en klaar is voor interactie.
De functie
main()fungeert als instappunt voor de app. Ze beheert de lay‑out, regelt het renderen en zorgt dat alle sessievariabelen en UI‑componenten correct zijn geïnitialiseerd. Dit is een samenvatting van wat de hierboven gedefinieerde functies doen:init_session_state(): Bereidt standaardwaarden voor zoalstranscription,summaryenchat_historyom de app‑status te behouden tijdens interacties.render_sidebar(): Laadt configuratiewidgets zoals de taalselector, verbindingstest en modelparameters.render_audio_processing(): Laat gebruikers audiobestanden uploaden en verwerken voor transcriptie en samenvatting.render_qa_section(): Maakt ten slotte meertalig vraag‑en‑antwoord mogelijk op geüploade audio.Als alles klaar is, start je de app met:
Zorg dat hij bereikbaar is via de URL die is opgegeven in
VOXTRAL_API_BASEin jeconfig.py. Zodra alle dependencies zijn geïnstalleerd, start je de Streamlit‑applicatie met de volgende opdracht in de terminal:Je browser opent de interface automatisch. De app is nu volledig functioneel met audio‑upload, realtime transcriptie, samenvattingen en meertalige Q&A, aangedreven door Voxtral Mini 3B.