Lewati ke konten utama

Voxtral dari Mistral: Panduan dengan Proyek Demo

Pelajari cara menjalankan model Voxtral Mini 3B dari Mistral dengan vLLM, menyiapkan API, dan membangun aplikasi peringkas audio serta tanya jawab berbasis Streamlit.
· 12 mnt Baca

Jelajahi bersama AI

Mistral baru-baru ini meluncurkan model audio multimodal open-source pertamanya, Voxtral Small dan Voxtral Mini, yang dibangun di atas arsitektur Mistral 3B dan dioptimalkan khusus untuk pemahaman audio serta tugas transkripsi.

Fokus saya dalam blog ini adalah Voxtral Mini 3B, sebuah model open-source ringkas yang dirancang untuk tugas audio-ke-teks waktu nyata seperti transkripsi, peringkasan, dan tanya jawab (Q&A). Dengan ukurannya yang efisien dan dukungan untuk penalaran konteks panjang, Voxtral Mini sangat bertenaga saat dipasangkan dengan kerangka inferensi throughput tinggi seperti vLLM, menjadikannya ideal untuk membangun aplikasi audio cepat dan offline.

Dalam tutorial ini, saya akan memandu Anda cara:

  • Menjalankan Voxtral Mini 3B dengan vLLM di Colab Pro
  • Mendeploy endpoint API yang ditunnel oleh ngrok untuk mengakses model Anda dari mana saja
  • Membangun asisten audio berbasis Streamlit yang melakukan transkripsi, peringkasan, dan Q&A menggunakan input audio mentah

Kami terus memperbarui pembaca tentang kabar terbaru AI melalui The Median, buletin gratis hari Jumat yang merangkum kisah-kisah utama pekan ini. Berlangganan dan tetap tajam hanya dalam beberapa menit per minggu:

Apa itu Voxtral dari Mistral?

Voxtral adalah keluarga model audio open‑source sepenuhnya dari Mistral yang dirancang untuk pemahaman ujaran yang andal. Voxtral hadir dalam dua ukuran model:

  • Voxtral Small: 24 B parameter, ideal untuk penggunaan skala produksi dan enterprise
  • Voxtral Mini: 3 B parameter, dioptimalkan untuk berjalan secara lokal pada perangkat edge

mistral's voxtral benchmarks

Sumber: Mistral

Voxtral menerima input audio mentah (seperti .wav atau .mp3) dan dilatih untuk secara efisien menghasilkan transkripsi dan ringkasan dari konten lisan. Voxtral adalah varian yang lebih kecil dan dioptimalkan untuk inferensi cepat serta deployment offline.

Model ini mengikuti format model Mistral dan kompatibel dengan kerangka inferensi throughput tinggi seperti vLLM, sehingga menjadi pilihan yang sangat baik untuk transkripsi waktu nyata atau aplikasi ujaran ringan.

Cara Menjalankan Voxtral Mini 3B Menggunakan vLLM

Pada bagian ini, saya akan memandu Anda cara menyajikan Voxtral Mini 3B menggunakan vLLM di Colab Pro dengan GPU T4 diaktifkan. vLLM dipilih karena kemampuan penyajian throughput tinggi dan latensi rendah yang ideal untuk model seperti Voxtral yang memerlukan respons streaming cepat dengan dukungan audio.

Selain itu, kita akan menggunakan PyNGrok untuk mengekspos server vLLM melalui endpoint publik, sehingga dapat diakses oleh aplikasi yang berjalan di mesin lokal Anda.

Langkah 1: Instal dependensi

Mari mulai dengan menginstal dependensi di lingkungan Colab kita. Jalankan perintah berikut di sel Colab:

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

Kita mulai dengan menginstal pustaka yang dibutuhkan menggunakan uv, penginstal paket Python yang lebih cepat. Ini menarik versi nightly dari vllm[audio] yang mencakup dukungan eksperimental untuk model bahasa‑audio seperti Voxtral. Jika Anda belum memasang uv di lingkungan Anda, maka terlebih dahulu pasang uv dengan menjalankan kode berikut:

!pip install uv

Langkah 2: Instal Mistral-Common

Berikutnya, kita memasang paket mistral-common, yang menyediakan utilitas penting untuk berinteraksi dengan Voxtral dan model keluarga Mistral lainnya. Paket ini mencakup tokenizer yang selaras dengan implementasi resmi dan validasi berbasis Pydantic untuk struktur pesan.

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

Paket mistral-common berisi modul utilitas untuk Voxtral dan model keluarga Mistral lainnya. Paket ini mencakup tokenizer, pesan bertipe dalam format Pydantic, dan fungsi bantu audio. Langkah ini memastikan kompatibilitas dengan penanganan internal Voxtral atas input audio dan pesan terstruktur.

Langkah 3: Siapkan VLLM

Setelah dependensi dasar Mistral siap, selanjutnya kita menyiapkan vLLM dengan mengkloning repositori utamanya.

Langkah 3.1: Kloning repositori vLLM

Kita mengkloning repositori GitHub vLLM resmi, yang memberi kita akses ke contoh audio bawaan dan menjadi dasar untuk meluncurkan inferensi offline atau terhost.

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

Langkah 3.2: Jalankan inferensi audio contoh 

Mari jalankan uji cepat untuk memastikan penyiapan kita benar.

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

Saya menjalankan contoh offline audio_language.py, yang melakukan inferensi bahasa‑audio pada dua sampel pradefinisi menggunakan model Voxtral dan mengonfirmasi apakah dekode audio dan generasi berfungsi dengan baik.

Langkah 4: Siapkan PyGrok

Setelah vLLM siap, mari konfigurasikan PyNGrok untuk mengekspos server vLLM di Colab melalui alamat internet yang dapat diakses publik.

  • Mulailah dengan membuat akun gratis di https://ngrok.com/
  • Gulir ke tab Connect dan salin tag autentikasi (disamarkan pada gambar di bawah), lalu simpan sebagai secret di Colab Secrets.

NGrok Token

Berikutnya, kita memasang PyNGrok di lingkungan colab dan menetapkan token autentikasi menggunakan token NGROK yang kita salin sebelumnya. Jika Anda sedang membuat purwarupa, Anda dapat meneruskan token langsung di sini.

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

Langkah 5: Sajikan model

Ini adalah langkah kunci, di mana kita meluncurkan model Voxtral Mini 3B melalui vLLM. 

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

Cuplikan kode mencakup beberapa flag penting:

  • --tokenizer_mode mistral: Menggunakan tokenizer khusus Mistral untuk tokenisasi yang akurat.
  • --config_format mistral dan --load_format mistral: Flag ini memastikan konfigurasi model dan bobot dimuat dalam format khusus Mistral, menjaga kompatibilitas.
  • --max-model-len 4864: Flag ini menetapkan panjang konteks input maksimum menjadi 4864 token.

Catatan: Biarkan sel ini tetap berjalan karena ini adalah server model aktif.

Langkah 6: Dapatkan endpoint publik NGrok

Setelah server vLLM Anda berjalan, jalankan kode berikut baris demi baris di terminal Python:

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

Kode di atas akan mengekspos model ke internet pada URL publik sementara seperti:

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

Simpan URL ini, yang akan digunakan di config.py lokal untuk terhubung ke model jarak jauh. Setelah selesai, akhiri koneksi dengan menjalankan:

ngrok.kill()

Membangun Demo Transkripsi dan Peringkasan Audio

Pada bagian ini, kita akan membangun UI Streamlit yang:

  1. Menerima audio sebagai input (unggahan pengguna)
  2. Mengirimkannya ke model melalui server vLLM
  3. Menampilkan transkripsi, ringkasan, dan memungkinkan pengguna mengajukan pertanyaan

Langkah 1: Menyiapkan dependensi

Sebelum membangun aplikasi, kita mendefinisikan semua dependensi yang diperlukan dalam berkas requirements.txt. Ini memastikan lingkungan yang konsisten di berbagai run lokal atau 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 

Berikut alasan kita memerlukan masing‑masing:

  • streamlit: Pustaka ini membantu membangun antarmuka audio interaktif.
  • openai: berinteraksi dengan server vLLM yang kompatibel dengan Voxtral menggunakan SDK OpenAI.
  • mistral-common: Menyediakan utilitas khusus Voxtral seperti AudioChunk dan TextChunk.
  • pyngrok: Mengekspos server vLLM lokal kita ke internet, memungkinkan aplikasi Streamlit mengaksesnya.
  • Pydub: Pustaka ini membantu mengonversi berkas audio untuk inferensi.
  • huggingface-hub dan requests: Digunakan untuk mengambil model dan konfigurasi (jika diperlukan).

Langkah 2: Menyiapkan variabel lingkungan

Untuk menjaga konfigurasi tetap rapi dan portabel, kita menyimpan detail API sebagai variabel lingkungan. Anda dapat mendefinisikannya di berkas .env:

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

VOXTRAL_API_BASE harus mengarah ke instance vLLM yang berjalan, yang bisa berupa localhost (http://localhost:8000) atau endpoint publik ngrok yang tampak seperti https://80xxxxxxxxxx.ngrok-free.app.

Catatan: Pastikan Anda menambahkan /v1 di akhir basis API untuk kompatibilitas OpenAI.

Langkah 3: Menyiapkan berkas konfigurasi

Agar aplikasi Anda modular, mudah disesuaikan, dan siap produksi, kita akan mendefinisikan kelas konfigurasi terpusat di config.py. Berkas ini akan mengendalikan pengaturan model, akses API, format audio yang didukung, bahasa, dan preferensi UI.

Langkah 3.1: Memuat variabel lingkungan

Sebelum kita mendefinisikan kelas konfigurasi, kita memuat semua variabel lingkungan yang disimpan di berkas .env. Ini membuat informasi sensitif terpisah dari kode.

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

Cuplikan ini memeriksa apakah berkas .env ada di direktori root. Jika ditemukan, ia membaca pasangan kunci‑nilai dan menetapkannya sebagai variabel lingkungan. Nilai‑nilai ini kini dapat diakses menggunakan os.getenv(), memastikan secret tidak ditanamkan langsung ke aplikasi.

Langkah 3.2: Mendefinisikan kelas Config

Sekarang, kita bungkus semua pengaturan ke dalam kelas Config yang ringkas untuk akses dan penggunaan ulang yang mudah.

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) 

Secara keseluruhan, kelas Config ini bertindak sebagai pusat kendali terpusat untuk aplikasi bertenaga Voxtral Anda. Baik saat mengonfigurasi parameter model, mengelola format audio, atau menetapkan tema aplikasi, pengaturan ini memastikan abstraksi yang bersih, keterpakaiulangan kode, dan kemudahan pemeliharaan.

Kelas ini mencakup:

  • Metode get_api_config(): Memusatkan semua kredensial terkait API. Di mana pun aplikasi Anda memanggil model Voxtral, Anda cukup memanggil Config.get_api_config() untuk mengambil semua yang diperlukan sekaligus.
  • Metode validate_config(): Sebelum memulai inferensi, metode ini memungkinkan Anda memvalidasi bahwa nilai konfigurasi penting (seperti base URL) telah didefinisikan dengan benar. Jika belum, Anda dapat mendeteksi lebih awal dan memberi tahu pengguna.
  • Metode get_language_code(): Memungkinkan Q&A multibahasa yang mulus dengan memetakan nama bahasa yang ramah pengguna dari UI (misalnya “French”) ke kode bahasa ISO standar (misalnya “fr”). Jika bahasa yang tidak didukung dikirim, akan mengembalikan None secara aman.

Langkah 4: Bangun aplikasi Streamlit

Mari telusuri setiap sub‑langkah yang membangun antarmuka dan logika aplikasi.

Langkah 4.1: Menyiapkan tata letak dan styling

Pada langkah ini, kita menginisialisasi frontend Streamlit, memuat dependensi, dan menyiapkan gaya CSS. Ini membentuk fondasi visual dan fungsional aplikasi.

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)

Dalam kode Python dan CSS di atas:

  • Kita mengimpor pustaka penting untuk UI, penanganan berkas, dan pemformatan pesan audio/teks menggunakan paket mistral_common milik Voxtral.
  • Kemudian kita mengonfigurasi tata letak aplikasi Streamlit berupa antarmuka dua panel dengan sidebar yang diperluas secara default.
  • Terakhir, kita menyuntikkan CSS khusus untuk memisahkan bagian‑bagian UI, seperti header, bagian audio, gelembung percakapan, dan kotak ringkasan. Ini meningkatkan hierarki visual aplikasi dengan judul bergaya, pesan info, dan gelembung obrolan berbeda untuk balasan pengguna vs. asisten.

Langkah 4.2: Inisialisasi sesi dan klien

Berikutnya, kita memastikan aplikasi berperilaku konsisten saat dimuat ulang dengan menginisialisasi variabel sesi dan klien.

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

Cuplikan kode ini menyiapkan keadaan internal aplikasi dan menangani koneksi ke server API Voxtral. Terdapat dua komponen kunci:

  1. Inisialisasi sesi: Memastikan data pengguna seperti transkripsi, ringkasan, dan berkas audio yang diunggah tersimpan dengan benar di seluruh interaksi dan pemuatan ulang aplikasi.
  2. Inisialisasi klien: Terhubung ke model Voxtral Mini 3B yang di‑host secara lokal melalui endpoint yang kompatibel dengan OpenAI yang diekspos melalui vLLM (dilayani lewat Ngrok). Jika koneksi gagal, pesan kesalahan ditampilkan di UI.

Langkah 4.3: Penggalan audio dan transkripsi waktu nyata

Langkah ini menangani logika inti menyiapkan berkas audio dan menghasilkan transkripsi menggunakan 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

Ada dua fungsi kunci di sini:

  1. Konversi penggalan audio: Pertama, kita mengonversi berkas audio yang diunggah ke format AudioChunk, yang merupakan persyaratan input untuk API Voxtral.
  2. Transkripsi streaming dengan umpan balik progres: Kita mengirim audio ke model secara streaming (stream=True) dan mendekodekannya per penggalan. Bilah progres diperbarui secara dinamis saat token diterima, memberikan umpan balik waktu nyata pada progres transkripsi.

Langkah 4.4: Menghasilkan ringkasan dari audio

Langkah ini mengirimkan input audio bersama prompt tekstual ke model Voxtral, yang mengembalikan ringkasan padat dan terstruktur dari konten audio.

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

Kode di atas menggunakan beberapa metode dan fungsi utama untuk menghasilkan ringkasan dari audio yang diunggah:

  • audio_chunk: Pertama, kita mengonversi berkas audio yang diunggah menjadi AudioChunk untuk pemrosesan audio Voxtral.
  • text_chunk: Lalu, prompt teks digunakan untuk mengarahkan model agar merangkum konten secara jelas dan komprehensif.
  • UserMessage: Ini menggabungkan audio_chunk dan text_chunk menjadi satu pesan multimodal dalam format yang kompatibel dengan OpenAI. 
  • Response.choices[0].message.content: Objek ini mengekstrak teks ringkasan sebenarnya dari respons model.

Langkah 4.5: Q&A multibahasa pada audio

Sekarang kita sudah memiliki ringkasan. Mari memungkinkan pengguna mengajukan pertanyaan bahasa alami tentang konten audio yang diunggah. Ini memanfaatkan kemampuan multimodal Voxtral dengan menggabungkan audio dan prompt teks untuk menghasilkan jawaban yang sadar konteks.

Fungsi berikut juga mendukung respons multibahasa dengan memodifikasi prompt secara dinamis berdasarkan bahasa yang dipilih.

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

Berikut garis besar yang terjadi di sini:

  • Fungsi ask_question() memungkinkan pengguna mengajukan pertanyaan apa pun tentang audio yang diunggah.
  • Dimulai dengan mengonversi berkas yang diunggah menjadi AudioChunk menggunakan fungsi file_to_chunk() yang dapat digunakan ulang, yang menyiapkan audio dalam format yang diharapkan API multimodal Voxtral.
  • Berikutnya, ia memeriksa bahasa yang dipilih. Jika bukan bahasa Inggris, pertanyaan pengguna diawali instruksi agar model merespons dalam bahasa yang diinginkan (misalnya Hindi atau Spanyol).
  • Pertanyaan pengguna dibungkus dalam TextChunk, dan baik audio maupun teks digabung menjadi UserMessage multimodal.
  • Kita mengirim pesan ini ke model, bersama nilai temperature dan top‑p dari konfigurasi untuk mengendalikan kualitas generasi.
  • Model kemudian mengembalikan respons satu giliran.

Langkah 4.6: Menyiapkan sidebar

Sidebar berfungsi sebagai panel kontrol, memungkinkan pengguna mengelola pengaturan sesi, memilih bahasa output, menguji koneksi ke API Voxtral, dan menyesuaikan perilaku respons model melalui slider yang intuitif.

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

Berikut rincian kode di atas:

  • Sidebar: Objek st.sidebar membuka sidebar yang dapat dilipat tempat kita menaruh alat konfigurasi aplikasi.
  • Uji koneksi: Tombol "Test Connection" memicu fungsi initialize_client(), yang mencoba terhubung ke API Voxtral dan melaporkan keberhasilan atau kegagalan menggunakan peringatan Streamlit.
  • Pemilihan bahasa: Menu dropdown memungkinkan pengguna memilih salah satu dari 12 bahasa yang didukung. Pilihan ini nantinya memberi tahu model untuk merespons dalam bahasa tersebut.
  • Parameter model: Slider memungkinkan pengguna mengendalikan parameter model seperti:
    • temperature: Mengendalikan kreativitas. Nilai lebih rendah membuat respons lebih deterministik sementara nilai lebih tinggi membuatnya lebih beragam.
    • top_p: Parameter ini mengendalikan nucleus sampling yang membantu membatasi generasi pada token yang paling mungkin.
  • Reset sesi: Tombol "Clear Session" mereset semua variabel status sesi dan menjalankan ulang aplikasi untuk memulai dari awal.

Langkah 4.7: Bagian unggah dan pemrosesan audio

Bagian ini memungkinkan pengguna mengunggah berkas audio (seperti .mp3, .wav, dll.), yang akan disimpan sementara. Setelah diunggah, pengguna dapat memilih untuk menyalin teks audio atau menghasilkan ringkasan tingkat tinggi. 

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")

Kita memerlukan struktur modular untuk memudahkan unggah audio, pemrosesan, dan penyimpanan hasil yang persisten di seluruh interaksi pengguna. Berikut cara saya melakukannya:

  • Pengunggah berkas: Pertama, kita memerlukan pengunggah berkas seret‑dan‑lepas yang menerima berbagai format audio yang ditentukan di Config.SUPPORTED_AUDIO_FORMATS. Setelah berkas diunggah, berkas ditulis ke berkas sementara dan disimpan di st.session_state.audio_file_path.
  • Inisialisasi klien: Klien yang kompatibel dengan Voxtral diinisialisasi untuk memungkinkan pemanggilan ringkasan dan transkripsi.
  • Tombol ringkasan dan transkripsi: Selanjutnya, kita mendefinisikan dua tombol:
    • Generate summary: Saat diklik, tombol ini mengirim audio yang diunggah ke model dengan prompt ringkasan. Spinner progres ditampilkan, dan jika berhasil, keluaran disimpan ke st.session_state.summary.
    • Transcribe audio: Tombol ini mengirim berkas audio ke endpoint transkripsi. Progres waktu nyata ditampilkan menggunakan spinner, dan hasilnya disimpan di st.session_state.transcription.
  • Terakhir, kedua hasil ditampilkan dalam area teks.

Langkah 4.8: Q&A interaktif multibahasa

Langkah ini memungkinkan pengguna mengajukan pertanyaan tentang audio yang diunggah dalam berbagai bahasa (mis., Inggris, Hindi, Spanyol). Bahasa yang dipilih digunakan untuk memformat respons model, dan setiap pasangan tanya‑jawab disimpan dalam riwayat percakapan yang dikelola sesi dan ditampilkan menggunakan gelembung obrolan.

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)

Berikut rincian yang terjadi pada cuplikan kode di atas:

  • Ask Question button: Bidang input teks memungkinkan pengguna mengetik pertanyaan dalam bahasa yang dipilih dan mengeklik tombol Ask Question. Setelah diklik, ini akan:
    • Menginisialisasi klien yang kompatibel dengan Voxtral.
    • Mengirim pertanyaan beserta audio yang diunggah ke model.
    • Menampilkan spinner saat menunggu respons model.
  • Penanganan respons: Jika respons diterima, maka akan:
    • Disimpan di st.session_state.chat_history dengan cap waktu.
    • Ditampilkan dengan pemformatan spesifik per peran menggunakan CSS kustom sebelumnya (gelembung pengguna vs. asisten).
    • Jika model gagal, pesan kesalahan yang jelas akan ditampilkan.
  • Riwayat percakapan: Jika pasangan Q&A sebelumnya ada, ditampilkan dalam urutan kronologis terbalik dengan pemisah.

Langkah 4.9: Meluncurkan aplikasi

Langkah terakhir ini menggabungkan semua komponen yang telah didefinisikan sebelumnya, termasuk inisialisasi status sesi, perenderan sidebar, penanganan unggah audio, transkripsi, ringkasan, dan Q&A menggunakan tata letak dua kolom.

Setelah server berjalan dan semua dependensi terpasang, langkah ini memastikan aplikasi disajikan ke browser melalui Streamlit dan siap untuk interaksi.

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() 

Fungsi main() bertindak sebagai titik masuk aplikasi. Fungsi ini mengendalikan tata letak, mengorkestrasi perenderan, dan memastikan semua variabel sesi serta komponen UI diinisialisasi dengan benar. Berikut ringkasan yang dideskripsikan fungsi‑fungsi di atas:

  • init_session_state(): Menyiapkan nilai default seperti transcription, summary, dan chat_history agar status aplikasi bertahan di seluruh interaksi.
  • render_sidebar(): Memuat widget konfigurasi termasuk pemilih bahasa, uji koneksi, dan parameter model.
  • render_audio_processing(): Memungkinkan pengguna mengunggah dan memproses berkas audio untuk transkripsi dan pembuatan ringkasan.
  • render_qa_section(): Terakhir, fungsi ini memungkinkan tanya jawab multibahasa pada audio yang diunggah.

Setelah semuanya siap, jalankan aplikasi menggunakan:

pip install -r requirements.txt

Pastikan aplikasi dapat diakses melalui URL yang ditentukan di VOXTRAL_API_BASE di dalam config.py Anda. Setelah semua dependensi terpasang, jalankan aplikasi Streamlit dengan menjalankan perintah berikut di terminal:

streamlit run app.py

Peramban Anda akan membuka antarmuka secara otomatis. Aplikasi kini berfungsi penuh dengan unggah audio, transkripsi waktu nyata, ringkasan, dan Q&A multibahasa, didukung oleh Voxtral Mini 3B.

Anda dapat menemukan semua kode yang telah kita bahas di repositori GitHub yang telah saya siapkan.

Kesimpulan

Voxtral Mini 3B adalah model open‑weight yang efisien untuk transkripsi dan pemahaman ujaran. Dalam tutorial ini, kita menjalankannya menggunakan vLLM, menyiapkan API, dan membangun aplikasi peringkas audio menggunakan Streamlit.

Baik Anda membangun peringkas podcast, asisten rapat, atau aplikasi perintah suara, Voxtral Mini dapat menjadi fondasi untuk penalaran audio yang cepat dan lokal.

Aashi Dutt

Penulis

Aashi Dutt

Saya adalah Google Developers Expert di ML (Gen AI), Kaggle 3x Expert, dan Women Techmakers Ambassador dengan pengalaman lebih dari 3 tahun di bidang teknologi. Saya ikut mendirikan startup health-tech pada 2020 dan sedang menempuh studi magister ilmu komputer di Georgia Tech dengan spesialisasi machine learning.

Topik

Terkait

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026

blogs

Spaghetti Plot dan Jalur Badai