arc/docs/AI_VOICE_CHAT_UPGRADE_SCENARIO.md
2026-08-18 17:20:26 +00:00

31 KiB
Raw Permalink Blame History

ارتقای چت صوتی ایجنت — STT، TTS، کاتالوگ مدیریت، ارائه‌دهندگان ابری

تاریخ بررسی: ۱۴۰۵/۰۵/۲۸ (۱۸ اوت ۲۰۲۶)
وضعیت: فازهای ۰–۵ و ۷ پیاده شده‌اند (cascade). فاز ۶ Realtime عمداً انجام نشده.
هدف سند: نقشهٔ پیاده‌سازی تدریجی تا سطح ایجنت صوتی حرفه‌ای (مرجع: ChatGPT Advanced Voice / OpenAI Realtime)
مراجع موجود: AI_VOICE_CHAT_IMPLEMENTATION.md (وضعیت فعلی)، AI_AGENT_SYSTEM_AUDIT.md (VOI-01، VOI-02، GAP-06)

این سند را بعد از هر فاز با وضعیت ✓ و یک سطر تاریخچه به‌روز کنید.

فاز وضعیت
۰ قرارداد + fallback env ✓
۱ کاتالوگ ادمین + catalog کاربر ✓
۲ ابر OpenAI + سیاست fail-closed ✓
۳ دیکته + بلندخوانی + chip STT/TTS ✓
۴ تماس = همان ایجنت (session/model/mode/approval) ✓
۵ متریک، سقف جلسه، Whisper اشتراکی ✓ (نمونهٔ WER طلایی باقی است)
۶ Realtime speech-to-speech عمداً انجام نشده
۷ لاگ مصرف صوت ✓ جزئی (بدون سهمیهٔ دقیقهٔ جدا در پلن)

۱. جمع‌بندی سریع

قابلیت در سیستم امروز کجا شکاف با سطح ChatGPT
گفت‌وگوی صوتی دوطرفه هست (آبشار محلی) WS /ws/ai/voice latency بالا؛ کیفیت فارسی پایین‌تر از ابر؛ بدون speech-to-speech
صدا → متن (STT) فقط داخل همان جلسهٔ صوت faster-whisper روی سرور، مدل small از env دیکته در باکس متن نیست؛ partial transcript نیست؛ ابر نیست
متن → صدا (TTS) فقط داخل همان جلسهٔ صوت Piper / Coqui / پیش‌فرض dummy (سکوت) خواندن پیام متنی نیست؛ انتخاب صدا نیست؛ ابر نیست
مدیریت ادمین مثل مدل متنی نیست مدل متن: جدول ai_models + صفحهٔ ادمین + credential صوت فقط ENV (VOICE_*)؛ کاربر مدل/صدا انتخاب نمی‌کند
ارائه‌دهندهٔ API (OpenAI و …) فقط برای LLM متن ai_provider_credentials هیچ adapter برای Whisper/TTS/Realtime ابری
ایجنت حین صوت (ابزار، تأیید نوشتن، مدل انتخابی) ناقص voice_ws حلقه را بدون session_id / execution_mode / request_model صدا می‌زند نوشتن بی‌تأیید یا بی‌کارت؛ trace متنی دیده نمی‌شود
سوییچ متن ↔ صوت در یک جلسه قفل composer هنگام صوت enabled: false ChatGPT در همان thread هم تایپ می‌کند هم حرف می‌زند

نتیجه: زیرساخت صوت وجود دارد و پخته است (VAD، WS، فشرده‌سازی وب، barge-in پروتکلی، بازخورد کیفیت). آنچه کم است محصول است نه اسکلت: سه حالت استفاده (تماس / دیکته / بلندخوانی)، کاتالوگ قابل مدیریت، کیفیت ابری اختیاری، و هم‌ترازی حلقهٔ ایجنت با چت متنی.


۲. آنچه در کد هست (واقعیت امروز)

۲.۱ معماری فعلی — آبشار (cascade)، نه Realtime

میکروفون کلاینت (PCM16 16kHz یا WebM/Opus)
    → WebSocket /ws/ai/voice  (auth در اولین فریم JSON)
    → VAD محلی (webrtcvad) + endpointing سکوت
    → STT محلی faster-whisper  (کل utterance یکجا؛ بدون streaming)
    → همان LLM ایجنت: AIService.chat_completion_stream
    → TextChunker جمله/۱۴۰ کاراکتر
    → TTS محلی Piper (یا dummy/coqui) → فریم PCM به کلاینت
    → پیام user/assistant در همان جلسهٔ چت ذخیره می‌شود

این همان «Standard Voice» قدیمی ChatGPT است (صدا→متن→مدل→صدا)، نه Advanced Voice / Realtime که مدل مستقیماً روی صوت فکر می‌کند.

فایل‌های اصلی:

لایه مسیر
WS و ارکستراسیون hesabixAPI/adapters/api/v1/ai/voice_ws.py
STT hesabixAPI/app/services/voice/stt.py (WhisperSTT)
TTS hesabixAPI/app/services/voice/tts.py (TTSFactory: piper / coqui / dummy)
VAD hesabixAPI/app/services/voice/vad.py
تنظیمات hesabixAPI/app/core/settings.py فیلدهای voice_*
بازخورد POST /api/v1/ai/voice/interactions/{id}/feedback + جدول ai_voice_interactions
کلاینت VoiceChatController (io/web) + AIChatVoiceSessionController + composer میکروفون

۲.۲ سه حالت محصول — امروز فقط یکی هست

کاربر و محصول به هر دو STT و TTS نیاز دارند، ولی نه لزوماً همیشه با هم:

حالت معنی برای کاربر امروز
A — تماس صوتی مثل تماس ChatGPT: حرف می‌زند، ایجنت جواب می‌دهد با صدا هست (آبشار محلی)
B — دیکته (STT alone) دکمهٔ میکروفون متن را داخل composer می‌گذارد؛ کاربر ویرایش و ارسال می‌کند نیست؛ میکروفون مستقیم تماس را شروع می‌کند
C — بلندخوانی (TTS alone) روی پیام دستیار «بخوان»؛ بدون میکروفون نیست

هدف ارتقا: هر سه حالت روی یک کاتالوگ STT/TTS سوار شوند. تماس صوتی هر دو را با هم مصرف می‌کند؛ دیکته و بلندخوانی جداگانه‌اند.

۲.۳ مدیریت ادمین: الگوی مدل متنی هست؛ صوت از آن جدا مانده

مدل‌های متنی (الگوی درست برای کپی):

  • جدول ai_models: code, display_name, provider, model_id, tier, قیمت مرجع، is_active, sort_order
  • API ادمین /admin/ai/models (CRUD + seed از config)
  • صفحهٔ AIModelsAdminPage با provider: openai / anthropic / local / custom
  • اعتبارنامه جدا: ai_provider_credentials (یک کلید per provider، تست اتصال)
  • BYOK کسب‌وکار: business_ai_provider_configs
  • کاربر در composer با AIChatModelChip مدل فعال را برمی‌دارد
  • پلن‌ها مدل‌های مجاز را محدود می‌کنند

صوت امروز:

  • فقط متغیر محیطی: VOICE_ENABLED, VOICE_STT_*, VOICE_TTS_ENGINE, مسیر Piper، …
  • پیش‌فرض TTS در کد: voice_tts_engine = "dummy" → در تولید اگر env ست نشده باشد کاربر سکوت می‌شنود (هشدار UI هست)
  • هیچ ردیف کاتالوگ، هیچ صفحهٔ ادمین، هیچ انتخاب کاربر، هیچ قیمت جدا برای دقیقهٔ صوت
  • credentialهای OpenAI موجود فقط chat completion را تست می‌کنند؛ Whisper/TTS ابری صدا زده نمی‌شوند
  • منوی تنظیمات سیستم دستهٔ «هوش مصنوعی» آیتم صوت ندارد

۲.۴ حلقهٔ ایجنت در مسیر صوت با چت متنی یکی نیست

چت متنی به chat_completion_stream می‌دهد: session_id, request_model, execution_mode, approve_writes, user_query, ادامهٔ run، رویدادهای SSE (trace، approval، citation).

مسیر صوت امروز تقریباً فقط این را صدا می‌زند:

ai_service.chat_completion_stream(
    messages=messages,
    use_function_calling=True,
    session_business_id=business_id,
)

پیامدها:

  • مدل انتخابی کاربر در chip اعمال نمی‌شود (مدل پیش‌فرض config/پلن).
  • execution_mode (تحلیلگر / با تأیید / خودکار) از UI صوت نمی‌آید.
  • approve_writes پیش‌فرض False است؛ ابزار نوشتن در صوت یا متوقف می‌شود یا رویداد awaiting_approval به کلاینت صوت forward نمی‌شود (_forward_agent_chunk فقط status و tool_start را می‌فهمد).
  • session_id نیست → persist run، حافظهٔ جلسه، plan، continuation مثل متن کامل نیست.
  • تایم‌لاین تفکر متنی و صوت دو کانال جدا هستند (VOI-01).
  • شارژ فقط توکن LLM است؛ دقیقهٔ STT/TTS و هزینهٔ ابر ثبت نمی‌شود.

۲.۵ UX و امنیت صوت (جزئیات مفید برای فازها)

آنچه خوب است:

  • Auth WS در query نیست؛ اولین فریم {"type":"auth","api_key"} با timeout ۱۵ ثانیه (ws_api_key_handshake.py) — بخش بزرگی از VOI-02 انجام شده.
  • Barge-in: اگر کاربر وسط TTS حرف بزند cancel_event ست می‌شود؛ کلاینت هم هنگام startRecording دستور barge_in می‌فرستد.
  • ذخیرهٔ PCM فقط با opt-in و voice_data_collection_enabled.
  • سهمیه قبل از start و قبل از هر utterance چک می‌شود.
  • وب: AudioWorklet PCM یا MediaRecorder WebM/Opus.
  • تست واحد تفسیر رویداد: ai_chat_voice_session_test.dart. تست بک‌اند مسیر صوت تقریباً نیست (ARC-06).

آنچه نیست / ضعیف است:

  • Rate limit per user روی WS (VOI-02 باقی‌مانده).
  • Transcript زنده (partial) هنگام حرف زدن کاربر.
  • سوییچ به تایپ وسط تماس بدون قطع جلسه.
  • انتخاب صدا / زبان / کیفیت در UI.
  • محدودیت نرخ و سقف همزمانی اتصال صوت (هر اتصال مدل Whisper را lazy-load می‌کند؛ روی CPU سنگین است).
  • متریک WER / latency perceived.

۳. رفتار مطلوب (سطح ChatGPT / ایجنت حرفه‌ای)

مرجع محصول: ChatGPT (حالت استاندارد + Advanced Voice)، Claude (فعلاً ضعیف‌تر در صوت)، Google Gemini Live.

۳.۱ تجربهٔ کاربر داخل همان جلسهٔ چت

  1. دیکته: نگه داشتن یا یک ضربه روی میکروفون → متن در composer ظاهر می‌شود (قابل ویرایش) → ارسال معمولی با همهٔ قابلیت ایجنت (ابزار، تأیید نوشتن، مدل).
  2. بلندخوانی: روی پیام دستیار «بخوان»؛ قطع با ضربه؛ انتخاب صدا از تنظیمات.
  3. تماس صوتی: دکمهٔ جدا (مثل گوشی ChatGPT) جلسه را به حالت صوت می‌برد ولی تاریخچه همان thread است. کاربر می‌تواند وسط تماس تایپ کند. Transcript زنده در حباب‌ها دیده می‌شود. وقتی ایجنت ابزار می‌زند («دارم موجودی را می‌خوانم») همان وضعیت در نوار صوت و در تایم‌لاین متنی می‌آید.
  4. تأیید نوشتن صوتی: ایجنت بلند می‌گوید «فاکتور فروش برای علی به مبلغ X بسازم؟ بگو تأیید یا رد» و همان کارت تأیید در UI ظاهر می‌شود؛ تا تأیید، write اجرا نشود.
  5. قطع و barge-in: حرف زدن کاربر TTS را فوری قطع کند؛ دکمهٔ پایان تماس قرمز بماند.
  6. انتخاب: مدل زبانی (همان chip موجود) + موتور STT + صدای TTS، محدود به پلن.

Latency هدف تماس آبشاری خوب: شروع شنیدن پاسخ < ۱.۵s برای عبارت کوتاه فارسی (VOI-01). Realtime ابری می‌تواند زیر ۵۰۰ms باشد ولی ابزار و فارسی را سخت‌تر می‌کند.

۳.۲ تجربهٔ مدیر سیستم (مثل مدل‌های متنی)

مدیر در تنظیمات سیستم بتواند:

  • STT محلی (Whisper size/path) یا STT ابری (کلید، مدل، زبان) را ردیف کاتالوگ کند.
  • TTS محلی (Piper voice id) یا TTS ابری (صدا، سرعت، زبان) را ردیف کند.
  • هر ردیف را فعال/غیرفعال، مرتب، قیمت‌گذاری مرجع، و محدود به پلن کند.
  • اتصال را با یک نمونهٔ کوتاه فارسی تست کند (مثل test-connection مدل متنی).
  • پیش‌فرض سراسری و پیش‌فرض پلن تعیین کند.
  • تصمیم بگیرد دادهٔ صوت به ابر برود یا فقط محلی بماند (سیاست حریم خصوصی per business).

کاربر نهایی فقط از کاتالوگ فعال و مجاز پلن انتخاب می‌کند؛ کلید API را نمی‌بیند (مگر BYOK کسب‌وکار در فاز بعدی).

۳.۳ دو مسیر فنی که نباید قاطی شوند

مسیر شرح ابزار ایجنت کیفیت مکالمه هزینه / حریم
Cascade (توصیهٔ پایه) STT → همان حلقهٔ متن → TTS کامل؛ همان ۱۰۰+ ابزار وابسته به کیفیت STT/TTS و latency آبشار قابل کنترل؛ محلی ممکن است
Realtime / speech-to-speech مدل چندرسانه‌ای مستقیم روی صوت (OpenAI Realtime، Gemini Live) باید tool را به جلسهٔ realtime وصل کرد؛ پیچیده‌تر طبیعی‌تر، قطع صحبت نرم‌تر داده به ابر؛ فارسی متغیر؛ هزینهٔ دقیقه

برای حسابیکس (ERP با write guard و ابزار دامنه) Cascade باید مسیر اصلی بماند. Realtime فقط فاز اختیاری برای مکالمهٔ کوتاه بدون نوشتن سنگین است، نه جایگزینی حلقهٔ ایجنت.


۴. پیشنهاد معماری (تکمیل اسکلت فعلی، نه بازنویسی)

۴.۱ لایهٔ Provider جدا از WS

امروز voice_ws.py مستقیماً WhisperSTT و TTSFactory.create می‌سازد. باید پشت یک قرارداد ثابت برود:

STTProvider.transcribe(pcm16, sample_rate, language) -> Transcript
    + اختیاری: transcribe_stream(...) -> partial + final

TTSProvider.synthesize_stream(text, voice_id, cancel) -> PCM frames

VoiceRuntime.resolve(business_id, user_id, session) -> (stt, tts, policy)

پیاده‌سازی‌های اول:

kind پیاده‌سازی منبع تنظیم
local_whisper کد فعلی WhisperSTT کاتالوگ + fallback env
local_piper کد فعلی PiperTTSEngine کاتالوگ + fallback env
dummy سکوت / تست فقط غیرتولید
openai_transcription POST /v1/audio/transcriptions (whisper-1 / gpt-4o-transcribe / gpt-4o-mini-transcribe) credential openai موجود
openai_tts POST /v1/audio/speech (tts-1 / tts-1-hd / gpt-4o-mini-tts) همان credential
بعداً Groq Whisper، Azure Speech، Google Chirp/TTS، ElevenLabs credential جدا در همان جدول با provider جدید

api_base_url فعلی برای gateway سازگار با OpenAI می‌تواند همان transcription/speech را هم پروکسی کند اگر ارائه‌دهنده پشتیبانی کند — در تست اتصال باید جداگانه چک شود.

۴.۲ کاتالوگ داده — پیشنهاد schema

جدول جدید بهتر از شلوغ کردن ai_models است، چون فیلدها فرق دارند (sample rate، voice id، زبان، قیمت per minute / per 1k chars). الگوی نام‌گذاری مثل متن:

ai_voice_models

فیلد نقش
code شناسه پایدار مثلاً stt-local-whisper-small
kind stt | tts | realtime
display_name نام فارسی/انگلیسی برای UI
provider local | openai | azure | google | groq | elevenlabs | custom
model_id شناسهٔ API یا فایل محلی (مثلاً whisper-1, fa_IR-ganji-medium)
language پیش‌فرض fa
voice_id فقط TTS (alloy، ganji، …)
tier basic/pro مثل مدل متن
is_active, sort_order
reference_cost_* مثلاً per_minute یا per_1k_chars
extra_json device/compute_type برای محلی، format خروجی، و …

سیاست انتخاب (ترتیب resolve):

  1. انتخاب صریح کاربر در جلسه (اگر پلن اجازه دهد)
  2. پیش‌فرض پلن
  3. پیش‌فرض فعال سراسری ادمین
  4. fallback ENV فعلی (سازگاری با نصب‌های موجود)

Credential: همان ai_provider_credentials گسترش داده شود (providerهای جدید + فلگ supports_stt / supports_tts / supports_chat) یا در فاز اول از کلید OpenAI موجود برای STT/TTS ابری استفاده شود تا ادمین دو بار کلید نگذارد.

۴.۳ API محصول (علاوه بر WS تماس)

Endpoint پیشنهادی حالت
POST /ai/voice/stt (multipart یا PCM) دیکته؛ پاسخ {text, language}
POST /ai/voice/tts یا SSE/WS کوتاه بلندخوانی یک متن؛ اختیاری stream
GET /ai/voice/catalog لیست STT/TTS مجاز کاربر
WS /ws/ai/voice تماس؛ بعد از فاز ۱ از VoiceRuntime.resolve تغذیه شود نه مستقیماً از env

احراز هویت، سهمیه، و عدم ذخیرهٔ صوت مگر opt-in برای هر سه یکی باشد.

۴.۴ هم‌ترازی حلقهٔ تماس با چت متنی

حداقل قرارداد start روی WS:

{
  "type": "start",
  "session_id": 123,
  "execution_mode": "supervised",
  "model_code": "gpt-4o-mini",
  "stt_code": "stt-local-whisper-small",
  "tts_code": "tts-piper-ganji",
  "input_codec": "pcm"
}

و chat_completion_stream(..., session_id=..., request_model=..., execution_mode=..., user_query=transcript).

رویدادهای جدید به کلاینت صوت: approval_required، trace_step (خلاصهٔ کوتاه قابل گفتن)، transcript_partial.


۵. فازهای اجرا

ترتیب طوری است که هر فاز به‌تنهایی قابل عرضه باشد و فاز بعد روی آن سوار شود. معیار پذیرش را قبل از بستن فاز روی جلسهٔ واقعی فارسی حسابداری اجرا کنید.

فاز ۰ — قرارداد و جداسازی (بدون ابر)

کار معیار پذیرش ریسک
Interface STTProvider / TTSProvider و انتقال Whisper/Piper فعلی پشت آن voice_ws دیگر مستقیماً کلاس بتن نسازد؛ تست واحد dummy STT/TTS رگرسیون تماس فعلی
سند ENV: fallback اگر کاتالوگ خالی است نصب‌های موجود بدون migration همچنان کار کنند

فاز ۱ — کاتالوگ ادمین (مثل مدل متنی)

کار معیار پذیرش ریسک
جدول ai_voice_models + CRUD ادمین + صفحه در دستهٔ AI تنظیمات مدیر ردیف STT محلی و TTS Piper بسازد، فعال/غیرفعال کند، تست کوتاه بزند کلید در لاگ
GET /ai/voice/catalog برای کاربر chip یا تنظیمات چت لیست غیرخالی برمی‌گرداند شلوغی composer
Seed از env فعلی (whisper-small + piper ganji + dummy) یک کلیک seed مثل مدل متنی

فاز ۲ — ارائه‌دهندهٔ API (حداقل OpenAI، قابل تعمیم)

کار معیار پذیرش ریسک
Adapter transcription + speech با credential موجود OpenAI ادمین ردیف openai بسازد، تست فارسی بزند، تماس از آن استفاده کند ارسال صوت مشتری به ابر
فلگ سیاست allow_cloud_audio per business (پیش‌فرض بسته برای کسب‌وکار حساس) بدون فلگ، resolve به local برگردد
Timeout، حجم سقف utterance، retry مثل STT فعلی فایل ۳۰ ثانیه‌ای بیش از سقف رد شود هزینهٔ غافلگیرکننده
لاگ usage با context.type=voice_stt / voice_tts در گزارش مصرف دیده شود حتی اگر هنوز پول جدا نباشد

ارائه‌دهندگان بعدی (فاز ۲+، هر کدام یک adapter): Groq (Whisper سریع و ارزان)، Azure Neural (fa-IR TTS قوی)، Google، ElevenLabs. اول OpenAI چون کلید و الگوی credential از قبل در پنل هست.

فاز ۳ — STT و TTS مستقل در چت متنی

کار معیار پذیرش ریسک
دیکته: میکروفون کوتاه → متن در composer؛ ارسال جدا کاربر می‌تواند «فروش امروز» را دیکته کند، ویرایش کند، بفرستد؛ حلقهٔ کامل ایجنت اجرا شود تداخل با دکمهٔ تماس
جدا کردن UX: میکروفون دیکته vs دکمهٔ تماس دو کنترل واضح در composer شلوغی موبایل
بلندخوانی پیام دستیار پخش PCM/صوت؛ Stop؛ عدم قفل شدن composer همپوشانی با تماس

این فاز بیشترین ارزش محصول را برای «هم صدا به متن و هم متن به صدا» می‌دهد بدون اینکه تماس Realtime لازم باشد.

فاز ۴ — تماس صوت = همان ایجنت متنی

کار معیار پذیرش ریسک
پاس دادن session_id / model / execution_mode مدل chip در تماس رعایت شود
Forward رویداد approval + کارت در UI؛ تا تأیید، TTS سؤال بپرسد نه اینکه write اجرا شود ساخت فاکتور از روی صوت بدون تأیید ممکن نباشد دور زدن SEC
قفل نبودن composer وسط تماس بتوان تایپ کرد؛ متن و صوت یک تاریخچه race دو utterance
transcript_partial اگر موتور STT streaming دارد؛ وگرنه حداقل transcript_final فوری در thread حباب کاربر قبل از «thinking» دیده شود

فاز ۵ — کیفیت مکالمه (بدون تغییر ارائه‌دهنده)

کار معیار پذیرش ریسک
متریک latency: vad_end → first_audio_out عبارت کوتاه فارسی < ۱.۵s روی ابر؛ محلی جدا گزارش شود
Rate limit اتصال صوت per user (VOI-02) اتصال بدون auth بعد از ۱۵s (موجود) + سقف اتصال همزمان
صف/یک مدل Whisper اشتراکی در فرایند به جای load per connection حافظهٔ سرور پایدار پیچیدگی lifecycle
نمونهٔ ارزیابی فارسی حسابداری (اعداد، نام کالا، «بدهکار») WER روی ۱۰ فایل طلایی ثبت شود

فاز ۶ — اختیاری: Realtime speech-to-speech

فقط بعد از فاز ۲–۴. جلسهٔ OpenAI Realtime (یا معادل) با:

  • ابزار فقط read در نسخهٔ اول
  • fallback به cascade اگر مدل realtime در دسترس نبود
  • سیاست ابری اجباری
  • عدم جایگزینی write guard

معیار پذیرش: مکالمهٔ کوتاه «سلام، فروش امروز چقدر بود؟» با حس طبیعی‌تر؛ موجودی از ابزار read بیاید؛ ساخت فاکتور همچنان به cascade+approval برگردد.

فاز ۷ — صورتحساب و پلن

کار معیار پذیرش
سهمیه دقیقه STT/TTS یا هزینهٔ جدا در پلن پلن basic فقط local؛ pro ابر
BYOK صوت برای کسب‌وکار (مثل متن) کلید روی business_ai_provider_configs برای transcription/speech
نمایش در UI سهمیه کاربر بفهمد دیکته از سهمیه صوت کم می‌کند

۶. ارائه‌دهندگان — راهنمای انتخاب (فارسی حسابداری)

کیفیت فارسی باید با فایل واقعی فاکتور/اعداد آزمایش شود؛ ادعاهای بازاریابی کافی نیست.

نقش محلی (حریم خصوصی) ابری پیشنهادی اول جایگزین
STT faster-whisper small فعلی؛ برای کیفیت large-v3 روی GPU OpenAI gpt-4o-mini-transcribe یا whisper-1 Groq Whisper (ارزان/سریع)، Azure fa-IR
TTS Piper fa_IR-ganji-medium (و amir/gyro) OpenAI TTS چندزبانه؛ کیفیت فارسی را A/B کنید Azure Neural fa-IR، Google fa-IR، ElevenLabs multilingual
Realtime نیست OpenAI Realtime Gemini Live

توصیهٔ محصول:

  • پیش‌فرض نصب self-host: STT whisper + TTS piper (تمایز حریم خصوصی که در ممیزی آمده حفظ شود).
  • پیش‌فرض ابر اگر مدیر کلید OpenAI دارد و سیاست اجازه دهد: STT ابری + TTS ابری برای کیفیت؛ LLM همان کاتالوگ متن.
  • هرگز ابر را بدون فلگ کسب‌وکار اجباری نکنید.

۷. آنچه نباید کرد

  • حذف پایپلاین محلی به نفع فقط ابر (مشتریان self-host و دادهٔ مالی).
  • فرستادن صوت به ابر وقتی allow_cloud_audio خاموش است.
  • چسباندن STT/TTS به جدول ai_models متنی بدون kind — فیلدها و قیمت‌گذاری فرق دارند.
  • جایگزینی حلقهٔ ایجنت با Realtime برای عملیات نوشتنی (فاکتور، سند).
  • ذخیرهٔ PCM پیش‌فرض برای «بهبود مدل» بدون opt-in.
  • یک دکمهٔ میکروفون که هم دیکته است هم تماس — دو نیت جدا.
  • TTS dummy در تولید بدون هشدار ادمین در کاتالوگ (الان فقط snackbar کلاینت است).

۸. سناریوهای پذیرش دستی (بعد از پیاده‌سازی فاز مربوط)

دیکته (فاز ۳)
۱. در چت متنی میکروفون دیکته → «موجودی کالای X را بگو».
۲. متن در باکس ظاهر شود، یک کلمه را دستی درست کند، ارسال.
۳. ایجنت ابزار موجودی بزند و پاسخ متنی بدهد. صدا پخش نشود مگر بلندخوانی.

بلندخوانی (فاز ۳)
۱. روی همان پاسخ «بخوان».
۲. صدا پخش شود؛ Stop قطع کند؛ بتوان همزمان پیام بعدی را تایپ کرد.

تماس + ابزار (فاز ۴)
۱. تماس صوتی: «گزارش فروش این ماه را خلاصه بگو».
۲. نوار وضعیت thinking/tool/speaking؛ متن در thread؛ صدا.
۳. وسط پاسخ حرف بزند (barge-in) و سوال را عوض کند.

تأیید نوشتن (فاز ۴)
۱. «برای علی فاکتور فروش ۱۰ عدد کالا بساز».
۲. کارت تأیید + پرسش صوتی؛ بدون تأیید سند ساخته نشود.

ادمین (فاز ۱–۲)
۱. ردیف Piper محلی و ردیف OpenAI STT/TTS.
۲. تست اتصال فارسی.
۳. غیرفعال کردن ابر → کاربر فقط محلی ببیند.
۴. کسب‌وکار بدون فلگ ابر حتی اگر کاتالوگ ابری فعال سراسری باشد، محلی بماند.

رگرسیون نصب فعلی
پس از فاز ۰–۱، بدون ردیف کاتالوگ، همان env VOICE_* تماس قبلی را حفظ کند.


۹. نگاشت به ممیزی و ترتیب پیشنهادی نسبت به کارهای دیگر

آیتم ممیزی این سند
VOI-01 کیفیت و هم‌ترازی متن فاز ۲ (کیفیت) + فاز ۳–۴ (هم‌ترازی UX و ایجنت)
VOI-02 auth/rate limit timeout auth موجود است؛ rate limit = فاز ۵
GAP-06 هم‌تراز GPT-4o Realtime عمداً فاز ۶ و اختیاری؛ Cascade حرفه‌ای هدف اصلی است
SEC تأیید نوشتن فاز ۴ روی صوت
BIL سهمیه فاز ۷
ARC-06 تست صوت از فاز ۰ تست واحد provider؛ از فاز ۲ تست HTTP mock ابر

ترتیب پیشنهادی نسبت به صف چت متنی (AI_CHAT_PRODUCT_ISSUES.md): دیکته/بلندخوانی (فاز ۳) را می‌توان موازی با باگ‌های UI متن پیش برد. تماس Realtime را پشت پایداری approval و God Widget نگذارید جلو بیفتد.

پیشنهاد صف اجرا وقتی مالک شروع کرد:

  1. فاز ۰ (جداسازی)
  2. فاز ۱ (ادمین/کاتالوگ)
  3. فاز ۳ (دیکته + بلندخوانی) — ارزش کاربر سریع
  4. فاز ۲ (ابر) — کیفیت
  5. فاز ۴ (ایجنت در تماس)
  6. فاز ۵ (سخت شدن تولید)
  7. فاز ۷ (پول)
  8. فاز ۶ (Realtime) فقط اگر محصول خواست

۱۰. چک‌لیست PR وقتی یک فاز پیاده شد

  • Adapter جدید: قرارداد STT/TTS + تست واحد مسیر اصلی و شکست (timeout، کلید خالی، زبان)
  • اگر ابر: صوت بدون allow_cloud_audio هرگز از سرور خارج نشود؛ تست fail-closed
  • کاتالوگ: CRUD ادمین + catalog کاربر + seed/fallback env
  • l10n کلیدهای UI جدید (fa/en)
  • اگر تماس: session_id / approval / model در مسیر WS
  • متریک AI_METRIC برای voice_stt_ms / voice_tts_ms / voice_ttfa_ms (time-to-first-audio)
  • به‌روز کردن وضعیت فاز در همین سند + یک سطر تاریخچه
  • بستن یا یادداشت روی VOI-01 / VOI-02 / GAP-06 در ممیزی فقط اگر معیار همان آیتم واقعاً تمام شد

۱۱. تاریخچهٔ به‌روزرسانی

تاریخ نسخه رخداد
۱۴۰۵/۰۵/۲۸ 0.1 بررسی کد بدون تغییر؛ ثبت شکاف کاتالوگ، سه حالت محصول، cascade در برابر Realtime، و فازهای اجرا
۱۴۰۵/۰۵/۲۸ 1.0 پیاده‌سازی cascade: کاتالوگ STT/TTS، دیکته، بلندخوانی، تماس با مدل/حالت/تأیید نوشتن، سیاست ابر fail-closed