چیت‌شیت

دستیارهای صوتی بی‌درنگ (Real-Time)

Real-Time Voice Assistants

VAD، تشخیص نوبت مکالمه، ورود ناگهانی به کلام (barge-in)، سقف تاخیر و گفتار تمام‌دوطرفه برای ایجنت صوتی با پاسخ‌دهی به‌موقع.

  • ۱۲ بخش
  • ۶ درس مرتبط
  • کد و دستورها عیناً از دوره‌ی اصلی
فهرست مطالب
  1. پایپ‌لاین صوتی آبشاری
  2. اسکژولر پروژه نهایی، یک نوبت گفت‌وگو
  3. سقف تاخیر در هر نوبت گفت‌وگو
  4. تنظیمات VAD و نوبت مکالمه
  5. بخش‌های Silero VAD
  6. ورود ناگهانی به کلام (barge-in) و ترفند تخلیه
  7. اجرای درس‌ها
  8. اصطلاحات کلیدی
  9. مدل تمام‌دوطرفه Moshi، یک گام 80 ms
  10. عیب‌یابی
  11. واژه‌نامه
  12. پرسش و پاسخ

پایپ‌لاین صوتی آبشاری

معماری
فریم‌هاگفتاررونویسی‌های ناقصcommitفراخوانیتوکن‌هاصوتلغو با ورود ناگهانی به کلام (barge-in)میکروفون16 kHz مونو، 20 msVADSilero، گیت گفتارSTT استریمینگرونویسی‌های ناقص (partials)تشخیص‌دهنده نوبت مکالمهامتیاز بالاتر از 0.6LLM با ابزارهااستریم توکن‌هاکانال جانبی ابزارعبارت پرکننده بعد از 300msTTS استریمینگاولین چانک در 200msبلندگوبافر لرزش WebRTC

اسکژولر پروژه نهایی، یک نوبت گفت‌وگو

گام‌به‌گام
  1. IDLEاولین فریم گفتار وضعیت را به LISTENING می‌برد.
  2. LISTENINGهر فریم سکوت 20 ms به silenceRunMs اضافه می‌کند.
  3. LISTENINGدر 500 ms سکوت، turnCompletionScore آخرین متن ناقص را می‌خواند.
  4. WAITINGامتیاز 0.6 یا بیشتر نوبت را commit می‌کند و turnCompleteMs را تنظیم می‌کند.
  5. THINKINGفراخوانی ابزار اجرا می‌شود. در 300 ms ایجنت می‌گوید: «یک لحظه، بگذارید بررسی کنم».
  6. THINKINGابزار در 420 ms برمی‌گردد. اولین توکن LLM حدود 140 ms بعد می‌رسد.
  7. SPEAKINGاولین صوت خروجی 180 ms پس از اولین توکن LLM صادر می‌شود.
  8. Barge-inگفتار حین THINKING یا SPEAKING باعث لغو TTS و فعال‌سازی مجدد ASR می‌شود.

سقف تاخیر در هر نوبت گفت‌وگو

پیش‌فرض‌ها
تنظیمپیش‌فرضنکته
Mic to buffer20 msیک فریم
VAD10 msاجرای Silero زیر 1 ms در هر فریم
ASR (streaming)150 msرونویسی‌های ناقص
LLM (first token)100 msاستریم توکن‌ها
TTS (first chunk)100 msشروع قبل از تکمیل کل پاسخ
Render to speaker20 msیک فریم
Total~400 msبالای 500 ms حس رباتیک ایجاد می‌کند
First TTS audio, laptop CPU800 msهدف پروژه نهایی فاز 6

تنظیمات VAD و نوبت مکالمه

پیش‌فرض‌ها
تنظیمپیش‌فرضنکته
Silero threshold0.5مقدار 0.3 حساس است؛ برش خوردن کلمه اول کمتر می‌شود
Minimum speech250 msحذف صدای سرفه و جابه‌جایی صندلی
Silence hangover500-800 msمقدار خیلی کم کلام کاربر را قطع می‌کند
Pre-roll buffer300-500 msکلمه اول را حفظ می‌کند
Energy gate-40 dBFSبا هر نویزی بالاتر از آن فعال می‌شود
Frame size20 ms320 نمونه در 16 kHz
Ring buffer32,000 samples2 s در 16 kHz
Turn commit (capstone)0.6به‌علاوه 500ms سکوت VAD

بخش‌های Silero VAD

کد
python
from silero_vad import load_silero_vad, get_speech_timestamps
vad = load_silero_vad()
audio = torch.tensor(waveform_16k, dtype=torch.float32)
segments = get_speech_timestamps(
    audio, vad, sampling_rate=16000,
    threshold=0.5,                # 0.3 حساس است
    min_speech_duration_ms=250,   # سرفه‌ها را حذف می‌کند
    min_silence_duration_ms=500,  # مهلت سکوت
    speech_pad_ms=300,            # پد بافر پیش از کلام
)
for s in segments:
    print(f"{s['start']/16000:.2f}s - {s['end']/16000:.2f}s")

ورود ناگهانی به کلام (barge-in) و ترفند تخلیه

کد
python
tts_task = asyncio.create_task(tts_loop())
while True:
    chunk = await mic.get()
    if vad(chunk):           # کاربر حین پخش TTS صحبت می‌کند
        tts_task.cancel()    # توقف پاسخ
        await speaker.stop()
        await new_turn()     # راه‌اندازی مجدد STT
        break

def flush_on_end(stt_client, audio_buffer):
    stt_client.send_audio(audio_buffer)
    stt_client.send_flush()  # اجبار به خروجی فوری
    return stt_client.recv_transcript(timeout_ms=150)

اجرای درس‌ها

دستورها
دستورکارکرد
python3 code/main.pyاجرای شبیه‌ساز یک درس
python main.pyاسکژولر پروژه نهایی، تماس‌های عادی و barge-in
pip install silero-vadاستفاده از VAD واقعی به جای استاب
npm installنصب کلاینت TypeScript
npm startدو نشست آفلاین و یک آزمون ارزیابی ws، خروج با 0
npm start -- --serveروشن نگه داشتن سرور ws
npm testاجراکننده node --test از طریق tsx
npm run typecheckاجرای tsc --noEmit

اصطلاحات کلیدی

مفهوم‌ها
Ring buffer
بافر حلقوی ثابت؛ بدون تخصیص حافظه در مسیر اجرای سریع (hot path).
Jitter buffer
مرتب‌سازی مجدد بسته‌های دیرهنگام؛ خیلی کوچک باعث بریدگی صوتی و خیلی بزرگ باعث تاخیر می‌شود.
Pre-roll
بافر پیش از کلام برای نگهداری صوت قبل از فعال‌شدن VAD؛ مانع از بریده‌شدن ابتدای کلمه اول می‌شود.
Silence hangover
مهلت سکوت؛ مدت انتظار پس از بازگشت VAD به 0، پیش از پایان نوبت.
Semantic endpoint
کلاسیفایری که علاوه‌بر سکوت، کلمات اداشده را نیز بررسی می‌کند.
Flush trick
ترفند تخلیه STT در پایان گفتار؛ 500 ms پیش‌نگری به حدود ~125 ms کاهش می‌یابد.
Filler
عبارت پرکننده کوتاه هنگام طول کشیدن ابزار بیش از 300ms.
DOWNSTREAM
فریم‌های Pipecat از مبدا به مقصد؛ ورودی صدا و خروجی گفتار.
UPSTREAM
فریم‌های کنترلی Pipecat؛ شامل لغو، معیارها و barge-in.

مدل تمام‌دوطرفه Moshi، یک گام 80 ms

گام‌به‌گام
  1. Mimiانکود صوت کاربر در 12.5 Hz با 8 کتاب کد.
  2. Temporal Transformerمدل 7B پارامتری؛ خواندن توکن‌های کاربر و آخرین توکن‌های خود مدل.
  3. Temporal Transformerتولید توکن متنی بعدی، همان تک‌گویی درونی.
  4. Depth Transformerدارای 2 لایه؛ پیش‌بینی متوالی 8 کتاب کد، یکی پس از دیگری.
  5. Clientتابع decode_audio_mimi توکن‌ها را به صوت تبدیل و پخش می‌کند.
  6. Budgetفریم 80 ms به‌علاوه 80 ms تاخیر آکوستیک برابر 160 ms است؛ 200 ms روی یک پردازنده L4 GPU.

عیب‌یابی

عیب‌یابی
  • کلمه اول جا می‌افتد

    علت
    شروع VAD با کمی تاخیر
    راه‌حل
    آستانه 0.3 و بافر پیش از کلام (pre-roll)
  • ایجنت روی کلام کاربر صحبت می‌کند

    علت
    ادامه کار LLM بعد از وقفه
    راه‌حل
    اتصال مستقیم VAD به لغو اجرای LLM
  • شنیدن «Thanks for watching» روی سکوت

    علت
    اجرای Whisper روی فریم‌های سکوت
    راه‌حل
    اعمال همیشگی گیت VAD
  • ASR صدای خود ربات را می‌شنود

    علت
    عدم حذف اکو
    راه‌حل
    WebRTC AEC3
  • ایجنت کلام کاربر را اواسط جمله قطع می‌کند

    علت
    مهلت سکوت (hangover) بسیار کوتاه است
    راه‌حل
    تنظیم روی 500-800 ms همراه تشخیص‌دهنده نوبت مکالمه
  • پاسخ اول کند است

    علت
    آماده‌سازی اولیه (warm-up) مدل TTS در اولین درخواست
    راه‌حل
    پیش‌گرم کردن با یک اجرای تستی (dummy run)
  • دست‌سازه‌های صوتی ووکوودر شنیده می‌شود

    علت
    چانک‌های TTS زیر 200 ms
    راه‌حل
    استفاده از چانک‌های 320 ms
  • قطعی و بریدگی صدا زیر بار پردازشی

    علت
    انسداد ترد صدا توسط GIL
    راه‌حل
    کتابخانه صوتی مبتنی بر C-callback

واژه‌نامه

اصطلاح‌ها
AEC
حذف اکو؛ حذف صدای بلندگو از ورودی میکروفون.
TPR @ 5% FPR
معیار ارزیابی VAD؛ مدل Silero حدود 87.7% و WebRTC VAD حدود 50.0%.
MultimodalAgent
کلاس LiveKit؛ ورودی صوت، خروجی صوت، بدون متن در میانه مسیر.
VoicePipelineAgent
کلاس LiveKit؛ اجرای STT، LLM و TTS با کنترل در سطح متن.

پرسش و پاسخ

پرسش و پاسخ
سرعت تعویض نوبت در انسان چقدر است؟
حدود 230 ms؛ بالاتر از 1500 ms حس خرابی می‌دهد.
پایپ‌لاین یا Moshi؟
برای ابزارها از پایپ‌لاین استفاده کنید؛ Moshi برای فراخوانی ابزار آموزش ندیده است.
چرا در استریمینگ Whisper ترفند تخلیه کار نمی‌کند؟
چون بلوک‌محور است و همیشه منتظر چانک‌ها می‌ماند.
تاخیر سرتاسری تراز اول چقدر است؟
450 تا 600 ms؛ بازه 800 تا 1200 ms رایج است.
معیار قبولی پروژه نهایی چیست؟
صدک p50 زمان رسیدن اولین صوت زیر 800ms، قطع نابه‌جا زیر 3%.
قابلیت barge-in در Pipecat به چه چیزی نیاز دارد؟
فریم‌های لغو UPSTREAM به سمت TTS و LLM.