# گزارش جامع: اعتبارسنجی گزارش‌ها و راهکار کرال موتور STT بله > **تاریخ:** ۱۵ مهر ۱۴۰۵ > **موضوع:** افزودن متن تولیدشده توسط قابلیت «تبدیل ویس به متن» پیام‌رسان بله به‌عنوان یک کاندید در خط‌لوله چندمدله STT بات تدارکات > **ورودی‌ها:** سه سند ارائه‌شده (تحلیل جامع، پلی‌بوک اجرایی، تحلیل مقایسه‌ای) + راستی‌آزمایی مستقل وب > **محدودیت:** `integration_report` شماره ۱ و ۲ در دسترس من نبود و فقط از روی نقل‌قول‌های همین اسناد قضاوت شده‌اند. دستورهای کشف (بخش ۴) در محیط من اجرا نشده‌اند، چون شبکه sandbox بسته بود. --- ## ۱. خلاصه مدیریتی 1. **Bot API رسمی بله STT ندارد.** همه اسناد در این مورد درست می‌گویند. 2. **تناقض اصلی** (مهندسی معکوس «غیرعملی است» در برابر «ساده است») هیچ‌کدام کاملاً درست نیست. مسیر شدنی است، ولی «افزودن یک متد» نیست و نیاز به یک فاز کشف دارد. 3. **دو فرض اثبات‌نشده** کل مسیر را تحت تأثیر قرار می‌دهد: - دکمه «تبدیل به متن» روی **وب** بله وجود دارد (هر سه سند فرض کرده‌اند، هیچ منبعی تأیید نکرده). - پکیج `aiobale-py` نسخه 0.3.9 فعال است (پیدا نشد؛ به بخش ۲ مراجعه کنید). 4. **کشف جدید:** پکیج `bale-sdk` با ۶۰۷ RPC تایپ‌شده و پروتوهای بازیابی‌شده. احتمال وجود RPC ترنسکریپشن در آن بالاست. ولی مجوز آن اختصاصی است. 5. **بزرگ‌ترین صرفه‌جویی:** آزمون دقت را **قبل از ساخت** و به‌صورت **دستی** روی ۳۰ ویس واقعی انجام دهید. اگر بله از خط‌لوله فعلی بهتر نبود، پروژه لازم نیست. 6. **ریسک حقوقی/ToS** (استفاده خودکار از حساب کاربری) تصمیم مدیریتی است و باید قبل از استقرار روشن شود. --- ## ۲. اعتبارسنجی گزارش‌ها ### ۲.۱ جدول ادعاها | ادعا | نتیجه | توضیح | |---|---|---| | Bot API رسمی STT ندارد | ✅ تأیید | پروب‌ها همگی ۴۰۴ داده‌اند و تایپ‌های SDKها برای Voice فقط شناسه فایل و مدت‌زمان دارند. **تذکر:** ۴۰۴ برای نام‌های حدسی چیزی درباره فیلد مخفی در payload نمی‌گوید؛ تست T1 (ویس به یک بات تستی و خواندن JSON کامل) هنوز لازم است (۳۰ دقیقه). | | بله قابلیت تبدیل ویس به متن دارد | ✅ با شرط | نسخه جدید بله این قابلیت را برای اندروید و iOS منتشر کرده. وجود دکمه در **وب** تأییدنشده است و ریسک اصلی مسیر Playwright همین است. | | مهندسی معکوس «غیرعملی» است (گزارش ۲) | ⚠️ بدبینانه | کلاینت‌های متن‌باز مهندسی‌معکوس‌شده وجود دارند. اما استدلال «Protobuf خودتوصیف است» نادرست است: wire format بدون `.proto` فقط تا حدی (شماره فیلد و نوع خام، بدون نام و معنا) دیکود می‌شود. | | مهندسی معکوس «در حد افزودن یک متد» است (پلی‌بوک) | ⚠️ خوش‌بینانه | کشف RPC، نگاشت فیلدها و پایداری نشست کار واقعی است. تخمین «نیم‌روز» برای T2 ریسکی است. | | `aiobale-py` v0.3.9 فعال است و نام `aiobale` را پکیج خالی گرفته | ❌ تأییدنشده / احتمالاً غلط | `aiobale-py` را پیدا نکردم. `aiobale` یک کتابخانه واقعی است (MIT، مستندات `docs.aiobale.ir`، نسخه‌های 0.1.x). فورک‌هایی مثل Autobale می‌گویند نسخه اصلی نگهداری نمی‌شود و باگ دارد. قبل از وابستگی به هر نام، `pip index versions` را اجرا کنید. | | `bale-sdk` (کشف جدید) | 🔎 مهم | از کلاینت وب بله مهندسی معکوس شده؛ ۶۰۷ RPC در ۵۲ سرویس، پروتوهای بازیابی‌شده، احراز با JWT یا OTP؛ نسخه 0.1.1 (ژوئن ۲۰۲۶). **مجوز اختصاصی و «همه حقوق محفوظ»**. | | تأخیر «زیر ۱ ثانیه» | ❌ رد | همه موافقند. اعداد ۱–۴ ثانیه (R2) و ۴–۸ ثانیه (Playwright) هم **اندازه‌گیری نشده‌اند**؛ فقط T5 عدد واقعی می‌دهد. | | AI Chat بله ویس را «پیاده» می‌کند (R3) | ⚠️ تأییدنشده و نامطلوب | حتی اگر درست باشد، خروجی «متن + تفسیر مدل» است و برای consensus مناسب نیست. با کنار گذاشتن موافقم. | | RAM ‏۳۵۰–۵۰۰ مگابایت برای Playwright | ✅ معقول | برای بات تک‌کاربره قابل‌تحمل است. | | Playwright در ۱–۲ روز | ⚠️ خوش‌بینانه | وابسته به وجود دکمه وب، چالش‌های ورود و پایداری سلکتورها. | | ساختار Gate / State-machine پلی‌بوک | ✅ قوی | بهترین بخش اسناد. ایراد: دروازه دقت (T7) بعد از ساخت آمده، در حالی که دستی و قبل از ساخت شدنی است. | | ریسک بن، ToS و حریم خصوصی | ✅ درست و حیاتی | فقط پلی‌بوک به آن پرداخته است. | | ترجیح WebSocket به POST gRPC (پلی‌بوک) | ✅ منطقی | کلاینت رسمی بله POST gRPC را عمدتاً برای چند متد احراز هویت استفاده می‌کند؛ استفاده زیاد از آن غیرعادی به نظر می‌رسد. | | «Playwright اول» (سند مقایسه‌ای) در برابر «R2 اول» (پلی‌بوک) | ⚠️ هر دو مشروط | بدون نتیجه کشف روز اول قابل تصمیم نیست. | ### ۲.۲ ایرادهای کد adapter در سند اول - کلید پیش‌فرض ضعیف (`bale_secure_token`) و مقایسه کلید با `!=` به‌جای مقایسه ثابت‌زمان. - بلعیدن همه استثناها بدون لاگ. - بازگرداندن ۲۰۰ با متن خالی: ممکن است بات آن را یک کاندید معتبر (خالی) در consensus بشمارد. باید در `bot/app/stt.py` بررسی شود که پاسخ ۵xx و متن خالی چطور مدیریت می‌شوند. توصیه: در خطا ۵۰۳ برگردد. - نبود قفل ترتیبی، سقف روزانه و تأخیر تصادفی در خود adapter. ### ۲.۳ نکات فنی اصلاح‌شده - فریم gRPC-Web پیشوند ۵ بایتی دارد (۱ بایت فلگ + ۴ بایت طول). این برای **POST gRPC-Web** درست است؛ اینکه فریم‌های WebSocket بله هم همان قالب را دارند فرض اثبات‌نشده‌ای است و باید در T2 دیده شود. - هاست‌ها و نام ماژول‌هایی مثل `maviz-ws.bale.ai` و `SpeechTranscript` از تحلیل باندل آمده‌اند و در وب ایندکس نشده‌اند. باید با چشم در کپچر تأیید شوند. --- ## ۳. راهکارها | راهکار | توضیح | رم | خلوص متن | ریسک | حکم | |---|---|---|---|---|---| | **A. مسیر رسمی** | درخواست API یا همکاری از بله | — | — | — | هزینه صفر؛ قبل از هر کار غیررسمی یک ایمیل بزنید | | **B. RPC مستقیم** | کلاینت کاربری روی WebSocket با `bale-sdk` یا `aiobale` + RPC ترنسکریپت | ≈ ۲۰ MB | خالص | متوسط (تغییر پروتکل، بن) | **بهترین نتیجه فنی**، مشروط به کشف RPC | | **C. Playwright** | Chromium headless روی `web.bale.ai` با پروفایل پایدار | ۳۵۰–۵۰۰ MB | خالص | کم–متوسط | مقاوم، **فقط اگر دکمه وب موجود باشد** | | **D. AI Chat** | ویس به چت هوش مصنوعی بله و استخراج از پاسخ | ≈ ۲۰ MB | ❌ متن + تفسیر | بالا | کنار گذاشته شود | | **E. سرویس ثالث** | پروکسی‌های STT با ادعای بله | — | نامشخص | حریم خصوصی/پایداری | کنار گذاشته شود | | **F. اندروید امولاتور** | اپ بله + uiautomator | زیاد | خالص | بالا (شکننده) | آخرین چاره اگر B و C ممکن نشد | --- ## ۴. مسیر دقیق اجرا ### گام ۰: آزمون دقت دستی (نیم‌روز، بدون کد) ۳۰ ویس واقعی تدارکاتی (با رضایت فرستندگان؛ صداها را بلندمدت نگه ندارید) را در اپ بله دستی به متن تبدیل کنید و سه حالت را مقایسه کنید: 1. خروجی فعلی بات (whisper/سایرین + consensus) 2. فقط متن بله 3. consensus با اضافه‌شدن بله سه معیار: WER متن، دقت استخراج اقلام (نام کالا، برند، تعداد، واحد) و تعداد موارد سخت لهجه‌ای که با بله درست شده‌اند. **معیار پیشنهادی:** کاهش نسبی خطای استخراج حدود ۱۵٪ یا بیشتر، یا حل حداقل ۲ مورد سخت. در غیر این صورت **STOP**. ### گام ۱: کشف سریع (حدود ۳۰ دقیقه) ```bash python -m venv .v && . .v/bin/activate pip index versions aiobale-py # وجود یا عدم وجود را بررسی کنید pip download bale-sdk --no-deps --no-binary :all: && tar xzf bale_sdk-*.tar.gz grep -rniE "transcri|speech|asr|stt" bale_sdk-*/proto bale_sdk-*/docs | head -50 ``` همچنین در پایتون `from bale import ALL_RPCS` را با همان کلیدواژه‌ها فیلتر کنید. همزمان **T1**: یک بات تستی مستقل بسازید، یک ویس بفرستید و JSON کامل آپدیت را بخوانید. اگر فیلد ترنسکریپشن وجود داشت، پروژه کرالر لازم نیست. ### گام ۲: وب و کپچر (نیم‌روز تا یک روز) 1. با **یک حساب اختصاصی شرکت** روی `web.bale.ai` وارد شوید و بررسی کنید دکمه «تبدیل به متن» روی ویس هست یا نه (روی ویس دریافتی و ارسالی). 2. DevTools تب Network را با Preserve log و فیلتر WS و Fetch/XHR ضبط کنید و هنگام کلیک روی دکمه ذخیره کنید: - URL کامل و ترابری (unary یا WS) - هدر احراز - `req.bin` و `resp.bin` - زمان پاسخ (همان تأخیر واقعی ASR) 3. ۵ تا ۱۰ ویس متنوع (کوتاه، بلند، لهجه‌دار) را تکرار کنید و در `findings.md` خلاصه کنید. 4. دیکود آفلاین: پیشوند ۵ بایتی را بردارید، سپس `protoc --decode_raw` یا `protoscope`. ### گام ۳: انتخاب مسیر | وضعیت | مسیر | |---|---| | RPC در `bale-sdk` یا کپچر پیدا شد | **B** | | RPC پیدا نشد ولی دکمه وب هست | **C** | | هیچ‌کدام | **F** یا توقف | | ترنسکرایب نیاز به امضا یا اثر انگشت مرورگر دارد | **C** | **الگوی پیشنهادی برای B:** بات خودتان با `sendVoice(file_id)` ویس را برای حساب کرالر بفرستد (کرالر یک‌بار بات را `/start` کرده). این‌طور نیازی به دانلود و آپلود مجدد نیست و `message_id` بومی در اختیار کرالر است. پس از دریافت متن، پیام حذف شود. اگر RPC به `message_id` نیاز نداشت، مستقیم فایل یا بایت داده شود. **مجوز:** `aiobale` مجوز MIT دارد ولی نگهداری نمی‌شود (فورک‌ها: Autobale و BaleClient). `bale-sdk` مجوز اختصاصی دارد؛ برای استفاده تجاری از نویسنده اجازه بگیرید. ### گام ۴: ساخت adapter سخت‌شده قرارداد OpenAI-compatible (همان `POST /v1/audio/transcriptions` که بات انتظار دارد) و موتور قابل‌سوییچ با `BALE_STT_ENGINE=grpc|playwright`. پیشنهاد کد: ```python import os, secrets, asyncio, logging from fastapi import FastAPI, File, Form, Header, HTTPException, UploadFile log = logging.getLogger("bale-stt") app = FastAPI() KEY = os.environ["BALE_STT_INTERNAL_KEY"] # بدون مقدار پیش‌فرض DAILY_CAP = int(os.environ.get("BALE_STT_DAILY_CAP", "100")) lock = asyncio.Lock() # اجرای ترتیبی count_today = 0 # در عمل با ریست روزانه @app.get("/healthz") def healthz(): return {"status": "ok"} @app.post("/v1/audio/transcriptions") async def transcribe(file: UploadFile = File(...), model: str = Form("bale-stt"), language: str = Form("fa"), authorization: str = Header("")): if not secrets.compare_digest(authorization, f"Bearer {KEY}"): raise HTTPException(401) if count_today >= DAILY_CAP: raise HTTPException(429) async with lock: try: text = await run_engine(await file.read()) # + تأخیر تصادفی ۱ تا ۳ ثانیه except Exception: log.exception("bale stt failed") raise HTTPException(503) # تا بات فقط همین کاندید را حذف کند if not text: raise HTTPException(503) return {"text": text} ``` اتصال به بات (بدون تغییر کد): ```env PROCUREMENT_BOT_STT_PROVIDER_3_NAME=bale PROCUREMENT_BOT_STT_PROVIDER_3_BASE_URL=http://bale-stt:8080/v1 PROCUREMENT_BOT_STT_PROVIDER_3_API_KEY= PROCUREMENT_BOT_STT_PROVIDER_3_MODEL=bale-stt PROCUREMENT_BOT_STT_PROVIDER_3_LANGUAGE=fa ``` > پرووایدر فقط وقتی فعال می‌شود که هم `BASE_URL` و هم `API_KEY` پر باشند. ### گام ۵: عملیات و ایمنی - فقط **شماره اختصاصی شرکت**؛ هرگز شماره شخصی. - `session_file` یا پروفایل مرورگر روی ولوم داکر و هرگز در گیت. - **OTP تنها گام انسانی** است. در ابطال نشست: هشدار به ادمین و هدایت ترافیک به سایر پرووایدرها. - اجرای ترتیبی، فاصله تصادفی ۱ تا ۳ ثانیه، سقف روزانه، و ترجیح WebSocket به POST gRPC. - حذف فوری پیام اسکرچ پس از استخراج و عدم نگهداری فایل صوتی روی دیسک. - پایش: نرخ موفقیت، p50 و p95 تأخیر، انواع خطا، وضعیت نشست. هشدار اگر نرخ خطا در ۳۰ دقیقه بیش از ۲۰٪ شد. - **Rollback:** خالی کردن `STT_PROVIDER_3_*` در env بات و توقف کانتینر. بات فوراً به وضعیت قبل برمی‌گردد. - سکرت‌هایی که در `docker-compose.yml` کامیت شده‌اند (توکن بات، کلید DeepSeek) باید rotate شوند و `DRAFT_TOKEN_SECRET` پیش‌فرض ضعیف را عوض کنید. - روی برنچ‌های دیگران (`prod-v7` و غیره) دخالت نکنید و بدون تأیید مالک چیزی پوش نشود. ### گام ۶: اندازه‌گیری و سواک - **T5:** ۵۰ تا ۱۰۰ ویس ترتیبی با فاصله انسانی؛ پذیرش پیشنهادی: موفقیت ≥ ۹۵٪ و p95 ≤ ۸ ثانیه. - **سواک یک‌هفته‌ای** با حجم کم (حدود ۱۰۰ ترنسکرایب در روز): ثبت تعداد ورود مجدد، چالش‌های امنیتی و عمر واقعی توکن. --- ## ۵. دروازه‌های تصمیم (خلاصه) | دروازه | شرط عبور | در صورت شکست | |---|---|---| | G0 دقت دستی | بهبود ≈ ۱۵٪ یا ۲ مورد سخت | **STOP** | | G1 (T1) | فیلد ترنسکریپشن نبود | اگر بود: پایان، مستقیم وصل شود | | G2 کشف | RPC یا دکمه وب پیدا شد | F یا توقف | | G3 پروتوتایپ | درخواست ساخته و پاسخ خوانده شد | سوییچ به C | | G4 نرخ و پایداری | ≥ ۹۵٪ موفقیت، p95 ≤ ۸ ثانیه | کاهش نرخ و backoff؛ در صورت بن: توقف | | G6 ToS | تصمیم مکتوب مدیریت | **STOP** یا حجم بسیار محدود | | G7 سواک | نشست سالم یک هفته | rollback و بازگشت به G4 | --- ## ۶. زمان‌بندی واقع‌بینانه | مرحله | زمان | |---|---| | گام ۰ و ۱ (دقت دستی + کشف سریع) | نیم‌روز | | گام ۲ (وب و کپچر) | ۱ روز | | ساخت B یا C | ۲ تا ۴ روز | | T5 و سواک | ۱ هفته | --- ## ۷. رجیستر ریسک | ریسک | احتمال | اثر | مقابله | |---|---|---|---| | بن یا rate-limit حساب | متوسط | توقف مسیر | حجم کم، WS-first، سقف روزانه، حساب اختصاصی قابل‌تعویض | | تغییر پروتکل یا UI بله | متوسط | قطع سرویس | هشدار خطا، فالبک، سوییچ موتور با env، rollback با env | | انقضای نشست و نیاز به OTP | بالا (دوره‌ای) | توقف موقت | ولوم نشست + هشدار + runbook ورود انسانی | | دکمه وب وجود ندارد | نامعلوم | ناممکن‌شدن C | بررسی در گام ۲ قبل از ساخت | | دقت ناکافی نسبت به هزینه | نامعلوم | هزینه بی‌فایده | G0 قبل از ساخت | | ToS / مسائل حقوقی | نامعلوم | توقف اجباری | تصمیم مکتوب مدیریت (G6)؛ ایمیل به بله (A) | | مجوز اختصاصی `bale-sdk` | بالا | ممنوعیت استفاده | اجازه از نویسنده یا استفاده از `aiobale` (MIT) | | حریم خصوصی صدا | کم | اعتباری | حذف فوری پیام‌ها، عدم نگهداری فایل | | وابستگی به یک فرد نگهدارنده | متوسط | رکود | مستندسازی و مالک رسمی | --- ## ۸. دروازه‌های انسانی 1. OTP ورود حساب (بار اول و هر انقضا). 2. تصمیم ToS / حقوقی. 3. جمع‌آوری نمونه ویس واقعی با رضایت. 4. تأیید نهایی استقرار و مرج توسط مهندس ارشد. --- ## ۹. توصیه نهایی 1. **همین هفته:** گام ۰ (دقت دستی) + ایمیل به بله + گام ۱ (کشف سریع و T1). 2. **اگر دقت توجیه داشت:** گام ۲ و انتخاب B یا C بر اساس شواهد. 3. **معماری:** adapter با قرارداد OpenAI و موتور قابل‌سوییچ؛ بات دست‌نخورده می‌ماند. 4. **تصمیم مدیریتی** درباره ToS قبل از استقرار. 5. اگر هر کدام از G0 یا G6 شکست خورد، **توقف** و ادامه با پرووایدرهای فعلی. --- ## منابع - aiobale (PyPI): https://pypi.org/project/aiobale - bale-sdk (PyPI): https://pypi.org/project/bale-sdk/ - Autobale (فورک aiobale): https://pypi.org/project/autobale/ - خبر انتشار نسخه بله با قابلیت تبدیل پیام صوتی به متن (خبرگزاری آنا): https://ana.ir/fa/news/994908 - مستندات رسمی بات بله: https://docs.bale.ai