هل تعتقد أن كتابة أوامر للذكاء الاصطناعي هي مجرد كتابة نص؟ اكتشف كيف تحول Prompt Engineering من مهارة جانبية إلى سلاح سري في يد المطورين المحترفين، مع استراتيجيات متقدمة تفوق الـ 90% من المستخدمين.
في أحد المشاريع الكبيرة لشركة تقنية ناشئة، واجه الفريق مشكلة غريبة: نموذج اللغة الكبير الذي يستخدمونه كان ينتج كود بايثون يعمل بشكل صحيح ولكنه غير قابل للصيانة على الإطلاق. الدوال كانت طويلة بلا داعٍ، المتغيرات تحمل أسماء عشوائية مثل x1 وtemp، والتعليقات إما مفقودة أو غير مفيدة. بعد أسبوعين من المعاناة، اكتشف المطور الرئيسي أن المشكلة ليست في النموذج نفسه، بل في الطريقة التي كانوا يكتبون بها الـ Prompts. تغيير بسيط في صياغة الأمر من 'اكتب كود بايثون لحل هذه المشكلة' إلى 'اكتب كود بايثون احترافي وقابل للصيانة، استخدم أسماء متغيرات واضحة، قسم الكود إلى دوال صغيرة، وأضف تعليقات توضيحية' أدى إلى تحسن مذهل في جودة المخرجات. هذا هو بالضبط ما يدور حوله Prompt Engineering: ليس مجرد كتابة أوامر، بل هندسة تفكير الآلة.
العديد من المطورين يعتقدون أن التعامل مع نماذج اللغة الكبيرة هو مجرد كتابة أسئلة أو أوامر بسيطة، ثم انتظار الإجابة. لكن الحقيقة هي أن هذه النماذج تعمل كآلات تفسير معقدة، تعتمد على السياق والذاكرة القصيرة المدى (context window) ومعالجة اللغة الطبيعية بطرق لا تشبه البشر. عندما تكتب Prompt سيئاً، فإنك في الواقع تطلب من النموذج أن يخمن نواياك بدلاً من أن يفهمها، وهذا يؤدي إلى مخرجات غير دقيقة أو حتى مضللة. في هذا المقال، سنغوص عميقاً في استراتيجيات Prompt Engineering المتقدمة التي ستحولك من مستخدم عادي إلى مهندس أوامر محترف، قادر على استخراج أقصى قدر من الدقة والكفاءة من نماذج اللغة الكبيرة.
لفهم كيف تعمل استراتيجيات Prompt Engineering المتقدمة، يجب أولاً أن نفهم ما يحدث داخل النموذج عندما يتلقى Prompt. عندما ترسل أمراً مثل 'اشرح مفهوم الـ Event Loop في جافاسكريبت'، فإن النموذج لا يبحث في قاعدة بيانات جاهزة للإجابة، بل يمر بمراحل معالجة معقدة. أولاً، يتم تقسيم النص إلى وحدات صغيرة تسمى Tokens، حيث قد يكون كل كلمة أو جزء من كلمة عبارة عن Token. على سبيل المثال، كلمة 'جافاسكريبت' قد تُقسم إلى ['جاڤا', 'سكريبت'] أو حتى ['جاڤ', 'اسك', 'ربت'] حسب الـ Tokenizer المستخدم. هذا التقسيم ليس مجرد عملية ميكانيكية، بل يؤثر بشكل مباشر على كيفية فهم النموذج للسياق.
بعد ذلك، يدخل النموذج في مرحلة الـ Attention Mechanism، حيث يحاول فهم العلاقات بين هذه الـ Tokens وتحديد أي منها أكثر أهمية للسياق المطلوب. هذا هو السبب في أن تغيير كلمة واحدة في Prompt يمكن أن يؤدي إلى نتائج مختلفة تماماً. مثلاً، إذا كتبت 'اشرح الـ Event Loop ببساطة' مقابل 'اشرح الـ Event Loop بتفصيل تقني'، فإن النموذج سيضبط آلية الانتباه لتفضيل الـ Tokens المرتبطة بالبساطة في الحالة الأولى، والتفاصيل التقنية في الحالة الثانية. المشكلة هنا أن الـ Context Window محدود، عادةً بين 4K إلى 32K tokens حسب النموذج، وهذا يعني أن النموذج قد 'ينسى' أجزاء من الـ Prompt إذا كان طويلاً جداً أو معقداً. لهذا السبب، فإن هندسة الـ Prompts تتطلب ليس فقط معرفة ما تريد، بل أيضاً كيفية تقديمه بطريقة تضمن أن النموذج 'يركز' على الأجزاء الصحيحة.
# مثال على كيفية تقسيم الـ Tokenizer لكلمات عربية وإنجليزية
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("gpt2")
prompt = "اشرح مفهوم الـ Event Loop في جافاسكريبت"
tokens = tokenizer.tokenize(prompt)
print(tokens)
# المخرجات المحتملة: ['اش', 'رح', 'مفهوم', 'ال', 'ĠEvent', 'ĠLoop', 'في', 'Ġجاڤ', 'اسك', 'ربت']
# لاحظ كيف تم تقسيم الكلمة العربية 'اشرح' إلى 'اش' و'رح'، وكيف أضيفت مسافات قبل الكلمات الإنجليزية
# هذا التقسيم يؤثر على كيفية معالجة النموذج للسياقواحدة من أكثر الاستراتيجيات فعالية في Prompt Engineering هي ما يسمى بـ Chain of Thought (CoT). الفكرة هنا ليست مجرد طلب الإجابة من النموذج، بل جعله يعرض خطوات تفكيره قبل الوصول إلى النتيجة النهائية. هذا الأسلوب أثبت فعاليته بشكل خاص في المهام التي تتطلب تفكيراً منطقياً أو رياضياً، حيث يمكن أن تزيد دقة الإجابات من 10% إلى أكثر من 90% في بعض الحالات. السر وراء نجاح هذه الاستراتيجية هو أنها تحاكي الطريقة التي يفكر بها البشر عندما يواجهون مشكلة معقدة: بدلاً من القفز إلى الحل مباشرة، نقوم بتقسيم المشكلة إلى خطوات أصغر ونحل كل خطوة على حدة.
لنأخذ مثالاً عملياً: إذا طلبت من النموذج حل مسألة رياضية مثل 'إذا كان سعر منتج 120 دولاراً، وتم تخفيضه بنسبة 25%، ثم أضيف عليه ضريبة مبيعات 10%، فما هو السعر النهائي؟'، فإن النموذج قد يعطي إجابة خاطئة إذا لم يستخدم CoT. لكن إذا كتبت Prompt بهذه الطريقة: 'حل هذه المسألة خطوة بخطوة: أولاً، احسب قيمة الخصم بنسبة 25% من السعر الأصلي. ثانياً، اطرح قيمة الخصم من السعر الأصلي. ثالثاً، أضف ضريبة المبيعات بنسبة 10% إلى السعر بعد الخصم. رابعاً، أعطِ السعر النهائي.'، فإن النموذج سيتبع هذه الخطوات بدقة أكبر. في تجربتي الشخصية، عندما استخدمت CoT مع نماذج مثل GPT-4 لحل مسائل برمجية معقدة، انخفض معدل الأخطاء بشكل ملحوظ، خاصة في المهام التي تتطلب أكثر من خطوة منطقية.
Prompt سيئ (بدون CoT):
"احسب السعر النهائي لمنتج سعره 120 دولار بعد خصم 25% وضريبة مبيعات 10%."
Prompt جيد (مع CoT):
"لحساب السعر النهائي لمنتج سعره 120 دولار بعد خصم 25% وضريبة مبيعات 10%، اتبع هذه الخطوات:
1. احسب قيمة الخصم: 25% من 120 دولار.
2. اطرح قيمة الخصم من السعر الأصلي.
3. احسب قيمة الضريبة: 10% من السعر بعد الخصم.
4. أضف قيمة الضريبة إلى السعر بعد الخصم.
5. أعطِ السعر النهائي مع شرح لكل خطوة."رغم فعالية CoT، إلا أنها ليست حلاً سحرياً لكل المشاكل. هناك حالات تفشل فيها هذه الاستراتيجية، خاصة عندما يكون الـ Prompt طويلاً ومعقداً جداً، مما يؤدي إلى ما يسمى بـ 'الانحراف السياقي' (Context Drift). هذا يحدث عندما يركز النموذج على خطوات تفكير خاطئة أو يفقد السياق في منتصف الحل. مثلاً، في مسائل البرمجة التي تتطلب أكثر من 5 أو 6 خطوات، قد يبدأ النموذج في تجاهل الخطوات الأولى أو يخلط بينها. أيضاً، في المهام التي تتطلب إبداعاً أو تفكيراً خارج الصندوق، قد تؤدي CoT إلى نتائج جامدة وغير مبتكرة، لأن النموذج يصبح مقيداً بالخطوات التي حددتها له.
من تجربتي، أفضل طريقة لاستخدام CoT هي دمجها مع استراتيجيات أخرى مثل Few-Shot Learning، حيث تقدم أمثلة على كيفية حل مشكلة مشابهة قبل طرح المشكلة الفعلية. هذا يعطي النموذج إطاراً مرجعياً دون تقييده تماماً. أيضاً، يجب أن تكون خطوات CoT مرنة بما يكفي للسماح للنموذج بالتكيف مع السيناريوهات غير المتوقعة. مثلاً، بدلاً من كتابة 'أولاً افعل كذا، ثانياً افعل كذا'، يمكنك كتابة 'ابدأ بتحليل المشكلة، ثم اقترح حلولاً ممكنة، وأخيراً اختر الحل الأمثل'. هذا يترك مساحة للنموذج للتفكير بشكل أكثر مرونة.
إذا كانت CoT تعلم النموذج 'كيف يفكر'، فإن Few-Shot Learning تعلمه 'كيف يبدو الحل الجيد'. هذه الاستراتيجية تعتمد على تقديم أمثلة قليلة (عادةً بين 2 إلى 5) على شكل Prompt والإجابة المثالية، قبل طرح السؤال الفعلي. الفكرة هنا هي أن النماذج الكبيرة مدربة على كميات هائلة من البيانات، لكنها قد لا تكون متخصصة في المجال الذي تعمل عليه. عندما تقدم أمثلة محددة، فإنك تساعد النموذج على ضبط آلية الانتباه الخاصة به لتتناسب مع السياق الذي تريده.
لنأخذ مثالاً من عالم تطوير البرمجيات: إذا أردت من النموذج كتابة دوال جافاسكريبت تتبع نمطاً معيناً، مثل استخدام الـ Closures لحفظ الحالة، فإن تقديم مثالين أو ثلاثة على شكل Prompt والإجابة سيساعد النموذج على فهم النمط المطلوب. بدون هذه الأمثلة، قد ينتج النموذج دوالاً تعمل بشكل صحيح ولكنها لا تتبع النمط الذي تريده. في إحدى المشاريع التي عملت عليها، كنا نستخدم نموذج لغة كبير لتوليد كود TypeScript لواجهة مستخدم معقدة. بدون Few-Shot Learning، كان الكود الناتج عشوائياً وغير متسق. بعد إضافة أمثلة قليلة على النمط المطلوب، تحسن الاتساق بشكل كبير، وأصبح الكود الناتج جاهزاً للاستخدام في الإنتاج تقريباً.
// مثال على Few-Shot Learning لكتابة دوال جافاسكريبت باستخدام Closures
const fewShotPrompt = `
// مثال 1: دالة عداد تستخدم Closure لحفظ الحالة
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
// مثال 2: دالة مضاعفة تستخدم Closure لحفظ العامل
function createMultiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = createMultiplier(2);
console.log(double(5)); // 10
// الآن اكتب دالة مشابهة تستخدم Closure لحفظ القيمة الأولية
// الدالة المطلوبة: createAdder(initialValue)
// يجب أن تعيد دالة تضيف القيمة الممررة إليها إلى initialValue
`;
// النموذج سيستخدم الأمثلة لفهم النمط المطلوب وينتج شيئاً مثل:
function createAdder(initialValue) {
return function(value) {
return initialValue + value;
};
}اختيار الأمثلة في Few-Shot Learning ليس عشوائياً. يجب أن تكون الأمثلة متنوعة بما يكفي لتغطي الحالات المختلفة التي قد يواجهها النموذج، لكنها في نفس الوقت يجب أن تكون متسقة مع النمط الذي تريده. مثلاً، إذا كنت تريد من النموذج كتابة كود يتبع نمطاً معيناً، يجب أن تحتوي الأمثلة على حالات مختلفة مثل المدخلات الصحيحة، المدخلات الفارغة، والقيم الحدية. أيضاً، يجب أن تكون الأمثلة واقعية وممثلة للمشكلة الفعلية التي تريد حلها. في إحدى المرات، استخدمت Few-Shot Learning لتدريب نموذج على كتابة اختبارات وحدة لواجهة برمجة تطبيقات RESTful. قدمت أمثلة على اختبارات لـ GET وPOST وPUT وDELETE، مع حالات نجاح وفشل. النتيجة كانت اختبارات أكثر دقة وشمولية مما لو كتبت Prompt عاماً مثل 'اكتب اختبارات لواجهة برمجة التطبيقات'.
هناك أيضاً نقطة مهمة تتعلق بحجم الأمثلة. إذا كانت الأمثلة طويلة جداً، فقد تؤدي إلى تجاوز حد الـ Context Window للنموذج، مما يجعله 'ينسى' الأجزاء الأولى من الـ Prompt. من تجربتي، أفضل النتائج تأتي عندما تكون الأمثلة قصيرة ومباشرة، وتركز على جوهر المشكلة. أيضاً، يجب أن تكون الأمثلة متسقة في الأسلوب والتنسيق، حتى لا تربك النموذج. مثلاً، إذا كنت تستخدم أمثلة لكتابة كود، يجب أن تتبع جميع الأمثلة نفس نمط التسمية والتعليقات والتنسيق. هذا يساعد النموذج على التركيز على المحتوى بدلاً من التفاصيل الشكلية.
واحدة من أكثر الاستراتيجيات التي أدهشتني فعاليتها هي Role Prompting، حيث تطلب من النموذج أن يتقمص دوراً معيناً قبل الإجابة على سؤالك. الفكرة هنا ليست مجرد تغيير أسلوب الإجابة، بل تغيير الطريقة التي 'يفكر' بها النموذج. عندما تطلب من النموذج أن يكون 'خبيراً في أمن المعلومات' أو 'مبرمجاً محترفاً في بايثون'، فإنك في الواقع توجه آلية الانتباه الخاصة به لتفضيل الـ Tokens والمعرفة المرتبطة بهذا الدور. هذا الأسلوب أثبت فعاليته بشكل خاص في المهام التي تتطلب خبرة متخصصة، حيث يمكن أن تزيد جودة الإجابات بشكل كبير.
لنأخذ مثالاً عملياً: إذا سألت النموذج 'كيف أحمي قاعدة البيانات الخاصة بي؟'، قد تحصل على إجابة عامة وغير مفيدة. لكن إذا استخدمت Role Prompting وكتبت 'أنت خبير في أمن المعلومات مع خبرة 20 عاماً في حماية قواعد البيانات. كيف تحمي قاعدة بيانات تحتوي على معلومات حساسة؟ أعطِ إرشادات محددة وتقنية.'، فإن الإجابة ستكون أكثر تفصيلاً ودقة. في أحد المشاريع التي عملت عليها، كنا نستخدم نماذج اللغة الكبيرة لمراجعة كود بايثون من حيث الأمان. بدون Role Prompting، كانت المراجعات سطحية وتفتقد الكثير من الثغرات. بعد إضافة Role Prompting مثل 'أنت خبير في أمن المعلومات متخصص في بايثون. راجع هذا الكود بحثاً عن ثغرات أمنية وقدم اقتراحات لإصلاحها.'، أصبحت المراجعات أكثر عمقاً وشمولية، وكشفت عن ثغرات لم نكن لنكتشفها بطريقة أخرى.
Prompt سيئ (بدون Role Prompting):
"كيف أحمي قاعدة البيانات الخاصة بي؟"
Prompt جيد (مع Role Prompting):
"أنت خبير في أمن المعلومات مع خبرة 20 عاماً في حماية قواعد البيانات من الهجمات الإلكترونية.
قاعدة البيانات الخاصة بي تحتوي على معلومات حساسة للعملاء، بما في ذلك أرقام البطاقات الائتمانية.
أريد إرشادات محددة وتقنية لحماية هذه البيانات من:
1. هجمات SQL Injection
2. هجمات القوة الغاشمة
3. تسريبات البيانات الداخلية
4. هجمات التصيد الاحتيالي
لكل نقطة، أعطِ حلولاً تقنية مفصلة مع أمثلة على الكود إذا لزم الأمر."رغم فعالية Role Prompting، إلا أنها ليست مناسبة لكل الحالات. مثلاً، في المهام التي تتطلب إبداعاً أو تفكيراً خارج الصندوق، قد تؤدي Role Prompting إلى نتائج جامدة وغير مبتكرة. أيضاً، إذا كان الدور المطلوب غير واضح أو غير محدد جيداً، فقد يؤدي ذلك إلى إجابات غير دقيقة. مثلاً، إذا كتبت 'أنت خبير في الذكاء الاصطناعي'، فهذا الدور واسع جداً وغير محدد، وقد ينتج عنه إجابات عامة وغير مفيدة. من تجربتي، أفضل النتائج تأتي عندما يكون الدور محدداً بوضوح، مثل 'أنت خبير في تعلم الآلة متخصص في نماذج اللغة الكبيرة' بدلاً من 'أنت خبير في الذكاء الاصطناعي'.
هناك أيضاً مشكلة تتعلق بتضارب الأدوار. إذا طلبت من النموذج أن يكون 'مبرمج بايثون خبير' و'خبير في أمن المعلومات' في نفس الوقت، فقد ينتج عنه إجابات غير متسقة أو متضاربة. الحل هنا هو تقسيم الـ Prompt إلى أجزاء، حيث تحدد الدور في بداية كل جزء. مثلاً، يمكنك كتابة 'أولاً، كخبير في بايثون، راجع هذا الكود بحثاً عن مشاكل الأداء. ثانياً، كخبير في أمن المعلومات، راجع نفس الكود بحثاً عن ثغرات أمنية.' هذا يساعد النموذج على التركيز على جانب واحد في كل مرة، مما ينتج عنه إجابات أكثر دقة وشمولية.
في بعض الأحيان، أفضل طريقة للحصول على إجابة دقيقة هي تقييد الخيارات المتاحة للنموذج. هذا ما تفعله استراتيجية Constrained Prompting، حيث تضع قيوداً واضحة على شكل الإجابة أو محتواها. الفكرة هنا ليست تقييد النموذج بشكل عشوائي، بل توجيهه نحو الإجابة الأكثر دقة وفائدة. هذه الاستراتيجية مفيدة بشكل خاص في المهام التي تتطلب تنسيقاً محدداً أو عندما تريد تجنب الإجابات الطويلة وغير المركزة.
لنأخذ مثالاً من عالم تطوير الويب: إذا أردت من النموذج توليد كود HTML لتنسيق معين، يمكنك تقييد الإجابة باستخدام Constrained Prompting. بدلاً من كتابة 'أنشئ تنسيقاً لـ card في HTML'، يمكنك كتابة 'أنشئ تنسيقاً لـ card في HTML باستخدام هذه القيود: استخدم فقط div وspan، لا تستخدم أكثر من 3 مستويات من الـ nesting، استخدم أسماء فئات وفق نمط BEM، وأضف تعليقات توضيحية لكل قسم.' هذا يضمن أن الكود الناتج سيكون متسقاً مع نمط المشروع ويقلل الحاجة إلى التعديلات اليدوية. في إحدى المرات، استخدمت هذه الاستراتيجية لتوليد وثائق واجهة برمجة تطبيقات RESTful. بدلاً من كتابة Prompt عاماً، وضعت قيوداً مثل 'استخدم تنسيق OpenAPI 3.0، قسم الوثيقة إلى paths وcomponents، واستخدم أمثلة واقعية لكل endpoint.' النتيجة كانت وثائق جاهزة للاستخدام تقريباً دون الحاجة إلى تعديل كبير.
Prompt سيئ (بدون Constrained Prompting):
"أنشئ تنسيقاً لـ card في HTML."
Prompt جيد (مع Constrained Prompting):
"أنشئ تنسيقاً لـ card في HTML باستخدام القيود التالية:
1. استخدم فقط عناصر div وspan وimg وp.
2. لا تستخدم أكثر من 3 مستويات من الـ nesting.
3. استخدم أسماء فئات وفق نمط BEM (Block__Element--Modifier).
4. أضف تعليقات توضيحية لكل قسم رئيسي.
5. اجعل التنسيق متجاوباً باستخدام flexbox.
6. استخدم ألواناً من لوحة الألوان التالية: #2c3e50, #3498db, #ecf0f1.
مثال على الهيكل المطلوب:
<div class="card">
<!-- صورة Card -->
<div class="card__image">
<img src="image.jpg" alt="الوصف">
</div>
<!-- محتوى Card -->
<div class="card__content">
<h3 class="card__title">العنوان</h3>
<p class="card__description">الوصف...</p>
</div>
</div>"المشكلة الرئيسية في Constrained Prompting هي أنه إذا وضعت قيوداً كثيرة جداً أو صارمة جداً، فقد تقتل إبداع النموذج وتجعله ينتج إجابات جامدة وغير مفيدة. مثلاً، إذا طلبت من النموذج كتابة مقال حول موضوع معين مع قيود صارمة على عدد الكلمات وتنسيق الفقرات واستخدام الكلمات، فقد ينتهي بك الأمر بمقال يبدو وكأنه مكتوب بواسطة روبوت. الحل هنا هو أن تكون القيود واضحة ولكنها مرنة بما يكفي للسماح ببعض الإبداع. مثلاً، بدلاً من كتابة 'اكتب مقالاً من 500 كلمة بالضبط، استخدم 5 فقرات، وكل فقرة تبدأ بجملة افتتاحية قوية'، يمكنك كتابة 'اكتب مقالاً بين 400 و600 كلمة، استخدم فقرات واضحة ومنطقية، واجعل كل فقرة تركز على فكرة رئيسية واحدة'.
هناك أيضاً نقطة مهمة تتعلق بتحديد الأولويات. ليس كل القيود متساوية الأهمية، وبعضها قد يكون ضرورياً أكثر من غيره. مثلاً، في توليد الكود، قد تكون القيود على التنسيق والأسماء أكثر أهمية من القيود على عدد الأسطر. من تجربتي، أفضل طريقة لاستخدام Constrained Prompting هي البدء بقيود قليلة ومراقبة النتائج، ثم إضافة قيود إضافية تدريجياً حسب الحاجة. أيضاً، يجب أن تكون القيود واقعية ومتوافقة مع المهمة المطلوبة. مثلاً، إذا طلبت من النموذج كتابة كود بايثون باستخدام نمط معين، يجب أن تتأكد أولاً من أن هذا النمط قابل للتطبيق في بايثون ولا يتعارض مع ممارسات البرمجة الجيدة.
إذا كنت تعتقد أن كتابة Prompt جيد هو عملية من خطوة واحدة، فأنت مخطئ. أفضل النتائج تأتي من استخدام استراتيجية Iterative Refinement، حيث تبدأ بـ Prompt أولي، ثم تحسنه تدريجياً بناءً على المخرجات. الفكرة هنا مشابهة لعملية كتابة الكود نفسها: نادراً ما يكتب المطورون كوداً مثالياً من المحاولة الأولى، بل يمرون بمراحل من الاختبار والتحسين. نفس المبدأ ينطبق على Prompt Engineering. في الواقع، هذه الاستراتيجية هي ما يفصل المطورين المحترفين عن المستخدمين العاديين للنماذج اللغوية الكبيرة.
لنأخذ مثالاً عملياً: إذا أردت من النموذج كتابة مقال تقني حول موضوع معين، قد تبدأ بـ Prompt بسيط مثل 'اكتب مقالاً عن تعلم الآلة'. لكن المقال الناتج سيكون عاماً وغير مفيد. بدلاً من ذلك، يمكنك استخدام Iterative Refinement بهذه الطريقة: أولاً، اطلب من النموذج تقديم مخطط للمقال. ثانياً، راجع المخطط وأضف تعديلاتك مثل 'أضف قسماً عن تحديات تعلم الآلة في الإنتاج' أو 'ركز أكثر على الجانب العملي بدلاً من النظري'. ثالثاً، اطلب من النموذج كتابة القسم الأول بناءً على المخطط المعدل. رابعاً، راجع القسم الأول وأضف ملاحظاتك مثل 'اجعل الأسلوب أكثر تقنية' أو 'أضف أمثلة من مشاريع حقيقية'. كرر هذه العملية حتى تحصل على مقال يلبي توقعاتك. في إحدى المرات، استخدمت هذه الاستراتيجية لكتابة وثائق تقنية لمشروع معقد. بدلاً من كتابة Prompt واحد طويل ومعقد، بدأت بمخطط بسيط، ثم أضفت التفاصيل تدريجياً بناءً على المخرجات الأولية. النتيجة كانت وثائق أكثر دقة وشمولية مما لو حاولت كتابة كل شيء دفعة واحدة.
# مثال على Iterative Refinement لكتابة مقال تقني
## المرحلة 1: طلب مخطط أولي
Prompt: "أنشئ مخططاً لمقال تقني عن 'تحديات تعلم الآلة في الإنتاج'. قسم المقال إلى 5 أقسام رئيسية مع عناوين فرعية."
## المرحلة 2: تحسين المخطط
Prompt: "عدل هذا المخطط بناءً على الملاحظات التالية:
1. أضف قسماً عن 'تكلفة البنية التحتية'.
2. قسم 'البيانات' يجب أن يشمل 'جودة البيانات' و'كمية البيانات'.
3. أضف أمثلة واقعية لكل تحدي."
## المرحلة 3: كتابة القسم الأول
Prompt: "اكتب القسم الأول من المقال ('مقدمة') بناءً على المخطط المعدل. اجعل الأسلوب تقنياً ولكن سهل الفهم، واستخدم أمثلة من شركات معروفة مثل Google وNetflix."
## المرحلة 4: تحسين القسم الأول
Prompt: "عدل هذا القسم بناءً على الملاحظات التالية:
1. اجعل المقدمة أكثر جاذبية باستخدام إحصائية مذهلة.
2. أضف مثالاً عن كيف استخدمت Netflix تعلم الآلة لتحسين توصيات الأفلام.
3. قلل من المصطلحات التقنية المعقدة."
## المرحلة 5: كتابة باقي المقال
Prompt: "اكتب باقي المقال بناءً على المخطط المعدل والملاحظات السابقة. حافظ على الاتساق في الأسلوب والأمثلة."أحد التحديات في Iterative Refinement هو معرفة متى تتوقف عن تحسين الـ Prompt. إذا واصلت التحسين بلا نهاية، فقد ينتهي بك الأمر إلى إضاعة الوقت في تفاصيل غير ضرورية. القاعدة الأساسية هنا هي أن تتوقف عندما تصل إلى نقطة تناقص العائدات، أي عندما تصبح التحسينات الإضافية طفيفة ولا تضيف قيمة كبيرة. مثلاً، إذا كنت تكتب مقالاً تقنياً، قد تلاحظ أن التحسينات الأولى تؤدي إلى تحسن كبير في الجودة، ولكن بعد 3 أو 4 تكرارات، تصبح التحسينات طفيفة جداً. في هذه الحالة، من الأفضل التوقف والتركيز على المهام الأخرى.
هناك أيضاً نقطة تتعلق بتوازن الجودة والوقت. في بعض الأحيان، قد تحتاج إلى نتيجة جيدة بسرعة، وليس مثالية. مثلاً، إذا كنت تستخدم النموذج لتوليد أفكار لمشروع جديد، قد لا تحتاج إلى Iterative Refinement العميق. لكن إذا كنت تكتب وثائق تقنية أو كود إنتاج، فإن الاستثمار في تحسين الـ Prompt قد يوفر عليك ساعات من العمل اليدوي لاحقاً. من تجربتي، أفضل طريقة هي تحديد مستوى الجودة المطلوب مسبقاً. مثلاً، يمكنك كتابة 'أريد مقالاً تقنياً جاهزاً للنشر في مدونة احترافية' أو 'أريد كوداً جاهزاً للإنتاج مع اختبارات وحدة'. هذا يساعدك على تحديد متى وصلت إلى النتيجة المطلوبة وتجنب التحسين المفرط.
حتى المطورين المحترفين قد يقعوا في فخاخ شائعة عند كتابة الـ Prompts. أحد أكبر هذه الفخاخ هو الاعتماد على الـ Prompts العامة جداً. مثلاً، كتابة 'اكتب كود بايثون' بدلاً من 'اكتب دالة بايثون تستخدم خوارزمية البحث الثنائي للبحث في قائمة مرتبة من الأعداد الصحيحة'. الـ Prompt العام سيؤدي إلى كود عام وغير مفيد، بينما الـ Prompt المحدد سيؤدي إلى كود دقيق ومفيد. المشكلة هنا أن الكثير من المطورين يعتقدون أن النماذج 'تفهم' ما يريدون دون الحاجة إلى التفاصيل، وهذا اعتقاد خاطئ تماماً. النماذج لا تفهم السياق بنفس الطريقة التي يفهمها البشر، بل تعتمد على الأنماط في البيانات التي تدربت عليها. لهذا السبب، كلما كانت الـ Prompts أكثر تحديداً، كانت النتائج أفضل.
فخ آخر شائع هو تجاهل الـ Context Window. إذا كتبت Prompt طويلاً جداً ومعقداً، قد يتجاوز حد الـ Context Window للنموذج، مما يؤدي إلى تجاهل أجزاء مهمة من الـ Prompt. مثلاً، إذا كتبت Prompt مكون من 1000 كلمة لشرح مفهوم معين، قد 'ينسى' النموذج الأجزاء الأولى من الـ Prompt ويركز فقط على الأجزاء الأخيرة. الحل هنا هو تقسيم الـ Prompt إلى أجزاء أصغر، أو استخدام استراتيجيات مثل Few-Shot Learning بدلاً من كتابة تعليمات طويلة. أيضاً، يجب أن تكون على دراية بحدود الـ Context Window للنموذج الذي تستخدمه. مثلاً، بعض النماذج تدعم 4K tokens فقط، بينما تدعم أخرى 32K أو أكثر. إذا كنت تعمل على مهمة معقدة، قد تحتاج إلى استخدام نموذج يدعم Context Window أكبر أو تقسيم المهمة إلى أجزاء أصغر.
بعد سنوات من العمل مع نماذج اللغة الكبيرة، سواء في مشاريع شخصية أو في شركات تقنية كبيرة، توصلت إلى بعض القواعد الذهبية التي أستخدمها دائماً عند كتابة الـ Prompts. أولاً، ابدأ دائماً بـ Prompt بسيط ثم حسنه تدريجياً باستخدام Iterative Refinement. لا تحاول كتابة الـ Prompt المثالي من المحاولة الأولى، بل دع المخرجات ترشدك إلى التحسينات اللازمة. ثانياً، استخدم استراتيجيات متعددة معاً للحصول على أفضل النتائج. مثلاً، يمكنك دمج Role Prompting مع Few-Shot Learning للحصول على إجابات أكثر دقة وشمولية. ثالثاً، كن محدداً قدر الإمكان في الـ Prompts. بدلاً من كتابة 'اكتب كود'، اكتب 'اكتب دالة جافاسكريبت تستخدم async/await لجلب البيانات من واجهة برمجة تطبيقات RESTful ومعالجتها'. كلما كانت التعليمات أكثر تحديداً، كانت النتائج أفضل.
أيضاً، لا تنسَ أن تتحقق دائماً من المخرجات، خاصة في المهام الحساسة مثل توليد الكود أو كتابة الوثائق التقنية. النماذج اللغوية الكبيرة قد تنتج أحياناً إجابات تبدو جيدة ولكنها تحتوي على أخطاء أو ثغرات. استخدم أدوات التحقق الآلي مثل linters واختبارات الوحدة للتأكد من جودة المخرجات. وأخيراً، استثمر الوقت في تعلم حدود وقدرات النموذج الذي تستخدمه. كل نموذج له نقاط قوة وضعف مختلفة، ومعرفة هذه النقاط ستساعدك على كتابة Prompts أكثر فعالية. مثلاً، إذا كنت تستخدم نموذجاً جيداً في توليد الكود ولكنه ضعيف في الكتابة الإبداعية، فلا تطلب منه كتابة مقالات أدبية. بدلاً من ذلك، ركز على استخدامه في المهام التي يتفوق فيها.
Prompt Engineering ليس مجرد كتابة أوامر، بل هو فن هندسة تفكير الآلة. كلما فهمت كيف 'يفكر' النموذج، كلما استطعت توجيهه بشكل أفضل للحصول على النتائج التي تريدها.
— المهندس خلف الكواليس