مستوى هذا المقال: متوسط. الافتراض إنك تعرف أساسيات نماذج اللغة (LLM) وتقدر تقرأ كود Python بسيط. لو انت مبتدئ تمامًا، ركّز على المثال البسيط في البداية وتجاوز الكود.
الوكلاء الأذكياء وحلقة ReAct: من نموذج بيتكلم لنموذج بينفّذ
لو نموذجك بيرد بكلام حلو بس مش بيجيب بيانات حديثة ولا بيعمل أي فعل، المشكلة مش في النموذج، المشكلة إنك مديله دور واحد بس: يتكلم. حلقة ReAct بتديله دورين: يفكّر وينفّذ. في آخر المقال هتقدر تبني وكيلًا بسيطًا بنفسك في أقل من 30 سطر.
المشكلة باختصار
الشات بوت العادي بياخد سؤالك ويطلع إجابة واحدة من ذاكرته وقت التدريب. مفيهوش لحظة يقول فيها "استنى، محتاج أدوّر على السعر الحالي" أو "محتاج أحسب الرقم ده". فبيهلوس أو بيرد بمعلومة قديمة. الوكيل (Agent) بيحل ده بإنه يلفّ في حلقة: يفكّر، ينفّذ أداة، يشوف النتيجة، ويكرّر لحد ما يوصل للإجابة.
المثال البسيط الأول
تخيّل موظف استقبال في فندق. لو سألته "الغرفة 214 فاضية؟" وهو قاعد بيرد من دماغه من غير ما يبص على الشاشة، ممكن يغلط. الموظف الشاطر بيعمل 3 حاجات: يفكّر ("محتاج أتأكد من نظام الحجز")، ينفّذ (يفتح الشاشة ويدوّر)، يقرا النتيجة ("الغرفة محجوزة لبكرة")، وبعدين يرد. لو السؤال مركّب، بيكرّر الدورة: يبص على الشاشة تاني، يسأل المطبخ، وهكذا لحد ما يجمع كل حاجة.
ReAct بالظبط كده: النموذج بيتناوب بين Reasoning (تفكير مكتوب بصوت عالٍ) وActing (استدعاء أداة حقيقية)، والنتيجة اللي بترجع من الأداة اسمها Observation بتتحقن في السياق فبيقرّر الخطوة اللي بعدها.
الشرح العلمي: إيه اللي بيحصل فعلاً
الاسم ReAct اختصار لـ Reasoning + Acting. الفكرة من ورقة Yao وزملائه سنة 2022. بدل ما النموذج يطلع الإجابة في خطوة واحدة، بيولّد أثر تفكير (Thought) يحدد فيه الخطوة التالية، وبعدين فعل (Action) على شكل استدعاء أداة، وبعدين بيستنى ملاحظة (Observation). التفكير المكتوب بيخلّي النموذج يخطّط ويصحّح مساره، والأفعال بتربطه بمصدر خارجي حقيقي بدل ما يعتمد على ذاكرته. الحلقة بتفضل تلف لحد ما النموذج يقرّر إنه وصل للإجابة النهائية.
ابنيه بنفسك في أقل من 30 سطر
ده وكيل ReAct مبسّط. لاحظ الحلقة الثلاثية والحارس max_steps، ده أهم سطر في الكود.
TOOLS = {
"search": lambda q: web_search(q), # يرجّع نص نتيجة البحث
"calc": lambda e: str(eval(e)), # حاسبة بسيطة
}
def react(goal, max_steps=6):
history = f"الهدف: {goal}\n"
for step in range(max_steps):
# 1) Thought + Action: النموذج يفكّر ويقرّر
reply = ask_llm(history +
"فكّر خطوة، ثم اكتب سطرًا واحدًا:\n"
"Action: <tool> | <input> أو Final: <answer>")
history += reply + "\n"
if reply.startswith("Final:"):
return reply.replace("Final:", "").strip()
# 2) ننفّذ الأداة
tool, arg = reply.replace("Action:", "").split("|")
observation = TOOLS[tool.strip()](arg.strip())
# 3) Observation: نرجّع النتيجة للنموذج
history += f"Observation: {observation}\n"
return "توقفت: تجاوزت الحد الأقصى للخطوات"