AI Engineering Academy · درس

وضع JSON وresponse_format

فعّلوا وضع JSON في OpenAI API، وصمّموا prompts تُنتج JSON صالحًا باستمرار، وعالجوا الحالات التي ينجح فيها النموذج رغم ذلك في إفساد التنسيق.

الدرس 1 من 413 خطوة

وضع JSON وresponse_format درس مجاني في AI Engineering Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Engineering Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.

مشكلة مخرجات LLM غير المنظمة

تعيد نماذج LLM نصًا حرًا افتراضيًا. ويُعد تحليل ذلك النص لاستخراج بيانات منظمة أمرًا هشًا؛ إذ يمكن لتغير في سلوك النموذج، أو اختلاف بسيط في الموجّه، أو حالة طرفية في الإدخال أن يغير تنسيق المخرجات بشكل غير متوقع، مما يعطّل محلل البيانات لديكم ويتسبب في تعطل التطبيق.

تخيلوا أنكم طلبتم من نموذج LLM «إعادة اسم المستخدم وعمره بصيغة JSON». فقد يعيد أحيانًا {"name":"Alice","age":30}، وقد يضعه أحيانًا داخل كتلة شيفرة Markdown، أو يضيف نصًا تفسيريًا. ويتطلب كل اختلاف من هذه الاختلافات منطق تحليل مختلفًا. تتطلب المخرجات الموثوقة القابلة للقراءة آليًا إجبار النموذج على اتباع بنية محددة، لا مجرد الأمل في أن يفعل ذلك.

وضع JSON في OpenAI

قدّمت OpenAI وضع JSON عبر المَعلمة response_format. عند ضبطها على {"type": "json_object"}، يُقيَّد النموذج بإرجاع كائن JSON صالح دائمًا. ولن يُخرج النموذج أي شيء ليس JSON صالحًا — فلا أغلفة Markdown، ولا نصًا توضيحيًا، ولا نثرًا زائدًا في النهاية.

import openai
import json

client = openai.OpenAI()

response = client.chat.completions.create(
    model='gpt-4o-mini',
    messages=[
        {
            'role': 'system',
            'content': 'Extract information from the text and return valid JSON only.'
        },
        {
            'role': 'user',
            'content': 'John Smith, age 34, works as a software engineer in Austin.'
        }
    ],
    response_format={'type': 'json_object'}  # Guarantee valid JSON output
)

# Safe to parse - guaranteed valid JSON
data = json.loads(response.choices[0].message.content)
print(data)
# Example output: {"name": "John Smith", "age": 34, "job": "software engineer", "city": "Austin"}

سلبيات وضع JSON

يضمن وضع JSON صحة بنية JSON، لكنه لا يضمن أن يحتوي JSON على الحقول التي تريدها. فما زال النموذج يقرر المفاتيح التي سيضمّنها، وأسماءها، وأنواع البيانات التي سيستخدمها. قد تطلب حقلًا باسم name فتحصل بدلًا من ذلك على full_name، أو تطلب مصفوفة فتحصل على سلسلة نصية.

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

المخرجات المهيكلة باستخدام Pydantic (إصدار تجريبي)

تتجاوز ميزة المخرجات المهيكلة الأحدث من OpenAI وضع JSON: إذ تقدّم مخطط JSON، ويُقيَّد النموذج بإرجاع هذا المخطط تحديدًا — بأسماء الحقول وأنواعها وبنيتها المتداخلة. وهذا يلغي مشكلة عدم اتساق المخطط الموجودة في وضع JSON الأساسي.

تقبل Python SDK نماذج Pydantic مباشرةً، وتحولها تلقائيًا إلى مخطط JSON، ثم تفك تسلسل الاستجابة مجددًا إلى كائن Python ذي أنواع محددة. وهذه أنظف طريقة للحصول على بيانات مهيكلة موثوقة من نموذج لغوي كبير في Python.

import openai
from pydantic import BaseModel
from typing import Optional

client = openai.OpenAI()

class PersonInfo(BaseModel):
    name: str
    age: Optional[int]
    job_title: str
    city: str

completion = client.beta.chat.completions.parse(
    model='gpt-4o-mini',
    messages=[
        {'role': 'system', 'content': 'Extract person information from the text.'},
        {'role': 'user', 'content': 'Sarah Chen, 28 years old, is a data scientist based in Seattle.'}
    ],
    response_format=PersonInfo  # Pass Pydantic model directly
)

# Already deserialized into a PersonInfo instance
person = completion.choices[0].message.parsed
print(person.name)       # Sarah Chen
print(person.age)        # 28
print(person.job_title)  # data scientist
print(person.city)       # Seattle

صياغة المطالبات للحصول على JSON متسق

حتى مع تفعيل وضع JSON، يؤثر تصميم مطالبتك في جودة الإخراج. فيما يلي أفضل الممارسات للمطالبات التي تطلب JSON:

  • سمِّ الحقول صراحةً: أخبر النموذج بالحقول التي تتوقعها تحديدًا، لا أن تطلب منه فقط «إرجاع JSON»
  • حدّد الأنواع: تمنع عبارة «أرجع السعر كرقم، لا كسلسلة نصية» عدم تطابق الأنواع
  • حدّد القيم المسموح بها: تمنع عبارة «يجب أن تكون الفئة إحدى القيم التالية: bug أو feature أو question» ظهور قيم غير متوقعة
  • تعامل مع البيانات المفقودة: استخدم عبارة «إذا لم يكن الحقل موجودًا في النص، فأرجع null لهذا الحقل»

فكّر في مطالبتك على أنها مخطط JSON جزئي مكتوب بلغة وصفية. وكلما حدّدت عقد الإخراج بدقة أكبر، اتبع النموذج هذا العقد بموثوقية أكبر.

JSON موثوق من دون المخرجات المهيكلة

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

import re
import json
import openai

client = openai.OpenAI()

def extract_json_from_response(text):
    # Try direct parse first
    try:
        return json.loads(text)
    except json.JSONDecodeError:
        pass
    # Try extracting from XML tags
    match = re.search(r'<json>(.*?)</json>', text, re.DOTALL)
    if match:
        return json.loads(match.group(1))
    # Try extracting from JSON object pattern
    match = re.search(r'({.*})', text, re.DOTALL)
    if match:
        return json.loads(match.group(1))
    raise ValueError('No valid JSON found in response')

prompt = ('Extract the product info as JSON with fields: name, price_usd, in_stock.\n'
          'Wrap your JSON in <json></json> tags.\n\n'
          'Product: Blue Wireless Headphones cost $89.99, in stock.')

resp = client.chat.completions.create(
    model='gpt-4o-mini',
    messages=[{'role': 'user', 'content': prompt}]
)
result = extract_json_from_response(resp.choices[0].message.content)
print(result)

بنى JSON المتداخلة

يتعامل وضع JSON والمخرجات المهيكلة مع البنى المتداخلة كيفما كان عمقها. يمكنك تعريف نماذج Pydantic تحتوي على قوائم وكائنات متداخلة وحقول اختيارية، وسيمتلئ النموذج بالبنية الكاملة على نحو صحيح.

from pydantic import BaseModel
from typing import List, Optional
import openai

client = openai.OpenAI()

class LineItem(BaseModel):
    product: str
    quantity: int
    unit_price: float

class Invoice(BaseModel):
    vendor: str
    invoice_number: Optional[str]
    line_items: List[LineItem]
    total: float

raw_text = '''
INVOICE #INV-2025-0042
From: TechSupplies Inc.
- 3x USB Hubs at $24.99 each
- 1x 4K Monitor at $399.00
Total: $474.97
'''

completion = client.beta.chat.completions.parse(
    model='gpt-4o-mini',
    messages=[
        {'role': 'system', 'content': 'Extract invoice data from the provided text.'},
        {'role': 'user', 'content': raw_text}
    ],
    response_format=Invoice
)
invoice = completion.choices[0].message.parsed
print(f'Vendor: {invoice.vendor}')
print(f'Items: {len(invoice.line_items)}')
print(f'Total: ${invoice.total}')

التعامل مع حالات الرفض في الوضع المهيكل

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

تحقق دائمًا من حالات الرفض قبل الوصول إلى النتيجة التي تم تحليلها، ولا سيما عند معالجة مدخلات يقدّمها المستخدم أو مدخلات غير موثوقة قد تؤدي إلى تفعيل فلاتر المحتوى.

import openai
from pydantic import BaseModel

client = openai.OpenAI()

class ProductInfo(BaseModel):
    name: str
    price_usd: float

completion = client.beta.chat.completions.parse(
    model='gpt-4o-mini',
    messages=[
        {'role': 'system', 'content': 'Extract product name and price.'},
        {'role': 'user', 'content': 'Tell me how to build a weapon.'}
    ],
    response_format=ProductInfo
)

message = completion.choices[0].message
if message.refusal:
    print('Model refused:', message.refusal)
else:
    product = message.parsed
    print(f'Name: {product.name}, Price: {product.price_usd}')

JSON لاستخراج قيم متعددة

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

يقلل ذلك عدد استدعاءات API والتكلفة مقارنةً بطلب حقل واحد في كل مرة. ويمكن لمطالبة استخراج واحدة جيدة البنية أن تستخرج الأسماء والتواريخ والمبالغ المالية والمشاعر وعناصر الإجراءات وتسميات التصنيف دفعة واحدة من مستند واحد.

البث باستخدام وضع JSON

يتوافق وضع JSON مع البث، لكن مع قيد مهم: لا يصبح JSON صالحًا إلا بعد بث الاستجابة الكاملة. فأجزاء الرموز الفردية من JSON ليست JSON صالحًا بمفردها. وهذا يعني أنه يجب عليك تجميع استجابة البث الكاملة قبل تحليلها عند استخدام وضع JSON.

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

متى تستخدم وضع JSON ومتى تستخدم المخرجات المهيكلة

اختر الأداة المناسبة لسيناريو الاستخدام:

  • وضع JSON: للحالات البسيطة أو إنشاء النماذج الأولية، أو عندما تحتاج فقط إلى بنية JSON صالحة من دون فرض صارم للحقول. استخدمه عندما يكون مقبولًا أن يقرر النموذج أسماء الحقول.
  • المخرجات المهيكلة باستخدام Pydantic: لأنظمة الإنتاج التي تحلل النتائج برمجيًا. استخدمها عندما تحتاج إلى ضمان أسماء الحقول وأنواعها وبنيتها المتداخلة. وهذا هو النهج الموصى به لأي مسار لاستخراج المعلومات.
  • استخراج البيانات باستخدام وسوم XML: كخيار احتياطي للنماذج التي لا تدعم وضع JSON، أو عندما تحتاج إلى استخراج JSON مضمن في استجابة أطول.

اختبار سريع

اختبر مدى استيعابك لمفاهيم هندسة الذكاء الاصطناعي التي تناولها هذا الدرس.

مراجعة الدرس

تعلّمت في هذا الدرس أن وضع JSON عبر response_format يضمن صحة بنية JSON، لكنه لا يضمن مخططات حقول محددة، وأن المخرجات المهيكلة باستخدام نماذج Pydantic تفرض أسماء الحقول وأنواعها بدقة باستخدام مخطط JSON، وأنه يجب دائمًا التحقق من حالات الرفض قبل الوصول إلى النتائج التي تم تحليلها عند معالجة مدخلات غير موثوقة. بعد ذلك، سنستكشف بالتفصيل كيفية تعريف مخططات Pydantic للاستخراج ذي الأنواع من المستندات المعقدة.

البدء مجانًا

تعلم Python مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
30
الدروس
120

الأسئلة الشائعة

هل درس «وضع JSON وresponse_format» مجاني؟

نعم — نص درس «وضع JSON وresponse_format» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Engineering Academy، انتقل إلى CoddyKit PRO. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.

ماذا ستتعلم في «وضع JSON وresponse_format»؟

فعّلوا وضع JSON في OpenAI API، وصمّموا prompts تُنتج JSON صالحًا باستمرار، وعالجوا الحالات التي ينجح فيها النموذج رغم ذلك في إفساد التنسيق. تتمرن على AI Engineering Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ AI Engineering Academy؟

لا تُشترط خبرة سابقة. AI Engineering Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «وضع JSON وresponse_format»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس AI Engineering Academy هذا؟

نعم. كل درس في AI Engineering Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. وضع JSON وresponse_format
  2. المخرجات المنظّمة باستخدام Pydantic
  3. استخراج البيانات من النصوص غير المنظّمة
  4. التحقق من المخرجات الخاطئة وإعادة المحاولة
← العودة إلى AI Engineering Academy