سازگاری با OpenAI و مهاجرت از OpenAI، Azure و دیگران
مهاجرت کد موجود به یوتاپن فقط با تغییر base_url؛ شکل شناسهٔ مدلها، مسیرهای پشتیبانیشده، فیلدهایی که عبور میکنند و جدول اشتباههای رایج.
بهروزرسانی: ۱۶ شهریور ۱۴۰۵
یوتاپن همان قرارداد chat/completions را پیاده کرده که SDK رسمی OpenAI با آن حرف میزند. اگر کدت الان با OpenAI، Azure OpenAI یا هر سرویس سازگار دیگری کار میکند، مهاجرت یعنی دو تغییر: آدرس پایه و کلید. شناسهٔ مدل هم شکل provider/model میگیرد. باقی صفحه دربارهٔ همین جزئیات و چند تفاوت کوچک است.
تغییر base_url
# قبل
client = OpenAI(api_key="sk-...")
# بعد
client = OpenAI(
base_url="https://api.uttapen.ir/v1",
api_key="sk-up-...",
)
در Node نام فیلد baseURL است؛ در PHP withBaseUri()؛ در Go option.WithBaseURL(). اگر SDK از متغیر محیطی میخواند، OPENAI_BASE_URL=https://api.uttapen.ir/v1 و OPENAI_API_KEY=sk-up-... را ست کن و کد را دست نزن. مسیر /v1 جزء آدرس است؛ بدون آن 404 میگیری.
شناسهٔ مدل
شناسهها به شکل سازنده/مدل هستند، چون کاتالوگ ما مدلهای چند سازنده را کنار هم دارد و اسم خالی مدل بین آنها یکتا نیست:
| قبل (OpenAI) | بعد (یوتاپن) |
|---|---|
gpt-5 | openai/gpt-5 |
gpt-5-mini | openai/gpt-5-mini |
o3 | openai/o3 |
| — | anthropic/claude-sonnet-4.5 |
| — | google/gemini-2.5-flash |
| — | deepseek/deepseek-chat |
فهرست کامل با قیمت تومانی در صفحهٔ مدلها یا GET /v1/models (بدون کلید هم کار میکند). پسوندهای :free، :batch و :online هم پشتیبانی میشوند. شناسهٔ بدون نام سازنده (gpt-5) پذیرفته نمیشود و 404 model_not_found برمیگرداند.
چه چیزهایی پشتیبانی میشود
| مسیر | وضعیت |
|---|---|
POST /v1/chat/completions | کامل؛ استریم و غیراستریم، tools، vision، فایل، response_format، reasoning |
POST /v1/embeddings | کامل |
POST /v1/completions | legacy؛ برای مدلهایی که پشتیبانی میکنند |
GET /v1/models، GET /v1/models/{id} | کامل، با بلوک uttapen_pricing |
POST /v1/responses | فعلاً 404 با پیام راهنما؛ از chat/completions استفاده کن |
/v1/files، /v1/fine_tuning، /v1/assistants، /v1/batches، /v1/audio، /v1/images | ندارد؛ 404 not_found |
Responses API بعد از تثبیت شکل رویدادهایش برای متر کردن هزینه اضافه میشود. تا آن روز، هر چیزی که در Responses میخواهی (tools، تصویر، JSON، reasoning) در chat/completions هم هست؛ فقط شکل بدنه فرق دارد.
فیلدهایی که عبور میکنند
بدنهٔ درخواست تو تقریباً دستنخورده به مدل میرسد. چند فیلد اضافه فراتر از قرارداد OpenAI هم پشتیبانی میشود:
provider— ترجیح یا اجبار یک ارائهدهندهٔ خاص برای یک مدل (مثلاً{"order": ["Anthropic"], "allow_fallbacks": false}در بدنه). برای کاربر حرفهای که به latency یا region حساس است.models— فهرست مدلهای جایگزین. اگر مدل اول جواب نداد، بعدی امتحان میشود. رزرو هزینه با گرانترین مدل فهرست محاسبه میشود، ولی شارژ نهایی با مدلی است که واقعاً پاسخ داده.reasoning،plugins،web_search_options،transforms— عبور میکنند و در برآورد هزینه لحاظ میشوند.
دو فیلد را خودمان اضافه میکنیم: usage: {include: true} تا مصرف واقعی برگردد، و stream: true به سمت مدل حتی وقتی تو استریم نخواستهای. در حالت دوم یوتاپن تکههای استریم را جمع میکند و یک JSON استاندارد تحویلت میدهد، پس از بیرون فرقی نمیبینی.
تفاوتهای رفتاری
- فیلدهای عددی باید عدد صحیح JSON باشند.
max_tokens،max_completion_tokens،max_output_tokens،nوbest_ofبهصورت"100"(رشته)،100.0یا1e2رد میشوند و400 invalid_requestمیگیری. دلیلش این است که برآورد هزینه نباید با نمایشی که مدل میپذیرد ولی ما نمیخوانیم دور زده شود. 402قبل از ارسال. اگر موجودی قابلاستفاده از برآورد هزینهٔ درخواست کمتر باشد، درخواست اصلاً به مدل نمیرود.max_tokensکوچکتر یعنی رزرو کوچکتر (قیمتگذاری).- حداکثر بدنه ۲۰ مگابایت است؛ بیشتر از آن
413. - پیامهای خطای مدل عیناً با همان status برمیگردند، فقط رشتههای داخلی زیرساخت از متن پاک شدهاند.
- بدون ذخیرهٔ محتوا. پرامپت و پاسخ در مسیر API جایی ثبت نمیشوند (حریم خصوصی).
- تأخیر اضافه نسبت به فراخوانی مستقیم مدل حدود ۱۰۰ میلیثانیه است.
اشتباههای رایج
| نشانه | علت | راهحل |
|---|---|---|
404 not_found روی هر درخواست | base_url بدون /v1 یا با /v1/chat/completions کامل | فقط https://api.uttapen.ir/v1 |
404 model_not_found با مدل معتبر | شناسه بدون نام سازنده یا با حروف بزرگ | openai/gpt-5-mini، همه حروف کوچک |
401 بعد از کار درست چند روزه | کلید منقضی یا لغو شده؛ یا کلید OpenAI قدیمی در env مانده | UTTAPEN_API_KEY را چک کن؛ OPENAI_API_KEY اگر ست است اولویت ندارد ولی گیجکننده است |
400 invalid_request روی max_tokens | مقدار رشته یا اعشاری | عدد صحیح بفرست |
402 روی درخواست کوچک | max_tokens ست نشده و سقف پیشفرض ۳۲٬۷۶۸ توکن خروجی برای مدل گران رزرو شده | max_tokens واقعی بده؛ وگرنه سقف خودش تا جایی که موجودی میکشد پایین میآید (هدر X-Uttapen-Max-Tokens) |
| کلاینت استریم قطع میشود | proxy میانی (nginx، Cloudflare) بافر میکند | proxy_buffering off یا هدر X-Accel-Buffering: no روی proxy خودت |
client.responses.create خطا میدهد | Responses API هنوز فعال نیست | chat.completions.create |
| خروجی SDK PHP در استریم میشکند | هدر X-Uttapen-Include-Meta با createStreamed | این هدر را فقط با کلاینت HTTP خام بفرست (PHP) |
مهاجرت از یک سرویس سازگار دیگر
اگر تا حالا از یک سرویس واسط دیگر با API سازگار OpenAI استفاده میکردی، فقط آدرس پایه و کلید عوض میشود و شکل شناسهٔ مدل همان سازنده/مدل میماند. تفاوتهای عملی: تسویه به تومان از کیف پول یوتاپن است، هزینهٔ هر درخواست در هدر پاسخ میآید، و هیچ درخواستی از IP ایران به سرویسهای خارجی نمیرسد.
مهاجرت از Azure OpenAI
کلاینت AzureOpenAI را با OpenAI معمولی جایگزین کن؛ api_version و azure_endpoint معنایی ندارند و نام deployment جای خودش را به شناسهٔ provider/model میدهد.
با شماره موبایل ثبتنام کن، کیف پول را از ۱۰۰٬۰۰۰ تومان شارژ کن و کلید بساز. مدلهای رایگان بدون شارژ هم کار میکنند — تا ۵۰ درخواست در روز. ساخت کلید API ←