چیت‌شیت

عرضه یک برنامه عملیاتی LLM

Shipping a Production LLM App

پایپ‌لاین درخواست، تلاش مجدد، زنجیره‌های جایگزین، استریم‌های SSE، ازسرگیری، محدودیت‌های دمو و یک درگاه جایگزین.

  • ۱۳ بخش
  • ۲ درس مرتبط
  • کد و دستورها عیناً از دوره‌ی اصلی
فهرست مطالب
  1. وظایف درس
  2. پایپ‌لاین درخواست
  3. تلاش مجدد با عقب‌گرد
  4. مدیریت خطاها
  5. پیش‌فرض‌های درون کد
  6. کدهای خطای دمو
  7. فرمت ارتباطی SSE
  8. ازسرگیری یک پاسخ استریم‌شده
  9. سیاست طرح پشتیبان درگاه
  10. فایل ارائه‌دهندگان درگاه
  11. وظایف پروژه
  12. اهداف و چک‌لیست
  13. پرسش و پاسخ

وظایف درس

کار و کد
وظیفهکد
نصب استک سرورpip install fastapi uvicorn
اجرای برنامه با 4 ورکرuvicorn production_app:app --host 0.0.0.0 --port 8000 --workers 4
انتخاب مدل اصلیLLM_MODEL=gpt-4o
راه‌اندازی سرور دموpython3 code/main.py --serve
الزامی کردن توکن دسترسیexport DEMO_ACCESS_TOKEN=<token>
ارسال یک پیش‌بینیcurl -s -X POST http://127.0.0.1:8000/api/predict -H 'Content-Type: application/json' -d '{"text": "ok"}'
مشاهده استریم رویدادهاcurl -N -X POST http://127.0.0.1:8000/api/stream -H 'Content-Type: application/json' -d '{"text": "<text>"}'
اجرای آزمون‌های دموpython3 -m unittest discover -s code/tests -v

پایپ‌لاین درخواست

معماری
قبولعدم اصابت کشکلاینتوب، موبایل، APIدرگاه APIاحراز هویت، محدودیت نرخ درخواستگاردریل‌های ورودیتزریق پرامپت، پاک‌سازی داده‌های حساس (PII)مسیریاب پرامپتقالب، نسخه A/Bکش معناییآستانه 0.92فراخوانی LLMتلاش مجدد، زنجیره جایگزینگاردریل‌های خروجیمتن نشانه‌گذاری‌شده جایگزین شدپاسخلاگ ارزیابی، هزینه، SSE

تلاش مجدد با عقب‌گرد

کد
python
async def call_llm_with_retry(prompt, model, max_retries=3):
    for attempt in range(max_retries + 1):
        try:
            ...                                                         # یک فراخوانی ارائه‌دهنده
        except (ConnectionError, TimeoutError):
            if attempt < max_retries:
                backoff = min(2 ** attempt + random.uniform(0, 1), 10)  # سقف 10 ثانیه
                await asyncio.sleep(backoff)
            else:
                raise
    raise ConnectionError(f"All {max_retries} retries exhausted for {model.value}")
# call_with_fallback walks FALLBACK_CHAIN, preferred model first.

مدیریت خطاها

عیب‌یابی
  • کد 429 از API

    علت
    محدودیت نرخ درخواست
    راه‌حل
    تلاش مجدد با عقب‌گرد. قرار دادن درخواست در صف
  • کد 500 از API

    علت
    خطای سرور
    راه‌حل
    3 بار تلاش مجدد. سوئیچ به مدل جایگزین
  • تایم‌اوت API بیش از 30 ثانیه

    علت
    ارائه‌دهنده کند
    راه‌حل
    یک بار تلاش مجدد. پرامپت کوتاه‌تر، مدل کوچک‌تر
  • خروجی ناقص یا ناهماهنگ

    علت
    شکست مدل
    راه‌حل
    تلاش مجدد همراه با درج خطا در پرامپت
  • مسدود شدن توسط گاردریل

    علت
    ورودی ناامن
    راه‌حل
    بدون تلاش مجدد. توضیح علت مسدودسازی
  • از کار افتادن پایگاه داده برداری

    علت
    خطای برنامه
    راه‌حل
    رد شدن از کانتکست RAG
  • از کار افتادن کش

    علت
    خطای برنامه
    راه‌حل
    فراخوانی مستقیم LLM
  • شکست تمام مدل‌ها

    علت
    اتمام زنجیره
    راه‌حل
    پاسخ کش‌شده، سپس عذرخواهی ثابت

پیش‌فرض‌های درون کد

پیش‌فرض‌ها
تنظیمپیش‌فرضنکته
similarity_threshold0.92امتیاز اصابت کش معنایی
ttl_seconds3600طول عمر ورودی کش
max_entries10000اندازه کش
max_retries3به ازای هر مدل در زنجیره
MAX_CHARS500محدودیت متن دمو
MAX_BODY_BYTES4096بدنه بزرگ‌تر خطای 413 می‌دهد
BUCKET_CAPACITY5شارژ مجدد 0.5 توکن در ثانیه
DAILY_CALL_CAP2000بیشتر از سقف خطای 503 می‌دهد

کدهای خطای دمو

دستورها
دستورعملکرد
413 body_too_largeبدنه بیش از 4,096 بایت
408 request_timeoutتوقف بدنه پیش از Content-Length
415 unsupported_media_typeنوع محتوا JSON نیست
400 bad_jsonبدنه یک شیء JSON نیست
422 text_too_longمتن بیش از 500 کاراکتر
422 control_charactersمتن دارای کاراکترهای کنترلی است
429 rate_limitedسطل توکن خالی است. هدر Retry-After را بخوانید
503 usage_cap_reachedسقف روزانه پر شد. هدر Retry-After را بخوانید

فرمت ارتباطی SSE

کد
bash
event: token  # نوع محتوا text/event-stream
data: {"index":0,"text":"Label:"}
  # یک خط خالی پایان هر رویداد را مشخص می‌کند
event: token
data: {"index":1,"text":" positive."}

event: done
data: {"label":"positive","score":1.0,"tokens":11}

ازسرگیری یک پاسخ استریم‌شده

گام‌به‌گام
  1. SSEDecoderبایت‌های چندتکه‌ی UTF-8 را به رویدادهای کامل متصل می‌کند.
  2. applyنیازمند شناسه‌های مثبت و پیوسته در حافظه است. وجود فاصله خطای noncontiguous answer event ID می‌دهد.
  3. applyشناسه تکراری با همان داده بی‌اثر است. داده‌ی متفاوت خطا می‌دهد.
  4. applyنوع داده text، citation یا complete است. ارجاعات نیازمند http یا https هستند.
  5. connectقطعی ارتباط پیش از complete وضعیت را interrupted می‌کند.
  6. connectفراخوانی بعدی Last-Event-ID را ارسال کرده و فقط رویدادهای بعدی را می‌گیرد.
  7. traceمقدار schemaVersion: 1 را همراه رویدادهای پذیرفته‌شده می‌نویسد. متد replay وضعیت را بازسازی می‌کند.

سیاست طرح پشتیبان درگاه

مقایسه
عاملکد 2xxکد 429 یا 5xxسایر وضعیت‌هالغو درخواست
ClassifyStatussuccessretryterminalندارد
ارائه‌دهنده بعدیخیربلهخیرخیر
وضعیت مسیرcompletedدر پایان exhaustedterminal-errorcancelled
پاسخ پروکسیبدنه دریافتی از بالادستدر پایان 502502504

فایل ارائه‌دهندگان درگاه

کد
bash
{"providers": [
  {"name": "primary", "url": "http://127.0.0.1:11434/v1/chat/completions"},
  {"name": "backup", "url": "http://127.0.0.1:11435/v1/chat/completions",
   "key_env": "ORCHARD_BACKUP_KEY"}],  # نام متغیر محیطی، نه کلید اصلی
 "max_attempts": 2,                    # 1 تا 16، یک بازدید به ازای هر ارائه‌دهنده
 "max_response_bytes": 65536,          # 1 بایت تا 16 مبی‌بایت
 "timeout_ms": 4000}                   # 1 تا 5000، کل مسیر

وظایف پروژه

کار و کد
وظیفهکد
ساخت یک پوشه کاریpython3 scripts/project_test.py <project> --init /tmp/<project>-work
نمره‌دهی به یک مرحلهpython3 scripts/project_test.py <project> --stage 1 --path /tmp/<project>-work --strict
استریم دمو، قطعی و سپس ازسرگیریcd projects/streaming-answer-recovery/solution && python3 demo.py
خواندن اندپوینت SSE خودتانnode --experimental-strip-types cli.ts <url> /tmp/trace.json
دموی درگاه، خطای 503 سپس پشتیبانcd projects/llm-gateway-with-fallbacks/solution && go run .
اجرای پروکسی درگاهgo run . --config /tmp/providers.json --listen 127.0.0.1:8088
فراخوانی پروکسیcurl --fail-with-body http://127.0.0.1:8088/v1/chat/completions --data-binary @fixtures/request.json

اهداف و چک‌لیست

نکته‌ها
  • تاخیر P50 زیر 2 ثانیه. تاخیر P99 زیر 10 ثانیه.
  • نرخ اصابت کش بالای 30%. نرخ مسدودسازی گاردریل زیر 5%.
  • هزینه هر درخواست زیر 0.01 دلار.
  • محدودیت نرخ درخواست هر کاربر بین 10 تا 50 درخواست در دقیقه.
  • تست بار با 100 کاربر همزمان پیش از راه‌اندازی.

پرسش و پاسخ

پرسش و پاسخ
چرا POST و نه EventSource؟
آبجکت EventSource فقط GET ارسال می‌کند. متد GET ورودی را در لاگ‌های URL ذخیره می‌کند.
شکست مدل پس از وضعیت 200؟
وضعیت ارسال شده است. یک رویداد error در استریم بفرستید.
در بدنه خطا چه مواردی قرار دارد؟
مقادیر code، message، hint و request_id.