Mistral ha recentemente lanciato i suoi primi modelli audio multimodali open-source, Voxtral Small e Voxtral Mini, basati sull’architettura Mistral 3B e ottimizzati specificamente per attività di comprensione e trascrizione audio.
In questo blog mi concentrerò su Voxtral Mini 3B, un modello compatto e open-source progettato per compiti audio‑to‑text in tempo reale come trascrizione, riassunto e Q&A. Con le sue dimensioni efficienti e il supporto per il ragionamento su contesti lunghi, Voxtral Mini è particolarmente potente se abbinato a framework di inferenza ad alto throughput come vLLM, risultando ideale per creare applicazioni audio veloci e offline.
In questo tutorial ti mostrerò come:
Eseguire Voxtral Mini 3B con vLLM su Colab Pro
Distribuire un endpoint API tramite tunnel ngrok per accedere al modello da ovunque
Creare un assistente audio con Streamlit che esegue trascrizione, riassunto e Q&A usando input audio grezzi
Teniamo aggiornatɜ lɜ nostrɜ lettorɜ sulle ultime novità dell’AI inviando The Median, la nostra newsletter gratuita del venerdì che riassume le notizie chiave della settimana. Iscriviti e resta sul pezzo in pochi minuti a settimana:
Che cos’è Voxtral di Mistral?
Voxtral è la famiglia di modelli audio completamente open source di Mistral progettata per una potente comprensione del parlato. Voxtral è disponibile in due dimensioni:
Voxtral Small: 24 B di parametri, ideale per l’uso enterprise in produzione
Voxtral Mini: 3 B di parametri, ottimizzato per l’esecuzione in locale su dispositivi edge
Voxtral accetta input audio grezzi (come .wav o .mp3) ed è addestrato per generare in modo efficiente trascrizioni e riassunti da contenuti parlati. Voxtral è una variante più piccola ottimizzata per inferenza rapida e deployment offline.
Segue il formato dei modelli Mistral ed è compatibile con framework di inferenza ad alto throughput come vLLM, il che lo rende un’ottima scelta per trascrizioni in tempo reale o applicazioni vocali leggere.
Come eseguire Voxtral Mini 3B con vLLM
In questa sezione ti spiegherò come servire Voxtral Mini 3B usando vLLM su un Colab Pro con GPU T4 abilitata. vLLM è stato scelto per le sue capacità di serving ad alto throughput e bassa latenza, ideali per modelli come Voxtral che richiedono risposte in streaming rapide con supporto audio.
Inoltre, useremo PyNGrok per esporre il server vLLM tramite un endpoint pubblico, rendendolo accessibile alle applicazioni in esecuzione sulla tua macchina locale.
Passaggio 1: Installa le dipendenze
Iniziamo installando le dipendenze nel nostro ambiente Colab. Esegui il seguente comando nella cella di Colab:
!uv pip install -U transformers accelerate "vllm[audio]"--torch-backend=auto --extra-index-url https://wheels.vllm.ai/nightlyOfferto da
Iniziamo installando le librerie richieste usando uv, un installer di pacchetti Python più veloce. Questo scarica la versione nightly di vllm[audio] che include il supporto sperimentale per modelli audio‑linguistici come Voxtral. Se non hai uv installato nel tuo ambiente, installalo prima eseguendo il seguente codice:
Successivamente, installiamo il pacchetto mistral-common, che fornisce utility essenziali per interagire con Voxtral e altri modelli della famiglia Mistral. Questo pacchetto include tokenizer allineati alle implementazioni ufficiali e validazione basata su Pydantic per le strutture dei messaggi.
!pip install mistral-common --upgrade
!python -c "import mistral_common; print(mistral_common.__version__)"Offerto da
Il pacchetto mistral-common contiene moduli di utilità per Voxtral e altri modelli della famiglia Mistral. Include tokenizer, messaggi tipizzati in formati Pydantic e funzioni di supporto audio. Questo passaggio garantisce la compatibilità con la gestione interna di Voxtral per input audio e messaggi strutturati.
Passaggio 3: Configura VLLM
Ora che abbiamo le dipendenze base di Mistral pronte, configuriamo vLLM clonandone il repository principale.
Passaggio 3.1: Clona il repository vLLM
Cloniamo l’repository GitHub ufficiale di vLLM, che ci dà accesso a esempi audio integrati e funge da base per avviare inferenza offline o hosted.
!git clone https://github.com/vllm-project/vllm && cd vllmOfferto da
Passaggio 3.2: Esegui un’inferenza audio di esempio
Facciamo un rapido sanity check per assicurarci che la configurazione sia corretta.
!python vllm/examples/offline_inference/audio_language.py --num-audios 2--model-type voxtralOfferto da
Ho eseguito l’esempio offline audio_language.py, che esegue inferenza audio‑linguistica su due campioni predefiniti usando il modello Voxtral e verifica che la decodifica e la generazione audio funzionino correttamente.
Passaggio 4: Configura PyGrok
Ora che vLLM è configurato, impostiamo PyNGrok per esporre il server vLLM su Colab tramite un indirizzo internet pubblicamente accessibile.
Scorri verso il basso nella scheda Connect, copia il tag di autenticazione (nascosto nell’immagine sotto) e salvalo come secret nei Colab Secrets.
Poi, installiamo PyNGrok nell’ambiente Colab e impostiamo il token di autenticazione usando il token NGROK copiato in precedenza. Se stai lavorando a un prototipo, puoi passare qui direttamente il token.
!pip install pyngrok -q
from pyngrok import ngrok
ngrok.set_auth_token("NGROK_TOKEN")Offerto da
Passaggio 5: Metti in serving il modello
Questo è il passaggio chiave, in cui avviamo il modello Voxtral Mini 3B tramite vLLM.
!vllm serve mistralai/Voxtral-Mini-3B-2507--tokenizer_mode mistral --config_format mistral --load_format mistral --max-model-len4864Offerto da
Lo snippet include diverse flag importanti:
--tokenizer_mode mistral: usa il tokenizer specifico di Mistral per una tokenizzazione accurata.
--config_format mistral e --load_format mistral: queste flag assicurano che sia la configurazione del modello sia i pesi vengano caricati nel formato personalizzato di Mistral, mantenendo la compatibilità.
--max-model-len 4864: imposta la massima lunghezza del contesto di input a 4864 token.
Nota: lascia in esecuzione questa cella perché è un server di modello attivo.
Passaggio 6: Ottieni l’endpoint pubblico NGrok
Una volta che il tuo server vLLM è in esecuzione, esegui il seguente codice riga per riga in un terminale Python:
from pyngrok import ngrok
ngrok.set_auth_token(NGROK_TOKEN)
public_url = ngrok.connect(8000)print("Public endpoint:", public_url)Offerto da
Il codice qui sopra esporrà il modello su internet a un URL pubblico temporaneo come:
In questa sezione costruiremo un’interfaccia Streamlit che:
Riceve audio in input (upload dell’utente)
Lo invia al modello tramite il server vLLM
Mostra la trascrizione, il riassunto e permette di fare domande
Passaggio 1: Configurare le dipendenze
Prima di creare l’app, definiamo tutte le dipendenze richieste in un file requirements.txt. Questo assicura ambienti consistenti tra esecuzioni locali o notebook Colab.
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 Offerto da
Ecco a cosa servono:
streamlit: libreria per costruire l’interfaccia audio interattiva.
openai: interfaccia il server vLLM compatibile con Voxtral usando l’SDK di OpenAI.
mistral-common: fornisce utility specifiche di Voxtral come AudioChunk e TextChunk.
pyngrok: espone il nostro server vLLM locale a internet, permettendo all’app Streamlit di accedervi.
Pydub: libreria per convertire file audio per l’inferenza.
huggingface-hub e requests: usate per recuperare modelli e configurazioni (se necessario).
Passaggio 2: Impostare la variabile d’ambiente
Per mantenere una configurazione pulita e portabile, salviamo i dettagli dell’API come variabili d’ambiente. Puoi definirle in un file .env:
VOXTRAL_API_KEY=dummy-key
VOXTRAL_API_BASE=NGROK_TOKEN/v1
VOXTRAL_MODEL_NAME=mistralai/Voxtral-Mini-3B-2507Offerto da
VOXTRAL_API_BASE deve puntare alla tua istanza vLLM in esecuzione, che può essere localhost (http://localhost:8000) o un endpoint pubblico ngrok del tipo https://80xxxxxxxxxx.ngrok-free.app.
Nota: Assicurati di aggiungere /v1 alla fine della base dell’API per la compatibilità con OpenAI.
Passaggio 3: Configurare il file di config
Per rendere la tua app modulare, facilmente regolabile e pronta per la produzione, definiremo una classe di configurazione centrale in config.py. Questo file controllerà impostazioni del modello, accesso all’API, formati audio supportati, lingue e preferenze della UI.
Passaggio 3.1: Caricare le variabili d’ambiente
Prima di definire la classe di configurazione, carichiamo eventuali variabili d’ambiente salvate in un file .env. Questo mantiene separate dal codice le informazioni sensibili.
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]= valueOfferto da
Questo snippet controlla se esiste un file .env nella directory root. Se trovato, legge le coppie chiave‑valore e le imposta come variabili d’ambiente. Questi valori sono poi accessibili tramite os.getenv(), evitando che i secret vengano hardcodati nell’app.
Passaggio 3.2: Definire la classe Config
Ora raccogliamo tutte le impostazioni in una chiara classe Config per un accesso e un riutilizzo semplici.
Insieme, questa classe Config funge da centro di controllo centralizzato per la tua app basata su Voxtral. Che tu stia configurando i parametri del modello, gestendo i formati audio o impostando il tema dell’app, questa struttura garantisce astrazione pulita, riusabilità del codice e manutenibilità.
La classe include:
Metodo get_api_config(): centralizza tutte le credenziali legate all’API. Ovunque l’app effettui una chiamata al modello Voxtral, puoi semplicemente usare Config.get_api_config() per recuperare tutto il necessario in un colpo solo.
Metodo validate_config(): prima di iniziare l’inferenza, permette di validare che i valori essenziali di configurazione (come la base URL) siano definiti correttamente. In caso contrario, puoi intercettare il problema in anticipo e avvisare l’utente.
Metodo get_language_code(): abilita un Q&A multilingue fluido mappando i nomi delle lingue dall’interfaccia (ad es. “French”) ai codici ISO standard (ad es. “fr”). Se viene passata una lingua non supportata, restituisce in modo sicuro None.
Passaggio 4: Costruisci l’app Streamlit
Vediamo passo passo i sotto-passaggi che compongono l’interfaccia e la logica dell’app.
Passaggio 4.1: Imposta il layout e lo stile
In questo passaggio inizializziamo il frontend Streamlit, carichiamo le dipendenze e impostiamo il CSS. Questo costituisce la base visiva e funzionale dell’app.
Importiamo le librerie essenziali per UI, gestione file e formattazione dei messaggi audio/testo usando il pacchetto mistral_common di Voxtral.
Configuriamo poi il layout dell’app Streamlit, un’interfaccia a due pannelli con una sidebar espansa di default.
Infine, iniettiamo CSS personalizzato per separare visivamente le varie parti della UI, come intestazioni, sezioni audio, messaggi in chat e riquadri di riepilogo. Questo migliora la gerarchia visiva dell’app con titoli stilizzati, messaggi informativi e balloon distinti per utente e assistente.
Passaggio 4.2: Inizializza sessione e client
Ora garantiamo un comportamento coerente dell’app tra i reload inizializzando variabili di sessione e client.
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")returnNoneOfferto da
Questo snippet imposta lo stato interno dell’app e gestisce la connessione al server API di Voxtral. Include due componenti chiave:
Inizializzazione della sessione: assicura che dati utente come trascrizioni, riassunti e file audio caricati esistano correttamente tra interazioni e ricariche dell’app.
Inizializzazione del client: si connette al modello Voxtral Mini 3B in hosting locale tramite l’endpoint compatibile con OpenAI esposto da vLLM (servito tramite Ngrok). In caso di errore, viene mostrato un messaggio nella UI.
Passaggio 4.3: Suddivisione audio e trascrizione in tempo reale
Questo passaggio gestisce la logica principale di preparazione del file audio e generazione di una trascrizione usando 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)}")returnNoneOfferto da
Qui ci sono due funzioni chiave:
Conversione in AudioChunk: prima convertiamo il file audio caricato nel formato AudioChunk, requisito di input per l’API di Voxtral.
Trascrizione in streaming con avanzamento: inviamo l’audio al modello in streaming (stream=True) e lo decodifichiamo chunk per chunk. Una barra di avanzamento si aggiorna dinamicamente man mano che arrivano i token, offrendo un feedback in tempo reale sull’avanzamento della trascrizione.
Passaggio 4.4: Generare un riassunto dall’audio
Questo passaggio invia l’input audio insieme a un prompt testuale al modello Voxtral, che restituisce un riassunto conciso e strutturato del contenuto audio.
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)}")returnNoneOfferto da
Il codice sopra usa diversi metodi e funzioni per generare un riassunto dall’audio caricato:
audio_chunk: per prima cosa convertiamo il file audio caricato in un AudioChunk per l’elaborazione audio di Voxtral.
text_chunk: poi, un prompt testuale istruisce il modello a riassumere il contenuto in modo chiaro e completo.
UserMessage: combina audio_chunk e text_chunk in un unico messaggio multimodale in formato compatibile con OpenAI.
Response.choices[0].message.content: questo oggetto estrae il testo del riassunto dalla risposta del modello.
Passaggio 4.5: Q&A multilingue sull’audio
Ora che abbiamo il riassunto, abilitiamo l’utente a porre domande in linguaggio naturale sul contenuto audio caricato. Questo sfrutta le capacità multimodali di Voxtral combinando audio e prompt testuali per generare risposte contestuali.
La seguente funzione supporta anche risposte multilingue modificando dinamicamente il prompt in base alla lingua selezionata.
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)}")returnNoneOfferto da
Ecco cosa succede nello snippet qui sopra:
La funzione ask_question() consente agli utenti di porre qualsiasi domanda sull’audio caricato.
Inizia convertendo il file caricato in un AudioChunk usando la funzione riutilizzabile file_to_chunk(), che prepara l’audio nel formato atteso dall’API multimodale di Voxtral.
Poi controlla la lingua selezionata. Se non è l’inglese, la domanda dell’utente viene prefissata con un’istruzione che chiede al modello di rispondere nella lingua desiderata (ad es. hindi o spagnolo).
La domanda dell’utente viene racchiusa in un TextChunk e sia l’audio che il testo vengono inseriti in un UserMessage multimodale.
Inviano quindi questo messaggio al modello, insieme a temperature e top‑p dalla configurazione per controllare la qualità della generazione.
Il modello restituisce una risposta single‑turn.
Passaggio 4.6: Configurare la sidebar
La sidebar funge da pannello di controllo, permettendo di gestire le impostazioni di sessione, selezionare la lingua di output, testare la connessione all’API di Voxtral e personalizzare il comportamento del modello con slider intuitivi.
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_pOfferto da
Ecco una panoramica del codice sopra:
Sidebar: l’oggetto st.sidebar apre una barra laterale comprimibile dove inseriamo gli strumenti di configurazione dell’app.
Test di connessione: un pulsante "Test Connection" richiama initialize_client(), che prova a connettersi all’API di Voxtral e segnala esito positivo o negativo tramite avvisi di Streamlit.
Selezione lingua: un menu a tendina consente di scegliere una delle 12 lingue supportate. Questa selezione informa in seguito il modello su quale lingua usare per rispondere.
Parametri del modello: degli slider permettono di controllare parametri come:
temperature: controlla la creatività. Valori più bassi rendono le risposte più deterministiche, quelli più alti più varie.
top_p: controlla il nucleus sampling, che limita la generazione ai token più probabili.
Reset della sessione: un pulsante "Clear Session" azzera tutte le variabili di stato e riavvia l’app per ripartire da zero.
Passaggio 4.7: Sezione di upload e processamento audio
Questa sezione permette agli utenti di caricare file audio (come .mp3, .wav, ecc.), che vengono salvati temporaneamente. Una volta caricato, l’utente può scegliere di trascrivere l’audio o generare un riassunto di alto livello.
Serve una struttura modulare per facilitare upload audio, processamento e memorizzazione persistente dei risultati tra le interazioni. Ecco come ho fatto:
Uploader di file: prima, un uploader drag‑and‑drop che accetta i formati definiti in Config.SUPPORTED_AUDIO_FORMATS. Una volta caricato, il file viene scritto in un file temporaneo e salvato in st.session_state.audio_file_path.
Inizializzazione client: viene inizializzato un client compatibile con Voxtral per consentire chiamate di riassunto e trascrizione.
Pulsanti per riassunto e trascrizione: definiamo due pulsanti:
Generate summary: quando cliccato, invia l’audio al modello con un prompt di riepilogo. Viene mostrato uno spinner e, se ha successo, l’output è salvato in st.session_state.summary.
Transcribe audio: invia il file audio all’endpoint di trascrizione. Lo stato di avanzamento è mostrato con uno spinner e il risultato viene salvato in st.session_state.transcription.
Infine, entrambi i risultati sono mostrati in un’area di testo.
Passaggio 4.8: Q&A interattivo multilingue
Questo passaggio consente di porre domande sul file audio caricato in più lingue (ad es. inglese, hindi, spagnolo). La lingua selezionata viene utilizzata per formattare la risposta del modello e ogni coppia domanda‑risposta è memorizzata nella cronologia conversazionale gestita dalla sessione e mostrata con balloon in stile chat.
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)Offerto da
Ecco una spiegazione dello snippet qui sopra:
Ask Question button: un campo di testo consente di digitare una domanda nella lingua selezionata e di cliccare il pulsante Ask Question. Una volta cliccato, il sistema:
Inizializza il client compatibile con Voxtral.
Invia la domanda insieme all’audio caricato al modello.
Mostra uno spinner mentre attende la risposta del modello.
Gestione della risposta: se viene ricevuta una risposta, essa viene:
Salvata in st.session_state.chat_history con un timestamp.
Visualizzata con formattazione specifica per ruolo usando il CSS personalizzato (balloon utente vs assistente).
Se il modello fallisce, viene mostrato un messaggio di errore chiaro.
Cronologia della conversazione: se esistono coppie Q&A precedenti, vengono mostrate in ordine cronologico inverso con un separatore.
Passaggio 4.9: Avvio dell’app
Questo passaggio finale riunisce tutti i componenti definiti in precedenza, inclusa l’inizializzazione dello stato di sessione, il rendering della sidebar, la gestione dell’upload audio, trascrizioni, riassunti e Q&A usando un layout a due colonne.
Una volta che il server è in esecuzione e tutte le dipendenze sono installate, questo passaggio assicura che l’app venga servita al browser tramite Streamlit ed è pronta all’uso.
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()Offerto da
La funzione main() funge da punto di ingresso dell’app. Controlla il layout, orchestra il rendering e assicura che tutte le variabili di sessione e i componenti UI siano inizializzati correttamente. Ecco un riepilogo delle funzioni definite sopra:
init_session_state(): prepara valori di default come transcription, summary e chat_history per mantenere lo stato dell’app tra le interazioni.
render_sidebar(): carica i widget di configurazione inclusi selettore della lingua, test di connessione e parametri del modello.
render_audio_processing(): consente di caricare e processare file audio per trascrizione e generazione del riassunto.
render_qa_section(): abilita infine il question answering multilingue sull’audio caricato.
Assicurati che sia accessibile tramite l’URL specificato in VOXTRAL_API_BASE nel tuo config.py. Una volta installate tutte le dipendenze, esegui l’applicazione Streamlit con il seguente comando nel terminale:
Il browser aprirà automaticamente l’interfaccia. L’app è ora pienamente funzionante con upload audio, trascrizione in tempo reale, riassunti e Q&A multilingue, il tutto alimentato da Voxtral Mini 3B.
Puoi trovare tutto il codice trattato qui in questo repository GitHub che ho preparato.
Conclusione
Voxtral Mini 3B è un modello efficiente e open‑weight per la trascrizione e la comprensione del parlato. In questo tutorial, lo abbiamo eseguito con vLLM, impostato un’API e creato un’app di riepilogo audio con Streamlit.
Che tu stia costruendo un riassuntore di podcast, un assistente per meeting o un’app di comandi vocali, Voxtral Mini può essere la base per un ragionamento audio veloce e locale.
Sono una Google Developers Expert in ML (Gen AI), una Kaggle 3x Expert e una Women Techmakers Ambassador con oltre 3 anni di esperienza nel tech. Ho co-fondato una startup health-tech nel 2020 e sto conseguendo un master in informatica al Georgia Tech, con specializzazione in machine learning.
Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Mistral ha recentemente lanciato i suoi primi modelli audio multimodali open-source, Voxtral Small e Voxtral Mini, basati sull’architettura Mistral 3B e ottimizzati specificamente per attività di comprensione e trascrizione audio.
In questo blog mi concentrerò su Voxtral Mini 3B, un modello compatto e open-source progettato per compiti audio‑to‑text in tempo reale come trascrizione, riassunto e Q&A. Con le sue dimensioni efficienti e il supporto per il ragionamento su contesti lunghi, Voxtral Mini è particolarmente potente se abbinato a framework di inferenza ad alto throughput come vLLM, risultando ideale per creare applicazioni audio veloci e offline.
In questo tutorial ti mostrerò come:
Teniamo aggiornatɜ lɜ nostrɜ lettorɜ sulle ultime novità dell’AI inviando The Median, la nostra newsletter gratuita del venerdì che riassume le notizie chiave della settimana. Iscriviti e resta sul pezzo in pochi minuti a settimana:
Che cos’è Voxtral di Mistral?
Voxtral è la famiglia di modelli audio completamente open source di Mistral progettata per una potente comprensione del parlato. Voxtral è disponibile in due dimensioni:
Fonte: Mistral
Voxtral accetta input audio grezzi (come .wav o .mp3) ed è addestrato per generare in modo efficiente trascrizioni e riassunti da contenuti parlati. Voxtral è una variante più piccola ottimizzata per inferenza rapida e deployment offline.
Segue il formato dei modelli Mistral ed è compatibile con framework di inferenza ad alto throughput come vLLM, il che lo rende un’ottima scelta per trascrizioni in tempo reale o applicazioni vocali leggere.
Come eseguire Voxtral Mini 3B con vLLM
In questa sezione ti spiegherò come servire Voxtral Mini 3B usando vLLM su un Colab Pro con GPU T4 abilitata. vLLM è stato scelto per le sue capacità di serving ad alto throughput e bassa latenza, ideali per modelli come Voxtral che richiedono risposte in streaming rapide con supporto audio.
Inoltre, useremo PyNGrok per esporre il server vLLM tramite un endpoint pubblico, rendendolo accessibile alle applicazioni in esecuzione sulla tua macchina locale.
Passaggio 1: Installa le dipendenze
Iniziamo installando le dipendenze nel nostro ambiente Colab. Esegui il seguente comando nella cella di Colab:
Iniziamo installando le librerie richieste usando uv, un installer di pacchetti Python più veloce. Questo scarica la versione nightly di
vllm[audio]che include il supporto sperimentale per modelli audio‑linguistici come Voxtral. Se non haiuvinstallato nel tuo ambiente, installalo prima eseguendo il seguente codice:Passaggio 2: Installa Mistral-Common
Successivamente, installiamo il pacchetto
mistral-common, che fornisce utility essenziali per interagire con Voxtral e altri modelli della famiglia Mistral. Questo pacchetto include tokenizer allineati alle implementazioni ufficiali e validazione basata su Pydantic per le strutture dei messaggi.Il pacchetto mistral-common contiene moduli di utilità per Voxtral e altri modelli della famiglia Mistral. Include tokenizer, messaggi tipizzati in formati Pydantic e funzioni di supporto audio. Questo passaggio garantisce la compatibilità con la gestione interna di Voxtral per input audio e messaggi strutturati.
Passaggio 3: Configura VLLM
Ora che abbiamo le dipendenze base di Mistral pronte, configuriamo vLLM clonandone il repository principale.
Passaggio 3.1: Clona il repository vLLM
Cloniamo l’repository GitHub ufficiale di vLLM, che ci dà accesso a esempi audio integrati e funge da base per avviare inferenza offline o hosted.
Passaggio 3.2: Esegui un’inferenza audio di esempio
Facciamo un rapido sanity check per assicurarci che la configurazione sia corretta.
Ho eseguito l’esempio offline
audio_language.py, che esegue inferenza audio‑linguistica su due campioni predefiniti usando il modello Voxtral e verifica che la decodifica e la generazione audio funzionino correttamente.Passaggio 4: Configura PyGrok
Ora che vLLM è configurato, impostiamo PyNGrok per esporre il server vLLM su Colab tramite un indirizzo internet pubblicamente accessibile.
Poi, installiamo PyNGrok nell’ambiente Colab e impostiamo il token di autenticazione usando il token NGROK copiato in precedenza. Se stai lavorando a un prototipo, puoi passare qui direttamente il token.
Passaggio 5: Metti in serving il modello
Questo è il passaggio chiave, in cui avviamo il modello Voxtral Mini 3B tramite vLLM.
Lo snippet include diverse flag importanti:
--tokenizer_mode mistral: usa il tokenizer specifico di Mistral per una tokenizzazione accurata.--config_format mistrale--load_format mistral: queste flag assicurano che sia la configurazione del modello sia i pesi vengano caricati nel formato personalizzato di Mistral, mantenendo la compatibilità.--max-model-len 4864: imposta la massima lunghezza del contesto di input a 4864 token.Nota: lascia in esecuzione questa cella perché è un server di modello attivo.
Passaggio 6: Ottieni l’endpoint pubblico NGrok
Una volta che il tuo server vLLM è in esecuzione, esegui il seguente codice riga per riga in un terminale Python:
Il codice qui sopra esporrà il modello su internet a un URL pubblico temporaneo come:
Salva questo URL, che verrà usato nel
config.pylocale per collegarsi al modello remoto. Al termine dell’esecuzione, termina la connessione eseguendo:Creare una demo di trascrizione e riassunto audio
In questa sezione costruiremo un’interfaccia Streamlit che:
Passaggio 1: Configurare le dipendenze
Prima di creare l’app, definiamo tutte le dipendenze richieste in un file
requirements.txt. Questo assicura ambienti consistenti tra esecuzioni locali o notebook Colab.Ecco a cosa servono:
AudioChunkeTextChunk.Passaggio 2: Impostare la variabile d’ambiente
Per mantenere una configurazione pulita e portabile, salviamo i dettagli dell’API come variabili d’ambiente. Puoi definirle in un file
.env:VOXTRAL_API_BASEdeve puntare alla tua istanza vLLM in esecuzione, che può essere localhost (http://localhost:8000) o un endpoint pubblico ngrok del tipo https://80xxxxxxxxxx.ngrok-free.app.Nota: Assicurati di aggiungere
/v1alla fine della base dell’API per la compatibilità con OpenAI.Passaggio 3: Configurare il file di config
Per rendere la tua app modulare, facilmente regolabile e pronta per la produzione, definiremo una classe di configurazione centrale in
config.py. Questo file controllerà impostazioni del modello, accesso all’API, formati audio supportati, lingue e preferenze della UI.Passaggio 3.1: Caricare le variabili d’ambiente
Prima di definire la classe di configurazione, carichiamo eventuali variabili d’ambiente salvate in un file
.env. Questo mantiene separate dal codice le informazioni sensibili.Questo snippet controlla se esiste un file
.envnella directory root. Se trovato, legge le coppie chiave‑valore e le imposta come variabili d’ambiente. Questi valori sono poi accessibili tramiteos.getenv(), evitando che i secret vengano hardcodati nell’app.Passaggio 3.2: Definire la classe Config
Ora raccogliamo tutte le impostazioni in una chiara classe
Configper un accesso e un riutilizzo semplici.Insieme, questa classe
Configfunge da centro di controllo centralizzato per la tua app basata su Voxtral. Che tu stia configurando i parametri del modello, gestendo i formati audio o impostando il tema dell’app, questa struttura garantisce astrazione pulita, riusabilità del codice e manutenibilità.La classe include:
get_api_config(): centralizza tutte le credenziali legate all’API. Ovunque l’app effettui una chiamata al modello Voxtral, puoi semplicemente usare Config.get_api_config() per recuperare tutto il necessario in un colpo solo.validate_config(): prima di iniziare l’inferenza, permette di validare che i valori essenziali di configurazione (come la base URL) siano definiti correttamente. In caso contrario, puoi intercettare il problema in anticipo e avvisare l’utente.get_language_code(): abilita un Q&A multilingue fluido mappando i nomi delle lingue dall’interfaccia (ad es. “French”) ai codici ISO standard (ad es. “fr”). Se viene passata una lingua non supportata, restituisce in modo sicuro None.Passaggio 4: Costruisci l’app Streamlit
Vediamo passo passo i sotto-passaggi che compongono l’interfaccia e la logica dell’app.
Passaggio 4.1: Imposta il layout e lo stile
In questo passaggio inizializziamo il frontend Streamlit, carichiamo le dipendenze e impostiamo il CSS. Questo costituisce la base visiva e funzionale dell’app.
Nel codice Python e CSS sopra:
mistral_commondi Voxtral.Passaggio 4.2: Inizializza sessione e client
Ora garantiamo un comportamento coerente dell’app tra i reload inizializzando variabili di sessione e client.
Questo snippet imposta lo stato interno dell’app e gestisce la connessione al server API di Voxtral. Include due componenti chiave:
Passaggio 4.3: Suddivisione audio e trascrizione in tempo reale
Questo passaggio gestisce la logica principale di preparazione del file audio e generazione di una trascrizione usando Voxtral Mini 3B.
Qui ci sono due funzioni chiave:
AudioChunk, requisito di input per l’API di Voxtral.stream=True) e lo decodifichiamo chunk per chunk. Una barra di avanzamento si aggiorna dinamicamente man mano che arrivano i token, offrendo un feedback in tempo reale sull’avanzamento della trascrizione.Passaggio 4.4: Generare un riassunto dall’audio
Questo passaggio invia l’input audio insieme a un prompt testuale al modello Voxtral, che restituisce un riassunto conciso e strutturato del contenuto audio.
Il codice sopra usa diversi metodi e funzioni per generare un riassunto dall’audio caricato:
audio_chunk: per prima cosa convertiamo il file audio caricato in unAudioChunkper l’elaborazione audio di Voxtral.text_chunk: poi, un prompt testuale istruisce il modello a riassumere il contenuto in modo chiaro e completo.UserMessage: combinaaudio_chunketext_chunkin un unico messaggio multimodale in formato compatibile con OpenAI.Response.choices[0].message.content: questo oggetto estrae il testo del riassunto dalla risposta del modello.Passaggio 4.5: Q&A multilingue sull’audio
Ora che abbiamo il riassunto, abilitiamo l’utente a porre domande in linguaggio naturale sul contenuto audio caricato. Questo sfrutta le capacità multimodali di Voxtral combinando audio e prompt testuali per generare risposte contestuali.
La seguente funzione supporta anche risposte multilingue modificando dinamicamente il prompt in base alla lingua selezionata.
Ecco cosa succede nello snippet qui sopra:
ask_question()consente agli utenti di porre qualsiasi domanda sull’audio caricato.AudioChunkusando la funzione riutilizzabilefile_to_chunk(), che prepara l’audio nel formato atteso dall’API multimodale di Voxtral.TextChunke sia l’audio che il testo vengono inseriti in unUserMessagemultimodale.Passaggio 4.6: Configurare la sidebar
La sidebar funge da pannello di controllo, permettendo di gestire le impostazioni di sessione, selezionare la lingua di output, testare la connessione all’API di Voxtral e personalizzare il comportamento del modello con slider intuitivi.
Ecco una panoramica del codice sopra:
st.sidebarapre una barra laterale comprimibile dove inseriamo gli strumenti di configurazione dell’app.initialize_client(), che prova a connettersi all’API di Voxtral e segnala esito positivo o negativo tramite avvisi di Streamlit.temperature: controlla la creatività. Valori più bassi rendono le risposte più deterministiche, quelli più alti più varie.top_p: controlla il nucleus sampling, che limita la generazione ai token più probabili.Passaggio 4.7: Sezione di upload e processamento audio
Questa sezione permette agli utenti di caricare file audio (come .mp3, .wav, ecc.), che vengono salvati temporaneamente. Una volta caricato, l’utente può scegliere di trascrivere l’audio o generare un riassunto di alto livello.
Serve una struttura modulare per facilitare upload audio, processamento e memorizzazione persistente dei risultati tra le interazioni. Ecco come ho fatto:
Config.SUPPORTED_AUDIO_FORMATS. Una volta caricato, il file viene scritto in un file temporaneo e salvato inst.session_state.audio_file_path.st.session_state.summary.st.session_state.transcription.Passaggio 4.8: Q&A interattivo multilingue
Questo passaggio consente di porre domande sul file audio caricato in più lingue (ad es. inglese, hindi, spagnolo). La lingua selezionata viene utilizzata per formattare la risposta del modello e ogni coppia domanda‑risposta è memorizzata nella cronologia conversazionale gestita dalla sessione e mostrata con balloon in stile chat.
Ecco una spiegazione dello snippet qui sopra:
Ask Questionbutton: un campo di testo consente di digitare una domanda nella lingua selezionata e di cliccare il pulsante Ask Question. Una volta cliccato, il sistema:st.session_state.chat_historycon un timestamp.Passaggio 4.9: Avvio dell’app
Questo passaggio finale riunisce tutti i componenti definiti in precedenza, inclusa l’inizializzazione dello stato di sessione, il rendering della sidebar, la gestione dell’upload audio, trascrizioni, riassunti e Q&A usando un layout a due colonne.
Una volta che il server è in esecuzione e tutte le dipendenze sono installate, questo passaggio assicura che l’app venga servita al browser tramite Streamlit ed è pronta all’uso.
La funzione
main()funge da punto di ingresso dell’app. Controlla il layout, orchestra il rendering e assicura che tutte le variabili di sessione e i componenti UI siano inizializzati correttamente. Ecco un riepilogo delle funzioni definite sopra:init_session_state(): prepara valori di default cometranscription,summaryechat_historyper mantenere lo stato dell’app tra le interazioni.render_sidebar(): carica i widget di configurazione inclusi selettore della lingua, test di connessione e parametri del modello.render_audio_processing(): consente di caricare e processare file audio per trascrizione e generazione del riassunto.render_qa_section(): abilita infine il question answering multilingue sull’audio caricato.Quando tutto è pronto, avvia l’app con:
Assicurati che sia accessibile tramite l’URL specificato in
VOXTRAL_API_BASEnel tuoconfig.py. Una volta installate tutte le dipendenze, esegui l’applicazione Streamlit con il seguente comando nel terminale:Il browser aprirà automaticamente l’interfaccia. L’app è ora pienamente funzionante con upload audio, trascrizione in tempo reale, riassunti e Q&A multilingue, il tutto alimentato da Voxtral Mini 3B.