مهندسی سامانههای هوش مصنوعی · فصل ۱ — Gateway، Structured Output، Prompt Governance و Qualification · 133
LLM Gateway و Provider-neutral Abstraction
میتواند مدل یا ابزار AI را فراخوانی کند اما contract، qualification، routing، cost، trust و failure را کنترل نمیکند. موضوع جاری: «LLM Gateway و Provider-neutral Abstraction». میتواند «LLM Gateway و Provider-neutral Abstraction» را در یک workflow AI محدود طراحی کند و validation، authority، cost یا failure controls مرتبط را مشخص کند.
خلاصهٔ درس
میتواند مدل یا ابزار AI را فراخوانی کند اما contract، qualification، routing، cost، trust و failure را کنترل نمیکند. موضوع جاری: «LLM Gateway و Provider-neutral Abstraction».
میتواند «LLM Gateway و Provider-neutral Abstraction» را در یک workflow AI محدود طراحی کند و validation، authority، cost یا failure controls مرتبط را مشخص کند.
خروجی این درس
میتواند «LLM Gateway و Provider-neutral Abstraction» را در یک workflow AI محدود طراحی کند و validation، authority، cost یا failure controls مرتبط را مشخص کند.
1. مسئله واقعی: تعویض SDK با abstraction برابر نیست
اگر business logic مستقیماً typeها، نام model، شکل message، exception و usage یک provider را ببیند، وابستگی فقط در importها نیست؛ semantics همان provider وارد هسته محصول شده است. یک متد عمومی مثل generate(prompt) ممکن است اسم SDK را پنهان کند اما تفاوت در refusal، tool call، structured output، streaming، usage و error را از بین نمیبرد. هدف این درس ساخت مرزی است که product-owned semantics را ثابت نگه دارد و تفاوتهای واقعی provider را قابل مشاهده نگه دارد.
2. ابتدا operation محصول را تعریف کنید
Gateway باید از یک operation محدود شروع کند، نه از همه قابلیتهای احتمالی LLM. در Lab، operation ما summarize_support_case است: متن ورودی میگیرد و یک summary ساختیافته با چند field مشخص برمیگرداند. Domain service فقط همین operation و contract آن را میشناسد. اینکه Provider Alpha schema را در یک field میگیرد و Provider Beta آن را در یک tool-like shape میبیند، مسئله adapter است نه domain logic.
3. Canonical request فقط semantics مالکشده را نگه میدارد
Canonical request باید fieldهایی را نگه دارد که محصول واقعاً به آنها متکی است: operation، input، required capabilities، timeout، trace id و contract version. هر field provider-specific فقط وقتی وارد contract مشترک میشود که محصول معنای آن را مالک باشد. گزینهای مثل reasoning level یا vendor-only tuning نباید صرفاً برای راحتی adapter به contract عمومی نشت کند؛ میتواند configuration خصوصی همان adapter باقی بماند.
4. Canonical response باید terminal state را صریح کند
خروجی مشترک فقط text نیست. حداقل باید terminal state، data payload، normalized error، raw provider evidence، usage state، provider/model provenance و trace id را حمل کند. REFUSAL نباید به empty text تبدیل شود و ERROR نباید به response خالی شبیه success تبدیل شود. Domain code باید بتواند تفاوت COMPLETE، REFUSAL و ERROR را بدون دانستن SDK provider تشخیص دهد.
5. Capability declaration قبل از translation است
هر adapter یک capability declaration نسخهدار دارد: text، tools، structured output، streaming و هر ویژگی دیگری که operation واقعاً لازم دارد. Gateway قبل از ارسال request بررسی میکند که capability لازم موجود است. اگر نیست، state باید UNSUPPORTED_CAPABILITY بماند. تبدیل پنهانی structured output به free-text یا tool call فقط وقتی مجاز است که یک degraded contract صریح و تستشده وجود داشته باشد.
6. Adapter map میکند؛ semantics را اختراع نمیکند
Adapter request مشترک را به shape provider ترجمه میکند و response را به contract مشترک برمیگرداند. اما adapter حق ندارد state جدیدی بسازد که provider یا policy آن را ثابت نکرده است. اگر Provider Beta refusal block دارد، باید همان fact حفظ شود. اگر usage دیرتر میآید، adapter نباید عدد صفر را بهعنوان usage نهایی بنویسد. اگر fieldی معادل ندارد، UNAVAILABLE یا UNKNOWN از عدد یا متن ساختگی بهتر است.
7. Lowest common denominator هدف نیست
Provider-neutral design زمانی خراب میشود که همه قابلیتها به کوچکترین مجموعه مشترک تقلیل داده شوند. این روش ممکن است قابلیت مهم یک provider را بیدلیل حذف کند یا برای provider دیگر معنای جعلی بسازد. بهتر است contract عملیاتمحور باشد: capability required را برای همان operation مشخص کند و اجازه دهد adapterها capability اضافی خود را خارج از business interface نگه دارند.
8. Unsupported، degraded و rejected سه حالت متفاوتاند
اگر provider capability لازم را ندارد، سه مسیر ممکن است وجود داشته باشد: رد کامل operation؛ اجرای محدود با degraded contract تعریفشده؛ یا defer تا evidence/adapter جدید فراهم شود. این انتخاب باید policy-driven و قابل audit باشد. یک fallback خودکار که semantics را عوض میکند اما همان response type را برمیگرداند، خطرناک است چون caller تصور میکند همان ضمانت قبلی حفظ شده است.
9. Error normalization باید raw provenance را حفظ کند
Gateway میتواند errorهای مختلف را به کلاسهایی مثل RATE_LIMIT, TIMEOUT, AUTH, PROVIDER_ERROR, REFUSAL و UNSUPPORTED_CAPABILITY normalize کند تا business logic وابسته به exception string نباشد. ولی raw provider code/message/request id باید برای debugging و governance نگه داشته شود. Normalization لایه تصمیم است، نه پاککردن evidence اصلی.
10. Usage normalization با UNKNOWN سازگار است
Providerها token/cost metadata را با shape و timing متفاوت میدهند. Canonical usage باید state داشته باشد: FINAL, PENDING یا UNAVAILABLE. اگر usage بعداً میرسد، همان لحظه نباید عدد fabricated ثبت شود. Cost governorهای بعدی میتوانند روی همین evidence کار کنند، اما AIE-001 فقط مرز درست usage را تعریف میکند و مالک policy هزینه نیست.
11. Auth و timeout نیز بخشی از boundary هستند
Domain service نباید API key یا credential provider را ببیند. Adapter/gateway credential boundary را نگه میدارد و فقط نتیجه احراز یا خطای typed را به contract مشترک منتقل میکند. Timeout نیز باید در canonical request policy مشخص باشد و adapter آن را به مکانیسم provider نگاشت کند. Retry policy پویا موضوع این درس نیست؛ مهم این است که timeout و failure قابل تمایز و قابل ردیابی باشند.
12. Provenance بدون provider identity ناقص است
هر response evidence باید provider adapter version، provider/model id، request id در صورت وجود، trace id، contract version و capability profile را نگه دارد. بدون اینها عبارت «Gateway جواب داد» برای debugging یا requalification کافی نیست. اگر alias یا backend عوض شود، provenance باید نشان دهد کدام provider و کدام mapping واقعاً request را اجرا کرده است.
13. Contract test دو provider را با یک domain workflow میسنجد
در Lab، Domain service یک function ثابت را صدا میزند. Alpha و Beta shapeهای متفاوت دارند، اما هر دو باید canonical response معتبر تولید کنند. تستها نه فقط success بلکه refusal، rate limit، timeout و raw provider error را هم بررسی میکنند. PASS یعنی domain workflow بدون branch provider-specific کار میکند و stateهای متفاوت نیز بدون flatten شدن حفظ میشوند.
14. Lab: هشت fixture قطعی و 64 assertion
Lab هشت case دارد: success در Alpha، success در Beta، refusal در Beta، rate limit در Alpha، timeout در Alpha، provider error ناشناخته در Beta، provider سوم بدون structured capability، و provider سوم با degraded tool-based mapping و usage غیرنهایی. برای هر case هشت خروجی ثابت بررسی میشود: capability result، request mapping، response state، normalized error، usage state، provenance، contract-test result و decision. مجموعاً 64 assertion اجرا میشود.
15. Exit checklist و انتقال
قبل از خروج بررسی کنید: operation و contract version مشخصاند؛ business logic هیچ type provider-specific ندارد؛ capability gap صریح است؛ refusal/error/unsupported flatten نمیشوند؛ raw provider evidence حفظ میشود؛ usage نامشخص جعلی نمیشود؛ auth و timeout boundary مشخصاند؛ و contract test روی دو provider مستقل پاس میشود. سپس provider سوم را اضافه کنید: text و tools دارد اما structured-output mode هممعنی ندارد و usage را asynchronous گزارش میکند. بدون تغییر domain interface تصمیم بگیرید PASS، CONDITIONAL، DEFER یا REJECT کدام است و residual gap را ثبت کنید.
ارزیابی
پاسخنامهی این درس در بستهی آموزش وجود ندارد؛ خودت جواب بده و صادقانه علامت بزن. «نیاز به مرور» درس را به صف تکرار میفرستد.
Q1 retrieval
Why is a shared generate(prompt) method insufficient proof of provider neutrality?
Q2 application
Provider Beta lacks the structured-output capability required by the operation. What should the gateway do before calling it?
Q3 diagnosis
A provider returns a refusal block but an adapter maps it to empty text. What failed?
Q4 evidence
What provenance makes a normalized response auditable?
Q5 transfer
A third provider supports tools but not the same structured-output mode and reports usage asynchronously. What must change?
ملاکهای ارزیابی (rubric)
- Contract boundary: operation and product-owned semantics are explicit; routing/model-quality outcomes remain out of scope.
- Provider mapping: Alpha/Beta mappings are versioned and no provider type appears in domain logic.
- Capability discipline: unsupported capability is preserved; any degradation is declared rather than silent.
- Error and usage evidence: normalized classes exist while raw provider evidence and usage uncertainty remain visible.
- Provenance: provider/model/adapter/trace identity is retained.
- Transfer: Gamma is evaluated from its changed capability and asynchronous-usage evidence rather than inheriting Alpha/Beta status.
منابع و تازگی
مطالعهٔ موارد (case studies)
تصاویر درس
فایلهای آزمایشگاه
Implement the bounded evaluator in starter.py for the supplied synthetic provider fixtures. Do not add network calls. Preserve unsupported capabilities, refusal/error state, usage uncertainty and provider provenance. The domain operation stays provider-neutral; adapter/capability evidence determines PASS, REJECT, DEFER or CONDITIONAL.
Run python run_checks.py to verify fixture shape. The learner path intentionally does not include the reference evaluator.
رسانه و اسلایدهای درس
فایلهای آموزشی (دانلود)