Files
anwar-pi-website/web/src/seed.ts
T
2026-10-09 16:20:55 +03:00

376 lines
41 KiB
TypeScript

/* Seed script — run: npx payload run src/seed.ts
Idempotent: skips any post whose slug already exists. */
import { getPayload } from 'payload'
import { readFileSync } from 'node:fs'
import path from 'node:path'
import config from './payload.config'
type SeedPost = {
title: string
slug: string
dek: string
access: 'free' | 'vip'
category: 'وكلاء' | 'نماذج' | 'استرجاع' | 'سلامة' | 'أدوات' | 'أعمال'
level: 'مبتدئ' | 'متوسط' | 'متقدم'
coverFile: string
readingMinutes: number
teaser?: string[]
body: string[]
}
const P = (t: string) => t // paragraph shorthand
const POSTS: SeedPost[] = [
{
title: 'بناء أول وكيل بالعربية: دليل البداية العملية',
slug: 'first-arabic-agent', level: 'مبتدئ',
dek: 'من فكرة إلى وكيل يعمل: كيف تفكّك مهمة إلى خطوات يتحكم بها نموذج، وأين تضع الحواجز قبل أول تشغيل.',
access: 'free', category: 'وكلاء', coverFile: 'agents-free.jpg', readingMinutes: 9,
body: [
P('الوكيل ليس نموذجاً سحرياً؛ إنه حلقة قرار: يقرأ الحالة، يختار إجراءً، ينفّذه، ثم يفحص النتيجة. من يفهم هذه الحلقة يبني وكيلاً موثوقاً، ومن لا يفهمها يجمع أدوات ويصلي.'),
P('ابدأ من المهمة لا من النموذج. اكتب المهمة كجملة واحدة قابلة للفحص: «استخرج فواتير الشهر من البريد وجمعها في جدول بالتاريخ والمبلغ». إن لم تستطع كتابة فحص واحد يقرر صحة النتيجة، فالمهمة ليست جاهزة للتفويض بعد.'),
P('ثم حدّد الأدوات بأقل صلاحية ممكنة. وكيل يقرأ البريد لا يحتاج صلاحية الحذف، ووكيل يكتب ملفات لا يحتاج الشبكة. كل صلاحية زائدة هي فشل محتمل بانتظار لحظة تشتّت.'),
P('الخطوة الثالثة: صمّم الحالة. ماذا يرى النموذج في كل خطوة؟ رسالة المستخدم، سجل الإجراءات، ونتيجة آخر إجراء فقط. الحالة المزدحمة تُنتج قرارات مزدحمة.'),
P('أخيراً: شغّل الحلقة على أصغر مهمة حقيقية، واقرأ كل قرار اتخذه الوكيل. أول تشغيل ليس إنتاجاً؛ إنه جلسة تصحيح تكشف لك أين يفترض النموذج ما لا يعرف.'),
P('بهذه الأساسات الأربعة — مهمة قابلة للفحص، أدوات ضيقة، حالة نظيفة، ومراجعة بشرية للأول — يكون وكيلك الأول صالحاً للتطوير لا للعرض فقط.'),
],
},
{
title: 'امنع وكيلك من الدوران في حلقة',
slug: 'agent-loop-stop-condition', level: 'متوسط',
dek: 'افصل التخطيط والتنفيذ والتحقق، وحدد متى يتوقف الوكيل ومتى يطلب تدخلاً بشرياً — مع قالب حالة وقائمة فحص جاهزة للتشغيل.',
access: 'vip', category: 'وكلاء', coverFile: 'agents-vip.jpg', readingMinutes: 18,
teaser: [
P('الوكيل الذي يدور في حلقة لا ينقصه ذكاء؛ ينقصه شرط توقف. هنا نبني الحلقة بحيث يستطيع الوكيل أن يقول «انتهيت» — أو «أحتاجك».'),
P('أغلب الوكلاء يفشل بطريقة واحدة: يعيدون تخطيط المهمة نفسها إلى ما لا نهاية. السبب دائماً بنية الحلقة: التخطيط والتنفيذ والتحقق مدموجة في تعليمة واحدة، فلا يملك الوكيل مرجعاً مستقلاً يخبره أن النتيجة تحققت فعلاً.'),
],
body: [
P('الوكيل الذي يدور في حلقة لا ينقصه ذكاء؛ ينقصه شرط توقف. هنا نبني الحلقة بحيث يستطيع الوكيل أن يقول «انتهيت» — أو «أحتاجك».'),
P('أغلب الوكلاء يفشل بطريقة واحدة: يعيدون تخطيط المهمة نفسها إلى ما لا نهاية. السبب دائماً بنية الحلقة: التخطيط والتنفيذ والتحقق مدموجة في تعليمة واحدة، فلا يملك الوكيل مرجعاً مستقلاً يخبره أن النتيجة تحققت فعلاً.'),
P('## اكتب نتيجة يمكن فحصها'),
P('ابدأ بما يجب أن يكون صحيحاً عند النهاية. «ابحث عن أفضل خيار» هدف ضبابي. أما «أنشئ قائمة من ثلاثة خيارات، مع المصدر والسعر وتاريخ التحقق» فيمكن اختباره بشرط واحد واضح.'),
P('قاعدة أنور بي آي: إذا لم تستطع كتابة اختبار بسيط للنتيجة، فلن يعرف الوكيل متى يتوقف.'),
P('## استخدم حلقة قصيرة وواضحة'),
P('البنية الموصى بها: خطوة تخطيط تُنتج قائمة إجراءات مرقّمة، خطوة تنفيذ تنفّذ إجراءً واحداً فقط في كل دورة، وخطوة تحقق تُطابق النتيجة مع الشرط المكتوب مسبقاً. التحقق منفصل عن التنفيذ — هذا الفصل هو ما يمنع «الانطباع بالإنجاز».'),
P('في كل دورة، اكتب حالة الوكيل ككائن واحد: المهمة، الإجراءات المنفذة، الشرط المتبقي، وعدد الدورات. الحد الأقصى للدورات ليس اختيارياً؛ اجعله ثابتاً صريحاً — عادة خمس إلى عشر دورات لأغلب المهام العملية.'),
P('## اجعل الأدوات ضيقة الصلاحية'),
P('كل أداة تعرف الوكيل عندها هي مخرج محتمل لا تراه. الأداة التي «تفعل كل شيء» تعني أن قرار الوكيل لا يمكن تفسيره بعد الفشل. قاعدة عملية: أداة واحدة لكل فعل، واسم يصف الأثر لا التقنية.'),
P('## متى يطلب تدخلاً بشرياً'),
P('عرّف ثلاث حالات إلزامية للتوقف: فشل التحقق مرتين متتاليتين، الحاجة لأداة غير معرّفة، أو تجاوز حد الدورات. في الحالات الثلاث يخرج الوكيل بسجل كامل وطلب واضح — لا يخمّن ولا يعيد المحاولة بلا نهاية.'),
P('قالب حالة الوكيل جاهز النسخ: حقل المهمة كنص قابل للفحص، قائمة الإجراءات مع حالتها، شرط التوقف، العداد، وسجل القرارات الأخيرة. ابدأ بهذا القالب في كل وكيل جديد، وستعرف فوراً أين ينحرف.'),
P('قائمة الفحص قبل كل تشغيل: هل الشرط مكتوب؟ هل حد الدورات مضبوط؟ هل لكل أداة صلاحية دنيا؟ هل يوجد مسار خروج واضح؟ أربع إجابات بنعم، ثم شغّل.'),
],
},
{
title: 'كيف تختار نموذجك: قرارات لا إعلانات',
slug: 'choosing-your-model', level: 'مبتدئ',
dek: 'السياق والسعر وسرعة الاستجابة: إطار عملي لاختيار النموذج المناسب لمهمتك بدلاً من مطاردة الأرقام القياسية.',
access: 'free', category: 'نماذج', coverFile: 'models-free.jpg', readingMinutes: 8,
body: [
P('اختيار النموذج قرار هندسي، لا مودّة. ابدأ من طبيعة المهمة: توليد نص عربي طويل، تصنيف قصير، استدعاء أدوات، أم تحليل مستندات؟ لكل نوع عتبات مختلفة.'),
P('المعيار الأول: جودة العربية على أمثلتك أنت. خمسين مثالاً حقيقياً من عملك أهم من أي لوحة صدارة. شغّلها على نموذجين أو ثلاثة وقارن بقرار بشري محايد.'),
P('المعيار الثاني: نافذة السياق الفعلية لا المعلنة. النموذج الذي يفعل مئة ألف رمز قد يتدهور بعد العشرين ألفاً. اختبر بسؤال في آخر المستند وآخر فيه.'),
P('المعيار الثالث: التكلفة لكل مهمة مكتملة، لا لكل رمز. المهمة الواحدة قد تحتاج خمس محاولات على نموذج رخيص لتوازي محاولة واحدة على أغلى — فالعبرة بالسعر النهائي للنتيجة.'),
P('المعيار الرابع: الاستدعاء البنيوي والأدوات. إن كان عملك يعتمد على JSON صارم أو استدعاء دوال، فاختبر هذا تحديداً؛ التدهور هنا لا يظهر في المحادثة الطبيعية.'),
P('الخلاصة: نموذج لكل فئة مهمة. نموذج قوي للمسودات والتحليل، ونموذج سريع صغير للتصنيف والتحويل. هذه البنية تخفض التكلفة وترفع الثبات معاً.'),
],
},
{
title: 'تقييم النماذج منهجياً: من الأسبوع إلى النظام',
slug: 'systematic-model-eval', level: 'متوسط',
dek: 'ابنِ طقم تقييم صغيراً يحميك من انحراف التحديثات: أمثلة، حكم آلي، ومقارنات أعمى قابلة لإعادة التشغيل.',
access: 'vip', category: 'نماذج', coverFile: 'models-vip.jpg', readingMinutes: 16,
teaser: [
P('كل مرة يتحرك السعر أو تظهر نسخة جديدة، تعود لنفس الحيرة: هل يتدهور عملنا؟ الحل ليس حدساً بل طقم تقييم صغير تعيد تشغيله في دقائق.'),
P('في هذا الدليل نبني الطقم من ثلاث طبقات: أمثلة ذهبية من عملك الحقيقي، حكم آلي يصنّف المخرجات، ومقارنة أعمى بين نموذجين على نفس المدخلات. الطبقات الثلاث لا تستهلك أكثر من أسبوع أول مرة، ثم تشتغل نصف ساعة أسبوعياً.'),
],
body: [
P('كل مرة يتحرك السعر أو تظهر نسخة جديدة، تعود لنفس الحيرة: هل يتدهور عملنا؟ الحل ليس حدساً بل طقم تقييم صغير تعيد تشغيله في دقائق.'),
P('الطبقة الأولى: خمسون إلى مئة مثال من إنتاجك الفعلي. مدخل، ومخرج مقبول يوافق عليه إنسان. تنوّع الأمثلة عمداً: سهل، صعب، حالات حافّة، وحالات يجب أن يرفضها النموذج.'),
P('الطبقة الثانية: حكم آلي. نموذج قوي يقرأ الزوج (مدخل، مخرج) ويصنّف: صحيح، جزئي، خطأ، مع سبب من سطر واحد. اكتب تعليمات الحكم بدقة كما تكتب تعليمات الوكيل، واختبر الحكم نفسه على عشرين عينة قرّرها أنت.'),
P('الطبقة الثالثة: المقارنة العمياء. أدر النموذجين على نفس المدخلات، قدّم المخرجات بلا أسماء، ودع الحكم يختار الأفضل أو يقول تعادل. النتيجة: نسبة فوز لكل نموذج مع فاصل الثقة.'),
P('اربط الطقم بمحفّز واحد: عند أي تغيير — نسخة، سعر، برومبت جديد — شغّل الطقم وسجّل النتيجة في جدول مؤرّخ. بعد شهرين سيكون عندك أرشيف يخبرك بقرار كل ترقية بلا جدال.'),
P('أخطاء شائعة: أمثلة مأخوذة من توثيق النموذج نفسه (منحازة)، حكم من نفس عائلة النموذج المُقيَّم (محاباة ذاتية)، وطقم لا يُحدَّث أبداً فيصبح سهلاً بصرياً بلا معنى. عالج الثلاثة بتحديث عُشر الأمثلة شهرياً.'),
],
},
{
title: 'الاسترجاع بلا تعقيد: أول نظام RAG بالعربية',
slug: 'simple-arabic-rag', level: 'مبتدئ',
dek: 'التقط، قسّم، فهرس، استرجع: أبسط بنية RAG تعمل فعلاً مع العربية، وأخطاء التقسيم التي تفسد كل شيء.',
access: 'free', category: 'استرجاع', coverFile: 'retrieval-free.jpg', readingMinutes: 10,
body: [
P('أغلب أنظمة الاسترجاع تفشل قبل أول تضمين: في التقسيم. النص العربي المقتطع من منتصف مقطع يفقد ضمائره ومرجعيته، فيصل للنموذج مقطعاً بلا سياق.'),
P('ابدأ من الأبسط: قسّم على العناوين والفقرات، لا على عدد رموز ثابت. المقطع الجيد: من ١٥٠ إلى ٤٠٠ كلمة، يبدأ بجملة تصلح وحدها، ويتضمن اسم المستند وموضعه.'),
P('الفهرسة: تضمين لكل مقطع، وتخزين في قاعدة متجهات أو حتى في جدول عادي إن كان حجمك أقل من مئة ألف مقطع. لا تعقّد قبل أن يتطلب الحجم ذلك.'),
P('الاسترجاع: خذ العشرين الأعلى تشابهاً، ثم مرّر أفضل خمسة للنموذج. أعد الترتيب بنموذج ثانٍ صغير إن كان الترتيب الأول ضعيفاً.'),
P('السؤال المهم: هل المشكلة في الاسترجاع أم في التوليد؟ اختبرها بفصل الاثنين: اعرض المقاطع المسترجعة لعين بشرية قبل وصولها للنموذج. إن كانت المقاطع صحيحة والإجابة خاطئة، فالخلل في البرومبت أو النموذج لا في الفهرس.'),
P('القياس: احتفظ بأربعين سؤالاً حقيقياً مع المقاطع الصحيحة المتوقعة. مقياس بسيط: هل المقطع الصحيح ضمن الخمسة الأولى؟ هذا الرقم وحده يحكم تطويرك.'),
],
},
{
title: 'قواعد بيانات المتجهات عملياً: متى تحتاجها فعلأً؟',
slug: 'vector-databases-in-practice', level: 'متوسط',
dek: 'ملايين المقاطع، فلاتر مركّبة، وزمن استجابة تحت المئة ميلي ثانية: متى تنتقل من جدول عادي إلى قاعدة متجهات، وكيف.',
access: 'vip', category: 'استرجاع', coverFile: 'retrieval-vip.jpg', readingMinutes: 14,
teaser: [
P('أكثر الأسئلة تكراراً: هل أحتاج قاعدة متجهات أصلاً؟ الجواب القصير: أقل مما تظن، لكن حين تحتاجها فالانتقال له معايير محددة.'),
P('نراجع هنا عتبات الحجم، خيارات الفهرسة، والفلاتر المركّبة على المتجهات مع أرقام زمن استجابة واقعية لكل خيار — من جدول Postgres بامتداد pgvector إلى الفهارس المتخصصة.'),
],
body: [
P('أكثر الأسئلة تكراراً: هل أحتاج قاعدة متجهات أصلاً؟ الجواب القصير: أقل مما تظن، لكن حين تحتاجها فالانتقال له معايير محددة.'),
P('العتبة العملية: تحت ألف مقطع، بحث خطي داخل تطبيقك يكفي ويُقاس بالميلي ثانية. تحت مئة ألف، امتداد pgvector على نفس قاعدة بياناتك الحالية هو الخيار الممل والصحيح — نفس النسخ الاحتياطي، نفس الأدوات، نفس الفلاتر.'),
P('ما فوق مئة ألف، أو متطلبات زمن صارمة مع فلاتر مركّبة (متجه + مستخدم + لغة + تاريخ)، هنا تبدأ القواعد المتخصصة. الفرق الجوهري ليس «السرعة» بل كيفية الجمع بين بحث المتجه والفلتر الدقيق دون مسح ضخم.'),
P('الفهرس: HNSW يعطي استرجاعاً سريعاً بذاكرة أكبر، وIVF يقلّل الذاكرة بجودة أقل قليلاً. ابدأ بـ HNSW بمقياس المسافة الذي درّبت عليه التضمين — الخطأ الأشيع هو مسافة كوزينية على تضمين مبني للمسافة الإقليدية.'),
P('الفلاتر المركّبة: صمّم المخطط بحيث تكون حقول الفلتر أعمدة عادية مفهرسة، وطبّق الفلتر قبل بحث المتجه حين تسمح القاعدة، أو بعد البحث على مرشحين أوسع إن لم تسمح. قِس زمن الاستجابة عند أعلى ٩٩٪ لا عند المتوسط.'),
P('التشغيل: أعد بناء الفهرس بعد تحميل أول مئة ألف مقطع، لا قبله؛ راقب جودة الاسترجاع بمقياس «الصحيح ضمن الخمسة» الذي بنيناه في الدليل السابق؛ واحتفظ بإصدار التضمين مع كل مقطع، فتغيير النموذج يعني إعادة فهرسة كاملة مخطط لها.'),
P('الخلاصة: ابدأ مملّاً — جدول وامتداد. انتقل لقاعدة متخصصة حين يقيدك حجم حقيقي أو زمن حقيقي، لا حين يُغرِيك جدول مقارنة.'),
],
},
{
title: 'حدود الوكيل الآمنة: من يمنع ماذا؟',
slug: 'safe-agent-guardrails', level: 'متوسط',
dek: 'الوكيل بدون حدود مسؤولية هو ثغرة بانتظار حدث. صمّم ما يمكنه فعله، وما يحتاج موافقة، وما لا يُسمح به إطلاقاً.',
access: 'free', category: 'سلامة', coverFile: 'safety-free.jpg', readingMinutes: 7,
body: [
P('الأمان في الوكلاء ليس طبقة إضافية؛ هو قيد تصميمي يبدأ من السؤال: ما أسوأ شيء يمكن أن يفعله هذا الوكيل بكلمات صحيحة؟'),
P('صنّف الأفعال إلى ثلاث فئات: آمنة (قراءة، حساب، صياغة)، محتاجة موافقة (إرسال بريد، تعديل ملف مشترك، إنشاء فاتورة)، وممنوعة (حذف جماعي، دفع مالي، وصول لبيانات خارج نطاق المهمة).'),
P('طبّق الفئات على مستوى الأدوات لا التعليمات. التعليمة «لا ترسل بريداً بلا موافقتي» تُنسى؛ أداة الإرسال التي تطلب توقيعاً بشرياً لا تُنسى.'),
P('احمِ الوكيل من مدخلاته أيضاً: نصوص مسترجعة من الويب أو المستخدمين قد تحمل تعليمات مخفية. المعالجة: اعزل محتوى المصادر داخل علامات واضحة، وأخبر النموذج صراحة أن ما بداخلها بيانات لا تعليمات.'),
P('سجّل كل قرار: المدخل، الإجراء، النتيجة، والسبب باختصار. السجل هو ما يحوّل الحادث من «كارثة غامضة» إلى «خطوة رقم ٧ فشلت».'),
P('وأخيراً: جرّب الخروج عن المسار عمداً قبل الإطلاق. أعطِ الوكيل مدخلاً مزيّفاً يحمل أوامر، ومهمة غامضة، وأداة معطوبة — وراقب أين ينكسر. الإصلاح قبل الإطلاق أرخص بأضعاف.'),
],
},
{
title: 'مراجعة مخرجات الوكلاء: بوابات الجودة',
slug: 'agent-output-review-gates', level: 'متقدم',
dek: 'لا تقرأ كل مخرج يدوياً ولا تثق بأي مخرج: بوابات عيّنة، حكم آلي، ومسار تصعيد يوقف التشغيل قبل أن تتراكم الأخطاء.',
access: 'vip', category: 'سلامة', coverFile: 'safety-vip.jpg', readingMinutes: 15,
teaser: [
P('مراجعة كل شيء مستحيل، ومراجعة لا شيء متهوّر. البديل: بوابات جودة مصمّمة بالمخاطرة — كلما ارتفع أثر الفشل ارتفعت صرامة البوابة.'),
P('نبني في هذا الدليل ثلاث بوابات: فحص آلي فوري قبل النشر، عيّنة بشرية بنسبة تتناسب مع المخاطر، ومسار تصعيد يجمّد الوكيل عند تكرار الانحراف. مع نماذج جاهزة لكل بوابة.'),
],
body: [
P('مراجعة كل شيء مستحيل، ومراجعة لا شيء متهوّر. البديل: بوابات جودة مصمّمة بالمخاطرة — كلما ارتفع أثر الفشل ارتفعت صرامة البوابة.'),
P('البوابة الأولى: فحص آلي فوري. قبل أن يخرج أي مخرج للنظام، يمرّ على قائمة شروط رخيصة: هل الرد في النطاق المطلوب؟ هل الحقول المطلوبة موجودة؟ هل لا يحتوي أثر تعليمات من المصادر؟ هذا الفحص يمنع ثلثي الأخطاء بتكلفة تافهة.'),
P('البوابة الثانية: عيّنة بشرية. نسبة المراجعة تُحدَّد بالمخاطرة: مخرجات داخلية قابلة للتصحيح ٥٪، مخرجات ترسل للعملاء ٢٠٪، مخرجات مالية أو قانونية ١٠٠٪. اختر العينات عشوائياً لا بالتسلسل، وإلا ستُراجع أول صفحة فقط.'),
P('البوابة الثالثة: التصعيد. عدّاد انحراف لكل وكيل؛ عند ثلاثة إنذارات في ساعة يتوقف التشغيل ويُبلغ الفريق. القاعدة: توقف مبكر مُزعج أفضل من استمرار واثق خاطئ.'),
P('الحكم الآلي في البوابات: نفس منهجية طقم التقييم — تعليمات صريحة، أمثلة معيارية، ومراجعة دورية للحكم نفسه. حكم منحرف يجعل البوابات الثلاث وهمية.'),
P('القياس: تتبّع ثلاثة أرقام أسبوعياً — نسبة الإمساك في البوابة الآلية، نسبة القبول في العينة البشرية، وعدد التجميدات. أي رقم يتحرك بلا تفسير، فالمشكلة عندك أنت لا عند الوكيل.'),
],
},
{
title: 'أدوات لا غنى عنها في ورشة الذكاء الاصطناعي',
slug: 'indispensable-ai-tools', level: 'مبتدئ',
dek: 'خمس فئات أدوات تغطي ٩٠٪ من العمل اليومي: تشغيل، تجريب، تقييم، مراقبة، وإدارة برومبت — بلا حشو.',
access: 'free', category: 'أدوات', coverFile: 'tools-free.jpg', readingMinutes: 6,
body: [
P('الأداة الصحيحة لا تصنع خبرة، لكنها تمنع ضياعها في ملفات متناثرة. خمس فئات تكفي أغلب الفرق.'),
P('التشغيل: بيئة واحدة موثوقة لتشغيل النماذج عبر واجهة موحّدة، بحيث تبدّل النموذج بمتغير بيئة لا بإعادة كتابة كود.'),
P('التجريب: دفتر تفاعلي للبرومبت مع نسخ مؤرّخ. القاعدة: كل برومبت يُعدّل له سجل — من عدّل، لماذا، وبأي نتيجة.'),
P('التقييم: جدول أمثلة ذهبية وسكربت مقارنة — كما في دليلي التقييم المنهجي. لا تحتاج منصة مدفوعة في البداية؛ تحتاج ملفاً صادقاً.'),
P('المراقبة: سجل طلبات بالتكلفة والزمن والمخرج لكل استدعاء إنتاجي. أول أسبوع بلا سجل يكلفك سؤال «من أين جاء هذا الـ٢٠٠ دولار؟».'),
P('إدارة البرومبت: مستودع واحد للبرومبتات النهائية حسب المهمة، مع نسخة مستقرة لكل إنتاج. البرومبت كود؛ عامله كذلك.'),
P('القاعدة الحاكمة عبر الفئات كلها: أدوات تُفحص بياناتها. أداة بلا سجل أو تصدير سترسلها في النهاية أداةً تثق بها بلا سبب.'),
],
},
{
title: 'أنابيب الأدوات والصلاحيات: من المفاتيح إلى التدقيق',
slug: 'tool-pipelines-and-permissions', level: 'متقدم',
dek: 'بنية أدوات تُدار بالمفاتيح والصلاحيات والتدقيق: كل أداة بعقد واضح، ومفتاح بعمر محدد، وسجل لا يُمحى.',
access: 'vip', category: 'أدوات', coverFile: 'tools-vip.jpg', readingMinutes: 13,
teaser: [
P('حين يتصل وكيلك بأدوات حقيقية — بريد، دفع، قواعد بيانات — تتغير الصورة كلياً: كل مفتاح مسؤولية، وكل صلاحية فشل محتمل بانتظار لحظة تشتت.'),
P('نبني هنا الأنابيب كاملة: عقود أدوات صريحة، مفاتيح بعمر قصير ونطاق أدنى، فصل بيئات، وتدقيق غير قابل للمحو — مع قائمة فحص جاهزة لمراجعة أي أداة قبل توصيلها بالوكيل.'),
],
body: [
P('حين يتصل وكيلك بأدوات حقيقية — بريد، دفع، قواعد بيانات — تتغير الصورة كلياً: كل مفتاح مسؤولية، وكل صلاحية فشل محتمل بانتظار لحظة تشتت.'),
P('عقد الأداة: لكل أداة صفحة واحدة — الاسم يصف الأثر، المدخلات بأنواعها، المخرجات، الأخطاء المحتملة، وحد الزمن. العقد هو ما يجعل فشل الأداة قابلاً للتفسير لا غامضاً.'),
P('المفاتيح: عمر قصير ونطاق أدنى. مفتاح قراءة فقط للمهام القرائية، ومفتاح كتابة منفصل بعمر ساعة للمهام الاستثنائية. المفتاح الدائم متعدد الصلاحيات هو ثغرة اليوم الأكثر شيوعاً في مشاريع الوكلاء.'),
P('فصل البيئات: وكيل التطوير يرى بيئة تطوير. أي اتصال بمصدر إنتاج يتطلب تعديلاً صريحاً في الإعداد مع سجل لمن فعّله ومتى. لا استثناءات «لمجرد اختبار سريع» — هذا نصّ كل تقرير حادثة تقريباً.'),
P('التدقيق: سجل إلحاقي لكل استدعاء أداة — من، أي أداة، أي مدخلات، أي نتيجة، متى. لا تعديل ولا حذف؛ التدوير فقط. السجل هو ما يحميك في المراجعة، ويحمي فريقك في الشك.'),
P('قائمة فحص ما قبل التوصيل: هل العقد مكتوب؟ هل المفتاح بنطاق أدنى؟ هل يوجد حد زمن؟ هل الفشل يعيد الوكيل لمسار آمن؟ هل الاستدعاء يسجَّل؟ خمس إجابات بنعم، ثم وصّل.'),
P('الأخطاء المتكررة: مشاركة مفتاح بين وكيلين، وصف أداة يقرأه النموذج مختلفاً عن سلوكها الفعلي، وغياب حد زمن فيتحول أي تعليق إلى تجميد كامل. عالجها مبكراً؛ كلها رخيصة قبل الحادثة.'),
],
},
{
title: 'الذكاء الاصطناعي في عملك: من أين تبدأ فعلاً؟',
slug: 'ai-in-your-business', level: 'مبتدئ',
dek: 'لا تبحث عن حالة استخدام؛ ابحث عن عمل متكرر بمعيار واضح. منهجية أربع خطوات لاختيار أول أتمتة تَستحق.',
access: 'free', category: 'أعمال', coverFile: 'business-free.jpg', readingMinutes: 7,
body: [
P('سؤال «ماذا نفعل بالذكاء الاصطناعي؟» يُجاب بالعكس: ابدأ من عمل متكرر يزعج فريقك، ينتهي بمعيار قابل للفحص، ويُراجَع خطأه بلا كارثة.'),
P('الخطوة الأولى: اكتب أهم ثلاث مهام متكررة في فريقك مع الوقت الذي تستهلكه شهرياً. لا تفكّر في النماذج بعد.'),
P('الخطوة الثانية: لكل مهمة، اكتب معيار النجاح بجملة قابلة للفحص. المهمة بلا معيار تنتقل للأسفل دائماً.'),
P('الخطوة الثالثة: اختر الأرخص خطراً — التي يُراجَع خطؤها قبل أن يصل لعميل. المراجعة الداخلية هي شبكة أمان تتيح لك التعلّم بلا ثمن.'),
P('الخطوة الرابعة: أتمتة تجريبية لأسبوعين، بقياس واحد: ساعات موفّرة مقابل ساعات تصحيح. إن لم تتفوق النسبة على ٣:١ بعد الجولة الثانية، أعد المهمة لفريقك وانتقل لغيرها.'),
P('القاعدة الحاكمة: الذكاء الاصطناعي يضاعف عملك القائم، جيداً كان أم رديئاً. أصلح الإجراء اليدوي أولاً؛ ثم أتمت إجراءً نظيفاً.'),
],
},
{
title: 'من نموذج أولي إلى إنتاج: قرارات الثبات',
slug: 'prototype-to-production', level: 'متقدم',
dek: 'الفارق بين تجربة تعمل وإنتاج يعتمد عليه: إعادة المحاولة، التراجع، مراقبة التكلفة، وخطط التدهور — كلها قرارات تكتب قبل الإطلاق.',
access: 'vip', category: 'أعمال', coverFile: 'business-vip.jpg', readingMinutes: 17,
teaser: [
P('النموذج الأولي الذي أبهرك في العرض سيتصرف مختلفاً في الإنتاج: نفس النموذج، لكن المخاطر والتنوع والضغط كلها أكبر. الفارق ليس في الذكاء بل في القرارات المحيطة.'),
P('هذا الدليل يراجع القرارات الخمسة التي تفصل الاثنين: ماذا يحدث عند الفشل؟ متى نعيد المحاولة؟ كيف نتراجع عن نسخة برومبت سيئة؟ متى نوقف الوكيل تلقائياً؟ وكيف نراقب التكلفة قبل أن تراقبنا الفاتورة؟'),
],
body: [
P('النموذج الأولي الذي أبهرك في العرض سيتصرف مختلفاً في الإنتاج: نفس النموذج، لكن المخاطر والتنوع والضغط كلها أكبر. الفارق ليس في الذكاء بل في القرارات المحيطة.'),
P('القرار الأول: سياسة الفشل. كل استدعاء نموذج له ثلاث حالات — نجاح، خطأ واضح، تعليق. حدّد سلوك كل حالة كتابةً: خطأ واضح يعيد المحاولة مرة واحدة ثم يسلك مساراً بديلاً؛ تعليق يتجاوز المهلة يفشل بسرعة ويسجّل. الفشل الصامت هو الخيار الوحيد الممنوع.'),
P('القرار الثاني: إعادة المحاولة والتراجع. أعد المحاولة على الأخطاء العابرة فقط (انقطاع، حد معدل) بتأخير تصاعدي، وبحد أقصى اثنتان. أما الأخطاء المنطقية فإعادة المحاولة عليها تضاعف الفاتورة ولا تعالج السبب.'),
P('القرار الثالث: إصدارات البرومبت كإصدارات كود. كل برومبت إنتاجي له رقم، وسجل تغيير، وقدرة تراجع فوري. برومبت بلا إصدار يعني أن تحسيناً صغيراً قد يكسر أسبوعاً كاملاً بلا طريق رجوع.'),
P('القرار الرابع: قواطع التشغيل. حد أدنى للجودة، وحد أقصى للتكلفة اليومية، وحد أقصى لمعدل الأخطاء — عند تجاوز أي حد يُجمّد الوكيل تلقائياً ويُشعَر الفريق. القواطع تُختبَر شهرياً كما تُختبَر النسخ الاحتياطية.'),
P('القرار الخامس: مراقبة التكلفة. تتبّع تكلفة كل مهمة مكتملة لا كل رمز، وقارن أسبوعياً مع القيمة المضافة. التكلفة التي لا يراها أحد ترتفع؛ التكلفة المرئية تستقر عند قيمتها.'),
P('خطة التدهور: اتفق مسبقاً على الخيار البديل إن تدهور النموذج أو انتهى — نموذج احتياطي، أو مسار يدوي، أو إيقاف ميزة. التدهور حدث مؤكد مؤجل، لا احتمال.'),
P('قائمة الإطلاق: سياسة فشل مكتوبة، إصدارات برومبت، قواطع مفعّلة ومختبرة، لوحة تكلفة مرئية، وخطة تدهور موقّعة. خمسة بنود، ثم أطلق.'),
],
},
{
title: 'ابنِ وكيلك الأول دون فوضى',
slug: 'article-agent-guide', level: 'مبتدئ',
dek: 'خريطة عملية تفصل التخطيط عن التنفيذ والتحقق، حتى تعرف لماذا نجح الوكيل — ولماذا فشل.',
access: 'free', category: 'وكلاء', coverFile: 'agents-free.jpg', readingMinutes: 12,
body: [
P('الوكيل الجيد ليس محادثة أطول. هو نظام صغير يعرف ما المطلوب، يختار أداة مناسبة، ثم يتحقق من النتيجة قبل أن يكمل.'),
P('أغلب التجارب الأولى تفشل لأن كل شيء يحدث داخل تعليمات واحدة: الهدف، والبيانات، والأدوات، والذاكرة. عندما يتعثر النظام لا تعرف هل المشكلة في الفهم أم التنفيذ أم التحقق. الحل ليس إضافة تعليمات أكثر؛ بل فصل المسؤوليات.'),
P('## ١. اكتب نتيجة يمكن فحصها'),
P('ابدأ بما يجب أن يكون صحيحاً عند النهاية. «ابحث عن أفضل خيار» هدف ضبابي. أما «أنشئ قائمة من ثلاثة خيارات، مع المصدر والسعر وتاريخ التحقق» فيمكن اختباره.'),
P('قاعدة أنور بي آي: إذا لم تستطع كتابة اختبار بسيط للنتيجة، فلن يعرف الوكيل متى يتوقف.'),
P('## ٢. استخدم حلقة قصيرة وواضحة'),
P('الحلقة العملية ثلاث خطوات: خطّط — حوّل الهدف إلى خطوة واحدة تالية، لا إلى خطة ضخمة لا تتغير. نفّذ — استدعِ أداة واحدة بمدخلات محددة وسجّل ما حدث فعلاً. تحقق — قارن الناتج بشرط النجاح، ثم توقف أو عدّل الخطوة التالية.'),
'```' + 'while not done:\n step = planner.next(goal, state)\n result = tools.run(step)\n state.record(result)\n done = verifier.check(goal, state)',
P('## ٣. اجعل الأدوات ضيقة الصلاحية'),
P('لا تمنح الوكيل أداة «نفّذ أي أمر». قدّم وظائف محددة مثل قراءة ملف، إنشاء مسودة، أو إرسال عنصر بعد موافقة. كلما ضاقت الأداة أصبح اختبارها ومراجعتها أسهل.'),
P('عملياً: تحقق من المدخلات قبل التنفيذ، واطلب موافقة بشرية قبل الإرسال أو الحذف أو الدفع، واحتفظ بسجل واضح للطلب والنتيجة.'),
P('## ٤. الذاكرة ليست صندوقاً واحداً'),
P('احتفظ بحالة المهمة الحالية منفصلة عن المعرفة طويلة المدى. لا ترسل تاريخ المحادثة كله في كل مرة. استخرج فقط ما يحتاجه القرار التالي، واحتفظ بالمصادر بجوار الحقائق.'),
P('## قائمة الفحص قبل التشغيل'),
P('هل توجد نتيجة نهائية قابلة للتحقق؟ هل لكل أداة مدخلات وصلاحيات محددة؟ هل يستطيع الوكيل التوقف عند الفشل؟ هل العمليات الحساسة تحتاج موافقة؟ هل يمكنك إعادة تشغيل المهمة من السجل؟'),
P('الخلاصة: ابدأ بحلقة صغيرة واختبار واحد. أضف الذاكرة والتخطيط المتقدم فقط عندما يثبت القياس أنك تحتاجهما.'),
],
},
]
async function ensureUser(payload: Awaited<ReturnType<typeof getPayload>>, email: string, password: string, role: 'free' | 'vip' | 'admin') {
const { docs } = await payload.find({ collection: 'users', where: { email: { equals: email } }, limit: 1 })
if (docs.length > 0) return docs[0]
return payload.create({
collection: 'users',
data: { email, password, role },
context: { systemActivation: true },
})
}
export async function main(): Promise<void> {
const payload = await getPayload({ config })
// Accounts
await ensureUser(payload, 'admin@anwarpi.ai', 'AnwarPi-Admin-2026!', 'admin')
if (process.env.SEED_TEST_USERS === '1') {
await ensureUser(payload, 'free@test.anwarpy.ai', 'Free1234!', 'free')
await ensureUser(payload, 'vip@test.anwarpy.ai', 'Vip1234!', 'vip')
}
console.log('✓ users ensured (admin/free/vip)')
// Media: upload covers from public/covers (post covers + per-category agent defaults)
const coverIds: Record<string, number> = {}
const coverFiles = new Set<string>([...POSTS.map((p) => p.coverFile),
'cover-agents.jpg', 'cover-models.jpg', 'cover-retrieval.jpg',
'cover-safety.jpg', 'cover-tools.jpg', 'cover-business.jpg', 'cover-default.jpg'])
for (const coverFile of coverFiles) {
const filePath = path.resolve(process.cwd(), 'public/covers', coverFile)
const buffer = readFileSync(filePath)
const doc = await payload.create({
collection: 'media',
data: {},
file: {
data: buffer,
mimetype: 'image/jpeg',
name: coverFile,
size: buffer.length,
},
})
coverIds[coverFile] = doc.id
}
console.log(`✓ ${Object.keys(coverIds).length} covers uploaded`)
// Posts (idempotent by slug)
let created = 0
let dayOffset = POSTS.length
for (const post of POSTS) {
const existing = await payload.find({ collection: 'posts', where: { slug: { equals: post.slug } }, limit: 1 })
if (existing.docs.length > 0) {
// backfill new fields (level) on existing posts
if (existing.docs[0].level !== post.level) {
await payload.update({ collection: 'posts', id: existing.docs[0].id, data: { level: post.level }, overrideAccess: true })
console.log(`- updated level: ${post.slug} → ${post.level}`)
} else {
console.log(`- skip existing: ${post.slug}`)
}
continue
}
// Build Lexical richText body: headings carry tag, every node needs version
const paragraphs = post.body.map((text) => {
if (text.startsWith('```')) {
return {
type: 'code',
version: 1,
code: text.slice(3),
}
}
if (text.startsWith('## ')) {
return {
type: 'heading',
tag: 'h2',
version: 1,
children: [{ type: 'text', version: 1, text: text.slice(3) }],
}
}
return {
type: 'paragraph',
version: 1,
children: [{ type: 'text', version: 1, text }],
}
})
const publishedAt = new Date(Date.now() - dayOffset * 24 * 60 * 60 * 1000).toISOString()
dayOffset -= 1
await payload.create({
collection: 'posts',
data: {
title: post.title,
slug: post.slug,
dek: post.dek,
access: post.access,
teaser: post.teaser?.join('\n\n'),
content: {
root: {
type: 'root',
children: paragraphs,
direction: 'rtl',
format: '',
indent: 0,
version: 1,
},
},
category: post.category,
level: post.level,
cover: coverIds[post.coverFile],
readingMinutes: post.readingMinutes,
publishedAt,
status: 'published',
},
})
created += 1
console.log(`✓ created: ${post.slug}`)
}
console.log(`Seed complete: ${created} posts created.`)
process.exit(0)
}
await main()