PersonaPlex

نموذج حوار كلام إلى كلام ثنائي الاتجاه كامل مبني على بنية Moshi (Kyutai). يولّد PersonaPlex 7B ردودًا منطوقة مباشرةً من المدخل المنطوق — دون خط أنابيب نصّي وسيط. يأتي النموذج مع 18 إعدادًا صوتيًا مسبقًا، ومتوفّر بتكميم 8-bit (المُوصى به) و4-bit. إعداد 8-bit هو الافتراضي — فهو أسرع بنسبة 30 % وينتج ردودًا متماسكة، بينما يُضعف 4-bit جودة المخرجات.

البنية المعمارية

PersonaPlex نموذج انحداري ذاتي متعدّد المسارات يضمّ ثلاثة مكوّنات أساسية:

المكوّنالتفاصيل
Temporal Transformer32 طبقة، dim=4096، 32 رأسًا، SwiGLU (hidden_scale=4.125)، RoPE، مكمَّم إلى 8-bit (افتراضيًا)
Depformer6 طبقات، dim=1024، 16 رأسًا، MultiLinear (weights_per_step=true)، dep_q=16
Mimi Codec16 codebook، معدّل إطارات 12.5 Hz، مخرج صوتي بتردّد 24 kHz

يعالج النموذج 17 مسارًا في آنٍ واحد: مسار نصّي واحد + 8 مسارات صوتية للمستخدم + 8 مسارات صوتية للوكيل. تتيح هذه البنية محادثة ثنائية الاتجاه كاملة يمكن فيها للنموذج أن يستمع ويتحدّث في الوقت ذاته.

الإعدادات الصوتية المسبقة

يحتوي PersonaPlex على 18 إعدادًا صوتيًا مدمجًا بأساليب طبيعية ومتنوّعة:

الفئةالإعدادات
أنثوي طبيعيNATF0, NATF1, NATF2, NATF3
ذكوري طبيعيNATM0, NATM1, NATM2, NATM3
أنثوي متنوّعVARF0, VARF1, VARF2, VARF3, VARF4
ذكوري متنوّعVARM0, VARM1, VARM2, VARM3, VARM4

المونولوج الداخلي

يولّد PersonaPlex مسارين متوازيين في كلّ خطوة: 8 رموز codebook صوتية لـ Mimi codec ورمز نصّي واحد للمونولوج الداخلي للنموذج. مسار النصّ هو ما “يفكّر” به النموذج أثناء حديثه — قد يتباعد قليلًا عن الصوت النهائي، لكنّه في الواقع يعكس الردّ المنطوق بدقّة كافية لاستخدامه تفريغًا مباشرًا.

تعود رموز النصّ على هيئة معرّفات قِطَع SentencePiece خام. فكّكها باستخدام SentencePieceDecoder الذي يأتي مع 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

في وضع البثّ، يُصدر respondStream أجزاء textTokens فور إنتاجها — فكّكها تدريجيًا لتغذية عرض ترجمات حيّ بينما لا يزال الصوت يتولّد. يفعل خيار --transcript في الـ CLI هذا تمامًا خلف الكواليس.

لماذا هذا مهمّ: يُبنى SentencePieceDecoder على قارئ protobuf المشترك AudioCommon.SentencePieceModel، لذلك يفكّك PersonaPlex وOmnilingualASR وأيّ نموذج مستقبلي مبني على SentencePiece عبر نفس تنفيذ المُرمِّز. راجع مرجع SentencePieceModel.

تلقينات النظام

مرّر أيّ تلقين نظام مخصّص كسلسلة نصّية بسيطة — دون حاجة إلى ترميز خارجي:

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

أو استخدم إعدادًا مدمجًا:

استخدام CLI

توليد ردّ منطوق من مُدخل صوتي:

# 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ملف الصوت المُدخل (WAV، إلزامي)
--voiceاسم الإعداد الصوتي (مثل NATM0، VARF2)
--system-promptإعداد تلقين النظام: assistant، focused، customer-service، teacher
--system-prompt-textنصّ تلقين نظام مخصّص (يطغى على --system-prompt)
--max-stepsالحدّ الأقصى لخطوات التوليد
--streamإصدار أجزاء صوتية أثناء التوليد
--compileاستخدام استدلال MLX المُصرَّف لتوليد أسرع
--transcriptإخراج التفريغ النصّي بجوار الصوت
--jsonإخراج JSON مع بيانات وصفية

يمكن أيضًا تعديل معاملات الاعتيان:

الخيارالافتراضيالوصف
--audio-temp0.8درجة حرارة اعتيان رموز الصوت
--audio-top-k250اعتيان top-k لرموز الصوت
--text-temp0.7درجة حرارة اعتيان رموز النصّ
--text-top-k25اعتيان top-k لرموز النصّ

البثّ

يُفعِّل خيار --stream إخراج الصوت في الزمن الحقيقي. تُصدَر أجزاء الصوت بمجرّد توليدها، فيمكن بدء التشغيل قبل اكتمال الردّ كاملًا. وهذا مفيد بشكل خاصّ للتطبيقات التفاعلية التي يهمّ فيها الزمن المنخفض.

الأداء

المقياسالقيمة
عامل الزمن الحقيقي (RTF)~1.4 (8-bit، قريب من الزمن الحقيقي)
زمن الخطوة~112 ms/خطوة على M2 Max (8-bit)
حجم النموذج (8-bit)~9.1 GB
ذروة الذاكرة (8-bit)~11 GB
حجم النموذج (4-bit)~4.9 GB
ذروة الذاكرة (4-bit)~7 GB
مهمّ

يتطلّب PersonaPlex 7B (8-bit) ما لا يقلّ عن 24 GB من الذاكرة. تتّسع نسخة 4-bit للأجهزة ذات 16 GB لكنّها تنتج مخرجات أدنى جودة. على الأجهزة ذات 8 GB لن تتّسع أيّ نسخة. استخدم --compile للحصول على أفضل أداء على العتاد المدعوم.

متغيّرات النموذج

النموذجالحجمHuggingFace
PersonaPlex-7B (8-bit) مُوصى به9.1 GBaufklarer/PersonaPlex-7B-MLX-8bit
PersonaPlex-7B (4-bit)4.9 GBaufklarer/PersonaPlex-7B-MLX-4bit

واجهة 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")