स्पीच-टू-स्पीच मॉडल
Soniqo conversational speech-to-speech के लिए दो native MLX model families support करता है: PersonaPlex 7B और VoiceChat 11B। दोनों speech लेते हैं और model audio सीधे generate करते हैं, लेकिन उनकी duplex architecture और runtime contracts अलग हैं।
मॉडल चुनें
| मॉडल | Conversation model | सबसे उपयुक्त |
|---|---|---|
| PersonaPlex 7B | Moshi, Depformer और Mimi के साथ simultaneous full duplex | एक साथ सुनना/बोलना और 18 selectable voices |
| VoiceChat 11B | FastConformer, Nemotron-H, EAR-TTS और neural codec के साथ continuous frame-synchronous duplex | 80 ms streaming frames, text/function events और checkpoint-native speech |
ये conversational speech-to-speech models हैं। Hibiki भी speech को सीधे speech में बदलता है, लेकिन उसका काम streaming speech translation है, इसलिए उसका documentation अलग है।
PersonaPlex 7B
Moshi आर्किटेक्चर (Kyutai) पर आधारित Full-duplex speech-to-speech dialogue मॉडल। PersonaPlex 7B सीधे बोले गए input से बोले गए responses उत्पन्न करता है — कोई intermediate text pipeline आवश्यक नहीं। मॉडल 18 voice presets के साथ आता है और 8-bit (अनुशंसित) और 4-bit क्वांटिज़ेशन में उपलब्ध है। 8-bit डिफ़ॉल्ट है — यह 30% तेज़ है और coherent responses उत्पन्न करता है, जबकि 4-bit output गुणवत्ता को degrade करता है।
VoiceChat 11B
Duplex speech-to-speech reference: SALM-Duplex: Efficient and Direct Duplex Modeling for Speech-to-Speech Language Model (Interspeech 2025), जिसे NVIDIA के upstream VoiceChat model card में cite किया गया है।
M5 Pro, 48 GB, Release, 80 ms live cadence, protected-head INT5: तीन controlled runs में whole-pipeline RTF 0.94, 0.92 और 0.92 था, और peak RSS लगभग 8.70 GB था। पहला spoken text 44.3–46.7 ms में और पहला playable audio 74.0–76.4 ms में मिला। ये warm compute आंकड़े हैं, सीखी हुई turn-taking latency नहीं; optimized INT8 performance को अभी दोबारा नहीं मापा गया है।
VoiceChat speech-swift का दूसरा native MLX speech-to-speech runtime है। यह causal FastConformer perception, Nemotron-H duplex text/function channels, स्वतंत्र text-conditioned EAR-TTS और 22.05 kHz neural codec को जोड़ता है। session लगातार 16 kHz mono audio लेता है और हर 80 ms में text events तथा 1,764-sample output frame देता है।
VoiceChatModel.load(from:) से load करें, VoiceChatSession शुरू करें और pushAudio से audio दें। पूरे bundle में encoder/, llm/ और tts/ होना चाहिए; पुराने understanding-only bundles अस्वीकार होते हैं।
INT5 परीक्षित M5 Pro पर RTF 1 से कम aggregate throughput बनाए रखता है। तीनों runs में total/frame p95 भी 76.2–78.6 ms के बीच और 80 ms से कम रहा; इसलिए deadline headroom अभी कम है। model turn onset और hardware compute latency को अलग मापें।
PersonaPlex आर्किटेक्चर और उपयोग
PersonaPlex तीन core कॉम्पोनेंट वाला multi-stream autoregressive मॉडल है:
| कॉम्पोनेंट | विवरण |
|---|---|
| Temporal Transformer | 32 layers, dim=4096, 32 heads, SwiGLU (hidden_scale=4.125), RoPE, 8-bit क्वांटाइज़्ड (डिफ़ॉल्ट) |
| Depformer | 6 layers, dim=1024, 16 heads, MultiLinear (weights_per_step=true), dep_q=16 |
| Mimi Codec | 16 codebooks, 12.5 Hz frame rate, 24 kHz ऑडियो आउटपुट |
मॉडल एक साथ 17 streams प्रोसेस करता है: 1 text stream + 8 user audio streams + 8 agent audio streams। यह आर्किटेक्चर full-duplex conversation सक्षम करती है जहाँ मॉडल एक साथ सुन और बोल सकता है।
Voice Presets
PersonaPlex में natural और varied styles में 18 बिल्ट-इन voice presets शामिल हैं:
| श्रेणी | Presets |
|---|---|
| Natural Female | NATF0, NATF1, NATF2, NATF3 |
| Natural Male | NATM0, NATM1, NATM2, NATM3 |
| Varied Female | VARF0, VARF1, VARF2, VARF3, VARF4 |
| Varied Male | VARM0, VARM1, VARM2, VARM3, VARM4 |
Inner Monologue
PersonaPlex प्रत्येक चरण पर दो parallel streams उत्पन्न करता है: Mimi codec के लिए 8 audio codebook tokens और मॉडल के आंतरिक monologue के लिए एक text token। Text stream वह है जो मॉडल बोलते समय "सोच रहा है" — यह अंतिम ऑडियो से थोड़ा diverge हो सकता है, लेकिन व्यवहार में यह spoken response को live transcript के रूप में उपयोग करने के लिए पर्याप्त रूप से closely mirror करता है।
Text tokens raw SentencePiece piece IDs के रूप में वापस आते हैं। उन्हें SentencePieceDecoder के साथ decode करें जो PersonaPlex ship करता है:
import PersonaPlex
import AudioCommon
let model = try await PersonaPlexModel.fromPretrained()
let decoder = model.tokenizer // SentencePieceDecoder?
let result = model.respond(userAudio: userSamples, voice: .NATM0)
let transcript = decoder?.decode(result.textTokens) ?? ""
print(transcript) // "Sure, I can help with that..."
playAudio(result.audio) // 24 kHz mono Float32
Streaming mode में, respondStream textTokens chunks उत्पन्न होने के साथ उत्सर्जित करता है — ऑडियो अभी भी generate हो रहा होता है तब एक live caption view को drive करने के लिए उन्हें incrementally decode करें। --transcript CLI flag ठीक यही व्यवहार पर्दे के पीछे करता है।
यह क्यों मायने रखता है: SentencePieceDecoder shared AudioCommon.SentencePieceModel protobuf reader पर बना है, इसलिए PersonaPlex, OmnilingualASR और कोई भी भविष्य का SentencePiece-आधारित मॉडल उसी tokenizer कार्यान्वयन के माध्यम से decode करता है। SentencePieceModel reference देखें।
System Prompts
किसी भी custom system prompt को एक plain string के रूप में pass करें — कोई external tokenization आवश्यक नहीं:
let response = model.respond(
userAudio: audio,
voice: .NATM0,
systemPrompt: "You enjoy having a good conversation."
)
या एक बिल्ट-इन preset का उपयोग करें:
assistant— सामान्य-उद्देश्य helpful assistant (डिफ़ॉल्ट)focused— Concise, direct responsescustomer-service— विनम्र, समाधान-उन्मुख support एजेंटteacher— धैर्यवान, explanatory teaching style
CLI उपयोग
एक ऑडियो input से एक spoken response उत्पन्न करें:
# Basic speech-to-speech
.build/release/speech respond --input question.wav
# Choose a voice preset
.build/release/speech respond --input question.wav --voice NATM0
# Stream audio output during generation
.build/release/speech respond --input question.wav --stream
# Custom system prompt text
.build/release/speech respond --input question.wav --system-prompt-text "You enjoy having a good conversation."
# Use a preset system prompt
.build/release/speech respond --input question.wav --system-prompt customer-service
# Get transcript alongside audio
.build/release/speech respond --input question.wav --transcript
# JSON output with metadata
.build/release/speech respond --input question.wav --json
विकल्प
| विकल्प | विवरण |
|---|---|
--input | Input ऑडियो फ़ाइल (WAV, आवश्यक) |
--voice | Voice preset नाम (जैसे, NATM0, VARF2) |
--system-prompt | System prompt preset: assistant, focused, customer-service, teacher |
--system-prompt-text | Custom system prompt text (--system-prompt को override करता है) |
--max-steps | अधिकतम generation steps |
--stream | Generation के दौरान ऑडियो chunks उत्सर्जित करें |
--compile | तेज़ generation के लिए MLX compiled inference का उपयोग करें |
--transcript | ऑडियो के साथ text transcript output करें |
--json | मेटाडेटा के साथ JSON आउटपुट |
Sampling पैरामीटर भी override किए जा सकते हैं:
| विकल्प | डिफ़ॉल्ट | विवरण |
|---|---|---|
--audio-temp | 0.8 | Audio token sampling temperature |
--audio-top-k | 250 | Audio token top-k sampling |
--text-temp | 0.7 | Text token sampling temperature |
--text-top-k | 25 | Text token top-k sampling |
Streaming
--stream flag रियल-टाइम ऑडियो आउटपुट सक्षम करता है। ऑडियो chunks उत्पन्न होने के साथ उत्सर्जित होते हैं, इसलिए playback पूर्ण response पूरा होने से पहले शुरू हो सकता है। यह विशेष रूप से interactive applications के लिए उपयोगी है जहाँ low latency मायने रखता है।
परफ़ॉर्मेंस
| मेट्रिक | मान |
|---|---|
| Real-time factor (RTF) | ~1.4 (8-bit, near real-time) |
| Step latency | M2 Max पर ~112 ms/step (8-bit) |
| मॉडल आकार (8-bit) | ~9.1 GB |
| Peak RAM (8-bit) | ~11 GB |
| मॉडल आकार (4-bit) | ~4.9 GB |
| Peak RAM (4-bit) | ~7 GB |
PersonaPlex 7B (8-bit) को कम से कम 24 GB RAM की आवश्यकता है। 4-bit वेरिएंट 16 GB डिवाइस पर फिट होता है लेकिन degraded output उत्पन्न करता है। 8 GB डिवाइस पर, कोई भी वेरिएंट फिट नहीं होगा। समर्थित हार्डवेयर पर सर्वश्रेष्ठ परफ़ॉर्मेंस के लिए --compile का उपयोग करें।
मॉडल वेरिएंट
| मॉडल | आकार | HuggingFace |
|---|---|---|
| PersonaPlex-7B (8-bit) अनुशंसित | 9.1 GB | aufklarer/PersonaPlex-7B-MLX-8bit |
| PersonaPlex-7B (4-bit) | 4.9 GB | aufklarer/PersonaPlex-7B-MLX-4bit |
Swift API
import PersonaPlex
import AudioCommon
let model = try await PersonaPlexModel.fromPretrained()
let response = model.respond(
userAudio: userSamples,
voice: .NATM0,
systemPrompt: "You are a helpful assistant."
)
try WAVWriter.write(samples: response.audio, sampleRate: 24000, to: URL(filePath: "answer.wav"))