بث مباشر 18.11 · الدفعة 318 نوفمبر، 19:00 بتوقيت موسكو — ورشة عملية مجانية لوكلاء الذكاء الاصطناعي · الدفعة 3 تبدأ 23.11ورشة 18 نوفمبر ←الدفعة 3 (23.11)
إصدارتحليل · على الرادارMachine Learning Mastery→ المصدر

اجتاز المخطط التحقق لكن مبلغ الفاتورة أقل بعشر مرات: كيف تتحقق من المخرجات المنظَّمة لنماذج اللغة الكبيرة

أعاد النموذج JSON صالحًا تمامًا: جميع المفاتيح موجودة، والأنواع صحيحة، والاقتباس من الفاتورة حقيقي. لكن المبلغ 12 500 سنت بدلًا من 125 000، أي 125 يورو بدلًا من 1 250. لا المحلِّل (parser) ولا JSON Schema يكتشفان ذلك. يستعرض الكاتب ثلاث طبقات حماية: عقد صارم في Pydantic مع مطابقة النص المصدر، وإعادة محاولة محدودة، وconstrained decoding.

معالج بواسطة الذكاء الاصطناعي من Machine Learning Mastery؛ بتحرير Hamidun News
اجتاز المخطط التحقق لكن مبلغ الفاتورة أقل بعشر مرات: كيف تتحقق من المخرجات المنظَّمة لنماذج اللغة الكبيرة
المصدر: Machine Learning Mastery. كولاج: Hamidun News.
استمع للمقال
بطاقة الحقائق والأرقام
المعيارالتفاصيل
المصدر الأصليMachine Learning Mastery ↗
رئيس التحرير
حقيقة رئيسية #1وضع strict في Pydantic لا يسمح بتحول السلسلة "125000" بصمت إلى رقم
حقيقة رئيسية #2إعادة المحاولة فقط عند shape_error، وبحد أقصى ثلاث محاولات
حقيقة رئيسية #3طابِق الرقم في الإجابة مع الاقتباس من المستند المصدر

إليكم فاتورة من أربعة أسطر: الرقم 2026-0417، الدافع Northwind Traders، «Total due: EUR 1,250.00»، الدفع خلال 30 يومًا. تطلبون من النموذج استخراج الرقم والعملة والمبلغ بالسنتات والسطر الذي أخذ منه المبلغ. تصل الإجابة هكذا: المبلغ 12 500، العملة EUR، الاقتباس «Total due: EUR 1,250.00».

ملف JSON صالح، وكل المفاتيح موجودة، والأنواع صحيحة، وEUR ضمن القائمة المسموح بها، والاقتباس موجود فعلًا في الفاتورة. لكن 12 500 سنت تساوي 125 يورو، بينما في الفاتورة 1 250. هذا خطأ بعشرة أضعاف، ولن يلاحظه أي محلِّل: فالرقم 12500 عدد صحيح سليم تمامًا. لا يمكن اكتشاف الخطأ إلا بالمقارنة مع النص المصدر، وعليكم كتابة هذه المقارنة بأنفسكم.

نشر موقع Machine Learning Mastery تحليلًا يوضح كيف تُبنى الحماية على ثلاث طبقات. أصبح structured output ميزة قياسية منذ فترة: فواجهة Responses API لدى OpenAI تقبل مخطط JSON أو نموذج Pydantic، وvLLM يفعل الشيء نفسه على الخادم المحلي عبر xgrammar. تنتهي معظم الدروس عند لحظة «تم تحليل JSON بنجاح». أما الكاتب فيرى أن البداية الحقيقية تكون هنا.

العقد والمطابقة مع المصدر

الطبقة الأولى هي عقد يملكه التطبيق، لا الـ prompt. في المثال هو نموذج Invoice بأربعة حقول. وتؤدي معلمتان في الإعدادات العمل الأساسي. يعطّل وضع strict=True التحويلات الضمنية في Pydantic: فالسلسلة "125000" في حقل عدد صحيح تُنتج خطأ int_type بدل أن تتحول بصمت إلى رقم. والأمر نفسه مع القيمة المنطقية True التي كانت ستصبح واحدًا. أما المعلمة extra="forbid" فتحوّل أي مفتاح زائد إلى خطأ بدل أن يكون حشوًا يُتجاهل.

وثمة تفصيل آخر: ثلاثة حقول تقبل null لكن ليس لها قيمة افتراضية. يستطيع النموذج أن يقول بصراحة «هذا غير موجود في الفاتورة»، لكنه لا يستطيع السكوت، ولا ينبغي له اختلاق رقم تجنبًا لكتابة null. تُخزَّن الأموال بالسنتات من النوع int حتى لا يتحول 1 250,00 إلى 1249,9999.

بعد ذلك تنفذ الدالة accept() أربع خطوات. أولًا التحليل والتحقق من الشكل، وهي الخطوة الوحيدة التي قد تعيد shape_error. ثم التحقق من وجود الاقتباس في المصدر حرفيًا. ثم مطابقة رقم الفاتورة والعملة مع النص. وأخيرًا يُقارَن المبلغ بالأرقام الواردة في الاقتباس: «1,250.00» بعد إزالة الفواصل تعطي 125000، بينما أرسل النموذج 12500، فيُرفض الكائن. النتائج أربع: accepted وneeds_review وrejected وshape_error. وإذا لم يكن المبلغ مذكورًا في الفاتورة فالنتيجة needs_review، أي يقرر إنسان، لا صفر مختلَق.

متى نعيد الطلب ومتى لا

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

تقتصر الملاحظات المرتجعة على خمسة أسباب حتى لا يتحول الـ prompt إلى محضر بكل الإخفاقات. ولا يتغير المخطط ولا النص المصدر بين المحاولات. ووفق أطروحات المقال، يجب ضبط إعادات النقل الخفية في الـ SDK نفسه بشكل منفصل، وإلا سيكون عدد الطلبات الفعلي أكبر مما احتسبتموه في الميزانية.

Constrained decoding: مفيد لكنه ليس حلًا سحريًا

الطبقة الثالثة هي constrained decoding. فالمولِّد لا يستطيع فعليًا إنتاج سوى الرموز (tokens) التي لا تُخرج الإجابة عن حدود المخطط، ولذلك فإن فئة كاملة من أخطاء الشكل لا تصل أصلًا إلى مرحلة التحقق. لكن المخطط لا يعبّر عن قاعدة «يجب أن تتطابق السنتات مع الاقتباس». فالمفكك الذي يلتزم بالمخطط التزامًا تامًا سيُخرج مع ذلك الرقم 12 500 نفسه. الكائن الصالح هو تصريح مرور إلى الفحص التالي، لا نتيجة نهائية.

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

الخلاصة العملية بسيطة. لا تثقوا بالتحقق «الأخضر» من المخطط: احتفظوا في الإجابة باقتباس يثبت القيمة، وتحققوا من الرقم مقابله. استخدموا إعادة المحاولة حيث يمكن أن تفيد فقط، وضعوا لها حدًا صارمًا. فعّلوا constrained decoding لتقليل أخطاء الشكل، لا بديلًا عن فحوصكم الخاصة. وينبغي تغطية كل مسار فشل باختبارات مع عميل وهمي (mock)، كما يفعل الكاتب.

القصة

أسئلة وأجوبة حول الخبر

ما أبرز التفاصيل حول العقد والمطابقة مع المصدر؟

الطبقة الأولى هي عقد يملكه التطبيق، لا الـ prompt. في المثال هو نموذج Invoice بأربعة حقول. وتؤدي معلمتان في الإعدادات العمل الأساسي. يعطّل وضع strict=True التحويلات الضمنية في Pydantic: فالسلسلة "125000" في حقل عدد صحيح تُنتج خطأ int_type بدل أن تتحول بصمت إلى رقم. والأمر نفسه مع القيمة المنطقية True التي كانت ستصبح واحدًا. أما المعلمة extra="forbid" فتحوّل أي مفتاح زائد إلى خطأ بدل أن يكون حشوًا يُتجاهل. وثمة تفصيل آخر: ثلاثة حقول تقبل null لكن ليس لها قيمة افتراضية.

ما أبرز التفاصيل حول متى نعيد الطلب ومتى لا؟

الطبقة الثانية هي إعادة المحاولة بسياسة صارمة. لا معنى للإعادة إلا مع shape_error: إذ يمكن أن نطلب من النموذج تصحيح الشكل بتزويده بقائمة الأخطاء. أما إذا كانت النتيجة rejected فالإعادة عديمة الفائدة لأن محتوى الفاتورة لن يتغير. كما أن رفض المزوّد أو خطأ الإعدادات يوقفان الحلقة فورًا. الحد الأقصى ثلاث محاولات: الأولى وبعدها إعادتا توليد على الأكثر. تقتصر الملاحظات المرتجعة على خمسة أسباب حتى لا يتحول الـ prompt إلى محضر بكل الإخفاقات. ولا يتغير المخطط ولا النص المصدر بين المحاولات.

ما أبرز التفاصيل حول Constrained decoding: مفيد لكنه ليس حلًا سحريًا؟

الطبقة الثالثة هي constrained decoding. فالمولِّد لا يستطيع فعليًا إنتاج سوى الرموز (tokens) التي لا تُخرج الإجابة عن حدود المخطط، ولذلك فإن فئة كاملة من أخطاء الشكل لا تصل أصلًا إلى مرحلة التحقق. لكن المخطط لا يعبّر عن قاعدة «يجب أن تتطابق السنتات مع الاقتباس». فالمفكك الذي يلتزم بالمخطط التزامًا تامًا سيُخرج مع ذلك الرقم 12 500 نفسه. الكائن الصالح هو تصريح مرور إلى الفحص التالي، لا نتيجة نهائية. وهناك قيود أيضًا. المثال تعليمي: عملتان وفحص بسيط للأرقام.

ZK
جمال حميدون — مدير المنتجات في Alpina Digital ومدير منتج AlpinaGPT. يبني منتجات الذكاء الاصطناعي منذ 2019. بدأ Hamidun News كمشروع شخصي ثم أصبح مُجمِّعًا إنتاجيًا بأكثر من 6000 قارئ.
✦ Unified AI Workspace · Nomad

Test Frontier LLMs & Autonomous Agents in One Workspace

Run Claude Opus 5.5, GPT-6, Gemini 3.1, and DeepSeek side-by-side in Nomad AI (nomadnet.ai) — unified model routing, deep research, and multimodal workflows under one subscription.

Try Nomad AI →Launch Nomad Agent
ما رأيك؟
جارٍ تحميل التعليقات…