انقل JSON Schema بين OpenAI وGemini: المجموعة المشتركة أصغر مما تتوقع

|الكاتب: فريق تحرير QUASA|5 دقيقة للقراءة
انقل JSON Schema بين OpenAI وGemini: المجموعة المشتركة أصغر مما تتوقع

لنقل مخطط JSON Schema واحد بين OpenAI وGemini، ابدأ بكائن ذي حقول محددة الأنواع، واجعل جميع الحقول مطلوبة، واضبط additionalProperties على false في كل كائن. ينص توثيق OpenAI للمخرجات المنظمة على شرطي required وadditionalProperties في الوضع الصارم، ويميز بين Structured Outputs، الذي يلتزم بالمخطط المدعوم، وJSON mode، الذي يضمن صلاحية JSON دون مطابقة مخطط بعينه.

يمكن إرسال تعريف البيانات نفسه إلى Gemini، لكن طريقة تضمينه في الطلب تختلف، وكذلك حدود الكلمات المقبولة. تسرد وثائق Gemini للمخرجات المنظمة مجموعة فرعية من JSON Schema وتوصي بالتحقق من القيم داخل التطبيق. لذلك اجعل المخطط المشترك مسؤولًا عن شكل البيانات، واحتفظ بقواعد صحة المحتوى ومسارات فشل التوليد في منطق التطبيق.

ما الذي يدخل في المخطط المشترك؟

النواة المحافظة أصغر من كامل JSON Schema، بل أصغر من مجموع ما تقبله الواجهتان منفردتين. هذه خريطة توافق عملية لمخرجات منظمة يمكن نقل تعريفها بينهما؛ وهي اختيار تصميمي محافظ، وليست ادعاءً بأن كل كلمة خارجها مرفوضة دائمًا.

  • الأنواع: استخدم string وnumber وinteger وboolean وobject وarray. عرّف حقول object عبر properties وعناصر array عبر items، مع نوع واضح لكل حقل وعنصر.
  • الحقول المطلوبة: أدرج كل اسم في properties ضمن required، وكرر ذلك داخل الكائنات المتداخلة. تتيح Gemini تحديد الحقول المطلوبة، بينما يتطلب وضع OpenAI الصارم إدراجها جميعًا؛ اعتماد الشرط الأشد يجعل التعريف قابلًا للنقل.
  • إغلاق الكائن: ضع additionalProperties بقيمة false في الجذر وفي كل كائن متداخل. بذلك يصبح ظهور مفتاح غير معروف مخالفة للمخطط بدل أن يمر بوصفه إضافة مقبولة.
  • التصنيف والغياب: استخدم enum نصية عندما تكون الفئات محددة، واستخدم type بقيمتي string وnull للحقل الذي يجب أن يظهر مفتاحه لكن قد تغيب قيمته. القيمة null هنا تمثل غياب المعلومة؛ حذف المفتاح نتيجة مختلفة يخالف قاعدة required.
  • القيود المتقدمة: اترك pattern وprefixItems والتراكيب الشرطية خارج النواة. يظهر prefixItems في دعم Gemini الموثق، بينما يضع OpenAI قيودًا على تركيب المخططات؛ كما أن بعض قيود الأطوال والحدود لا تتاح في OpenAI للنماذج المضبوطة. يظهر anyOf في أمثلة الطرفين، لكن OpenAI يشترط أن يكون الجذر كائنًا وألا يبدأ بـanyOf، لذا لا تحتاجه نقطة البداية المحافظة.

يمكن أن يساعد description النموذج على فهم معنى الحقل، لكنه لا يحوّل المعنى المكتوب إلى اختبار لصحة البيانات. إذا وصفت حقلًا بأنه تاريخ أو بريد إلكتروني، فلا تستنتج من الوصف وحده أن القيمة صحيحة أو أنها وردت في النص المدخل.

ابنِ تعريفًا مرجعيًا صغيرًا

افترض، كمثال توضيحي، أن التطبيق يستخرج قيمة نصية من رسالة. عرّف status بقيمتي found وmissing، وvalue بوصفه نصًا أو null. كلا الحقلين مطلوب، والكائن مغلق؛ بذلك يبقى شكل الناتج ثابتًا حتى عند غياب القيمة:

{"type":"object","properties":{"status":{"type":"string","enum":["found","missing"]},"value":{"type":["string","null"]}},"required":["status","value"],"additionalProperties":false}

يفرض هذا التعريف وجود المفتاحين ونوع كل قيمة، لكنه يسمح بنيويًا بأن تكون status مساوية لـmissing بينما تحمل value نصًا. قاعدة الاتساق بين الحقلين تنتمي إلى مدقق التطبيق: عند missing يجب أن تكون value مساوية لـnull، وعند found يجب أن تكون نصًا غير فارغ. هذا الفرق مهم خصوصًا إذا كانت الاستجابة ستُخزن أو ستتحول إلى قرار آلي.

احتفظ بنسخة مرجعية واحدة للمخطط، ثم اشتق منها إعداد الطلب الخاص بكل مزود. عندما تضيف حقلًا، ضعه في properties وrequired للكائن الصحيح، وحدد بوضوح هل تقبل قيمته null. وإذا احتجت إلى نمط نصي أو شرط يربط حقولًا متعددة، أضفه أولًا إلى مدقق التطبيق؛ بعدها تستطيع تقييم فائدته كامتداد خاص بمسار معين دون تحميل النواة المشتركة افتراضًا غير مضمون.

كيف ترسل المخطط إلى كل واجهة؟

إعادة استخدام المخطط لا تعني نسخ غلاف الطلب. في Chat Completions لدى OpenAI يوضع التعريف داخل response_format من نوع json_schema، مع name وschema وstrict بقيمة true داخل json_schema. وفي Responses API يوضع داخل text.format من نوع json_schema مع schema وstrict؛ أما json_object فهو وضع JSON ولا يفرض مطابقة المخطط.

في واجهة Interactions لدى Gemini يوضع التعريف في response_format من نوع text، مع mime_type بقيمة application/json وschema الذي يحمل كائن المخطط. وهكذا يبقى تعريف status وvalue واحدًا، بينما تتولى طبقة التكامل بناء الغلاف المناسب لكل API. راجع أيضًا دعم النموذج والمسار اللذين اخترتهما قبل الاعتماد على أي قيد إضافي؛ قبول كلمة في توثيق عام لا يغني عن ملاءمة إعداد التشغيل الفعلي.

عند إدخال المخطط في التكامل، يكشف طلب بسيط لكل مسار أخطاء التهيئة قبل أن تختلط بأخطاء الاستخراج. إذا رفضت الواجهة الطلب، افحص موضع schema والكلمات المضافة والكائنات التي ينقصها required أو additionalProperties. أما نجاح الطلب وعودة JSON مطابق، فيثبتان سلامة مسار البنية في تلك الحالة فقط.

افصل مطابقة البنية عن صحة المحتوى

بعد وصول استجابة مكتملة، حلّل JSON وتحقق محليًا من مطابقته للمخطط، ثم نفذ قواعد المجال التي لا يعبّر عنها التعريف المحافظ. في المثال السابق، افحص العلاقة بين status وvalue قبل تخزين النتيجة. احتفظ بسبب فشل المطابقة منفصلًا عن سبب فشل قاعدة المحتوى، لأن إصلاح نوع حقل يختلف عن مراجعة قيمة مستخرجة من المدخل.

قد تكون القيمة نصًا صحيح النوع ومخطئة في المعنى: اسم لشخص آخر، أو تاريخًا لم يرد في الرسالة، أو مبلغًا من سياق مختلف. إذا كانت صحة الاستخراج مؤثرة في القرار، فقارن القيمة بالمدخل الأصلي أو أرسلها للمراجعة وفق أهمية الاستخدام. مطابقة enum والأنواع تحمي العقد البرمجي، لكنها لا تثبت صلة القيمة بمصدرها.

عامل الرفض والتوليد غير المكتمل كحالتين مستقلتين

اجعل لمسار المعالجة نهايات واضحة: نتيجة مكتملة تجتاز التحقق، ورفض للطلب، واستجابة فاشلة أو غير مكتملة. قد يظهر الرفض في OpenAI خارج المخطط المحدد، وقد ينقطع الناتج عند بلوغ حد التوليد. لذلك افحص حالة الاستجابة وإشارات الرفض أو الفشل قبل محاولة تحليل JSON؛ وطبق ترتيب الفحص نفسه على استجابة Gemini وفق حقول المسار الذي تستخدمه.

لا تسجل الرفض أو انقطاع التوليد على أنهما status مساوية لـmissing. في المثال، تعني missing أن المهمة اكتملت ولم يُعثر على القيمة في المدخل؛ أما الرفض والفشل فلا يقدمان حكمًا على وجودها. هذا الفصل يتيح إعادة المحاولة أو إبلاغ المستدعي بسبب التعذر من دون إدخال نتيجة تبدو مطابقة للمخطط وتحمل معنى خاطئًا.

اقرأ أيضًا:

مشاركة:

اشترك في نشرتنا الإخبارية

احصل على أحدث أخبار الويب 3 والذكاء الاصطناعي والعملات المشفرة مباشرة في بريدك.

0