PersonaPlex
Modelo de diálogo voz a voz full-duplex basado en la arquitectura Moshi (Kyutai). PersonaPlex 7B genera respuestas habladas directamente a partir de la entrada hablada — sin pipeline intermedio de texto. El modelo incluye 18 presets de voz y está disponible con cuantización de 8 bits (recomendada) y 4 bits. 8 bits es el valor por defecto — es un 30 % más rápido y produce respuestas coherentes, mientras que 4 bits degrada la calidad de la salida.
Arquitectura
PersonaPlex es un modelo autorregresivo multi-stream con tres componentes principales:
| Componente | Detalles |
|---|---|
| Temporal Transformer | 32 capas, dim=4096, 32 cabezas, SwiGLU (hidden_scale=4.125), RoPE, cuantizado a 8 bits (por defecto) |
| Depformer | 6 capas, dim=1024, 16 cabezas, MultiLinear (weights_per_step=true), dep_q=16 |
| Codec Mimi | 16 codebooks, frame rate de 12.5 Hz, salida de audio a 24 kHz |
El modelo procesa 17 streams simultáneamente: 1 stream de texto + 8 streams de audio del usuario + 8 streams de audio del agent. Esta arquitectura permite la conversación full-duplex en la que el modelo puede escuchar y hablar al mismo tiempo.
Presets de voz
PersonaPlex incluye 18 presets de voz integrados con estilos naturales y variados:
| Categoría | Presets |
|---|---|
| Femenino natural | NATF0, NATF1, NATF2, NATF3 |
| Masculino natural | NATM0, NATM1, NATM2, NATM3 |
| Femenino variado | VARF0, VARF1, VARF2, VARF3, VARF4 |
| Masculino variado | VARM0, VARM1, VARM2, VARM3, VARM4 |
Monólogo interno
PersonaPlex genera dos streams paralelos en cada paso: 8 tokens de codebook de audio para el codec Mimi y un token de texto para el monólogo interno del modelo. El stream de texto es lo que el modelo está “pensando” mientras habla — puede divergir ligeramente del audio final, pero en la práctica refleja la respuesta hablada con suficiente fidelidad como para usarlo como transcripción en vivo.
Los tokens de texto se devuelven como IDs de piezas SentencePiece en crudo. Decodifícalos con el SentencePieceDecoder que incluye PersonaPlex:
import PersonaPlex
import AudioCommon
let model = try await PersonaPlexModel.fromPretrained()
let decoder = try model.makeTextDecoder() // SentencePieceDecoder
let result = model.respondWithTranscript(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
En modo streaming, respondStream emite chunks de textTokens según se van produciendo — decodifícalos de forma incremental para alimentar una vista de subtítulos en vivo mientras el audio sigue generándose. El flag --transcript de la CLI hace exactamente esto por detrás.
Por qué importa: SentencePieceDecoder está construido sobre el lector de protobuf compartido AudioCommon.SentencePieceModel, así que PersonaPlex, OmnilingualASR y cualquier futuro modelo basado en SentencePiece decodifican a través de la misma implementación del tokenizador. Consulta la referencia de SentencePieceModel.
Prompts del sistema
Pasa cualquier prompt del sistema personalizado como una simple cadena de texto — no hace falta tokenización externa:
let response = model.respond(
userAudio: audio,
voice: .NATM0,
systemPrompt: "You enjoy having a good conversation."
)
O usa un preset integrado:
assistant— Asistente útil de propósito general (por defecto)focused— Respuestas concisas y directascustomer-service— Agente de soporte educado y orientado a solucionesteacher— Estilo docente paciente y explicativo
Uso de la CLI
Genera una respuesta hablada a partir de una entrada de audio:
# Basic speech-to-speech
.build/release/audio respond --input question.wav
# Choose a voice preset
.build/release/audio respond --input question.wav --voice NATM0
# Stream audio output during generation
.build/release/audio respond --input question.wav --stream
# Custom system prompt text
.build/release/audio respond --input question.wav --system-prompt-text "You enjoy having a good conversation."
# Use a preset system prompt
.build/release/audio respond --input question.wav --system-prompt customer-service
# Get transcript alongside audio
.build/release/audio respond --input question.wav --transcript
# JSON output with metadata
.build/release/audio respond --input question.wav --json
Opciones
| Opción | Descripción |
|---|---|
--input | Archivo de audio de entrada (WAV, obligatorio) |
--voice | Nombre del preset de voz (p. ej., NATM0, VARF2) |
--system-prompt | Preset de prompt del sistema: assistant, focused, customer-service, teacher |
--system-prompt-text | Texto personalizado del prompt del sistema (sobrescribe --system-prompt) |
--max-steps | Pasos máximos de generación |
--stream | Emite chunks de audio durante la generación |
--compile | Usa inferencia compilada de MLX para una generación más rápida |
--transcript | Emite la transcripción de texto junto al audio |
--json | Salida JSON con metadatos |
Los parámetros de sampling también se pueden sobrescribir:
| Opción | Por defecto | Descripción |
|---|---|---|
--audio-temp | 0.8 | Temperatura de sampling de tokens de audio |
--audio-top-k | 250 | Top-k sampling para tokens de audio |
--text-temp | 0.7 | Temperatura de sampling de tokens de texto |
--text-top-k | 25 | Top-k sampling para tokens de texto |
Streaming
El flag --stream activa la salida de audio en tiempo real. Los chunks de audio se emiten conforme se generan, por lo que la reproducción puede comenzar antes de que la respuesta completa esté lista. Esto resulta especialmente útil para aplicaciones interactivas donde la baja latencia importa.
Rendimiento
| Métrica | Valor |
|---|---|
| Factor de tiempo real (RTF) | ~1.4 (8 bits, casi en tiempo real) |
| Latencia por paso | ~112 ms/paso en M2 Max (8 bits) |
| Tamaño del modelo (8 bits) | ~9.1 GB |
| RAM máxima (8 bits) | ~11 GB |
| Tamaño del modelo (4 bits) | ~4.9 GB |
| RAM máxima (4 bits) | ~7 GB |
PersonaPlex 7B (8 bits) requiere al menos 24 GB de RAM. La variante de 4 bits cabe en dispositivos con 16 GB pero produce una salida degradada. En dispositivos con 8 GB no cabe ninguna de las variantes. Usa --compile para obtener el mejor rendimiento en el hardware compatible.
Variantes del modelo
| Modelo | Tamaño | HuggingFace |
|---|---|---|
| PersonaPlex-7B (8 bits) recomendado | 9.1 GB | aufklarer/PersonaPlex-7B-MLX-8bit |
| PersonaPlex-7B (4 bits) | 4.9 GB | aufklarer/PersonaPlex-7B-MLX-4bit |
API de Swift
import PersonaPlex
let model = try await PersonaPlexModel.loadFromHub()
let response = try await model.respond(
audioFile: "question.wav",
voice: .NATM0,
systemPrompt: .assistant
)
try response.audio.write(to: "answer.wav")