Pular para o conteúdo principal

Voxtral da Mistral: Um guia com projeto de demonstração

Aprenda a usar o modelo Voxtral Mini 3B da Mistral com vLLM, configurar uma API e criar um resumidor de áudio e um aplicativo de perguntas e respostas baseados em Streamlit.
Atualizado 23 de jul. de 2025  · 12 min lido

A Mistral lançou recentemente seus primeiros modelos de áudio multimodal de código aberto, o Voxtral Small e o Voxtral Mini, que são baseados na arquitetura Mistral 3B e foram otimizados especialmente para tarefas de compreensão e transcrição de áudio.

Neste blog, vou focar no Voxtral Mini 3B, um modelo compacto e de código aberto feito pra tarefas de áudio pra texto em tempo real, tipo transcrição, resumo e perguntas e respostas. Com seu tamanho eficiente e suporte para raciocínio de contexto longo, o Voxtral Mini é super poderoso quando usado com estruturas de inferência de alto rendimento, como o vLLM, o que o torna ideal para criar aplicativos de áudio rápidos e offline.

Neste tutorial, vou te mostrar como:

  • Execute o Voxtral Mini 3B com vLLM no Colab Pro
  • Implemente um endpoint de API com túnel ngrok para acessar seu modelo de qualquer lugar
  • Crie um assistente de áudio baseado em Streamlit que faz transcrição, resumo e perguntas e respostas usando áudio bruto como entrada.

A gente mantém nossos leitores atualizados sobre as últimas novidades em IA enviando o The Median, nosso boletim informativo gratuito às sextas-feiras, que traz as principais notícias da semana. Inscreva-se e fique por dentro em só alguns minutos por semana:

O que é o Voxtral da Mistral?

Voxtral é a família de modelos de áudio totalmente open source da Mistral, feita pra entender super bem o que a gente fala.  O Voxtral está disponível em dois tamanhos:

  • : 24 parâmetros B, perfeito para uso em empresas e em escala de produção
  • Voxtral Mini: 3 parâmetros B, otimizados para rodar localmente em dispositivos de ponta dispositivos de ponta

benchmarks do mistral's voxtral

Fonte: Mistral

O Voxtral aceita áudio bruto (como .wav ou .mp3) e foi treinado pra gerar transcrições e resumos de conteúdo falado de um jeito eficiente. O Voxtral é uma versão menor, otimizada pra inferência rápida e implantação offline.

Segue o formato do modelo Mistral e é compatível com estruturas de inferência de alto rendimento, como vLLM, o que o torna uma excelente escolha para transcrição em tempo real ou aplicações de voz leves.

Como rodar o Voxtral Mini 3B usando o vLLM

Nesta seção, vou te mostrar como usar o Voxtral Mini 3B com o vLLM em um Colab Pro com GPU T4 ativada. O vLLM foi escolhido por causa da alta capacidade de processamento e baixa latência, que são ideais para modelos como o Voxtral, que precisam de respostas rápidas de streaming com suporte para áudio.

Além disso, vamos usar o PyNGrok para expor o servidor vLLM por meio de um endpoint público, tornando-o acessível para aplicativos em execução na sua máquina local.

Passo 1: Instalar dependências

Vamos começar instalando as dependências no nosso ambiente Colab. Execute o seguinte comando na célula Colab:

!uv pip install -U transformers accelerate "vllm[audio]" --torch-backend=auto --extra-index-url https://wheels.vllm.ai/nightly

Começamos instalando as bibliotecas necessárias usando o uv, um instalador de pacotes Python mais rápido. Isso pega a versão noturna do vllm[audio], que tem suporte experimental para modelos de linguagem de áudio como o Voxtral. Se você não tem o uv instalado no seu ambiente, primeiro instale o uv executando o seguinte código:

!pip install uv

Passo 2: Instalar Mistral-Common

Depois, a gente instala o pacote mistral-common, que tem os utilitários essenciais pra interagir com o Voxtral e outros modelos da família Mistral. Esse pacote inclui tokenizadores alinhados com implementações oficiais e validação baseada em Pydantic para estruturas de mensagens.

!pip install mistral-common --upgrade
!python -c "import mistral_common; print(mistral_common.__version__)"

O pacote mistral-common tem módulos úteis para o Voxtral e outros modelos da família Mistral. Inclui tokenizadores, mensagens digitadas nos formatos Pydantic e funções auxiliares de áudio. Essa etapa garante que tudo funcione bem com o jeito que o Voxtral lida com entradas de áudio e mensagens estruturadas.

Passo 3: Configurar o VLLM

Agora que já temos as dependências básicas do Mistral prontas, vamos configurar o vLLM clonando o repositório principal dele.

Passo 3.1: Clone o repositório vLLM

Clonamos o repositório GitHub oficial do vLLM, que nos dá acesso a exemplos de áudio integrados e serve como base para iniciar a inferência offline ou hospedada.

!git clone https://github.com/vllm-project/vllm && cd vllm

Passo 3.2: Executar uma inferência de áudio de amostra 

Vamos fazer uma checada rápida pra garantir que a nossa configuração tá certa.

!python vllm/examples/offline_inference/audio_language.py --num-audios 2 --model-type voxtral

Eu rodei o exemplo offline audio_language.py, que faz a inferência do idioma do áudio em duas amostras pré-definidas usando o modelo Voxtral e confirma se a decodificação e a geração do áudio estão funcionando direitinho.

Passo 4: Configurar o PyGrok

Com o vLLM já configurado, vamos configurar o PyNGrok para expor o servidor vLLM no Colab através de um endereço de internet acessível ao público.

  • Comece criando uma conta gratuita em https://ngrok.com/
  • Role pra baixo na aba “Conectar” e copie a tag de autenticação (escondida na imagem abaixo) e salve como um segredo nos Segredos do Colab.

NGrok Token

Depois, a gente instala o PyNGrok no ambiente colab e configura o token de autenticação usando o token NGROK que a gente copiou antes. Se você estiver trabalhando em um protótipo, pode passar o token diretamente aqui.

!pip install pyngrok -q
from pyngrok import ngrok
ngrok.set_auth_token("NGROK_TOKEN")

Passo 5: Sirva o modelo

Essa é a etapa principal, onde a gente lança o modelo Voxtral Mini 3B usando o vLLM. 

!vllm serve mistralai/Voxtral-Mini-3B-2507 --tokenizer_mode mistral --config_format mistral --load_format mistral --max-model-len 4864

O trecho de código tem várias coisas importantes:

  • --tokenizer_mode mistral: Isso usa o tokenizador específico do Mistral para uma tokenização precisa.
  • --config_format mistral e --load_format mistral: Essas flags garantem que tanto a configuração do modelo quanto os pesos sejam carregados no formato personalizado do Mistral, mantendo a compatibilidade.
  • --max-model-len 4864: Essa bandeira define o comprimento máximo do contexto de entrada para 4864 tokens.

Observação: Mantenha essa célula funcionando, pois este é um servidor modelo ativo.

Passo 6: Pega o endpoint público do NGrok

Depois que o servidor vLLM estiver funcionando, execute o seguinte código linha por linha em um terminal Python:

from pyngrok import ngrok
ngrok.set_auth_token(NGROK_TOKEN)
public_url = ngrok.connect(8000)
print("Public endpoint:", public_url)

O código acima vai deixar o modelo disponível na internet em um URL público temporário tipo:

https://80xxxxxxxxxx.ngrok-free.app

Salve este URL, que vai ser usado no config.py local para se conectar ao modelo remoto. Depois que a execução terminar, encerre a conexão executando:

ngrok.kill()

Criando uma demonstração de transcrição e resumo de áudio

Nesta seção, vamos criar uma interface Streamlit que:

  1. Pega áudio como entrada (carregado pelo usuário)
  2. Manda isso pro modelo pelo servidor vLLM
  3. Mostra a transcrição, o resumo e deixa o usuário fazer perguntas.

Passo 1: Configurando dependências

Antes de criar o aplicativo, a gente define todas as dependências necessárias em um arquivo chamado “ requirements.txt ”. Isso garante ambientes consistentes em execuções locais ou notebooks 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 

Eis porque precisamos de cada um deles:

  • streamlit: Essa biblioteca ajuda a criar uma interface de áudio interativa.
  • openai: faz a ponte com o servidor vLLM que dá certo com o Voxtral usando o SDK da OpenAI.
  • mistral-common: Ele oferece utilitários específicos do Voxtral, como AudioChunk e TextChunk.
  • pyngrok: Isso expõe nosso servidor vLLM local à internet, permitindo que o aplicativo Streamlit acesse-o.
  • Pydub: Essa biblioteca ajuda a converter arquivos de áudio para inferência.
  • huggingface-hub e solicitações: São usados para buscar modelos e configurações (se necessário).

Passo 2: Configurando a variável de ambiente

Para manter a configuração limpa e portátil, a gente guarda os detalhes da API como variáveis de ambiente. Você pode definir isso dentro de um arquivo .env:

VOXTRAL_API_KEY=dummy-key
VOXTRAL_API_BASE=NGROK_TOKEN/v1
VOXTRAL_MODEL_NAME=mistralai/Voxtral-Mini-3B-2507

VOXTRAL_API_BASE deve apontar para a sua instância vLLM em execução, que pode ser localhost (http://localhost:8000) ou um endpoint público ngrok semelhante a https://80xxxxxxxxxx.ngrok-free.app.

Observação: Certifique-se de adicionar /v1 no final da base da API para compatibilidade com OpenAI.

Passo 3: Configurando o arquivo de configuração

Para deixar seu aplicativo modular, fácil de ajustar e pronto para produção, vamos definir uma classe de configuração central em config.py. Esse arquivo controla as configurações do modelo, o acesso à API, os formatos de áudio compatíveis, os idiomas e as preferências da interface do usuário.

Passo 3.1: Carregar variáveis de ambiente

Antes de definir a classe config, carregamos todas as variáveis de ambiente salvas em um arquivo .env. Isso mantém as informações confidenciais separadas do código.

import os
from typing import Optional
from pathlib import Path
# Load environment variables from .env file
env_file = Path(".env")
if env_file.exists():
    with open(env_file, 'r') as f:
        for line in f:
            if line.strip() and not line.startswith('#'):
                key, value = line.strip().split('=', 1)
                os.environ[key] = value

Esse trecho de código verifica se existe um arquivo .env no diretório raiz. Se achar, ele lê os pares chave-valor e define como variáveis de ambiente. Agora dá pra acessar esses valores usando os.getenv(), garantindo que os segredos não fiquem gravados no app.

Passo 3.2: Defina a classe Config

Agora, vamos juntar todas as configurações numa classe Config bem organizada, pra facilitar o acesso e reutilização.

class Config:
    # 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"
    }
    @classmethod
    def get_api_config(cls) -> dict:
        return {
            "api_key": cls.VOXTRAL_API_KEY,
            "base_url": cls.VOXTRAL_API_BASE,
            "model_name": cls.MODEL_NAME
        }    
    @classmethod
    def validate_config(cls) -> bool:
        if not cls.VOXTRAL_API_BASE:
            return False
        return True    
    @classmethod
    def get_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) 

Juntos, essa classe Config funciona como o centro de controle centralizado para o seu aplicativo com tecnologia Voxtral. Se você está configurando parâmetros do modelo, gerenciando formatos de áudio ou definindo o tema do aplicativo, essa configuração garante uma abstração clara, reutilização do código e facilidade de manutenção.

A aula inclui:

  • get_api_config() método: Esse método centraliza todas as credenciais relacionadas à API. Sempre que seu aplicativo fizer uma chamada para o modelo Voxtral, você pode simplesmente usar Config.get_api_config() para pegar tudo o que precisa de uma vez só.
  • validate_config() método: Antes de começar a inferência, esse método permite que você verifique se os valores de configuração essenciais (como a URL base) estão definidos corretamente. Se não, você pode pegar o problema logo e avisar o usuário.
  • get_language_code() método: Esse método permite perguntas e respostas em vários idiomas sem complicações, mapeando nomes de idiomas fáceis de entender da interface do usuário (por exemplo, “francês”) para códigos de idioma ISO padronizados (por exemplo, “fr”). Se um idioma não suportado for passado, ele retorna None com segurança.

Passo 4: Criar o aplicativo Streamlit

Vamos ver cada subetapa que forma a interface e a lógica do aplicativo.

Passo 4.1: Configurar o layout e o estilo

Nesta etapa, a gente inicializa o front-end do Streamlit, carrega as dependências e configura o estilo CSS. Isso é a base visual e funcional do aplicativo.

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)

No código Python e CSS acima:

  • Importamos bibliotecas essenciais para interface do usuário, gerenciamento de arquivos e formatação de mensagens de áudio/texto usando o pacote mistral_common da Voxtral.
  • Depois, a gente configura o layout do app Streamlit, que é uma interface com dois painéis e uma barra lateral que fica aberta por padrão.
  • Por fim, colocamos um CSS personalizado pra separar visualmente as diferentes partes da interface do usuário, como cabeçalhos, seções de áudio, balões de bate-papo e caixas de resumo. Isso melhora a hierarquia visual do aplicativo com títulos estilizados, mensagens informativas e balões de bate-papo distintos para respostas do usuário e do assistente.

Passo 4.2: Inicializar sessão e cliente

Depois, a gente garante que o app funcione direitinho sempre que for recarregado, inicializando as variáveis de sessão e o cliente.

def init_session_state():
    defaults = {
        'transcription': "",
        'summary': "",
        'chat_history': [],
        'audio_file_path': None
    }
    for key, default_value in defaults.items():
        if key not in st.session_state:
            st.session_state[key] = default_value
def initialize_client():
    config = Config.get_api_config() 
    client = OpenAI(
        api_key=config["api_key"],
        base_url=config["base_url"],
    ) 
    # Test connection
    try:
        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")
        return None

Esse trecho de código configura o estado interno do aplicativo e cuida da conexão com o servidor da API Voxtral. Tem dois pontos principais:

  1. Inicialização da sessão: Isso garante que os dados do usuário, como transcrições, resumos e arquivos de áudio enviados, fiquem certinhos em todas as interações e recargas do aplicativo.
  2. Inicialização do cliente: Ele se conecta ao modelo Voxtral Mini 3B hospedado localmente por meio do endpoint compatível com OpenAI exposto através do vLLM (servido pelo Ngrok). Se a conexão falhar, uma mensagem de erro vai aparecer na interface do usuário.

Passo 4.3: Divisão de áudio e transcrição em tempo real

Esta etapa trata da lógica central da preparação do arquivo de áudio e da geração de uma transcrição usando o Voxtral Mini 3B.

def file_to_chunk(file_path: str) -> AudioChunk:
    audio = Audio.from_file(file_path, strict=False)
    return AudioChunk.from_audio(audio)
def transcribe_audio(client, audio_file_path):
    try:
        with open(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 in enumerate(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)}")
        return None

Tem duas funções principais aqui:

  1. Conversão de trechos de áudio: Primeiro, a gente converte o arquivo de áudio que você mandou pro formato “ AudioChunk ”, que é o formato que a API do Voxtral precisa.
  2. Transcrição em streaming com feedback do progresso: A gente manda o áudio pro modelo em um fluxo (stream=True) e decodifica pedaço por pedaço. Uma barra de progresso atualiza automaticamente conforme os tokens são recebidos, dando aos usuários um feedback em tempo real sobre o andamento da transcrição.

Passo 4.4: Criar resumo a partir do áudio

Essa etapa manda a entrada de áudio junto com um aviso em texto pro modelo Voxtral, que devolve um resumo curto e estruturado do conteúdo do áudio.

def generate_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)}")
        return None

O código acima usa vários métodos e funções importantes para gerar um resumo a partir do áudio enviado:

  • audio_chunk: Primeiro, a gente transforma o arquivo de áudio que você mandou num arquivo AudioChunk pra poder processar o áudio com o Voxtral.
  • text_chunk: Depois, usa-se um prompt de texto pra dizer pro modelo resumir o conteúdo de um jeito claro e completo.
  • UserMessage: Isso junta o audio_chunk e o text_chunk numa mensagem multimodal só, num formato compatível com o OpenAI. 
  • Response.choices[0].message.content: Esse objeto pega o texto resumido real da resposta do modelo.

Passo 4.5: Perguntas e respostas em vários idiomas com áudio

Agora, temos o resumo. Vamos permitir que os usuários façam perguntas em linguagem natural sobre o conteúdo de áudio enviado. Isso usa os recursos multimodais do Voxtral, combinando áudio com prompts de texto para gerar respostas que entendem o contexto.

A função a seguir também dá suporte a respostas em vários idiomas, mudando o prompt de forma dinâmica com base no idioma escolhido.

def ask_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)}")
        return None

Aqui vai um resumo do que tá rolando por aqui:

  • A função “ ask_question() ” permite que os usuários façam qualquer pergunta sobre o áudio enviado.
  • Começa convertendo o arquivo que você mandou num objeto de áudio ( AudioChunk ) usando a função reutilizável file_to_chunk(), que prepara o áudio no formato que a API multimodal do Voxtral espera.
  • Depois, ele dá uma olhada no idioma que você escolheu. Se não for em inglês, a pergunta do usuário vem com uma instrução pedindo pro modelo responder no idioma que a pessoa quer (por exemplo, hindi ou espanhol).
  • A pergunta do usuário é colocada em uma tag TextChunk, e tanto o áudio quanto o texto são agrupados em um objeto multimodal UserMessage.
  • Enviamos essa mensagem para o modelo, junto com os valores de temperatura e top-p da configuração para controlar a qualidade da geração.
  • Depois, o modelo mostra uma resposta de volta única.

Passo 4.6: Configurando a barra lateral

A barra lateral funciona como um painel de controle, permitindo que os usuários gerenciem as configurações da sessão, escolham o idioma de saída, testem a conexão com a API do Voxtral e personalizem o comportamento de resposta do modelo por meio de controles deslizantes intuitivos.

def render_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' else None
            st.rerun()        
        return selected_language, temperature, top_p

Aqui está uma explicação do código acima:

  • Barra lateral: O objeto “ st.sidebar ” abre uma barra lateral que dá pra fechar, onde a gente guarda as ferramentas de configuração do app.
  • Teste de conexão: Um botão “Testar conexão” aciona a função “ initialize_client() ”, que tenta se conectar à API do Voxtral e mostra se deu certo ou não usando alertas do Streamlit.
  • Escolha o idioma: Um menu suspenso permite que os usuários escolham um dos 12 idiomas disponíveis. Essa escolha vai dizer ao modelo para responder naquele idioma.
  • Parâmetros do modelo: Um controle deslizante permite que você controle os parâmetros do modelo, como:
    • temperature: Isso controla a criatividade. Os valores mais baixos tornam as respostas mais determinísticas, enquanto os mais altos as tornam mais variadas.
    • top_p: Esse parâmetro controla a amostragem do núcleo, o que ajuda a restringir a geração aos tokens mais prováveis.
  • Sessão reiniciada: Um botão “Limpar sessão” zera todas as variáveis de estado da sessão e reinicia o aplicativo para começar do zero.

Passo 4.7: Seção de upload e processamento de áudio

Esta seção permite que os usuários enviem arquivos de áudio (como .mp3, .wav, etc.), que são salvos temporariamente. Depois de fazer o upload, os usuários podem escolher entre transcrever o áudio ou gerar um resumo de alto nível. 

def render_audio_processing():
    st.markdown('<h3 class="section-header">Audio Upload & Processing</h3>', unsafe_allow_html=True)    
    uploaded_file = st.file_uploader(
        "Choose an audio file",
        type=Config.SUPPORTED_AUDIO_FORMATS,
        help="Upload an audio file to transcribe and analyze"
    )
    if uploaded_file is not None:
        with tempfile.NamedTemporaryFile(delete=False, suffix=f".{uploaded_file.name.split('.')[-1]}") as tmp_file:
            tmp_file.write(uploaded_file.getvalue())
            st.session_state.audio_file_path = tmp_file.name
        st.success(f"File uploaded: {uploaded_file.name}")
        # Initialize client
        client = initialize_client()
        col1, col2 = st.columns(2) 
        with col1:
            if st.button("Generate Summary", type="primary"):
                with st.spinner("Generating summary..."):
                    summary = generate_summary(client, st.session_state.audio_file_path)
                    if summary:
                        st.session_state.summary = summary
        with col2:
            if st.button("Transcribe Audio", type="secondary"):
                with st.spinner("Transcribing audio..."):
                    transcription = transcribe_audio(client, st.session_state.audio_file_path)
                    if transcription:
                        st.session_state.transcription = transcription
        if st.session_state.summary:
            st.markdown('<h4>Summary</h4>', unsafe_allow_html=True)
            st.markdown(f'<div class="success-box">{st.session_state.summary}</div>', unsafe_allow_html=True)
        if st.session_state.transcription:
            st.markdown('<h4>Audio Transcription</h4>', unsafe_allow_html=True)
            st.text_area("Transcription", st.session_state.transcription, height=200, label_visibility="collapsed")

Precisamos de uma estrutura modular pra facilitar o upload de áudio, o processamento e o armazenamento dos resultados das interações dos usuários. Olha só como eu fiz:

  • Enviador de arquivos: Primeiro, precisamos de um carregador de arquivos do tipo arrastar e soltar que aceite vários formatos de áudio definidos em Config.SUPPORTED_AUDIO_FORMATS. Depois que um arquivo é enviado, ele é gravado em um arquivo temporário e salvo em st.session_state.audio_file_path.
  • Inicialização do cliente: Um cliente que funciona com o Voxtral é inicializado pra permitir chamadas pra resumo e transcrição.
  • Botões de resumo e transcrição: Depois, vamos definir dois botões:
    • Gerar resumo: Quando você clica nesse botão, o áudio que você mandou vai pro modelo com um aviso de resumo. Um indicador de progresso é mostrado e, se tudo der certo, o resultado é salvo em st.session_state.summary.
    • Transcrever áudio: Esse botão manda o arquivo de áudio para o ponto final da transcrição. O progresso em tempo real é mostrado usando um spinner, e o resultado é guardado em st.session_state.transcription.
  • Por fim, os dois resultados aparecem numa área de texto.

Passo 4.8: Perguntas e respostas interativas em vários idiomas

Essa etapa permite que os usuários façam perguntas sobre o áudio enviado em vários idiomas (por exemplo, inglês, hindi, espanhol). O idioma escolhido é usado pra formatar a resposta do modelo, e cada par de pergunta e resposta é guardado num histórico de conversas gerenciado pela sessão e mostrado usando balões de chat.

def render_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 in reversed(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)

Aqui tá um resumo do que tá rolando no trecho de código acima:

  • Ask Question botão: Um campo de entrada de texto permite que os usuários digitem uma pergunta no idioma escolhido e cliquem no botão ” (Pergunte ao especialista) ou “ ” (Envie a pergunta). Uma vez, cliquei nele:
    • Inicializa o cliente compatível com Voxtral.
    • Manda a pergunta junto com o áudio que você mandou pro modelo.
    • Mostra um indicador giratório enquanto espera a resposta do modelo.
  • Tratamento de respostas: Se recebermos uma resposta, ela será:
    • Armazenado em st.session_state.chat_history com um carimbo de data/hora.
    • Renderizado com formatação específica para cada função usando o CSS personalizado de antes (bolha de usuário vs. assistente).
    • Se o modelo falhar, vai aparecer uma mensagem de erro clara.
  • Histórico de conversas: Se já tiverem pares de perguntas e respostas anteriores, elas vão aparecer na ordem cronológica inversa, com um separador.

Passo 4.9: Começando a usar o app

Essa última etapa junta todos os componentes que a gente definiu antes, como inicializar o estado da sessão, renderizar a barra lateral, cuidar dos uploads de áudio, transcrição, resumos e perguntas e respostas usando um layout de duas colunas.

Depois que o servidor estiver funcionando e todas as dependências estiverem instaladas, essa etapa garante que o aplicativo seja servido ao navegador via Streamlit e esteja pronto para interação.

def main():
    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() 

A função “ main() ” é tipo o ponto de partida do app. Ele controla o layout, coordena a renderização e garante que todas as variáveis da sessão e componentes da interface do usuário sejam inicializados corretamente. Aqui está um resumo do que as funções definidas acima descrevem:

  • init_session_state(): Essa função prepara valores padrão como transcription, summary e chat_history para manter o estado do aplicativo durante as interações.
  • render_sidebar(): Carrega widgets de configuração, incluindo seletor de idioma, teste de conexão e parâmetros do modelo.
  • render_audio_processing(): Essa função permite que os usuários enviem e processem arquivos de áudio para transcrição e geração de resumos.
  • render_qa_section(): Por fim, essa função permite responder perguntas em vários idiomas em áudios que você carregar.

Quando tudo estiver pronto, execute o aplicativo usando:

pip install -r requirements.txt

Dá uma olhada se tá acessível pelo URL que tá em VOXTRAL_API_BASE dentro do seu config.py. Depois que todas as dependências estiverem instaladas, execute o aplicativo Streamlit digitando o seguinte comando no terminal:

streamlit run app.py

O seu navegador vai abrir a interface automaticamente. O app agora tá funcionando direitinho com upload de áudio, transcrição em tempo real, resumos e perguntas e respostas em vários idiomas, tudo com a ajuda do Voxtral Mini 3B.

Você pode encontrar todo o código que abordamos aqui neste repositório GitHub que eu criei.

Conclusão

O Voxtral Mini 3B é um modelo eficiente e aberto para transcrição e compreensão de fala. Neste tutorial, a gente rodou o vLLM, configurou uma API e criou um aplicativo de resumo de áudio usando o Streamlit.

Se você está criando um resumidor de podcasts, um assistente de reuniões ou um aplicativo de comando de voz, o Voxtral Mini pode servir como base para um raciocínio de áudio rápido e local.


Aashi Dutt's photo
Author
Aashi Dutt
LinkedIn
Twitter

Sou Google Developers Expert em ML (Gen AI), Kaggle 3x Expert e Women Techmakers Ambassador com mais de 3 anos de experiência em tecnologia. Fui cofundador de uma startup de tecnologia de saúde em 2020 e estou fazendo mestrado em ciência da computação na Georgia Tech, com especialização em machine learning.

Tópicos

Aprenda IA com esses cursos!

Curso

Implementando IA na produção com FastAPI

4 h
1.7K
Aprenda a usar o FastAPI pra desenvolver APIs que dão suporte a modelos de IA, feitos pra atender às demandas do mundo real.
Ver detalhesRight Arrow
Iniciar curso
Ver maisRight Arrow
Relacionado

blog

O que é o Mistral Large 2? Como funciona, casos de uso e muito mais

O Mistral Large 2 é o modelo de idioma mais recente da Mistral AI, competindo com modelos como GPT-4o, Llama 3.1 e Claude 3 Opus.
Ryan Ong's photo

Ryan Ong

8 min

Tutorial

Guia para iniciantes no uso da API do ChatGPT

Este guia o orienta sobre os conceitos básicos da API ChatGPT, demonstrando seu potencial no processamento de linguagem natural e na comunicação orientada por IA.
Moez Ali's photo

Moez Ali

Tutorial

Guia de Introdução ao Ajuste Fino de LLMs

O ajuste fino dos grandes modelos de linguagem (LLMs, Large Language Models) revolucionou o processamento de linguagem natural (PLN), oferecendo recursos sem precedentes em tarefas como tradução de idiomas, análise de sentimentos e geração de textos. Essa abordagem transformadora aproveita modelos pré-treinados como o GPT-2, aprimorando seu desempenho em domínios específicos pelo processo de ajuste fino.
Josep Ferrer's photo

Josep Ferrer

Tutorial

Como usar a API de conversão de texto em fala da OpenAI

A API TTS da OpenAI é um ponto de extremidade que permite que os usuários interajam com seu modelo de IA TTS que converte texto em linguagem falada com som natural.
Kurtis Pykes 's photo

Kurtis Pykes

Tutorial

Primeiros passos com o Claude 3 e a API do Claude 3

Saiba mais sobre os modelos Claude 3, benchmarks de desempenho detalhados e como acessá-los. Além disso, descubra a nova API Python do Claude 3 para geração de texto, acesso a recursos de visão e streaming.
Abid Ali Awan's photo

Abid Ali Awan

Tutorial

Como treinar um LLM com o PyTorch

Domine o processo de treinamento de grandes modelos de linguagem usando o PyTorch, desde a configuração inicial até a implementação final.
Zoumana Keita 's photo

Zoumana Keita

Ver maisVer mais