نقاط رئيسية
- يشمل الوصف مسارات URL، وهياكل طلبات JSON واستجاباتها، ومصادقة Bearer، والبث المتدفق (SSE).
- لا يخبرك ذلك عن النموذج الذي يجيب، أو سلوكه، أو تكلفته.
- التبديل يعني عادة تغيير قيمتين: عنوان URL الأساسي ومفتاح واجهة برمجة التطبيقات.
- اختبر البث المتدفق، والأدوات، ووضع JSON، وأكواد الأخطاء قبل الاعتماد على مزوّد الخدمة.
الإجابة المختصرة
عندما يقول مزوّد الخدمة إن واجهة برمجة التطبيقات الخاصة به متوافقة مع OpenAI، فهذا يعني أنه يقبل نفس طلبات HTTP التي ترسلها مكتبات عملاء OpenAI ويعيد استجابات بنفس الهيكل. تحتفظ بكودك، وتغير نقطة النهاية والمفتاح، وتذهب المكالمة إلى خادم مختلف.
هذا هو الوعد الكامل. إنه بيان حول الواجهة، مثل قول إن شاحنين يستخدمان نفس المقبس. لا يخبرك بما يوجد في الطرف الآخر من الكابل. النموذج، وقواعد السلامة الخاصة به، وسعره وحدوده كلها يحددها مزوّد الخدمة، وهي تختلف كثيراً.
ما يغطيه الوصف فعلياً
في الممارسة العملية، توافق OpenAI هو قائمة قصيرة من الأشياء الملموسة. إذا كان مزوّد الخدمة يدعم جميعها، يعمل معظم كود العميل دون تغيير.
- المسارات. تذهب طلبات الدردشة إلى
POST /v1/chat/completions، وقائمة النماذج تأتي منGET /v1/models. - المصادقة. ينتقل المفتاح في رأس
Authorization: Bearer. - جسم الطلب. سلسلة
model، ومصفوفةmessagesمن الكائنات التي تحتوي علىroleوcontent، وحقول أخذ عينات اختيارية مثلtemperature، وtop_p، وstopوseed. - جسم الاستجابة. مصفوفة
choicesتحتوي على رسالة المساعد، وfinish_reason، وكائنusageيحتوي على عد الرموز. - البث المتدفق. مع
stream: trueيرسل الخادم أحداثاً مرسلة من الخادم (SSE)، يحمل كل منها جزءاً صغيراً من JSON، وينتهي بعلامة نهائية. - الميزات الاختيارية. استدعاء الدوال، وضع JSON والحقول المشابهة، حيث يختار المزوّد دعمها.
نظراً لأن العديد من الأدوات كُتبت بناءً على هذا التنسيق، أصبح هدفاً شائعاً. يسمح محررات النصوص، وأطر عمل الوكلاء، وواجهات لعب الأدوار، والنصوص العادية بإدخال نقطة نهاية مخصصة، وهذا كل ما تحتاجه.
لماذا أصبح هذا التنسيق هو الهدف المشترك
انتشر تنسيق إكمال الدردشة لأنه كان بسيطاً وظهر مبكراً. يمكن لمؤلف أداة يدعمه مرة واحدة الوصول إلى العديد من الخوادم الخلفية، ويمكن لمؤلف خادم خلفي يدعمه مرة واحدة الوصول إلى العديد من الأدوات. هذه صفقة جيدة للطرفين، لذا التزم التنسيق، حتى بين الخدمات التي لا علاقة لها بالشركة التي صممته.
بالنسبة لك كمطور، هذا له معنى عملي. لا يحتاج كودك إلى تكامل مختلف لكل مزوّد خدمة. يمكنك نقل نموذج أولي بين نقاط النهاية في فترة بعد الظهر، ومقارنة نموذجين باستخدام نفس المطالبات، أو الاحتفاظ بمزوّد خدمة ثانٍ كحل احتياطي عندما يكون الأول بطيئاً. تكلفة تغيير رأيك منخفضة، وهذا يسهل تجربة خدمة جديدة دون الالتزام بها.
الجانب الآخر هو أن السطح المشترك يخفي الاختلافات الحقيقية. نظراً لأن التبديل سهل جداً، فمن المغري افتراض أن كل شيء خلف نقطة النهاية متكافئ. ليس كذلك، وتوضح الأقسام أدناه حيث تظهر الفجوات عادةً.
ما لا يخبرك به
هنا حيث يفاجأ الناس. يترك الوصف كل ما يحدد ما إذا كان API مفيداً لعملك.
النموذج خلفه
يمكن لنقطة النهاية المتوافقة تقديم أي نموذج. يقدم بعضها نماذج مفتوحة الأوزان، وبعضها يحول الطلبات إلى عدة موردين، وبعضها يغلف نموذجاً مملوكاً. لا يعني التوافق أن الخدمة تديرها OpenAI، ولا يعني أن النموذج يتصرف مثل نماذجهم. اسم النموذج الذي تمرره في model هو مجرد سلسلة يحددها مزوّد الخدمة.
سلوك الرفض
قواعد المحتوى تخص النموذج ومزوّد الخدمة وليس البروتوكول. يمكن لواجهتي برمجة تطبيقات متوافقتين أن تردّا على نفس الموجّه بطريقتين متعاكستين. إذا كان استخدامك يتعلق بالقصة الخيالية أو التمثيل الأدائي أو محتوى بالغ قانوني آخر، تحقق مما يقوله مزوّد الخدمة حول حالات الرفض قبل ربط أي شيء.
عمق الميزات
بعض مزوّد الخدمة يطبّقون الدردشة فقط. وآخرون يضيفون الأدوات، وضع JSON، احتمالات السجل أو نقاط نهاية إضافية. العميل الذي يرسل حقلًا يتجاهله الخادم لن يفشل دائمًا بشكل صاخب، لذا من الممكن حدوث عدم تطابق صامت.
الحدود، التسعير والأخطاء
حدود المعدل، طول السياق، الحد الأقصى لحجم الجسم والسعر لكل رمز هي خيارات من قِبل مزوّد الخدمة. تختلف أيضًا هياكل الأخطاء في التفاصيل حتى عندما تتطابق رموز حالة HTTP، لذا يجب أن يعتمد منطق إعادة المحاولة على رموز الحالة والعناوين بدلاً من نص الرسالة.
اختبار توافق سريع
يمكنك التحقق من موفّر الخدمة في بضع دقائق بطلبات ثلاث. استبدل المفتاح بمفتاحك الخاص. يستخدم هذا المثال عنوان URL الأساسي لهذا الموقع.
curl https://api.kimicode.top/v1/models \
-H "Authorization: Bearer YOUR_API_KEY"
curl https://api.kimicode.top/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "uncensored",
"messages": [{"role": "user", "content": "Reply with the word ready."}]
}'
تؤكد المكالمة الأولى صحة المفتاح وتعرض معرفات النماذج. تتحقق الثانية من شكل المحادثة. ثم اختبر الأجزاء التي يعتمد عليها تطبيقك: أضف "stream": true وراقب القطع المتزايدة، مرر مصفوفة tools إذا كنت تستخدم استدعاء الدوال، واضبط response_format على {"type":"json_object"} إذا كنت بحاجة إلى مخرجات قابلة للتحليل.
قم أيضًا بإثارة خطأ عن قصد، مثل مفتاح غير صالح. تريد رؤية حالة HTTP نظيفة وجسم خطأ بصيغة JSON يمكن للعميل الخاص بك معالجته.
نفس الاستدعاء في Node
تأخذ مكتبة JavaScript نفس القيمتين. إليك مكالمة بث، وهي الشكل الذي تستخدمه معظم واجهات المحادثة.
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.kimicode.top/v1",
apiKey: process.env.API_KEY,
});
const stream = await client.chat.completions.create({
model: "بدون رقابة",
stream: true,
messages: [{ role: "user", content: "Name three uses of SSE." }],
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
إذا طُبع النص كلمة بكلمة، فإن مسار البث يعمل من البداية للنهاية. نفس الحلقة تعمل مع أي مزوّد متوافق، وهذا هو الهدف الكامل من التنسيق.
كيف يبدو التبديل في الكود
مع مكتبة Python الرسمية، التغيير هو معاملين للمُنشئ. يبقى باقي برنامجك كما كان.
from openai import OpenAI
client = OpenAI(
base_url="https://api.kimicode.top/v1",
api_key="YOUR_API_KEY",
)
resp = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Summarize SSE in one sentence."}],
)
print(resp.choices[0].message.content)
تتبع Node SDK نفس الفكرة مع خيارات baseURL و apiKey. تقرأ العديد من الأدوات المتغيرات OPENAI_BASE_URL و OPENAI_API_KEY من البيئة، لذا يمكنك أحياناً التبديل دون تعديل الكود على الإطلاق.
تذكر تغيير سلسلة النموذج أيضًا. سيفشل الطلب الذي يسمي نموذجًا لا يستضيفه الخادم الجديد، وهذا هو الخطأ الأول الأكثر شيوعًا.
أين يناسب API هذا الموقع
هذه الخدمة هي API مستضاف للنصوص فقط يتبع تنسيق OpenAI. يشغل نموذج واحد مفتوح الأوزان، يديره مزوّد مستقل ومضبط للإجابة دون رفض المحتوى للاستخدام القانوني للبالغين. ليس API الرسمي لأي بائع نماذج ولا يوجّه الطلبات بين المزودين. معرف النموذج هو uncensored.
يدعم البث عبر SSE مع الإبلاغ عن الاستخدام في النهاية، استدعاء الدوال، وضع JSON، ويمرر temperature و top_p و stop و seed والعقوبات. نافذة السياق هي 100,000 رمز للموجّه والإكمال معاً. لا يولد صوراً أو صوتاً، ولا يقدم تضمينات أو ضبطاً دقيقاً. قاعدة واحدة ثابتة: لا محتوى جنسي يتضمن القاصرين.
الفوترة مسبقة الدفع ومقاسة: $0.15 لكل مليون رمز مدخل و $0.50 لكل مليون رمز مخرج، بدون اشتراك. يمكنك رؤية الأرقام على صفحة التسعير، و المستندات تشرح طلباً أولياً. إذا أردت تجربته دون دفع، يمكن للحسابات الجديدة المطالبة برصيد تجريبي مجاني بقيمة $0.50 بنقرة واحدة على صفحة مفتاح API.
أخطاء التوافق الشائعة
- عنوان URL الأساسي غير صحيح. يجب أن ينتهي عنوان URL بـ
/v1. تضيف العملاء/chat/completionsبأنفسهم، لذا فإن إضافته إلى العنوان الأساسي ينتج خطأ 404. - معاملات غير مدعومة. إذا أرسلت مكتبة حقل لا يعرفه الخادم، تحقق مما إذا كان مرفوضاً أو يتم تجاهله بصمت، ثم أزلها.
- البث والتزامن. يحتفظ الطلب المتدفق بمكان تزامن حتى ينتهي البث. إذا فتح تطبيقك العديد من التدفقات، فقد تواجه خطأ 429 برمز
concurrencyرغم أن عدد الطلبات في الدقيقة منخفض. - إعادة المحاولة عند 429. تعامل مع 429 كإشارة للانتظار. عندما يكون هناك رأس
Retry-Afterموجود، التزم به. - حساب الرموز. لا تفترض أن مرمز مزود آخر يتطابق. اقرأ كائن
usageفي المخرجات للحصول على الأرقام التي تُحسب عليها الفوترة.
لا يُعدّ أيّ من هذه المشكلات صعب الإصلاح بمجرد معرفة كيفية البحث عنها، ومعظمها يختزل في قراءة رسالة الخطأ الأولى بعناية.
