المستوى: متوسط — الكلام ده للي عنده أساس في البرمجة وبيتعامل مع الـ APIs، مش لأول يوم في البايثون.
لو بنيت شات بوت وسألته عن سعر الدولار النهاردة فاخترع رقم، المشكلة مش إنه غبي. المشكلة إنه ملوش وصول لبياناتك ولا للإنترنت. استدعاء الدوال (Function Calling) بيحل ده بالظبط: النموذج يطلب تشغيل دالة حقيقية عندك، وانت تنفّذها وترجّعله النتيجة.
استدعاء الدوال: إزاي النموذج بيطلب تشغيل كودك بـ JSON منظّم
المشكلة باختصار
نموذج اللغة بيتوقّع الكلمة اللي بعدها بناءً على تدريبه. يعني معندوش سعر صرف لحظي، ولا رصيد عميل، ولا صلاحية يبعت إيميل. لو سألته حاجة زي دي، هيألّف إجابة واثقة وغالبًا غلط، وده اللي بنسميه الهلوسة. الحل مش إنك تكبّر البرومبت وتحشيه بيانات. الحل إنك تديله أدوات وتخليه يقرّر بنفسه امتى يستخدمها.
يعني إيه استدعاء الدوال؟
تخيّل موظف استقبال خبير بيرد على أي سؤال بطلاقة، بس ممنوع يلمس أنظمة الشركة. لما تطلب منه حاجة محتاجة النظام — «اطبعلي فاتورة العميل ده» — هو مش بيروح ينفّذ بنفسه. بيملالك استمارة مكتوبة بدقة: اسم الإجراء المطلوب، وتفاصيله. انت بتاخد الاستمارة، تنفّذها على النظام، وترجّعله النتيجة عشان يكمّل كلامه مع العميل.
علميًا: انت بتوصّف للنموذج مجموعة «أدوات» (tools)، كل واحدة ليها اسم ووصف وschema بصيغة JSON Schema يحدّد المعاملات وأنواعها. النموذج بيقرأ السؤال، ولو محتاج أداة، بيرجّع كتلة منظّمة (tool call) فيها اسم الدالة والمعاملات كـ JSON — مش نص حر. تطبيقك هو اللي بينفّذ الكود فعليًا، ويرجّع النتيجة للنموذج في الدورة اللي بعدها.
إزاي بتشتغل — الحلقة
- المستخدم يسأل: «كام درجة الحرارة في القاهرة دلوقتي؟».
- النموذج يرجّع طلب أداة: بدل رد نصي، يرجّع
{"name":"get_weather","arguments":{"city":"Cairo"}}. - تطبيقك ينفّذ الدالة: ينده الـ API الحقيقي ويجيب 34 درجة.
- ترجّع النتيجة للنموذج في رسالة نتيجة الأداة (tool result).
- النموذج يصيغ الإجابة النهائية بلغة طبيعية للمستخدم.
ركز في نقطة مهمة: النموذج ما نفّذش أي كود. هو بس طلب التنفيذ. ده بيخليك تتحكم في الأمان بالظبط، لأنك انت اللي بتقرّر أنهي دوال متاحة وبأي صلاحيات.
مثال كود شغّال
ده مثال بصيغة واجهة OpenAI، ونفس الفكرة موجودة عند Anthropic باسم tool use. عرّفنا أداة واحدة، وبعتناها مع الرسالة:
from openai import OpenAI
import json
client = OpenAI()
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "ارجع درجة الحرارة الحالية لمدينة",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
}]
messages = [{"role": "user", "content": "كام الحرارة في القاهرة؟"}]
resp = client.chat.completions.create(
model="gpt-4o-mini", messages=messages, tools=tools
)
call = resp.choices[0].message.tool_calls[0]
args = json.loads(call.function.arguments) # {"city": "Cairo"}
# تطبيقك هو اللي بينفّذ الدالة الحقيقية
result = get_weather(args["city"]) # مثلاً 34
# ارجع النتيجة للنموذج عشان يصيغ الرد النهائي
messages.append(resp.choices[0].message)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": str(result)
})
final = client.chat.completions.create(
model="gpt-4o-mini", messages=messages, tools=tools
)
print(final.choices[0].message.content)