API وب (HTTP)¶
سرویس FastAPI درس ۱۲ همان PersianRAG را پشت HTTP میگذارد، با استریم، کش، محدودیت نرخ، لاگ ساختاریافته و رابط وب درس ۱۳. جزئیات طراحی و اندازهگیریها در درس ۱۲ است.
اجرا¶
pip install "parsrag[api,loaders]"
parsrag serve --docs data/fixtures/corpus # http://127.0.0.1:8000
یا با Docker و PostgreSQL + pgvector:
docker compose up --build # http://localhost:8000
PARSRAG_LLM_PROVIDER=ollama PARSRAG_LLM_MODEL=qwen2.5:7b docker compose up
مستندات تعاملی OpenAPI در /docs ساخته میشود.
نقطههای پایانی (Endpoints)¶
| مسیر | کار | پاسخ |
|---|---|---|
GET / |
رابط وب راستبهچپ (بارگذاری، پرسش، ارجاع قابلکلیک) | HTML |
GET /health |
سلامت سرویس | وضعیت، تعداد سند و قطعه، نسخهٔ نمایه، آمار کش |
POST /ingest |
افزودن سند بهصورت JSON؛ با "upsert": true سند تغییرکرده بازنمایه و سند بیتغییر رد میشود |
{"documents": [{"id", "text", "title", "metadata"}]} |
POST /ingest/files |
بارگذاری فایل (TXT، MD، HTML، DOCX، PDF) | مثل بالا |
GET /documents، GET /documents/{id} |
فهرست و متن کامل سندها | JSON |
DELETE /documents/{id} |
حذف سند با قطعهها و بردارهایش | تعداد قطعههای حذفشده |
POST /ask |
پرسش ← پاسخ با ارجاع؛ filters اختیاری |
AskResponse |
POST /ask/stream |
همان، بهصورت رویدادهای سرور (Server-Sent Events) | sources ← token… ← done |
curl -s -X POST http://127.0.0.1:8000/ask -H 'content-type: application/json' \
-d '{"question": "هزینهٔ پیک در تهران چقدر است؟"}'
{"text": "هزینهٔ پیک در تهران 200 هزار تومان است.", "abstained": false, "cached": false,
"citations": [{"number": 1, "doc_id": "kahroba-shipping", "section": "شیوههای ارسال سفارش",
"start": 0, "end": 375, "passage": "# شیوههای ارسال سفارش\n\n..."}],
"timings": {"retrieve_ms": 7.0, "generate_ms": 0.9, "total_ms": 7.9}}
passage متن اصلی سند است (با start و end)، نه متن نرمالشده.
فیلتر فراداده¶
/ask و /ask/stream فیلد اختیاری filters را میپذیرند؛ همان معنای rag.ask(..., filters=...) در کتابخانه (بخش «فیلتر فراداده») را دارد (مقدار ساده یا فهرستی از مقدارها، حداکثر ۲۰ کلید):
curl -s -X POST http://127.0.0.1:8000/ask -H 'content-type: application/json' \
-d '{"question": "هزینهٔ پیک در تهران چقدر است؟", "filters": {"doc_id": ["kahroba-shipping"]}}'
کش پاسخ، فیلترها را هم در کلید حساب میکند. اگر هیچ سندی جور نباشد، پاسخ «نمیدانم» با abstain_reason: "no_results" است.
با محافظ درس ۱۴، فیلد security مشکلهای پیداشده در پاسخ را فهرست میکند (مثلاً ["link_removed"])، و پاسخ ردشده "abstain_reason": "unsafe" دارد. در این حالت /ask/stream پاسخ را اول کامل بررسی میکند و بعد توکنها را میفرستد.
استریم¶
event: sources
data: [{"number": 1, "doc_id": "kahroba-shipping", ...}]
event: token
data: {"text": "هزینهٔ "}
event: done
data: {"answer": "هزینهٔ پیک در تهران 200 هزار تومان است. [1]", "citations": [...], ...}
اگر مدل وسط کار خطا بدهد یا از مهلت بگذرد، بهجای done یک event: error میآید. چون پرسش در بدنهٔ POST است، در مرورگر از fetch و ReadableStream استفاده کنید، نه EventSource.
پیکربندی با متغیرهای محیطی¶
| متغیر | معنا | پیشفرض |
|---|---|---|
PARSRAG_CONFIG |
فایل parsrag.toml یا .json (خط فرمان) |
— |
PARSRAG_INDEX |
پوشهای که parsrag ingest ساخته |
— |
PARSRAG_DOCS |
پوشهای که هنگام شروع نمایه میشود | — |
PARSRAG_DATABASE_URL |
PostgreSQL + pgvector بهجای حافظه | — |
PARSRAG_LLM_PROVIDER |
fake / openai / ollama |
از پیکربندی |
PARSRAG_LLM_MODEL |
نام مدل | از پیکربندی |
PARSRAG_LLM_BASE_URL |
نشانی API سازگار با OpenAI | از پیکربندی |
PARSRAG_LLM_TIMEOUT |
ثانیه تا خطای 504 llm_timeout |
30 |
PARSRAG_CACHE_SIZE |
تعداد پاسخهای کششده (۰ = بدون کش) | 256 |
PARSRAG_CACHE_TTL |
عمر هر پاسخ در کش (ثانیه) | 3600 |
PARSRAG_RATE_LIMIT |
درخواست در دقیقه برای هر کاربر (۰ = خاموش) | 60 |
PARSRAG_MAX_UPLOAD_MB |
بزرگترین فایل قابلبارگذاری | 20 |
PARSRAG_LOG_LEVEL |
DEBUG / INFO / WARNING |
INFO |
PARSRAG_SECURITY |
محافظ تزریق پرامپت (درس ۱۴)؛ 1 روشن، 0 خاموش |
از پیکربندی |
کلید کش، پرسشِ نرمالشده بهاضافهٔ نسخهٔ نمایه است؛ برای همین همان پرسش با «ي» و «ك» عربی، بدون «؟» یا با فاصلهٔ اضافه هم به همان پاسخ کششده میرسد (در درس ۱۲: ۱۱۷ از ۱۱۷ گونهٔ املایی، در برابر ۰ با کلید خام).
خطاها¶
همهٔ خطاها یک بدنهٔ یکسان دارند: {"error": "...", "message": "..."}.
| وضعیت | کد | error |
|---|---|---|
| هنوز سندی نمایه نشده | 409 | empty_index |
| سند تکراری | 409 | duplicate_document |
| سند پیدا نشد | 404 | not_found |
| انباره حذف را پشتیبانی نمیکند | 409 | not_supported |
| ورودی نامعتبر (پرسش خالی، بیش از ۲۰۰۰ نویسه) | 422 | اعتبارسنجی FastAPI |
| فایل بزرگتر از حد / نوع پشتیبانینشده | 413 / 415 | file_too_large / unsupported_file |
| درخواست زیاد | 429 | rate_limited و سرآیند Retry-After |
| مدل خطا داد | 502 | llm_error |
| مدل در مهلت جواب نداد | 504 | llm_timeout |