درخواست خروجی JSON از مدل‌های زبانی یکی از پرکاربردترین نیازهای سیستم‌های خودکار است. اگر بخواهید خروجی مدل را با کد پردازش کنید، JSON انتخاب طبیعی است. اما همان‌طور که در تجربه‌های واقعی دیده‌ایم، تولید JSON پایدار از مدل‌های زبانی چالش‌های خاص خود را دارد. در این نوشتار، تکنیک‌هایی را بررسی می‌کنیم که در پروژه‌های واقعی، نرخ انطباق JSON را به سطح قابل اتکا رسانده‌اند.

چکیده‌ای از مسیر پیش رو

در این نوشتار ابتدا تعریف خروجی JSON و دلیل اهمیت آن بررسی می‌شود. سپس تعریف Schema، نقش مثال‌ها، حالت Strict، مدیریت Streaming، اعتبارسنجی و Retry ارائه می‌گردد. در ادامه، ساختارهای تودرتو، زبان فارسی و شاخص‌های سنجش نرخ انطباق بررسی می‌شود. در انتها، اشتباهات رایج و نگاه معمارانه ارائه خواهد شد.

خروجی JSON از مدل زبانی چیست؟

خروجی JSON به معنای دریافت پاسخ مدل در قالب JavaScript Object Notation است. این قالب، استاندارد رایج برای تبادل داده در سیستم‌های نرم‌افزاری محسوب می‌شود. برای مطالعه پایه‌های این حوزه، نوشتار JSON چیست و چطور داده‌ها را ساختاردهی می‌کند را ببینید.

مزیت اصلی JSON، ترکیب سادگی خواندن برای انسان و قابلیت پردازش خودکار برای ماشین است. اگر خروجی مدل در قالب JSON باشد، لایه‌های بعدی می‌توانند آن را با کد پردازش کنند بدون نیاز به بازبینی انسانی. برای مطالعه دقیق‌تر در مورد قالب‌های خروجی، نوشتار درخواست خروجی در قالب مشخص را ببینید.

در ادبیات پردازش داده، JSON بخشی از خانواده Serialization Formats است و در ویکی‌پدیا نیز به‌عنوان JSON معرفی شده است.

چرا JSON به‌طور پیش‌فرض از مدل خارج نمی‌شود؟

مدل‌های زبانی، برای تولید متن طبیعی آموزش دیده‌اند. JSON، برخلاف متن طبیعی، ساختار صریحی دارد که باید دقیقاً رعایت شود. سه چالش اصلی در تولید JSON:

۱. فشار برای توضیح اضافه

مدل تمایل دارد قبل یا بعد از JSON، توضیح شفاهی بنویسد. این توضیح، JSON را از قالب خالص خارج می‌کند و پردازش خودکار را شکست می‌دهد.

۲. عدم دقت در علائم ساختاری

JSON به علائم مشخصی مثل آکولاد، براکت، کاما و دو نقطه حساس است. مدل ممکن است در بخش‌های پیچیده، این علائم را اشتباه بگذارد یا فراموش کند.

۳. مدیریت نقل قول‌ها

JSON برای رشته‌ها از نقل قول دوگانه استفاده می‌کند. اگر متن حاوی کاراکترهای خاص باشد، مدل ممکن است آن‌ها را به‌درستی فرار (Escape) نکند. این مشکل در زبان فارسی با کاراکترهای ویژه بیشتر دیده می‌شود.

تولید JSON از مدل زبانی، ترکیبی از هنر طراحی پرامپت و مهندسی کنترل ساختار است. بدون دقت در هر دو جنبه، خروجی قابل اتکا نخواهد بود.

تعریف Schema در پرامپت

Schema، توصیف ساختاری JSON است که به مدل کمک می‌کند دقیقاً بداند چه چیزی مورد انتظار است. تعریف Schema در پرامپت، یکی از مؤثرترین تکنیک‌های افزایش نرخ انطباق است.

ساختار پایه Schema

{
  "type": "object",
  "properties": {
    "product_name": {"type": "string"},
    "price": {"type": "number"},
    "in_stock": {"type": "boolean"},
    "tags": {"type": "array", "items": {"type": "string"}}
  },
  "required": ["product_name", "price"]
}

نکات کلیدی

  • تعریف نوع داده: برای هر فیلد، نوع صریح مشخص کنید.
  • فیلدهای اجباری: با کلمه‌ی required مشخص کنید.
  • محدودیت مقادیر: با کلمه‌ی enum، مقادیر مجاز را تعریف کنید.
  • ساختار تودرتو: در صورت نیاز، ساختارهای تودرتو را در Schema تعریف کنید.
  • نمونه‌های کوچک: برای هر فیلد، در صورت امکان یک نمونه‌ی کوچک ارائه دهید.

برای مطالعه دقیق‌تر در مورد Schema، نوشتار قالب‌های پرامپت و نحوه ساخت آن‌ها را ببینید.

نقش مثال در تولید JSON پایدار

مثال‌ها، یکی از مؤثرترین ابزارها برای افزایش نرخ انطباق JSON هستند. اگر یک یا دو نمونه از خروجی مطلوب در پرامپت ارائه دهید، مدل تمایل دارد همان ساختار را در خروجی خود دنبال کند. برای مطالعه دقیق‌تر، نوشتار تأثیر مثال در پرامپت نویسی را ببینید.

ساختار پیشنهادی:

ورودی نمونه:
"محصول X با قیمت 250000 تومان موجود است"

خروجی نمونه:
{
  "product_name": "X",
  "price": 250000,
  "in_stock": true,
  "tags": []
}

نکات کلیدی در ارائه مثال

  • مثال باید از دامنه‌ی واقعی داده‌ها انتخاب شود.
  • مثال‌های متنوع، انعطاف‌پذیری مدل را افزایش می‌دهند.
  • مثال‌های خیلی کوچک ممکن است ساختار را ناقص نشان دهند.
  • مثال‌های خیلی بزرگ، بودجه توکن را مصرف می‌کنند.

حالت Strict و Structured Outputs

برخی APIها امکان فعال‌سازی حالت Strict را فراهم می‌کنند. در این حالت، مدل موظف است دقیقاً از Schema تعریف‌شده تبعیت کند. اگر ارائه‌دهنده‌ی شما این قابلیت را پشتیبانی می‌کند، فعال‌سازی آن یکی از مؤثرترین راه‌ها برای افزایش نرخ انطباق است.

مزایا

  • نرخ انطباق نزدیک به ۱۰۰٪
  • نبود فیلدهای اضافی
  • رعایت دقیق انواع داده
  • کاهش نیاز به اعتبارسنجی و Retry

محدودیت‌ها

  • همه ارائه‌دهندگان این قابلیت را ندارند.
  • در حالت Strict، انعطاف مدل کاهش می‌یابد.
  • Schema باید با محدودیت‌های حالت Strict سازگار باشد.
  • هزینه‌ی هر درخواست ممکن است بالاتر باشد.

مدیریت JSON در حالت Streaming

در حالت Streaming، JSON به‌صورت تکه‌تکه ارسال می‌شود. این موضوع، چالش‌هایی ایجاد می‌کند:

نبود ساختار معتبر در میانه Streaming

در ابتدای Streaming، JSON ناقص است و نمی‌توان آن را با Parser استاندارد پردازش کرد. راه‌حل، استفاده از Parserهای Streaming است که قابلیت پردازش JSON ناقص را دارند.

مدیریت خطا در میانه Streaming

اگر مدل در میانه Streaming خطا کند، ممکن است JSON ناقص باقی بماند. لایه‌ی پردازش باید این حالت را تشخیص دهد و مطابق راهبرد بازیابی عمل کند.

نمایش تدریجی به کاربر

در برخی کاربردها، نمایش تدریجی JSON به کاربر معنا ندارد، چون ساختار در میانه‌ی تولید معتبر نیست. در این موارد، بهتر است ابتدا کل JSON جمع‌آوری شود و سپس نمایش داده شود.

اعتبارسنجی و پردازش خطا

پس از دریافت خروجی، اعتبارسنجی آن در سه سطح ضروری است:

سطحنوع بررسیابزار پیشنهادی
ساختاریمعتبر بودن JSONJSON Parser
Schemaانطباق با SchemaJSON Schema Validator
منطقیسازگاری بین فیلدهاکد سفارشی

در صورت شکست اعتبارسنجی، سه راهبرد اصلی وجود دارد:

  1. ارسال مجدد با تأکید بیشتر روی قالب
  2. ارسال با مثال معکوس که نشان دهد کدام خطا رخ داده
  3. اصلاح خودکار با کد در صورت امکان

راهبردهای Retry و اصلاح خروجی

در سیستم‌های تولیدی، Retry یکی از راهبردهای رایج در مواجهه با خروجی نامعتبر است. برای Retry مؤثر:

Retry با Prompt Refinement

در Retry، پرامپت را با تأکید بیشتری روی قالب و ارائه‌ی مثال‌های بیشتر ارسال کنید. Retry ساده بدون تغییر پرامپت، احتمالاً نتیجه‌ی مشابهی می‌دهد.

Retry با Feedback از خطا

اگر خطای قبلی مشخص است، در Retry خطای رخ‌داده را نشان دهید و بخواهید این خطا را تکرار نکند. این تکنیک که با عنوان Corrective Retry شناخته می‌شود، نرخ موفقیت را بالا می‌برد.

Retry با مدل بزرگ‌تر

اگر مدل سبک نتوانست JSON معتبر تولید کند، از مدل بزرگ‌تر استفاده کنید. این راهبرد در معماری‌های Routing رایج است. برای مطالعه دقیق‌تر، نوشتار مسیریابی مدل‌های زبانی بر اساس هزینه، تأخیر و کیفیت را ببینید.

ساختارهای تودرتو و مدیریت پیچیدگی

ساختارهای تودرتو، نرخ خطا را در تولید JSON افزایش می‌دهند. سه راهبرد برای مدیریت پیچیدگی:

محدودسازی عمق تودرتویی

ساختارهای بسیار عمیق، احتمال خطا را بالا می‌برند. سعی کنید ساختار را تا حد ممکن تخت نگه دارید.

شکستن به چند مرحله

اگر ساختار بسیار پیچیده است، آن را به چند مرحله بشکنید. ابتدا ساختار سطح بالا را بگیرید و سپس زیرساختارها را در نوبت‌های جداگانه پر کنید.

استفاده از آرایه به‌جای شیء تودرتو

در برخی موارد، استفاده از آرایه به‌جای ساختار تودرتو، خطا را کاهش می‌دهد. آرایه‌ها ساختار ساده‌تری دارند و مدل راحت‌تر آن‌ها را تولید می‌کند. برای مطالعه دقیق‌تر، نوشتار پرامپت نویسی برای استخراج اطلاعات را ببینید.

مدیریت زبان فارسی در JSON

تولید JSON برای متن فارسی، چالش‌های خاصی دارد:

نقل قول‌های درونی

متن فارسی ممکن است حاوی کاراکترهای خاصی باشد که در JSON باید Escape شوند. در پرامپت صریحاً مشخص کنید که این کاراکترها باید به‌درستی فرار داده شوند.

نیم‌فاصله و کاراکترهای خاص

کاراکتر نیم‌فاصله (ZWNJ) در برخی موارد می‌تواند باعث مشکل در Parserهای ساده‌شود. توصیه می‌شود از یک Parser استاندارد و به‌روز استفاده کنید که با این کاراکترها سازگار است.

جهت متن (Bidi)

در نمایش، متن فارسی و انگلیسی در JSON می‌توانند با مشکل Bidi مواجه شوند. این مشکل در سطح تولید JSON وجود ندارد، اما در نمایش خروجی باید به آن توجه کرد.

اشتباهات رایج در درخواست JSON

  • نبود Schema صریح در پرامپت
  • نبود مثال خروجی
  • عدم درخواست صریح برای خروجی فقط JSON بدون توضیح اضافه
  • نداشتن اعتبارسنجی ساختاری
  • نبود راهبرد Retry در صورت شکست
  • نادیده گرفتن محدودیت‌های حالت Strict
  • عدم توجه به Escape کاراکترهای خاص
  • استفاده از ساختارهای بسیار عمیق
  • عدم مدیریت فارسی در پرامپت
  • نبود پایش نرخ انطباق

سنجش نرخ انطباق JSON

چند شاخص کلیدی برای سنجش کیفیت JSON تولیدشده:

شاخصتوضیح
JSON Parse Rateدرصد خروجی‌هایی که به‌عنوان JSON معتبر Parse می‌شوند
Schema Compliance Rateدرصد خروجی‌های منطبق با Schema
Field Completenessدرصد فیلدهای اجباری که پر شده‌اند
Type Accuracyدرصد فیلدها با نوع داده صحیح
Retry Rateنرخ ارسال مجدد به‌دلیل شکست JSON

پایش این شاخص‌ها به‌صورت مستمر، اجازه می‌دهد قبل از این که خطا در لایه‌های بالادست ظاهر شود، انحراف را تشخیص دهید. برای مطالعه دقیق‌تر، نوشتار معیارهای ارزیابی پرامپت را ببینید.

پرسش‌های متداول درباره JSON

چطور مطمئن شویم مدل همیشه JSON معتبر تولید می‌کند؟

سه راهکار کلیدی: فعال‌سازی حالت Strict (اگر پشتیبانی شود)، تعریف Schema صریح در پرامپت، و ارائه‌ی مثال‌های متعدد. به‌علاوه، همیشه لایه‌ی اعتبارسنجی و راهبرد Retry را پیش‌بینی کنید.

آیا استفاده از JSON در پرامپت توکن بیشتری مصرف می‌کند؟

بله، ساختار JSON بیش از متن آزاد توکن مصرف می‌کند. اما این هزینه در برابر مزیت پردازش خودکار، معمولاً توجیه‌پذیر است. برای مطالعه دقیق‌تر، نوشتار تأثیر محدودیت توکن بر پرامپت نویسی را ببینید.

آیا خروجی JSON قابل اعتماد است؟

با طراحی دقیق پرامپت و لایه اعتبارسنجی، بله. اما حتی با بهترین پرامپت، احتمال شکست کوچکی وجود دارد که باید با راهبردهای Retry و Fallback مدیریت شود.

آیا می‌توان JSON را از حالت Streaming گرفت؟

بله، اما نیاز به Parserهای Streaming دارد که قابلیت پردازش JSON ناقص را داشته باشند. برای کاربردهای ساده، توصیه می‌شود ابتدا کل JSON را جمع‌آوری و سپس پردازش کنید.

آیا Structured Outputs جایگزین طراحی پرامپت دقیق می‌شود؟

نه، Structured Outputs یک ابزار مکمل است. طراحی پرامپت هنوز برای تعریف درست Schema و محتوای موردنظر ضروری است. این دو در کنار هم، نرخ انطباق را بالا می‌برند.

نگاه معمارانه به تولید JSON

از منظر معماری، تولید JSON پایدار یک موضوع چندلایه است. لایه اول، طراحی پرامپت است. لایه دوم، استنتاج است. لایه سوم، اعتبارسنجی است. لایه چهارم، بازیابی در صورت شکست است.

در سیستم‌های بالغ، معمولاً از ترکیب Structured Outputs و اعتبارسنجی دقیق استفاده می‌شود. اگر Structured Outputs در دسترس باشد، نرخ انطباق نزدیک به ۱۰۰٪ می‌شود. اما حتی در این حالت، لایه‌ی اعتبارسنجی منطقی همچنان ضروری است، چرا که مدل ممکن است داده‌ی نادرست تولید کند حتی اگر ساختار JSON معتبر باشد. برای مطالعه دقیق‌تر، نوشتار پرامپت نویسی برای دقت واقعی را ببینید.

نکته مهم دیگر این است که تولید JSON باید با معماری پنجره زمینه هماهنگ باشد. اگر Schema بزرگ باشد، بخش قابل توجهی از بودجه توکن مصرف می‌شود. راه‌حل، استفاده از کش پرامپت برای بخش‌های ثابت Schema است. برای مطالعه دقیق‌تر، نوشتار کش پیشوندی برای کاهش محاسبات مدل را ببینید.

در سیستم‌های مقیاس بزرگ، معمولاً یک لایه‌ی مرکزی برای مدیریت JSON وجود دارد. این لایه، Schema را نگه می‌دارد، اعتبارسنجی را انجام می‌دهد، و در صورت شکست، راهبرد Retry را اجرا می‌کند. نبود این لایه، معمولاً به کد پراکنده و ناسازگار در جای‌های مختلف منجر می‌شود.

آخرین نکته‌ای که در پروژه‌های JSON بارها تجربه کرده‌ایم: همیشه نسخه‌بندی Schema را جدی بگیرید. اگر Schema را تغییر دهید، ممکن است لایه‌های بالادست که به ساختار قدیم وابسته بودند، دچار خطا شوند. نسخه‌بندی صریح Schema، یک سرمایه‌گذاری کوچک با بازده بزرگ است. برای مطالعه دقیق‌تر، نوشتار نسخه‌بندی پرامپت را ببینید.

تجربه شما

اگر در پروژه‌ای واقعی روی درخواست خروجی JSON از مدل‌های زبانی کار کرده‌اید، برای ما جالب است بدانید کدام چالش بیشترین زمان را گرفته است: تعریف Schema، مدیریت خطا، یا زبان فارسی. اگر رویکرد متفاوتی برای افزایش نرخ انطباق دارید، تجربه‌تان را در دیدگاه‌ها بنویسید تا خواننده بعدی از آن استفاده کند.