تحتوي واجهات API المتوافقة مع OpenAI الآن على تنسيقين رئيسيين للطلبات: التنسيق القديم /v1/chat/completions والتنسيق الأحدث /v1/responses. يقبل GetVibe API كليهما باستخدام مفتاح واحد وعنوان أساسي واحد، وهو https://getvibeapi.com/v1. إليك كيفية اختلافهما عمليًا، وأيهما تختار، والفخ الوحيد عند الانتقال بينهما.
الخلاصة المختصرة
| Chat Completions | Responses | |
|---|---|---|
| نقطة النهاية | POST /v1/chat/completions | POST /v1/responses |
| الإدخال | مصفوفة messages | input: سلسلة نصية أو مصفوفة من العناصر |
| المطالبة النظامية | رسالة ذات دور system | الحقل instructions |
| الإجابة | choices[0].message | مصفوفة output: استدلال ورسالة واستدعاءات دوال |
| حد الإخراج | max_tokens | max_output_tokens |
| من يستخدمه | معظم حزم SDK وأطر العمل وتطبيقات الدردشة | Codex CLI وحزم SDK الأحدث للوكلاء |
لا يغيّر التنسيق النموذج أو السعر أو عدد الرموز: إذ تُحاسب على رموز الإدخال والإخراج الخاصة بالنموذج في كلتا الحالتين.
الطلب نفسه بالتنسيقين
Chat Completions:
curl https://getvibeapi.com/v1/chat/completions \
-H "Authorization: Bearer $GETVIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-luna",
"messages": [
{"role": "system", "content": "أجب في جملة واحدة."},
{"role": "user", "content": "ماذا يعني HTTP 429؟"}
],
"max_tokens": 300
}'
Responses:
curl https://getvibeapi.com/v1/responses \
-H "Authorization: Bearer $GETVIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-luna",
"instructions": "أجب في جملة واحدة.",
"input": "ماذا يعني HTTP 429؟",
"max_output_tokens": 300
}'
في Chat Completions يوجد النص في choices[0].message.content. أما في Responses، فيوجد داخل output: بالنسبة إلى نماذج الاستدلال، يكون العنصر الأول عنصر reasoning، وتكون الإجابة هي العنصر من النوع message. لا يتعين عليك اجتياز المصفوفة يدويًا؛ إذ تحتوي حزمة Python SDK على خاصية output_text.
import os
from openai import OpenAI
client = OpenAI(base_url="https://getvibeapi.com/v1", api_key=os.environ["GETVIBE_API_KEY"])
chat = client.chat.completions.create(
model="gpt-6-luna",
messages=[{"role": "system", "content": "أجب في جملة واحدة."},
{"role": "user", "content": "ماذا يعني HTTP 429؟"}],
)
print(chat.choices[0].message.content)
resp = client.responses.create(
model="gpt-6-luna",
instructions="أجب في جملة واحدة.",
input="ماذا يعني HTTP 429؟",
)
print(resp.output_text)
لا يقتصر Responses على نماذج OpenAI. قبل النشر، أرسلنا طلب Responses نفسه إلى gpt-6-luna وclaude-sonnet-5.5 وdeepseek-v4.1-flash، وقد أجابت النماذج الثلاثة جميعًا. أعاد DeepSeek عنصر reasoning قبل عنصر message، تمامًا كما هو موضح أعلاه.
سجل المحادثة: أرسله بنفسك
هذا هو الشيء الوحيد الذي ينبغي معرفته قبل الانتقال. يمكن لـ Responses API الخاصة بـ OpenAI الاحتفاظ بمحادثة على الخادم، بحيث يشير الطلب التالي إلى الطلب السابق باستخدام previous_response_id. لا يخزّن GetVibe API محادثاتك، ولذلك فإن previous_response_id غير مدعوم، ويتم تجاهل store. عندما جربناه، رُفض الطلب بخطأ 400.
النمط العملي هو نفسه المتبع مع Chat Completions: أرسل السجل الكامل في input.
history = [{"role": "user", "content": "اسمي Ana. تذكّره."}]
first = client.responses.create(model="gpt-6-luna", input=history)
history.append({"role": "assistant", "content": first.output_text})
history.append({"role": "user", "content": "ما اسمي؟ كلمة واحدة."})
second = client.responses.create(model="gpt-6-luna", input=history)
print(second.output_text) # Ana
الأدوات: بنية مختلفة
يعمل استدعاء الدوال بالتنسيقين، لكن تعريف الأداة يبدو مختلفًا. ففي Chat Completions تكون حقول الدالة متداخلة داخل كائن function؛ أما في Responses فتوجد مباشرةً على الأداة. يصل الاستدعاء كعنصر function_call منفصل، وتعيد النتيجة كعنصر function_call_output يحمل قيمة call_id نفسها.
import json
tools = [{
"type": "function",
"name": "get_weather",
"description": "الطقس الحالي في مدينة",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
"additionalProperties": False,
},
}]
items = [{"role": "user", "content": "كيف الطقس في دنفر؟"}]
resp = client.responses.create(model="gpt-6-luna", input=items, tools=tools)
for item in resp.output:
if item.type == "function_call":
result = {"city": "Denver", "temp_f": 54, "sky": "overcast"} # دالتك
items.append({"type": "function_call", "call_id": item.call_id,
"name": item.name, "arguments": item.arguments})
items.append({"type": "function_call_output", "call_id": item.call_id,
"output": json.dumps(result)})
final = client.responses.create(model="gpt-6-luna", input=items, tools=tools)
print(final.output_text)
في تجربتنا، استدعى النموذج get_weather باستخدام {"city":"Denver"}، وأجاب الطلب الثاني بأن درجة الحرارة في دنفر تبلغ 54°F والجو غائم. يوجد إصدار Chat Completions من الحلقة نفسها في دليل استدعاء الدوال الخاص بنا.
البث
يدعم التنسيقان "stream": true، لكن الأحداث تختلف. يرسل Chat Completions أسطر data: موحّدة، بحيث يوجد كل جزء جديد من النص في choices[0].delta.content. أما Responses فيرسل أحداثًا مسماة: response.created أولًا، ثم response.output_text.delta مع أجزاء النص، ثم response.completed في النهاية. إذا حللت البث بنفسك بدلًا من استخدام حزمة SDK، فستحتاج إلى محلل للتنسيق المحدد.
أيهما تختار؟
- Chat Completions إذا كان لديك كود يعمل عليه بالفعل، أو كنت تستخدم إطار عمل أو تطبيق دردشة أو منصة بلا كود. تكاد كل الأدوات تتحدث هذا التنسيق، ولا يوجد سبب لإعادة كتابة كود يعمل لمجرد تغيير التنسيق.
- Responses إذا كانت إحدى الأدوات تتطلبه. المثال الرئيسي هو Codex CLI، الذي يتحدث إلى
/v1/responses؛ ويتوفر الإعداد في وثائق Codex CLI وفي دليل Codex CLI الخاص بنا.
في كلتا الحالتين، تظل قائمة النماذج والأسعار نفسها. راجع مرجع API للاطلاع على كل حقل، وصفحة النماذج لمعرفة الأسعار الحالية.
