feat(stack): full overhaul — hardening, ops tooling, monitoring, analytics, chatbot
Security: deep /api/health (DB+MinIO probes, 503 on failure) + /api/live; rate-limited public forms with honeypots; real client IP behind Traefik (--proxy-headers); TipTap URL sanitization on write (nh3); non-root containers + slim .dockerignore; prod MinIO console bound to 127.0.0.1; HSTS/nosniff on TLS routers; JWT 8h; no default credentials in code. Reliability: Alembic migrations (create_all baseline); graceful shutdown (exec uvicorn); hardened backups (checksums, sanity check, freshness gauge, optional rclone off-site) + restore.sh + hourly db-backup sidecar (ops profile); stack.sh ops tooling (deploy/logs/health/backup/restore/monitoring); .gitattributes LF for shell scripts. Orchestration: json-file log rotation, pinned images, per-service memory limits, edge/internal networks, Traefik ping/accesslog/metrics + flood limiter, conditional minio-setup, pgvector db image, one-shot db-init (umami + aramesh_chatbot databases). Chatbot: unified from site-chatbot branch (RAG + pgvector, SSE, ChatWidget). Monitoring: Prometheus/Alertmanager/Loki/Promtail/Grafana + cAdvisor, node/postgres/blackbox exporters, provisioned dashboards and 10 alert rules; alerts delivered to Bale (tapi.bale.ai — Telegram-compatible). Analytics: Umami on shared Postgres, build-time tracker injection, custom events (contact/newsletter/phone/chat/lang) via frontend/src/analytics.ts. Hygiene: CSV export for contact messages and subscribers; upload image optimization (Pillow); CI script + GitHub-compatible workflow; audit.sh; gen-env.sh for strong credentials.
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
# دستیار هوشمند سایت (چتبات)
|
||||
|
||||
سرویس گفتگوی محتوای سایت «گروه ساختمانی آرامش» — بازدیدکننده به فارسی سؤال میپرسد و
|
||||
دستیار **فقط از روی محتوای خود سایت** (مقالهها، پروژهها، خدمات، سؤالات متداول، اطلاعات تماس و…)
|
||||
پاسخ میدهد؛ اگر پاسخ در محتوا نباشد، بهجای ساخت جواب، صادقانه اعلام میکند.
|
||||
|
||||
این سرویس پورت خط لولهٔ پروژهٔ `llm-srerver-chatbot` (نسخه v13) با چهار تغییر اصلی برای این سایت است:
|
||||
|
||||
1. **پایگاه sparse بهجای SPLADE از BM25 استفاده میکند** — SPLADE انگلیسیمحور است و روی
|
||||
فارسی عملاً بیفایده؛ BM25 با نرمالسازی فارسی (ی/ک عربی، اعراب، ارقام، نیمفاصله) جایگزین شده است.
|
||||
2. **ذخیرهساز برداری pgvector است، نه FAISS** — بردارها در یک دیتابیس جدا (`aramesh_chatbot`)
|
||||
روی همان نمونه Postgres نگهداری میشوند؛ همگامسازی افزایشی است (فقط سطرهای جدید/تغییریافته
|
||||
امبد میشوند)، بکاپگیری با خود دیتابیس است و فایل ایندکس جدا وجود ندارد.
|
||||
3. **تأخیر کمتر** — مسیریابی `alpha` با LLM و گسترش چندپرسشی (multi-query) بهصورت پیشفرض
|
||||
خاموشاند (با متغیر محیطی قابل فعالسازی)؛ بازنویسی پرسش فقط وقتی تاریخچه گفتگو وجود دارد اجرا میشود.
|
||||
4. **استریم واقعی توکنبهتوکن** با `astream_events` بهجای دیف پیامهای کامل.
|
||||
|
||||
## خط لوله هر پیام
|
||||
|
||||
```
|
||||
پرسش کاربر
|
||||
│
|
||||
├─[اگر تاریخچه هست] بازنویسی پرسش با LLM (حل ضمیرها و اشارهها: «اون دومی» → موضوع واقعی)
|
||||
│
|
||||
├─ بازیابی ترکیبی: pgvector (معنایی، کسینوسی روی HNSW — MiniLM چندزبانه)
|
||||
│ + BM25 (کلیدواژه، متن نرمالشده فارسی)
|
||||
│ نمرهها min-max → ترکیب α×معنایی + (1-α)×کلیدواژه
|
||||
│
|
||||
├─ برش خوشهای (K-Means K=2 + silhouette ≥ 0.55) — مرز طبیعی کیفیت
|
||||
│
|
||||
├─ ریرنک با BAAI/bge-reranker-v2-m3 → نگهداشتن ۳ سند برتر
|
||||
│
|
||||
└─ تولید پاسخ فارسی با LLM (قواعد تکیه بر داده + معرفی صفحه مرتبط + پیام جایگزین مشخص)
|
||||
```
|
||||
|
||||
ایندکس از محتوای PostgreSQL سایت ساخته میشود (`articles` منتشرشده، `projects`، `services`،
|
||||
`faqs`، `brand`، `offices`، `investment_models`، `process_steps`، `why_us`، `team`،
|
||||
`testimonials`، `timeline`، `story`). متنهای بلند به قطعات ~۷۰۰ نویسهای همپوشان برش میخورند.
|
||||
|
||||
- **ایندکس برداری در pgvector**: جدول `chatbot_chunks` در دیتابیس اختصاصی
|
||||
`aramesh_chatbot` (روی همان نمونه Postgres) با ستون `embedding vector(384)` و
|
||||
ایندکس HNSW کسینوسی؛ هر قطعه `doc_id` پایدار و `content_hash` دارد و همگامسازی
|
||||
فقط سطرهای جدید/تغییریافته را امبد میکند. دیتابیس و جدول در شروع سرویس خودکار ساخته میشوند.
|
||||
- **بازسازی خودکار**: یک حلقهٔ پسزمینه هر `INDEX_REFRESH_SECONDS` ثانیه محتوا را چک
|
||||
میکند و اگر ادمین چیزی را در پنل عوض کرده باشد، فقط تغییرات همگام میشود
|
||||
(امبد اجباری همه: `POST /chat/reindex`).
|
||||
- **ماندگاری گفتگو**: در حافظهٔ همان پروسه (MemorySaver لنگگراف) — با ریاستارت پاک میشود.
|
||||
|
||||
## متغیرهای محیطی (در `.env` ریشه پروژه)
|
||||
|
||||
| متغیر | پیشفرض | توضیح |
|
||||
|---|---|---|
|
||||
| `LLM_BASE_URL` | خالی | **اجباری** — نشانی سرویس LLM سازگار با OpenAI. بدون آن چتبات بالا میآید ولی پاسخ نمیدهد |
|
||||
| `LLM_API_KEY` | خالی | کلید API (برای سرور داخلی `not-needed` بگذارید) |
|
||||
| `LLM_MODEL` | `openai/gpt-oss-120b` | نام مدل |
|
||||
| `CHAT_REINDEX_TOKEN` | خالی | توکن `POST /chat/reindex` — اگر خالی باشد آن مسیر ۴۰۳ میدهد |
|
||||
| `CHATBOT_DB_NAME` | `aramesh_chatbot` | نام دیتابیس اختصاصی چتبات روی همان نمونه Postgres (بردارها اینجا میروند) |
|
||||
| `EMBEDDING_DIM` | `384` | بعد بردار مدل امبدینگ — با تعویض مدل امبدینگ باید هماهنگ شود |
|
||||
| `RERANKER_ENABLED` | `true` | روی سرور کمرم (زیر ~۴GB) `false` بگذارید |
|
||||
| `ALPHA_DENSE` | `0.5` | وزن جستوجوی معنایی در ترکیب نمرهها (۰ تا ۱) |
|
||||
| `BEST_OF_K` | `3` | تعداد سند نهایی که به LLM میرود |
|
||||
| `INDEX_REFRESH_SECONDS` | `600` | بازسازی خودکار ایندکس پس از تغییر محتوا (۰ = خاموش) |
|
||||
| `RATE_LIMIT_MESSAGES` / `RATE_LIMIT_WINDOW` | `20` / `300` | سقف پیام هر IP در پنجره زمانی (ثانیه) |
|
||||
|
||||
`DATABASE_URL` در داکر از `docker-compose.yml` تزریق میشود — دیتابیس سایت فقط خوانده
|
||||
میشود و نوشتن (بردارها) فقط در دیتابیس جدا `aramesh_chatbot` انجام میگیرد.
|
||||
|
||||
## پیشنیاز pgvector
|
||||
|
||||
سرویس `db` استک از ایمیج `pgvector/pgvector:pg17` استفاده میکند (همان postgres:17 +
|
||||
افزونهٔ vector). اگر Postgres سایت روی نمونهٔ دیگری است، باید افزونهٔ pgvector روی آن
|
||||
فعال باشد؛ در غیر این صورت شروع چتبات با خطای واضح متوقف میشود.
|
||||
|
||||
## مسیرها
|
||||
|
||||
| مسیر | توضیح |
|
||||
|---|---|
|
||||
| `GET /chat/stream?message=…&thread_id=…` | استریم SSE توکنبهتوکن پاسخ (`{"content": …}` و در پایان `{"done": true}`) |
|
||||
| `GET /chat/suggestions` | ۴ پیشنهاد پرسش (کش ۱۰ دقیقه؛ جایگزین: خود سؤالات متداول) |
|
||||
| `GET /chat/eval?message=…` | مخصوص ارزیابی RAGAS — پاسخ + اسناد بازیابیشده با thread تازه |
|
||||
| `GET /chat/healthz` | وضعیت ایندکس/LLM/تعداد اسناد |
|
||||
| `POST /chat/reindex` | بازسازی اجباری ایندکس (هدر `X-Reindex-Token`) |
|
||||
|
||||
مسیرهای `GET /chat/{scope}/stream|eval|suggestions` هم برای سازگاری با اسکریپت
|
||||
`eval_ragas.py` قدیمی موجود است — کافی است `--url` را به نشانی این سرویس بدهید.
|
||||
|
||||
## اجرا
|
||||
|
||||
با داکر (بخشی از استک اصلی است — `docker compose up -d --build`):
|
||||
|
||||
```bash
|
||||
# در .env ریشه:
|
||||
LLM_BASE_URL=http://172.16.22.21:4460/v1 # یا هر سرویس سازگار با OpenAI
|
||||
LLM_API_KEY=not-needed
|
||||
```
|
||||
|
||||
اولین بوت مدلها را دانلود میکند (~۱.۵GB: امبدینگ + ریرنکر) و در والیوم
|
||||
`chatbot_cache` کش میشود؛ بوتهای بعدی چند ثانیه طول میکشد.
|
||||
|
||||
اجرای محلی بدون داکر:
|
||||
|
||||
```bash
|
||||
cd chatbot
|
||||
python -m venv .venv && source .venv/bin/activate # ویندوز: .venv\Scripts\activate
|
||||
pip install -r requirements.txt
|
||||
export DATABASE_URL="postgresql+psycopg://aramesh:PASS@localhost:5432/arameshplaza"
|
||||
export LLM_BASE_URL="http://…" LLM_MODEL="openai/gpt-oss-120b"
|
||||
uvicorn chatbot.app:api --port 8000 # از ریشه پوشه والد
|
||||
```
|
||||
|
||||
## منابع مورد نیاز
|
||||
|
||||
- **رم**: با ریرنکر ~۴GB (مدل ۵۶۸M پارامتری روی CPU)؛ بدون ریرنکر ~۲GB
|
||||
- **CPU**: امبدینگ و ریرنک روی CPU اجرا میشوند؛ GPU لازم نیست
|
||||
- **شبکه**: دسترسی به PostgreSQL و به نشانی `LLM_BASE_URL`
|
||||
|
||||
## نکات امنیتی
|
||||
|
||||
- دیتابیس سایت فقط **خواندن**؛ نوشتن فقط در دیتابیس اختصاصی `aramesh_chatbot` انجام میشود
|
||||
- محدودسازی نرخ per-IP فعال است (پیشفرض ۲۰ پیام در ۵ دقیقه)
|
||||
- CORS باز است ولی کوکی/اعتبارنامهای رد و بدل نمیشود؛ در تولید همهچیز هممبدأ (پشت Traefik) است
|
||||
Reference in New Issue
Block a user