دوز مباشرة للمحتوى الرئيسي
دروس فالذكاء الاصطناعي

بني قرارات سريعة ومُهيكلة ديال LLM محلية مع Rizzo Flow

تعلّم كيفاش تثبّت Rizzo Flow، وتشغّل السيرفر المحلي ديالو بـ llama.cpp، وتحصل على قرارات مُهيكلة من نوع منطقي، اختيار، نقطة، ورقم. هاد الدليل كيغطي ساحة التجربة، وواجهات API الأصلية والمتوافقة مع Jev، واختيارات العتاد، والامتناع عن القرار، والمعالجة على دفعات، وحدود السياق، والأمان، واعتبارات الأداء العملية.

بني قرارات سريعة ومُهيكلة ديال LLM محلية مع Rizzo Flow

شنو هو Rizzo Flow؟

Rizzo Flow هو نظام مفتوح المصدر ومحلي فالأولوية، كيحوّل النصوص غير المهيكلة ولا حالة JSON لـقرارات مهيكلة مع الاحتمالات ديالها. بلا ما يطلب من نموذج لغوي يولّد نثر ولا JSON رمز برمز، كيقرا الاحتمال اللي كييعطيه النموذج لمجموعة محدودة من حروف الأجوبة من بعد المرور الأمامي.

هاد التصميم كيدعم قرارات بحال:

  • جواب منطقي فيه الاحتمال ديال true.
  • اختيار من بين اختيارات مسمّاة، مع احتمال خاص بكل اختيار.
  • نقطة على مستويات مرتّبة ديال شبكة التقييم.
  • تقدير رقمي مبني على نقاط مرجعية تمثيلية.

Rizzo Flow كيخدم فالأجهزة ديالك باستعمال llama.cpp. ويقدر يستعمل Apple Metal أو NVIDIA CUDA أو Vulkan أو AMD ROCm أو Intel SYCL أو التنفيذ عبر CPU. وكيوفّر حتى واجهة HTTP متوافقة مع Jev، وهادشي كيخلّي التطبيقات المتوافقة توجّه الطلبات لـ URL محلي بلا ما تستعمل خدمة مستضافة.

شعار مشروع Rizzo Flow

Rizzo Flow مشروع مستقل. كيعيد إنتاج نمط الواجهة اللي ورا Jev، وماشي البنية الاحتكارية ديال Jev ولا التدريب ديالو. الاحتمالات ديالو ما معايراش إلا إلا عايرتيها باستعمال بيانات تمثيلية من عندك.

كيفاش كيتخدمو القرارات بصفر رمز

فكل طلب، Rizzo Flow كيحط الحالة فبداية الموجّه وكيعالجها مرة وحدة. من بعد كتتفرّع الأسئلة انطلاقاً من ذاكرة الحالة المشتركة. كل جواب ممكن كيتربط بحرف كبير، والنظام كيقرا غير قيم اللوجيتس ديال الحروف المسموح بها.

  1. كتتحوّل الحالة لنص وكتتعمّر مسبقاً فذاكرة KV ديال النموذج.
  2. كل سؤال كيتقدّم كمشكل اختيار من متعدد مقيّد.
  3. الأسئلة اللي كتشارك نفس الحالة كتتقيّم فدفعات صغيرة.
  4. كتتحوّل لوجيتسات الأجوبة المسموح بها لاحتمالات باستعمال softmax.
  5. كترجع شيفرة Python بيانات منطقية أو اختيارات أو نقط أو بيانات رقمية متحقَّق من المخطط ديالها.

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

الخصائص الرئيسية

  • خدمة محلية بالكامل: استدلال النموذج كيوقع فالجهاز ديالك.
  • نتائج مهيكلة: التطبيقات كتوصل بقيم منظمة بلاصة نص مولَّد.
  • توزيعات الاحتمالات: نتائج الاختيارات والنقط كتعرض الاحتمالات، وماشي غير الجواب اللي عندو أكبر احتمال.
  • أربع بدائيات أصلية: boolean وchoice وscore وnumeric.
  • الامتناع الاختياري: الواجهة الأصلية تقدر تبلّغ على نقص الأدلة أو عدم اليقين أو نتيجة رقمية خارج النطاق.
  • المعالجة على دفعات بحالة مشتركة: عدة أسئلة فطلب واحد كتعيد استعمال ذاكرة KV ديال الحالة.
  • نقاط نهاية متوافقة مع Jev: العملاء الحاليين يقدرو يستعملو /v1/systemone و/v1/models.
  • نموذج بسياق طويل: Spark-X2.5 كيدعم سياقاً أصلياً حتى لـ 1,048,576 رمز، مع أن Rizzo Flow كيستعمل افتراضياً 8,192 رمز لكل سؤال.
  • أدوات محلية: الخادم فيه ملعب تجريبي، وتوثيق تفاعلي لـ OpenAPI، وعرض Snake.

المتطلبات المسبقة

قبل ما تثبّت Rizzo Flow، تأكد بلي عندك:

  • Python 3.11 ولا أحدث.
  • Git.
  • uv لتدبير التبعيات والبيئة.
  • مساحة كافية فالقرص للنموذج وبيئة التشغيل المختارين.

تحميل نموذج Spark-X2.5-4B Q8_0 الافتراضي حجمو تقريباً 4.4 GB. تحميل بيئة التشغيل كيختلف حسب المنصة، من حوالي 11 MB فـ Mac حتى تقريباً 570 MB لحزمة CUDA.

ثبّت الخادم وبدا الخدمة

نسخ المستودع، سَوّي التبعيات المثبّتة ديالو، حمّل بيئة التشغيل والنموذج الافتراضيين، وبدا الخدمة:

git clone https://github.com/Rizzo-AI-Academy/rizzo-flow
cd rizzo-flow
uv sync --locked
uv run rizzo download
uv run rizzo serve

أمر التحميل كيختار حزمة llama.cpp رسمية مبنية مسبقاً للجهاز الحالي، وكيتحقق من مجموع التحقق SHA-256 ديالها، وكيحمّل Spark-X2.5-4B Q8_0. والتحميلات اللي تقطعات تقدر تكمل من البلاصة اللي وقفات فيها.

تحميل النموذج كياخذ تقريباً عشر ثواني حسب توثيق المشروع. ملي تكون الخدمة واجدة، حل:

ملعب Rizzo Flow للقرارات المحلية

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

استعمل النموذج الأصغر

إلى بغيتي تحميل أول أسرع، ثبّت نموذج 1.7B:

uv run rizzo download --size 1.7b
uv run rizzo serve --size 1.7b

ملف 1.7B Q8_0 الحجم ديالو تقريباً 1.8 GB وكيخدم تقريباً بضعف السرعة، ولكن README كينبّه باللي الدقة ديالو ناقصة بزاف. وحتى هو كيميل يختار خيار «المعطيات غير كافية» ملي كيكون الامتناع مفعّل، لذلك جرّبو مزيان على الخدمة ديالك.

دير أول قرار ديالك

أسرع اختبار للـ API كيستعمل الـ endpoint المتوافق مع Jev: POST /v1/systemone. الطلب التالي كيسول واش رسالة دعم كاتبيّن الاستعجال:

curl http://127.0.0.1:8017/v1/systemone \
  -H 'Content-Type: application/json' \
  -d '{
    "state": "Help! My payouts have been failing for 3 days.",
    "model": "rizzo-latest",
    "questions": {
      "is_urgent": {
        "type": "noul",
        "instructions": "واش هاد الرسالة كاتبيّن الاستعجال؟"
      }
    }
  }'

نتيجة noul هي احتمال «نعم»، وكتتمثل فعدد بين صفر وواحد. الاستجابة كاتبيّن المعرّف الحقيقي ديال النموذج المحلي، حتى إلا استعمل الطلب rizzo-latest ولا اسم مختصر.

طرح عدة أسئلة فطلب واحد

Rizzo Flow مصمم باش يقيّم عدة أسئلة على نفس الحالة. جمعهم فطلب واحد كيخلي الأسئلة يتقاسمو ذاكرة KV cache ديال الحالة:

curl http://127.0.0.1:8017/v1/systemone \
  -H 'Content-Type: application/json' \
  -d '{
    "state": "Help! My payouts have been failing for 3 days.",
    "model": "rizzo-latest",
    "questions": {
      "is_urgent": {
        "type": "noul",
        "instructions": "واش هاد الرسالة كاتبيّن الاستعجال؟"
      },
      "department": {
        "type": "choice",
        "instructions": "شنو هو الفريق اللي خاصو يتكلف بهاد الحالة؟",
        "criteria": {
          "billing": "الدفوعات، الفواتير، واسترجاع الأموال",
          "technical": "الأخطاء والتوقفات",
          "sales": null
        }
      },
      "frustration": {
        "type": "score",
        "instructions": "شحال الزبون منزعج؟",
        "criteria": ["هادئ", "منزعج", "غاضب بزاف"]
      }
    }
  }'

الاستجابة فيها احتمال «نعم» بالنسبة لـ noul، واحتمالات جميع اختيارات choice، ونقطة محسوبة حسب الاحتمالات مع اللائحة التوضيحية ديالها. القيمة usage.output_tokens ديما كتكون صفر.

استعمل API الأصلي ديال القرارات

الـ endpoint الأصلي POST /v1/decisions كيوفّر جميع إمكانيات Rizzo Flow، بما فيها الأسئلة الرقمية والامتناع. الأنواع الأربعة ديال الأسئلة هي:

  • boolean: كيرجع قيمة محددة النوع واحتمال كونها صحيحة.
  • choice: كيرجع الاختيار المحدد والتوزيع الكامل ديال الاختيارات.
  • score: كيرجع نقطاً محسوبة حسب الاحتمالات ومطبّعة عبر مستويات مرتبة.
  • numeric: كيرجع تقديراً، والوسيط، ومدى التشتت، واحتمال كون القيمة تحت أو فوق النطاق.

قدّر قيمة رقمية انطلاقاً من القيم المرجعية

السؤال الرقمي كيحدّد قيماً مرجعية تمثيلية متزايدة. فهاد المثال، كنطلبو من النموذج يقرا النسبة المئوية المبلّغ عليها للامتلاء:

curl http://127.0.0.1:8017/v1/decisions \
  -H 'Content-Type: application/json' \
  -d '{
    "state": {"measurement": 75, "unit": "percent"},
    "questions": {
      "fill": {
        "type": "numeric",
        "instructions": "قرا النسبة المئوية المبلّغ عليها للامتلاء.",
        "unit": "percent",
        "anchors": [
          {"value": 0, "description": "فارغ"},
          {"value": 50, "description": "نص عامر"},
          {"value": 75, "description": "ثلاثة أرباع عامرة"},
          {"value": 100, "description": "عامرة بالكامل"}
        ]
      }
    }
  }'

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

فهم الامتناع

الأسئلة الأصلية كتسمح بالامتناع بشكل افتراضي. Rizzo Flow كيزيد خياراً داخلياً ديال «المعطيات غير كافية»، والأسئلة الرقمية كتضم حتى احتمالات أقل من النطاق وأعلى من النطاق. حسب الاختيار والسياسة المحددين، القيمة الأساسية تقدر تكون null، والحالة تقدر تبلّغ على insufficient_evidence أو out_of_range أو uncertain.

الصيغة المتوافقة مع Jev ما كتستعملش الامتناع. نتيجة نعم/لا ديالها كاتتحسب على جوج اختيارات بالضبط. إلا استعملتي النموذج الأصغر 1.7B عبر API الأصلي، فكّر تضبط allow_abstain على false، كيف موصى به فالمشروع، وتحقّق من التأثير ديالو على البيانات ديالك.

شغّل القرارات بلا خادم

بالنسبة للسكريبتات والاختبارات أو التقييمات السريعة، دوز ملف الطلب مباشرة للـ CLI:

uv run rizzo decide examples/ticket.json

وتقدر حتى تفعّل البيئة الافتراضية وتحيد السابقة uv run:

source .venv/bin/activate
rizzo decide examples/ticket.json

فـ PowerShell، فعّلها بهاد الأمر:

.venv\Scripts\activate

اختار النموذج، والكمّية، والجهاز

الإعداد الافتراضي كيستعمل Spark-X2.5-4B Q8_0. والكمّيات الأخرى الموثقة هي Q4_K_M وBF16:

  • 4B Q8_0: تقريباً 4.4 GB، وهو الإعداد الافتراضي.
  • 4B Q4_K_M: تقريباً 2.6 GB.
  • 4B BF16: تقريباً 8.2 GB.
  • 1.7B Q8_0: تقريباً 1.8 GB.
  • 1.7B Q4_K_M: تقريباً 1.1 GB.
  • 1.7B BF16: تقريباً 3.4 GB.

عاين الأجهزة اللي باينة لوقت التشغيل قبل ما تبدا الخادم:

uv run rizzo devices

ومن بعد تقدر تختار عائلة الأجهزة بشكل صريح:

uv run rizzo serve --device cuda
uv run rizzo serve --device vulkan
uv run rizzo serve --device metal
uv run rizzo serve --device cpu

عائلات الأجهزة المسمّاة كتمثّل متطلبات وماشي غير تلميحات، وهادشي علاش Rizzo Flow ما كيهبطش بصمت من عائلة GPU محددة لـ CPU. حزم runtime الإضافية تقدر تهبطها بشكل منفصل:

uv run rizzo download --only runtime --runtime rocm
uv run rizzo download --only runtime --runtime sycl
uv run rizzo download --only runtime --runtime cpu

الإعدادات المتقدمة ونصائح عملية

جمع الأسئلة المرتابطة

حطّ جميع الأسئلة اللي كتهم نفس الحالة فطلب واحد. هادي نقطة أساسية فتصميم Rizzo Flow: الحالة كتتعمر مرة وحدة، وكتتقيّم لواحق الأسئلة فدفعات صغار. الحجم الافتراضي للدفعة الصغيّرة ديال الأسئلة هو أربعة، وتقدر تبدلو بـ --batch-size.

uv run rizzo serve --batch-size 8

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

كبّر السياق بحذر

مع أن Spark-X2.5 عندو سياق أصلي ديال مليون token، السيرفر كيستعمل افتراضياً 8,192 token لكل سؤال. طلّع الحد بـ --ctx:

uv run rizzo serve --ctx 32768

ذاكرة KV cache كتتخصص عند الإقلاع. بالنسبة للموديل 4B، الـREADME كيقدّر حوالي 144 KiB لكل token، يعني تقريباً 1.4 GiB فالحد الافتراضي و4.8 GiB عند 32,000 token. المدخلات اللي كتفوت الحد المضبوط كيتترفض وما كتتقصّش. من بعد تقريباً 60,000 token، خاص حتى يتزاد سقف الحالة ديال 256 KB الموجود فـ schema.py.

أمّن نقاط النهاية المتوافقة

عيّن RIZZO_API_KEY قبل ما تشغّل السيرفر باش تفرض مصادقة Bearer على نقاط النهاية المتوافقة مع Jev:

export RIZZO_API_KEY="replace-with-a-secret"
uv run rizzo serve

فـWindows PowerShell:

$env:RIZZO_API_KEY = "replace-with-a-secret"
uv run rizzo serve

فشل المصادقة كيرجع HTTP 401. وبيانات الطلب غير الصالحة تقدر ترجع HTTP 422.

وجّه عميلاً متوافقاً

العميل اللي متصمّم لـTypeSafe API المستضافة يقدر يستعمل الخدمة المحلية غير بتبديل عنوان URL الأساسي ديالو:

export TYPESAFE_BASE_URL=http://127.0.0.1:8017

المشروع كيذكر أن هاد الإعداد بمتغير البيئة متصمّم للـSDKs الرسمية، ولكن مازال ما تجرّبش معاها. الواجهة متوافقة، ولكن الموديل المحلي الأساسي ماشي Jev.

تعامل مع الثقة والاحتمالات بشكل صحيح

قيمة الثقة ديال الـAPI المتوافق كتصف شكل توزيع الاختيارات. ماشي احتمال مُتحقَّق منو بأن الجواب صحيح. وبالمثل، احتمالات الموديل الخام تقدر تكون واثقة بزاف أو ما معايراش مزيان.

تحقّق من القرارات فمجموعة بيانات موسومة وممثلة، وعايرها للبيئة الفعلية ديال النشر ملي يكون ضروري. السيرفر كيقبل ملف المعايرة عبر --calibration:

uv run rizzo serve --calibration fit.json

المعايرة مرتبطة بملف الموديل، والـruntime، والتكميم، والواجهة الخلفية ديال العتاد اللي تدار فيه الملاءمة. CUDA وVulkan وMetal يقدرو يديرو التقريب بطرق مختلفة، والتكميم يقدر يبدّل الاحتمالات الراجعة.

احترم حد خانات الأجوبة

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

استعمل ملف موديل مخصص أو نسخة مخصصة من llama.cpp

شغّل السيرفر بملف GGUF محدد باستعمال --model:

uv run rizzo serve --model /path/to/model.gguf

باش تستعمل تثبيت مخصص ديال llama.cpp، وجّه RIZZO_LLAMA_DIR للمجلد اللي فيه libllama. الـREADME كيطلب commit ديال llama.cpp هو 161755f حيث الـbindings مرتبطة بالـheader ديال داك الإصدار.

اكتاشف عرض Snake التوضيحي

Rizzo Flow كيتخذ قرارات الحركة الحية فـSnake

صفحة Snake المحلية كتبيّن كيفاش القرارات الموصوفة كتابياً تقدر تتحكم فتطبيق تفاعلي. كل حركة كترسل طلب POST /v1/decisions واحد فيه وصف للوحة وسؤال اختيار كيسرد الحركات القانونية. الصفحة كتعرض احتمالات الأجوبة، وlogits، والأوقات، وسجل القرارات بلا ما تولّد نص.

العرض حتى هو كيبين درس مهم فالنمذجة: تمثيل المدخلات مهم. الـREADME كيذكر أن الموديل 4B كيدير أحسن بزاف مع مستشعرات محسوبة لكل حركة مقارنة مع شبكة ASCII بوحدها. هاد الملاحظات جاية من عدد قليل ديال الألعاب غير الرسمية، وما خاصهاش تتعتبر benchmark.

الفحوصات التشغيلية

استعمل GET /health باش تراجع مصدر الموديل وهاشات الملفات. مخططات الطلب والجواب متاحة حتى هي فـrequest.schema.json وresponse.schema.json. بالنسبة للنشرات القابلة لإعادة الإنتاج، خَلّي الموديل، والتكميم، والـruntime، والواجهة الخلفية، وإعدادات السياق، والمعايرة ثابتين.

الـREADME كيذكر تقريباً 50 ميلي ثانية لقرار قصير باستعمال Spark-X2.5-4B Q8_0 على RTX 5060 Ti، ولكن هاد القياس مرتبط بالعتاد وحمولة العمل. نفس التوثيق كيذكر أن إعدادات Apple Silicon وAMD وIntel وLinux NVIDIA وCPU ما دازوش كاملين من اختبارات مكافئة، لذلك دير benchmark فالجهاز ديالك قبل ما تحدد توقعات التأخير.

الخلاصة

Rizzo Flow كيوفّر واجهة محلية وعملية لتحويل الحالة غير المهيكلة لقرارات مُنظّمة واحتمالية بلا ما يولّد نصوص. بدا ببيئة التجريب، وجمّع الأسئلة المرتابطة فطلب واحد، واستعمل الـAPI الأصلية ملي تحتاج تقديرات رقمية ولا الامتناع عن الإجابة. قبل الاستعمال فالإنتاج، اختبر الدقة، ووقت الاستجابة، والمعايرة، والتكميم، وسلوك الواجهة الخلفية على بيانات كتمثّل التطبيق الحقيقي ديالك.