PersonaPlex

Modelo de dialogo fala para fala full-duplex baseado na arquitetura Moshi (Kyutai). PersonaPlex 7B gera respostas faladas diretamente de entrada falada — sem pipeline intermediario de texto. O modelo vem com 18 presets de voz e esta disponivel em quantizacao 8-bit (recomendado) e 4-bit. 8-bit e o padrao — e 30% mais rapido e produz respostas coerentes, enquanto 4-bit degrada a qualidade de saida.

Arquitetura

PersonaPlex e um modelo autoregressivo multi-stream com tres componentes principais:

ComponenteDetalhes
Temporal Transformer32 camadas, dim=4096, 32 heads, SwiGLU (hidden_scale=4.125), RoPE, quantizado em 8-bit (padrao)
Depformer6 camadas, dim=1024, 16 heads, MultiLinear (weights_per_step=true), dep_q=16
Codec Mimi16 codebooks, frame rate de 12.5 Hz, saida de audio a 24 kHz

O modelo processa 17 streams simultaneamente: 1 stream de texto + 8 streams de audio do usuario + 8 streams de audio do agente. Esta arquitetura permite conversa full-duplex onde o modelo pode ouvir e falar ao mesmo tempo.

Presets de voz

PersonaPlex inclui 18 presets de voz integrados em estilos naturais e variados:

CategoriaPresets
Feminino naturalNATF0, NATF1, NATF2, NATF3
Masculino naturalNATM0, NATM1, NATM2, NATM3
Feminino variadoVARF0, VARF1, VARF2, VARF3, VARF4
Masculino variadoVARM0, VARM1, VARM2, VARM3, VARM4

Monologo interno

PersonaPlex gera dois streams paralelos a cada passo: 8 tokens de codebook de audio para o codec Mimi e um token de texto para o monologo interno do modelo. O stream de texto e o que o modelo esta “pensando” enquanto fala — ele pode divergir ligeiramente do audio final, mas na pratica espelha a resposta falada de perto o suficiente para usar como transcricao ao vivo.

Os tokens de texto voltam como IDs brutos de pieces do SentencePiece. Decodifique-os com o SentencePieceDecoder que o PersonaPlex fornece:

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

No modo streaming, respondStream emite chunks textTokens conforme sao produzidos — decodifique-os incrementalmente para alimentar uma visualizacao de legendas ao vivo enquanto o audio ainda esta sendo gerado. A flag CLI --transcript faz exatamente isso por baixo dos panos.

Por que importa: SentencePieceDecoder e construido sobre o leitor protobuf compartilhado AudioCommon.SentencePieceModel, entao PersonaPlex, OmnilingualASR e qualquer futuro modelo baseado em SentencePiece decodificam pela mesma implementacao de tokenizer. Veja a referencia do SentencePieceModel.

System prompts

Passe qualquer system prompt customizado como uma string simples — sem tokenizacao externa necessaria:

let response = model.respond(
    userAudio: audio,
    voice: .NATM0,
    systemPrompt: "You enjoy having a good conversation."
)

Ou use um preset integrado:

Uso do CLI

Gerar uma resposta falada a partir de uma 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

Opcoes

OpcaoDescricao
--inputArquivo de audio de entrada (WAV, obrigatorio)
--voiceNome do preset de voz (por exemplo, NATM0, VARF2)
--system-promptPreset de system prompt: assistant, focused, customer-service, teacher
--system-prompt-textTexto de system prompt customizado (sobrescreve --system-prompt)
--max-stepsMaximo de passos de geracao
--streamEmitir chunks de audio durante a geracao
--compileUsar inferencia compilada MLX para geracao mais rapida
--transcriptEmitir a transcricao de texto junto com o audio
--jsonSaida JSON com metadados

Parametros de sampling tambem podem ser sobrescritos:

OpcaoPadraoDescricao
--audio-temp0.8Temperatura de sampling de tokens de audio
--audio-top-k250Sampling top-k de tokens de audio
--text-temp0.7Temperatura de sampling de tokens de texto
--text-top-k25Sampling top-k de tokens de texto

Streaming

A flag --stream habilita saida de audio em tempo real. Os chunks de audio sao emitidos conforme sao gerados, entao a reproducao pode comecar antes da resposta completa terminar. Isso e particularmente util para aplicacoes interativas onde baixa latencia importa.

Desempenho

MetricaValor
Fator de tempo real (RTF)~1.4 (8-bit, proximo de tempo real)
Latencia por passo~112 ms/passo em M2 Max (8-bit)
Tamanho do modelo (8-bit)~9.1 GB
RAM de pico (8-bit)~11 GB
Tamanho do modelo (4-bit)~4.9 GB
RAM de pico (4-bit)~7 GB
Importante

PersonaPlex 7B (8-bit) requer pelo menos 24 GB de RAM. A variante 4-bit cabe em dispositivos de 16 GB mas produz saida degradada. Em dispositivos de 8 GB, nenhuma das variantes cabera. Use --compile para melhor desempenho em hardware suportado.

Variantes do modelo

ModeloTamanhoHuggingFace
PersonaPlex-7B (8-bit) recomendado9.1 GBaufklarer/PersonaPlex-7B-MLX-8bit
PersonaPlex-7B (4-bit)4.9 GBaufklarer/PersonaPlex-7B-MLX-4bit

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