first commit
This commit is contained in:
129
README.md
Normal file
129
README.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# چتبات تلفنی فارسی (Asterisk + STT + Ollama + TTS)
|
||||
|
||||
## ساختار پروژه
|
||||
```
|
||||
voicebot/
|
||||
├── docker-compose.yml
|
||||
├── .env.example # قالب فایل تنظیمات - کپی کن به .env و پرش کن
|
||||
├── asterisk/
|
||||
│ ├── Dockerfile
|
||||
│ ├── entrypoint.sh # کانفیگها رو موقع استارت از .env میسازه
|
||||
│ ├── templates/ # قالبهای کانفیگ (دستی ادیت نکن)
|
||||
│ │ ├── pjsip-base.conf.template
|
||||
│ │ ├── pjsip-trunk.conf.template
|
||||
│ │ ├── extensions.conf.template
|
||||
│ │ ├── agi.conf
|
||||
│ │ └── modules.conf
|
||||
│ └── config/ # اینجا خالیه - خروجی خودکار ساخته میشه
|
||||
├── agi-scripts/
|
||||
│ └── voicebot.py # orchestrator اصلی (STT -> Ollama -> TTS)
|
||||
├── stt/ # سرویس گفتار-به-متن (faster-whisper)
|
||||
├── tts/ # سرویس متن-به-گفتار (Piper)
|
||||
└── models/
|
||||
├── whisper/ # مدل whisper اینجا کش میشه (خودکار دانلود میشه)
|
||||
└── piper/ # باید مدل صدای فارسی رو دستی بذاری
|
||||
|
||||
```
|
||||
|
||||
## همهی تنظیمات فقط در یک فایل: `.env`
|
||||
|
||||
دیگه لازم نیست تو چند فایل کانفیگ Asterisk بگردی. کافیه `.env.example` رو کپی کنی و مقادیر رو پر کنی:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
nano .env # یا هر ادیتوری که دوست داری
|
||||
```
|
||||
|
||||
محتوای فایل:
|
||||
|
||||
```ini
|
||||
# ---------- Ollama ----------
|
||||
OLLAMA_URL=http://OLLAMA_HOST:11434/api/generate
|
||||
OLLAMA_MODEL=llama3
|
||||
|
||||
# ---------- STT (faster-whisper) ----------
|
||||
WHISPER_MODEL=medium
|
||||
WHISPER_DEVICE=cpu
|
||||
|
||||
# ---------- TTS (Piper) ----------
|
||||
PIPER_VOICE=/models/piper/fa_IR-model.onnx
|
||||
|
||||
# ---------- ترانک مرکز تماس شماره ۱ ----------
|
||||
TRUNK1_NAME=callcenter1
|
||||
TRUNK1_HOST=CALLCENTER1_IP
|
||||
TRUNK1_USERNAME=USERNAME
|
||||
TRUNK1_PASSWORD=CALLCENTER1_PASS
|
||||
|
||||
# ---------- ترانک مرکز تماس شماره ۲ (اختیاری) ----------
|
||||
TRUNK2_NAME=
|
||||
TRUNK2_HOST=
|
||||
TRUNK2_USERNAME=
|
||||
TRUNK2_PASSWORD=
|
||||
|
||||
# ---------- SIP User داخلی (تست) ----------
|
||||
TEST_USER_EXTEN=1000
|
||||
TEST_USER_PASSWORD=CHANGE_ME_STRONG_PASSWORD
|
||||
```
|
||||
|
||||
با هر بار اجرای `docker compose up -d --build`، اسکریپت `entrypoint.sh` داخل کانتینر Asterisk خودکار فایلهای `pjsip.conf` و `extensions.conf` رو از روی همین `.env` میسازه. یعنی:
|
||||
- اگه `TRUNK2_HOST` رو خالی بذاری، ترانک دوم اصلاً ساخته نمیشه.
|
||||
- اگه پرش کنی، ترانک دوم هم خودکار به `pjsip.conf` اضافه میشه (بدون اینکه چیزی رو دستی بنویسی).
|
||||
- تغییر شمارهی تست (`TEST_USER_EXTEN`) هم فقط با عوض کردن همین متغیر انجام میشه.
|
||||
|
||||
> ⚠️ فایل `.env` رو در `.gitignore` نگه دار (چون رمزها توشه) - فقط `.env.example` رو commit کن.
|
||||
>
|
||||
> 💡 بعد از هر تغییر در `.env`، کافیه `docker compose up -d` بزنی (نیازی به `--build` نیست، چون کانفیگ موقع استارت کانتینر ساخته میشه، نه موقع build). فقط اگه خود Dockerfile یا کد رو عوض کردی `--build` لازمه.
|
||||
|
||||
## مرحله ۱: دانلود مدل صدای فارسی Piper
|
||||
|
||||
Piper به یک مدل ONNX فارسی نیاز دارد. مدلهای آماده را از مخزن رسمی دانلود کن:
|
||||
|
||||
```bash
|
||||
mkdir -p models/piper
|
||||
cd models/piper
|
||||
wget https://huggingface.co/rhasspy/piper-voices/resolve/main/fa/fa_IR/gyro/medium/fa_IR-gyro-medium.onnx -O fa_IR-model.onnx
|
||||
wget https://huggingface.co/rhasspy/piper-voices/resolve/main/fa/fa_IR/gyro/medium/fa_IR-gyro-medium.onnx.json -O fa_IR-model.onnx.json
|
||||
cd ../..
|
||||
```
|
||||
> اگر لینک بالا در دسترس نبود، در صفحهی huggingface.co/rhasspy/piper-voices دنبال پوشهی `fa/fa_IR` بگرد و آخرین نسخه رو بردار.
|
||||
|
||||
## مرحله ۲: تنظیم اطلاعات ترانک SIP و Ollama
|
||||
|
||||
همهی اینها الان در همون فایل `.env` هست (بخش بالا رو ببین) - نیازی به دست زدن به فایلهای داخل `asterisk/` نیست.
|
||||
|
||||
## مرحله ۳: بالا آوردن سرویسها
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
docker compose logs -f asterisk
|
||||
```
|
||||
|
||||
بار اول که stt-service بالا میاد، مدل whisper (چند صد مگابایت) دانلود میشه - صبر کن کامل بشه.
|
||||
|
||||
## مرحله ۴: تست
|
||||
|
||||
با هر سافتفون (مثل Zoiper یا Linphone) به extension داخلی که در `.env` تحت `TEST_USER_EXTEN` تعریف کردی (پیشفرض `1000`) با یوزر `test-user` و پسورد `TEST_USER_PASSWORD` وصل شو و تماس بگیر. باید صدای خوشآمدگویی رو بشنوی، بعد صحبت کن و منتظر پاسخ بات باش.
|
||||
|
||||
برای اتصال واقعی مرکز تماس، تماس روی ترانک PJSIP وارد context به نام `from-trunk` میشه که در `extensions.conf` تعریف شده.
|
||||
|
||||
## نکات مهم برای Production
|
||||
|
||||
1. **لتنسی**: اگه سرعت پاسخ کند بود:
|
||||
- مدل whisper رو از `medium` به `small` تغییر بده (دقت کمتر، سرعت بیشتر)
|
||||
- اگه GPU داری، `WHISPER_DEVICE=cuda` رو در docker-compose ست کن
|
||||
- مدل Ollama رو سبکتر انتخاب کن (مثلاً یک مدل 7B به جای 70B)
|
||||
|
||||
2. **Barge-in (قطع صحبت بات)**: نسخهی فعلی ساده است (نوبتی: بات حرف میزنه، بعد کاربر). برای barge-in واقعی باید از AMI events مثل `TALK_DETECT` استفاده کنی که پیچیدهتره - در صورت نیاز میتونم اضافهاش کنم.
|
||||
|
||||
3. **مدیریت چند تماس همزمان**: چون AGI برای هر تماس یک پراسس جداست، همزمانی بهصورت خودکار پشتیبانی میشه؛ فقط مطمئن شو سرویسهای STT/TTS/Ollama منابع کافی (CPU/RAM/GPU) برای بار همزمان دارن.
|
||||
|
||||
4. **امنیت SIP Trunk**: حتماً `type=identify` رو با IP دقیق مرکز تماس محدود کن و فایروال روی پورت 5060 و رنج RTP بذار.
|
||||
|
||||
5. **لاگ و مانیتورینگ**: `agi.verbose()` در اسکریپت لاگها رو تو کنسول Asterisk میریزه (`asterisk -rvvv` برای دیدن زنده).
|
||||
|
||||
## گام بعدی (اختیاری)
|
||||
اگه بخوای میتونم اینها رو هم اضافه کنم:
|
||||
- پشتیبانی از AMI برای barge-in و real-time monitoring
|
||||
- ذخیرهی تاریخچهی مکالمات در دیتابیس (برای گزارشگیری)
|
||||
- health-check و auto-restart برای سرویسها
|
||||
- صف تماس (queue) قبل از رسیدن به بات
|
||||
Reference in New Issue
Block a user