يمكن للمطورين الآن التحكم في تكلفة إصلاح ملفات JSON غير الصالحة الناتجة عن النماذج اللغوية الكبيرة (LLMs) من خلال تحديد عدد محاولات الإصلاح بمحاولتين فقط، كما يوضح حلقة Python بسيطة. هذا النمط — التوليد، التحليل، التحقق، إعادة المحاولة، ثم القبول أو الفشل — يحول "JSON الذي قد يكون صالحاً" إلى معدل نجاح قابل للقياس ويمنع الاستهلاك المفرط للرموز (tokens).

لماذا تهم حلقة الإصلاح

غالباً ما تُعطى النماذج اللغوية الكبيرة تعليمات بـ "إرجاع JSON"، ومع ذلك، غالباً ما تحتوي المخرجات على أخطاء في الصيغة، أو مفاتيح مفقودة، أو قيم تكسر قواعد العمل. أي نظام لاحق يتوقع حمولة (payload) صارمة سيتعطل أو ينتج نتائج خاطئة إذا تم تزويده بمثل هذه المخرجات. وبدون طريقة منهجية لاكتشاف هذه المشكلات وتصحيحها، تضطر الفرق إما إلى قبول معدل فشل مرتفع أو إهدار الأموال عبر تكرار الأوامر للنموذج حتى يصل إلى النتيجة الصحيحة.

طبقات التحقق الثلاث

تفصل الحلقة الموثوقة عملية التحقق إلى:

  • الصيغة (Syntax) – هل يمكن تحليل السلسلة النصية كـ JSON على الإطلاق؟
  • الهيكل (Shape) – هل يحتوي الكائن (object) في المستوى الأعلى على المفاتيح المتوقعة تماماً؟
  • الدلالة (Semantic) – هل تحترم القيم قيود النطاق (على سبيل المثال، يجب أن تنتمي "الفئة" إلى مجموعة محددة مسبقاً)؟

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

مثال Python بسيط

يستخدم الكود التالي المكتبة القياسية فقط. وهو يحدد مخططاً (schema) صغيراً (قاموس يحتوي على المفاتيح category و summary) وقائمة ثابتة من الفئات المسموح بها.

import json

CATEGORIES = {"bug", "feature", "question"}

def validate(raw: str):
    try:
        value = json.loads(raw)
    except json.JSONDecodeError as exc:
        return None, f"syntax: {exc.msg}"

    if not isinstance(value, dict):
        return None, "shape: root must be an object"
    if set(value) != {"category", "summary"}:
        return None, "shape: expected category and summary"
    if value["category"] not in CATEGORIES:
        return None, "semantic: invalid category"
    if not isinstance(value["summary"], str) or not value["summary"].strip():
        return None, "semantic: summary must be text"

    return value, None

تفرض حلقة الإصلاح نفسها سقفاً صارماً للمحاولات:

MAX_ATTEMPTS = 2
raw = model_response   # initial LLM output

for attempt in range(MAX_ATTEMPTS + 1):
    value, error = validate(raw)
    if error is None:
        break
    if attempt == MAX_ATTEMPTS:
        raise RuntimeError(f"failed after {MAX_ATTEMPTS} retries: {error}")

    # Send the error and schema back to the model for a fix
    raw = ask_model_to_repair(raw, error)

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

قاعدتان للإصلاح الفعال من حيث التكلفة

  1. حافظ على إيجاز أوامر الإصلاح – قم بتضمين JSON الخام فقط، ورسالة الخطأ، والمخطط. إن إضافة سجل دردشة طويل يؤدي إلى تضخم استهلاك الرموز (tokens) ويمكن أن يربك النموذج، مما يرفع تكلفة كل إعادة محاولة دون تحسين الدقة.

  2. افصل التحقق عن التحقق من الحقائق – يمكن للمحلل (parser) اكتشاف المشكلات الهيكلية، لكنه لا يستطيع التحقق مما إذا كانت عبارة "الملخص" (summary) صحيحة. ينتمي التحقق من الحقائق إلى مرحلة لاحقة؛ فمحاولة "إصلاح" ادعاء خاطئ تجعل الكذبة تبدو منظمة فحسب.

قياس النجاح

يوفر تسجيل نوع الخطأ في كل محاولة (الصيغة، الهيكل، الدلالة) وما إذا كانت الحلقة قد نجحت مقياساً ملموساً: نسبة استجابات LLM التي تصبح قابلة للاستخدام ضمن عدد المحاولات المحدود. يمكن للفرق تتبع ذلك بمرور الوقت، أو مقارنة أساليب الأوامر (prompts)، أو تجربة تعريفات مخططات مختلفة.

السلبيات المحتملة

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

ما يجب مراقبته لاحقاً

  • هندسة الأوامر للإصلاح (Prompt engineering for repair) – يمكن لتحسين تنسيق رسالة الخطأ أن يقلل من عدد إعادة المحاولات المطلوبة.
  • المحللات البديلة (Alternative parsers) – توفر بعض المكتبات تحليلاً مرناً يمكنه التصحيح التلقائي للمشكلات الطفيفة؛ ومقارنة تكلفتها مقابل الحلقة المحدودة أمر يستحق العناء.
  • تحديثات النماذج – قد تنتج إصدارات LLM الأحدث JSON أكثر نظافة بشكل مباشر، مما قد يسمح بخفض حد إعادة المحاولة بشكل أكبر.

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